Skip to content

[clean strict optional] Fix more strict optional errors #3292

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 21 additions & 14 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ def check_first_pass(self) -> None:

all_ = self.globals.get('__all__')
if all_ is not None and all_.type is not None:
all_node = all_.node
assert all_node is not None
seq_str = self.named_generic_type('typing.Sequence',
[self.named_type('builtins.str')])
if self.options.python_version[0] < 3:
Expand All @@ -188,7 +190,7 @@ def check_first_pass(self) -> None:
if not is_subtype(all_.type, seq_str):
str_seq_s, all_s = self.msg.format_distinctly(seq_str, all_.type)
self.fail(messages.ALL_MUST_BE_SEQ_STR.format(str_seq_s, all_s),
all_.node)
all_node)

def check_second_pass(self, todo: List[DeferredNode] = None) -> bool:
"""Run second or following pass of type checking.
Expand Down Expand Up @@ -346,12 +348,13 @@ def check_overlapping_overloads(self, defn: OverloadedFuncDef) -> None:
self.msg.overloaded_signatures_arg_specific(i + 1, defn.impl)
impl_type_subst = impl_type
if impl_type.variables:
impl_type_subst = unify_generic_callable(impl_type, sig1, ignore_return=False)
if impl_type_subst is None:
unified = unify_generic_callable(impl_type, sig1, ignore_return=False)
if unified is None:
self.fail("Type variable mismatch between " +
"overload signature {} and implementation".format(i + 1),
defn.impl)
return
impl_type_subst = unified
if not is_subtype(sig1.ret_type, impl_type_subst.ret_type):
self.msg.overloaded_signatures_ret_specific(i + 1, defn.impl)

Expand Down Expand Up @@ -593,7 +596,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str) -> None:
not isinstance(typ.ret_type, NoneTyp) and
not self.dynamic_funcs[-1]):
self.fail(messages.MUST_HAVE_NONE_RETURN_TYPE.format(fdef.name()),
item.type)
item)

show_untyped = not self.is_typeshed_stub or self.options.warn_incomplete_stub
if self.options.disallow_untyped_defs and show_untyped:
Expand Down Expand Up @@ -1257,7 +1260,7 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type
self.infer_variable_type(inferred, lvalue, self.expr_checker.accept(rvalue),
rvalue)

def check_compatibility_all_supers(self, lvalue: NameExpr, lvalue_type: Type,
def check_compatibility_all_supers(self, lvalue: NameExpr, lvalue_type: Optional[Type],
rvalue: Expression) -> bool:
lvalue_node = lvalue.node

Expand Down Expand Up @@ -1300,8 +1303,9 @@ def check_compatibility_all_supers(self, lvalue: NameExpr, lvalue_type: Type,
break
return False

def check_compatibility_super(self, lvalue: NameExpr, lvalue_type: Type, rvalue: Expression,
base: TypeInfo, base_type: Type, base_node: Node) -> bool:
def check_compatibility_super(self, lvalue: NameExpr, lvalue_type: Optional[Type],
rvalue: Expression, base: TypeInfo, base_type: Type,
base_node: Node) -> bool:
lvalue_node = lvalue.node
assert isinstance(lvalue_node, Var)

Expand Down Expand Up @@ -1574,10 +1578,12 @@ def check_multi_assignment_from_iterable(self, lvalues: List[Lvalue], rvalue_typ
else:
self.msg.type_not_iterable(rvalue_type, context)

def check_lvalue(self, lvalue: Lvalue) -> Tuple[Type, IndexExpr, Var]:
lvalue_type = None # type: Type
index_lvalue = None # type: IndexExpr
inferred = None # type: Var
def check_lvalue(self, lvalue: Lvalue) -> Tuple[Optional[Type],
Optional[IndexExpr],
Optional[Var]]:
lvalue_type = None # type: Optional[Type]
index_lvalue = None # type: Optional[IndexExpr]
inferred = None # type: Optional[Var]

if self.is_definition(lvalue):
if isinstance(lvalue, NameExpr):
Expand Down Expand Up @@ -2750,8 +2756,8 @@ def find_isinstance_check(node: Expression,
# Check for `x is None` and `x is not None`.
is_not = node.operators == ['is not']
if any(is_literal_none(n) for n in node.operands) and (is_not or node.operators == ['is']):
if_vars = {} # type: Dict[Expression, Type]
else_vars = {} # type: Dict[Expression, Type]
if_vars = {} # type: TypeMap
else_vars = {} # type: TypeMap
for expr in node.operands:
if expr.literal == LITERAL_TYPE and not is_literal_none(expr) and expr in type_map:
# This should only be true at most once: there should be
Expand Down Expand Up @@ -2829,7 +2835,8 @@ def flatten_types(t: Type) -> List[Type]:
return [t]


def get_isinstance_type(expr: Expression, type_map: Dict[Expression, Type]) -> List[TypeRange]:
def get_isinstance_type(expr: Expression,
type_map: Dict[Expression, Type]) -> Optional[List[TypeRange]]:
all_types = flatten_types(type_map[expr])
types = [] # type: List[TypeRange]
for typ in all_types:
Expand Down
6 changes: 4 additions & 2 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def visit_name_expr(self, e: NameExpr) -> Type:
return self.narrow_type_from_binder(e, result)

def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type:
result = None # type: Type
result = None # type: Optional[Type]
node = e.node
if isinstance(node, Var):
# Variable reference.
Expand Down Expand Up @@ -157,6 +157,7 @@ def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type:
# Unknown reference; use any type implicitly to avoid
# generating extra type errors.
result = AnyType()
assert result is not None
return result

def analyze_var_ref(self, var: Var, context: Context) -> Type:
Expand Down Expand Up @@ -468,7 +469,8 @@ def analyze_type_type_callee(self, item: Type, context: Context) -> Type:
# i.e. its constructor (a poor approximation for reality,
# but better than AnyType...), but replace the return type
# with typevar.
callee = self.analyze_type_type_callee(item.upper_bound, context)
callee = self.analyze_type_type_callee(item.upper_bound,
context) # type: Optional[Type]
if isinstance(callee, CallableType):
if callee.is_generic():
callee = None
Expand Down
11 changes: 6 additions & 5 deletions mypy/checkmember.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ def analyze_class_attribute_access(itype: Instance,
builtin_type: Callable[[str], Instance],
not_ready_callback: Callable[[str, Context], None],
msg: MessageBuilder,
original_type: Type) -> Type:
original_type: Type) -> Optional[Type]:
"""original_type is the type of E in the expression E.var"""
node = itype.type.get(name)
if not node:
Expand All @@ -403,7 +403,9 @@ def analyze_class_attribute_access(itype: Instance,
t = node.type
if t:
if isinstance(t, PartialType):
return handle_partial_attribute_type(t, is_lvalue, msg, node.node)
symnode = node.node
assert symnode is not None
return handle_partial_attribute_type(t, is_lvalue, msg, symnode)
if not is_method and (isinstance(t, TypeVarType) or get_type_vars(t)):
msg.fail(messages.GENERIC_INSTANCE_VAR_CLASS_ACCESS, context)
is_classmethod = is_decorated and cast(Decorator, node.node).func.is_class
Expand Down Expand Up @@ -515,12 +517,10 @@ def type_object_type_from_function(init_or_new: FuncBase, info: TypeInfo,
# We need to first map B's __init__ to the type (List[T]) -> None.
signature = cast(FunctionLike,
map_type_from_supertype(signature, info, init_or_new.info))

special_sig = None # type: Optional[str]
if init_or_new.info.fullname() == 'builtins.dict':
# Special signature!
special_sig = 'dict'
else:
special_sig = None

if isinstance(signature, CallableType):
return class_callable(signature, info, fallback, special_sig)
Expand Down Expand Up @@ -630,6 +630,7 @@ class B(A): pass
self_param_type, original_type)[0]

def expand(target: Type) -> Type:
assert typearg is not None
return expand_type(target, {func.variables[0].id: typearg})

arg_types = [expand(x) for x in func.arg_types[1:]]
Expand Down
7 changes: 4 additions & 3 deletions mypy/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class Constraint:
It can be either T <: type or T :> type (T is a type variable).
"""

type_var = None # Type variable id
type_var = None # type: TypeVarId
op = 0 # SUBTYPE_OF or SUPERTYPE_OF
target = None # type: Type

Expand Down Expand Up @@ -53,10 +53,11 @@ def infer_constraints_for_callable(

for i, actuals in enumerate(formal_to_actual):
for actual in actuals:
if arg_types[actual] is None:
actual_arg_type = arg_types[actual]
if actual_arg_type is None:
continue

actual_type = get_actual_type(arg_types[actual], arg_kinds[actual],
actual_type = get_actual_type(actual_arg_type, arg_kinds[actual],
tuple_counter)
c = infer_constraints(callee.arg_types[i], actual_type,
SUPERTYPE_OF)
Expand Down
1 change: 1 addition & 0 deletions mypy/exprtotype.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def expr_to_unanalyzed_type(expr: Expression) -> Type:
# Parse string literal type.
try:
result = parse_type_comment(expr.value, expr.line, None)
assert result is not None
except SyntaxError:
raise TypeTranslationError()
return result
Expand Down
2 changes: 1 addition & 1 deletion mypy/fastparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def parse(source: Union[str, bytes], fnam: str = None, errors: Errors = None,
return tree


def parse_type_comment(type_comment: str, line: int, errors: Errors) -> Optional[Type]:
def parse_type_comment(type_comment: str, line: int, errors: Optional[Errors]) -> Optional[Type]:
try:
typ = ast3.parse(type_comment, '<type_comment>', 'eval')
except SyntaxError as e:
Expand Down
4 changes: 2 additions & 2 deletions mypy/infer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def infer_function_type_arguments(callee_type: CallableType,
arg_types: List[Optional[Type]],
arg_kinds: List[int],
formal_to_actual: List[List[int]],
strict: bool = True) -> List[Type]:
strict: bool = True) -> List[Optional[Type]]:
"""Infer the type arguments of a generic function.

Return an array of lower bound types for the type variables -1 (at
Expand All @@ -36,7 +36,7 @@ def infer_function_type_arguments(callee_type: CallableType,


def infer_type_arguments(type_var_ids: List[TypeVarId],
template: Type, actual: Type) -> List[Type]:
template: Type, actual: Type) -> List[Optional[Type]]:
# Like infer_function_type_arguments, but only match a single type
# against a generic type.
constraints = infer_constraints(template, actual, SUBTYPE_OF)
Expand Down
4 changes: 2 additions & 2 deletions mypy/join.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Calculation of the least upper bound types (joins)."""

from collections import OrderedDict
from typing import cast, List
from typing import cast, List, Optional

from mypy.types import (
Type, AnyType, NoneTyp, TypeVisitor, Instance, UnboundType,
Expand Down Expand Up @@ -305,7 +305,7 @@ def join_instances_via_supertype(t: Instance, s: Instance) -> Type:
# Compute the "best" supertype of t when joined with s.
# The definition of "best" may evolve; for now it is the one with
# the longest MRO. Ties are broken by using the earlier base.
best = None # type: Type
best = None # type: Optional[Type]
for base in t.type.bases:
mapped = map_instance_to_supertype(t, base.type)
res = join_instances(mapped, s)
Expand Down
15 changes: 10 additions & 5 deletions mypy/meet.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections import OrderedDict
from typing import List, Optional
from typing import List, Optional, cast, Tuple

from mypy.join import is_similar_callables, combine_similar_callables, join_type_list
from mypy.types import (
Expand Down Expand Up @@ -255,10 +255,15 @@ def visit_typeddict_type(self, t: TypedDictType) -> Type:
for (_, l, r) in self.s.zip(t):
if not is_equivalent(l, r):
return self.default(self.s)
items = OrderedDict([
(item_name, s_item_type or t_item_type)
for (item_name, s_item_type, t_item_type) in self.s.zipall(t)
])
item_list = [] # type: List[Tuple[str, Type]]
for (item_name, s_item_type, t_item_type) in self.s.zipall(t):
if s_item_type is not None:
item_list.append((item_name, s_item_type))
else:
# at least one of s_item_type and t_item_type is not None
assert t_item_type is not None
item_list.append((item_name, t_item_type))
items = OrderedDict(item_list)
mapping_value_type = join_type_list(list(items.values()))
fallback = self.s.create_anonymous_fallback(value_type=mapping_value_type)
return TypedDictType(items, fallback)
Expand Down
Loading