From 178ad41c5a915bc5157e9d4c87af310b65991262 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Thu, 14 Sep 2017 13:20:35 +0200 Subject: [PATCH 1/5] Clean-up most of checker; started checkexpr --- mypy/checker.py | 80 ++++++++++++++++++++++++--------------------- mypy/checkexpr.py | 20 ++++++------ mypy_self_check.ini | 6 ---- 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index e9ca186bd566..383e76c4c71e 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -205,7 +205,7 @@ def check_first_pass(self) -> None: self.fail(messages.ALL_MUST_BE_SEQ_STR.format(str_seq_s, all_s), all_node) - def check_second_pass(self, todo: List[DeferredNode] = None) -> bool: + def check_second_pass(self, todo: Optional[List[DeferredNode]] = None) -> bool: """Run second or following pass of type checking. This goes through deferred nodes, returning True if there were any. @@ -279,8 +279,8 @@ def accept(self, stmt: Statement) -> None: except Exception as err: report_internal_error(err, self.errors.file, stmt.line, self.errors, self.options) - def accept_loop(self, body: Statement, else_body: Statement = None, *, - exit_condition: Expression = None) -> None: + def accept_loop(self, body: Statement, else_body: Optional[Statement] = None, *, + exit_condition: Optional[Expression] = None) -> None: """Repeatedly type check a loop body until the frame doesn't change. If exit_condition is set, assume it must be False on exit from the loop. @@ -562,15 +562,15 @@ def visit_func_def(self, defn: FuncDef) -> None: 'original type') def check_func_item(self, defn: FuncItem, - type_override: CallableType = None, - name: str = None) -> None: + type_override: Optional[CallableType] = None, + name: Optional[str] = None) -> None: """Type check a function. If type_override is provided, use it as the function type. """ # We may be checking a function definition or an anonymous function. In # the first case, set up another reference with the precise type. - fdef = None # type: FuncDef + fdef = None # type: Optional[FuncDef] if isinstance(defn, FuncDef): fdef = defn @@ -597,7 +597,7 @@ def enter_attribute_inference_context(self) -> Iterator[None]: yield None self.inferred_attribute_types = old_types - def check_func_def(self, defn: FuncItem, typ: CallableType, name: str) -> None: + def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str]) -> None: """Type check a function definition.""" # Expand type variables with value restrictions to ordinary types. for item, typ in self.expand_typevars(defn, typ): @@ -610,7 +610,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str) -> None: # function. In the first case, set up another reference with the # precise type. if isinstance(item, FuncDef): - fdef = item + fdef = item # type: Optional[FuncDef] else: fdef = None @@ -634,12 +634,13 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str) -> None: self.msg.unimported_type_becomes_any(prefix, arg_type, fdef) check_for_explicit_any(fdef.type, self.options, self.is_typeshed_stub, self.msg, context=fdef) - if name in nodes.reverse_op_method_set: - self.check_reverse_op_method(item, typ, name) - elif name in ('__getattr__', '__getattribute__'): - self.check_getattr_method(typ, defn, name) - elif name == '__setattr__': - self.check_setattr_method(typ, defn) + if name: # Special method names + if name in nodes.reverse_op_method_set: + self.check_reverse_op_method(item, typ, name) + elif name in ('__getattr__', '__getattribute__'): + self.check_getattr_method(typ, defn, name) + elif name == '__setattr__': + self.check_setattr_method(typ, defn) # Refuse contravariant return type variable if isinstance(typ.ret_type, TypeVarType): if typ.ret_type.variance == CONTRAVARIANT: @@ -1454,7 +1455,7 @@ def check_compatibility_super(self, lvalue: NameExpr, lvalue_type: Optional[Type # lvalue had a type defined; this is handled by other # parts, and all we have to worry about in that case is # that lvalue is compatible with the base class. - compare_node = None # type: Node + compare_node = None # type: Optional[Node] if lvalue_type: compare_type = lvalue_type compare_node = lvalue.node @@ -1533,7 +1534,7 @@ def lvalue_type_from_base(self, expr_node: Var, return None, None def check_compatibility_classvar_super(self, node: Var, - base: TypeInfo, base_node: Node) -> bool: + base: TypeInfo, base_node: Optional[Node]) -> bool: if not isinstance(base_node, Var): return True if node.is_classvar and not base_node.is_classvar: @@ -1600,7 +1601,7 @@ def check_multi_assignment(self, lvalues: List[Lvalue], rvalue: Expression, context: Context, infer_lvalue_type: bool = True, - msg: str = None) -> None: + msg: Optional[str] = None) -> None: """Check the assignment of one rvalue to a number of lvalues.""" # Infer the type of an ordinary rvalue expression. @@ -1801,7 +1802,7 @@ def infer_variable_type(self, name: Var, lvalue: Lvalue, self.fail(messages.NEED_ANNOTATION_FOR_VAR, context) self.set_inference_error_fallback_type(name, lvalue, init_type, context) elif (isinstance(lvalue, MemberExpr) and self.inferred_attribute_types is not None - and lvalue.def_var in self.inferred_attribute_types + and lvalue.def_var and lvalue.def_var in self.inferred_attribute_types and not is_same_type(self.inferred_attribute_types[lvalue.def_var], init_type)): # Multiple, inconsistent types inferred for an attribute. self.fail(messages.NEED_ANNOTATION_FOR_VAR, context) @@ -1844,6 +1845,7 @@ def set_inferred_type(self, var: Var, lvalue: Lvalue, type: Type) -> None: var.is_inferred = True if isinstance(lvalue, MemberExpr) and self.inferred_attribute_types is not None: # Store inferred attribute type so that we can check consistency afterwards. + assert lvalue.def_var is not None self.inferred_attribute_types[lvalue.def_var] = type self.store_type(lvalue, type) @@ -2223,22 +2225,25 @@ def visit_try_without_finally(self, s: TryStmt, try_frame: bool) -> None: self.accept(s.body) for i in range(len(s.handlers)): with self.binder.frame_context(can_skip=True, fall_through=4): - if s.types[i]: - t = self.check_except_handler_test(s.types[i]) - if s.vars[i]: + typ = s.types[i] + if typ: + t = self.check_except_handler_test(typ) + var = s.vars[i] + if var: # To support local variables, we make this a definition line, # causing assignment to set the variable's type. - s.vars[i].is_def = True + var.is_def = True # We also temporarily set current_node_deferred to False to # make sure the inference happens. # TODO: Use a better solution, e.g. a # separate Var for each except block. am_deferring = self.current_node_deferred self.current_node_deferred = False - self.check_assignment(s.vars[i], self.temp_node(t, s.vars[i])) + self.check_assignment(var, self.temp_node(t, var)) self.current_node_deferred = am_deferring self.accept(s.handlers[i]) - if s.vars[i]: + var = s.vars[i] + if var: # Exception variables are deleted in python 3 but not python 2. # But, since it's bad form in python 2 and the type checking # wouldn't work very well, we delete it anyway. @@ -2246,14 +2251,13 @@ def visit_try_without_finally(self, s: TryStmt, try_frame: bool) -> None: # Unfortunately, this doesn't let us detect usage before the # try/except block. if self.options.python_version[0] >= 3: - source = s.vars[i].name + source = var.name else: source = ('(exception variable "{}", which we do not ' 'accept outside except: blocks even in ' - 'python 2)'.format(s.vars[i].name)) - var = cast(Var, s.vars[i].node) - var.type = DeletedType(source=source) - self.binder.cleanse(s.vars[i]) + 'python 2)'.format(var.name)) + cast(Var, var.node).type = DeletedType(source=source) + self.binder.cleanse(var) if s.else_body: self.accept(s.else_body) @@ -2452,7 +2456,7 @@ def check_untyped_after_decorator(self, typ: Type, func: FuncDef) -> None: if mypy.checkexpr.has_any_type(typ): self.msg.untyped_decorated_function(typ, func) - def check_async_with_item(self, expr: Expression, target: Expression, + def check_async_with_item(self, expr: Expression, target: Optional[Expression], infer_lvalue_type: bool) -> None: echk = self.expr_checker ctx = echk.accept(expr) @@ -2468,7 +2472,7 @@ def check_async_with_item(self, expr: Expression, target: Expression, echk.check_awaitable_expr( res, expr, messages.INCOMPATIBLE_TYPES_IN_ASYNC_WITH_AEXIT) - def check_with_item(self, expr: Expression, target: Expression, + def check_with_item(self, expr: Expression, target: Optional[Expression], infer_lvalue_type: bool) -> None: echk = self.expr_checker ctx = echk.accept(expr) @@ -2502,8 +2506,8 @@ def visit_continue_stmt(self, s: ContinueStmt) -> None: def check_subtype(self, subtype: Type, supertype: Type, context: Context, msg: str = messages.INCOMPATIBLE_TYPES, - subtype_label: str = None, - supertype_label: str = None) -> bool: + subtype_label: Optional[str] = None, + supertype_label: Optional[str] = None) -> bool: """Generate an error if the subtype is not compatible with supertype.""" if is_subtype(subtype, supertype): @@ -2621,7 +2625,9 @@ def lookup_qualified(self, name: str) -> SymbolTableNode: parts = name.split('.') n = self.modules[parts[0]] for i in range(1, len(parts) - 1): - n = cast(MypyFile, n.names.get(parts[i], None).node) + sym = n.names.get(parts[i]) + assert sym is not None, "Internal error: attempted lookup of unknown name" + n = cast(MypyFile, sym.node) last = parts[-1] if last in n.names: return n.names[last] @@ -2659,7 +2665,7 @@ def find_partial_types(self, var: Var) -> Optional[Dict[Var, Context]]: return partial_types return None - def temp_node(self, t: Type, context: Context = None) -> TempNode: + def temp_node(self, t: Type, context: Optional[Context] = None) -> TempNode: """Create a temporary node with the given, fixed type.""" temp = TempNode(t) if context: @@ -2904,7 +2910,7 @@ def or_conditional_maps(m1: TypeMap, m2: TypeMap) -> TypeMap: def convert_to_typetype(type_map: TypeMap) -> TypeMap: - converted_type_map = {} # type: TypeMap + converted_type_map = {} # type: Dict[Expression, Type] if type_map is None: return None for expr, typ in type_map.items(): @@ -3278,7 +3284,7 @@ def is_valid_inferred_type_component(typ: Type) -> bool: return True -def is_node_static(node: Node) -> Optional[bool]: +def is_node_static(node: Optional[Node]) -> Optional[bool]: """Find out if a node describes a static function method.""" if isinstance(node, FuncDef): diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index eb1f315eb6ba..8cef0e37e130 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -21,7 +21,7 @@ ConditionalExpr, ComparisonExpr, TempNode, SetComprehension, DictionaryComprehension, ComplexExpr, EllipsisExpr, StarExpr, AwaitExpr, YieldExpr, YieldFromExpr, TypedDictExpr, PromoteExpr, NewTypeExpr, NamedTupleExpr, TypeVarExpr, - TypeAliasExpr, BackquoteExpr, EnumCallExpr, + TypeAliasExpr, BackquoteExpr, EnumCallExpr, SymbolTableNode, ARG_POS, ARG_NAMED, ARG_STAR, ARG_STAR2, MODULE_REF, TVAR, LITERAL_TYPE, ) from mypy.literals import literal @@ -201,11 +201,12 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type: and len(e.args) == 2): for typ in mypy.checker.flatten(e.args[1]): if isinstance(typ, NameExpr): + node = None # type: Optional[SymbolTableNode] try: node = self.chk.lookup_qualified(typ.name) except KeyError: # Undefined names should already be reported in semantic analysis. - node = None + pass if ((isinstance(typ, IndexExpr) and isinstance(typ.analyzed, (TypeApplication, TypeAliasExpr))) # node.kind == TYPE_ALIAS only for aliases like It = Iterable[int]. @@ -217,6 +218,7 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type: elif typ.node.is_newtype: self.msg.fail(messages.CANNOT_ISINSTANCE_NEWTYPE, e) self.try_infer_partial_type(e) + type_context = None # type: Optional[CallableType] if isinstance(e.callee, LambdaExpr): formal_to_actual = map_actuals_to_formals( e.arg_kinds, e.arg_names, @@ -228,8 +230,6 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type: type_context = CallableType(arg_types, e.callee.arg_kinds, e.callee.arg_names, ret_type=self.object_type(), fallback=self.named_type('builtins.function')) - else: - type_context = None callee_type = self.accept(e.callee, type_context, always_allow_any=True) if (self.chk.options.disallow_untyped_calls and self.chk.in_checked_function() and @@ -487,9 +487,9 @@ def check_call_expr_with_callee_type(self, def check_call(self, callee: Type, args: List[Expression], arg_kinds: List[int], context: Context, - arg_names: List[str] = None, - callable_node: Expression = None, - arg_messages: MessageBuilder = None, + arg_names: Optional[List[str]] = None, + callable_node: Optional[Expression] = None, + arg_messages: Optional[MessageBuilder] = None, callable_name: Optional[str] = None, object_type: Optional[Type] = None) -> Tuple[Type, Type]: """Type check a call. @@ -976,8 +976,8 @@ def check_argument_types(self, arg_types: List[Type], arg_kinds: List[int], callee: CallableType, formal_to_actual: List[List[int]], context: Context, - messages: MessageBuilder = None, - check_arg: ArgChecker = None) -> None: + messages: Optional[MessageBuilder] = None, + check_arg: Optional[ArgChecker] = None) -> None: """Check argument types against a callable type. Report errors if the argument types are not compatible. @@ -1059,7 +1059,7 @@ def check_arg(self, caller_type: Type, original_caller_type: Type, def overload_call_target(self, arg_types: List[Type], arg_kinds: List[int], arg_names: List[str], overload: Overloaded, context: Context, - messages: MessageBuilder = None) -> Type: + messages: Optional[MessageBuilder] = None) -> Type: """Infer the correct overload item to call with given argument types. The return value may be CallableType or AnyType (if an unique item diff --git a/mypy_self_check.ini b/mypy_self_check.ini index c54a3bad3ce9..aa4683befee4 100644 --- a/mypy_self_check.ini +++ b/mypy_self_check.ini @@ -12,12 +12,6 @@ warn_unused_ignores = True [mypy-mypy.binder] disallow_any = unimported -[mypy-mypy.checker] -strict_optional = False - -[mypy-mypy.checkexpr] -strict_optional = False - [mypy-mypy.semanal] strict_optional = False From 9d77fbc84390b0e4ed100c55ce218fda574661d4 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Thu, 14 Sep 2017 17:27:23 +0200 Subject: [PATCH 2/5] More clean-up --- mypy/applytype.py | 13 ++++--- mypy/checkexpr.py | 95 +++++++++++++++++++++++++++------------------ mypy/constraints.py | 4 +- mypy/fastparse.py | 6 ++- mypy/infer.py | 4 +- mypy/messages.py | 8 ++-- mypy/nodes.py | 6 +-- 7 files changed, 80 insertions(+), 56 deletions(-) diff --git a/mypy/applytype.py b/mypy/applytype.py index 75831116562e..894b03a09627 100644 --- a/mypy/applytype.py +++ b/mypy/applytype.py @@ -1,4 +1,4 @@ -from typing import List, Dict +from typing import List, Dict, Sequence, Optional import mypy.subtypes from mypy.sametypes import is_same_type @@ -8,7 +8,7 @@ from mypy.nodes import Context -def apply_generic_arguments(callable: CallableType, types: List[Type], +def apply_generic_arguments(callable: CallableType, orig_types: Sequence[Optional[Type]], msg: MessageBuilder, context: Context) -> CallableType: """Apply generic type arguments to a callable type. @@ -18,10 +18,10 @@ def apply_generic_arguments(callable: CallableType, types: List[Type], Note that each type can be None; in this case, it will not be applied. """ tvars = callable.variables - assert len(tvars) == len(types) + assert len(tvars) == len(orig_types) # Check that inferred type variable values are compatible with allowed # values and bounds. Also, promote subtype values to allowed values. - types = types[:] + types = list(orig_types) for i, type in enumerate(types): values = callable.variables[i].values if values and type: @@ -47,8 +47,9 @@ def apply_generic_arguments(callable: CallableType, types: List[Type], # Create a map from type variable id to target type. id_to_type = {} # type: Dict[TypeVarId, Type] for i, tv in enumerate(tvars): - if types[i]: - id_to_type[tv.id] = types[i] + typ = types[i] + if typ: + id_to_type[tv.id] = typ # Apply arguments to argument types. arg_types = [expand_type(at, id_to_type) for at in callable.arg_types] diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 8cef0e37e130..f32d4a0cb852 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -1,7 +1,7 @@ """Expression type checker. This file is conceptually part of TypeChecker.""" from collections import OrderedDict -from typing import cast, Dict, Set, List, Tuple, Callable, Union, Optional, Iterable +from typing import cast, Dict, Set, List, Tuple, Callable, Union, Optional, Iterable, Sequence, Any from mypy.errors import report_internal_error from mypy.typeanal import has_any_from_unimported_type, check_for_explicit_any, set_any_tvars @@ -281,12 +281,13 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type: def check_typeddict_call(self, callee: TypedDictType, arg_kinds: List[int], - arg_names: List[str], + arg_names: Sequence[Optional[str]], args: List[Expression], context: Context) -> Type: if len(args) >= 1 and all([ak == ARG_NAMED for ak in arg_kinds]): # ex: Point(x=42, y=1337) - item_names = arg_names + assert all(arg_name is not None for arg_name in arg_names) + item_names = cast(List[str], arg_names) item_args = args return self.check_typeddict_call_with_kwargs( callee, OrderedDict(zip(item_names, item_args)), context) @@ -487,7 +488,7 @@ def check_call_expr_with_callee_type(self, def check_call(self, callee: Type, args: List[Expression], arg_kinds: List[int], context: Context, - arg_names: Optional[List[str]] = None, + arg_names: Optional[Sequence[Optional[str]]] = None, callable_node: Optional[Expression] = None, arg_messages: Optional[MessageBuilder] = None, callable_name: Optional[str] = None, @@ -675,8 +676,7 @@ def infer_arg_types_in_context(self, callee: Optional[CallableType], if callee: fixed = min(fixed, callee.max_fixed_args()) - arg_type = None # type: Type - ctx = None # type: Type + ctx = None # type: Optional[Type] for i, arg in enumerate(args): if i < fixed: if callee and i < len(callee.arg_types): @@ -703,7 +703,8 @@ def infer_arg_types_in_context2( Returns the inferred types of *actual arguments*. """ - res = [None] * len(args) # type: List[Type] + dummy = None # type: Any + res = [dummy] * len(args) # type: List[Type] for i, actuals in enumerate(formal_to_actual): for ai in actuals: @@ -750,7 +751,7 @@ def infer_function_type_arguments_using_context( ret_type = NoneTyp() args = infer_type_arguments(callable.type_var_ids(), ret_type, erased_ctx) # Only substitute non-Uninhabited and non-erased types. - new_args = [] # type: List[Type] + new_args = [] # type: List[Optional[Type]] for arg in args: if isinstance(arg, UninhabitedType) or has_erased_component(arg): new_args.append(None) @@ -793,7 +794,7 @@ def infer_function_type_arguments(self, callee_type: CallableType, inferred_args = infer_function_type_arguments( callee_type, pass1_args, arg_kinds, formal_to_actual, - strict=self.chk.in_checked_function()) # type: List[Type] + strict=self.chk.in_checked_function()) if 2 in arg_pass_nums: # Second pass of type inference. @@ -810,9 +811,10 @@ def infer_function_type_arguments(self, callee_type: CallableType, # if they shuffle type variables around, as we assume that there is a 1-1 # correspondence with dict type variables. This is a marginal issue and # a little tricky to fix so it's left unfixed for now. - if isinstance(inferred_args[0], (NoneTyp, UninhabitedType)): + first_arg = inferred_args[0] + if isinstance(first_arg, (NoneTyp, UninhabitedType)): inferred_args[0] = self.named_type('builtins.str') - elif not is_subtype(self.named_type('builtins.str'), inferred_args[0]): + elif not first_arg or not is_subtype(self.named_type('builtins.str'), first_arg): self.msg.fail(messages.KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE, context) else: @@ -827,8 +829,8 @@ def infer_function_type_arguments_pass2( args: List[Expression], arg_kinds: List[int], formal_to_actual: List[List[int]], - inferred_args: List[Type], - context: Context) -> Tuple[CallableType, List[Type]]: + old_inferred_args: Sequence[Optional[Type]], + context: Context) -> Tuple[CallableType, List[Optional[Type]]]: """Perform second pass of generic function type argument inference. The second pass is needed for arguments with types such as Callable[[T], S], @@ -843,6 +845,7 @@ def infer_function_type_arguments_pass2( # None or erased types in inferred types mean that there was not enough # information to infer the argument. Replace them with None values so # that they are not applied yet below. + inferred_args = list(old_inferred_args) for i, arg in enumerate(inferred_args): if isinstance(arg, (NoneTyp, UninhabitedType)) or has_erased_component(arg): inferred_args[i] = None @@ -875,7 +878,7 @@ def get_arg_infer_passes(self, arg_types: List[Type], return res def apply_inferred_arguments(self, callee_type: CallableType, - inferred_args: List[Type], + inferred_args: Sequence[Optional[Type]], context: Context) -> CallableType: """Apply inferred values of type arguments to a generic function. @@ -896,9 +899,10 @@ def apply_inferred_arguments(self, callee_type: CallableType, return self.apply_generic_arguments(callee_type, inferred_args, context) def check_argument_count(self, callee: CallableType, actual_types: List[Type], - actual_kinds: List[int], actual_names: List[str], + actual_kinds: List[int], + actual_names: Optional[Sequence[Optional[str]]], formal_to_actual: List[List[int]], - context: Context, + context: Optional[Context], messages: Optional[MessageBuilder]) -> bool: """Check that there is a value for all required arguments to a function. @@ -925,11 +929,16 @@ def check_argument_count(self, callee: CallableType, actual_types: List[Type], ok = False if kind != nodes.ARG_NAMED: if messages: + assert context, "Internal error: messages given without context" messages.too_many_arguments(callee, context) else: if messages: + assert context, "Internal error: messages given without context" + assert actual_names, "Internal error: named kinds without names given" + act_name = actual_names[i] + assert act_name is not None messages.unexpected_keyword_argument( - callee, actual_names[i], context) + callee, act_name, context) is_unexpected_arg_error = True elif kind == nodes.ARG_STAR and ( nodes.ARG_STAR not in formal_kinds): @@ -938,6 +947,7 @@ def check_argument_count(self, callee: CallableType, actual_types: List[Type], if all_actuals.count(i) < len(actual_type.items): # Too many tuple items as some did not match. if messages: + assert context, "Internal error: messages given without context" messages.too_many_arguments(callee, context) ok = False # *args can be applied even if the function takes a fixed @@ -948,13 +958,17 @@ def check_argument_count(self, callee: CallableType, actual_types: List[Type], not is_unexpected_arg_error): # No actual for a mandatory positional formal. if messages: + assert context, "Internal error: messages given without context" messages.too_few_arguments(callee, context, actual_names) ok = False elif kind == nodes.ARG_NAMED and (not formal_to_actual[i] and not is_unexpected_arg_error): # No actual for a mandatory named formal if messages: - messages.missing_named_argument(callee, context, callee.arg_names[i]) + argname = callee.arg_names[i] + assert argname is not None + assert context, "Internal error: messages given without context" + messages.missing_named_argument(callee, context, argname) ok = False elif kind in [nodes.ARG_POS, nodes.ARG_OPT, nodes.ARG_NAMED, nodes.ARG_NAMED_OPT] and is_duplicate_mapping( @@ -962,12 +976,14 @@ def check_argument_count(self, callee: CallableType, actual_types: List[Type], if (self.chk.in_checked_function() or isinstance(actual_types[formal_to_actual[i][0]], TupleType)): if messages: + assert context, "Internal error: messages given without context" messages.duplicate_argument_value(callee, i, context) ok = False elif (kind in (nodes.ARG_NAMED, nodes.ARG_NAMED_OPT) and formal_to_actual[i] and actual_kinds[formal_to_actual[i][0]] not in [nodes.ARG_NAMED, nodes.ARG_STAR2]): # Positional argument when expecting a keyword argument. if messages: + assert context, "Internal error: messages given without context" messages.too_many_positional_arguments(callee, context) ok = False return ok @@ -1057,7 +1073,7 @@ def check_arg(self, caller_type: Type, original_caller_type: Type, self.msg.note_call(original_caller_type, call, context) def overload_call_target(self, arg_types: List[Type], arg_kinds: List[int], - arg_names: List[str], + arg_names: Optional[Sequence[Optional[str]]], overload: Overloaded, context: Context, messages: Optional[MessageBuilder] = None) -> Type: """Infer the correct overload item to call with given argument types. @@ -1120,7 +1136,8 @@ def overload_call_target(self, arg_types: List[Type], arg_kinds: List[int], return match[0] def erased_signature_similarity(self, arg_types: List[Type], arg_kinds: List[int], - arg_names: List[str], callee: CallableType, + arg_names: Optional[Sequence[Optional[str]]], + callee: CallableType, context: Context) -> int: """Determine whether arguments could match the signature at runtime. @@ -1160,7 +1177,7 @@ def check_arg(caller_type: Type, original_caller_type: Type, caller_kind: int, return similarity def match_signature_types(self, arg_types: List[Type], arg_kinds: List[int], - arg_names: List[str], callee: CallableType, + arg_names: Optional[Sequence[Optional[str]]], callee: CallableType, context: Context) -> bool: """Determine whether arguments types match the signature. @@ -1186,7 +1203,7 @@ def check_arg(caller_type: Type, original_caller_type: Type, caller_kind: int, context=context, check_arg=check_arg) return ok - def apply_generic_arguments(self, callable: CallableType, types: List[Type], + def apply_generic_arguments(self, callable: CallableType, types: Sequence[Optional[Type]], context: Context) -> CallableType: """Simple wrapper around mypy.applytype.apply_generic_arguments.""" return applytype.apply_generic_arguments(callable, types, self.msg, context) @@ -1245,7 +1262,6 @@ def analyze_descriptor_access(self, instance_type: Type, descriptor_type: Type, bound_method = bind_self(function, descriptor_type) typ = map_instance_to_supertype(descriptor_type, dunder_get.info) dunder_get_type = expand_type_by_instance(bound_method, typ) - owner_type = None # type: Type if isinstance(instance_type, FunctionLike) and instance_type.is_type_obj(): owner_type = instance_type.items()[0].ret_type @@ -1351,13 +1367,13 @@ def visit_comparison_expr(self, e: ComparisonExpr) -> Type: Comparison expressions are type checked consecutive-pair-wise That is, 'a < b > c == d' is check as 'a < b and b > c and c == d' """ - result = None # type: mypy.types.Type + result = None # type: Optional[mypy.types.Type] # Check each consecutive operand pair and their operator for left, right, operator in zip(e.operands, e.operands[1:], e.operators): left_type = self.accept(left) - method_type = None # type: mypy.types.Type + method_type = None # type: Optional[mypy.types.Type] if operator == 'in' or operator == 'not in': right_type = self.accept(right) # TODO only evaluate if needed @@ -1407,6 +1423,7 @@ def visit_comparison_expr(self, e: ComparisonExpr) -> Type: else: result = join.join_types(result, sub_result) + assert result is not None return result def get_operator_method(self, op: str) -> str: @@ -1679,9 +1696,9 @@ def visit_index_expr_helper(self, e: IndexExpr) -> Type: return result def visit_tuple_slice_helper(self, left_type: TupleType, slic: SliceExpr) -> Type: - begin = None # type: int - end = None # type: int - stride = None # type:int + begin = None # type: Optional[int] + end = None # type: Optional[int] + stride = None # type: Optional[int] if slic.begin_index: begin = self._get_value(slic.begin_index) @@ -1698,6 +1715,7 @@ def visit_tuple_slice_helper(self, left_type: TupleType, slic: SliceExpr) -> Typ if stride is None: return self.nonliteral_tuple_index_helper(left_type, slic) + assert begin and stride and end return left_type.slice(begin, stride, end) def nonliteral_tuple_index_helper(self, left_type: TupleType, index: Expression) -> Type: @@ -1872,7 +1890,7 @@ def visit_tuple_expr(self, e: TupleExpr) -> Type: if isinstance(type_context, TupleType): type_context_items = type_context.items - elif is_named_instance(type_context, 'builtins.tuple'): + elif type_context and is_named_instance(type_context, 'builtins.tuple'): assert isinstance(type_context, Instance) if type_context.args: type_context_items = [type_context.args[0]] * len(e.items) @@ -1887,7 +1905,6 @@ def visit_tuple_expr(self, e: TupleExpr) -> Type: j = 0 # Index into type_context_items; irrelevant if type_context_items is none for i in range(len(e.items)): item = e.items[i] - tt = None # type: Type if isinstance(item, StarExpr): # Special handling for star expressions. # TODO: If there's a context, and item.expr is a @@ -1977,9 +1994,10 @@ def visit_dict_expr(self, e: DictExpr) -> Type: else: method = self.analyze_external_member_access('update', rv, arg) self.check_call(method, [arg], [nodes.ARG_POS], arg) + assert rv is not None return rv - def find_typeddict_context(self, context: Type) -> Optional[TypedDictType]: + def find_typeddict_context(self, context: Optional[Type]) -> Optional[TypedDictType]: if isinstance(context, TypedDictType): return context elif isinstance(context, UnionType): @@ -2148,7 +2166,9 @@ def analyze_super(self, e: SuperExpr, is_lvalue: bool) -> Type: if self.chk.scope.active_class() is not None: self.chk.fail('super() outside of a method is not supported', e) return AnyType(TypeOfAny.from_error) - args = self.chk.scope.top_function().arguments + method = self.chk.scope.top_function() + assert method is not None + args = method.arguments # super() in a function with empty args is an error; we # need something in declared_self. if not args: @@ -2157,6 +2177,7 @@ def analyze_super(self, e: SuperExpr, is_lvalue: bool) -> Type: 'enclosing function', e) return AnyType(TypeOfAny.from_error) declared_self = args[0].variable.type + assert declared_self is not None, "Internal error: type of self is None" return analyze_member_access(name=e.name, typ=fill_typevars(e.info), node=e, is_lvalue=False, is_super=True, is_operator=False, builtin_type=self.named_type, @@ -2457,12 +2478,11 @@ def visit_yield_from_expr(self, e: YieldFromExpr, allow_none_return: bool = Fals # the context should be Generator[X, Y, T], where T is the # context of the 'yield from' itself (but it isn't known). subexpr_type = self.accept(e.expr) - iter_type = None # type: Type # Check that the expr is an instance of Iterable and get the type of the iterator produced # by __iter__. if isinstance(subexpr_type, AnyType): - iter_type = AnyType(TypeOfAny.from_another_any, source_any=subexpr_type) + iter_type = AnyType(TypeOfAny.from_another_any, source_any=subexpr_type) # type: Type elif self.chk.type_is_iterable(subexpr_type): if is_async_def(subexpr_type) and not has_coroutine_decorator(return_type): self.chk.msg.yield_from_invalid_operand_type(subexpr_type, e) @@ -2609,7 +2629,7 @@ def is_async_def(t: Type) -> bool: def map_actuals_to_formals(caller_kinds: List[int], - caller_names: List[Optional[str]], + caller_names: Optional[Sequence[Optional[str]]], callee_kinds: List[int], callee_names: List[Optional[str]], caller_arg_type: Callable[[int], @@ -2659,6 +2679,7 @@ def map_actuals_to_formals(caller_kinds: List[int], break j += 1 elif kind in (nodes.ARG_NAMED, nodes.ARG_NAMED_OPT): + assert caller_names is not None, "Internal error: named kinds without names given" name = caller_names[i] if name in callee_names: map[callee_names.index(name)].append(i) @@ -2719,7 +2740,7 @@ def visit_type_var(self, t: TypeVarType) -> bool: return True -def has_erased_component(t: Type) -> bool: +def has_erased_component(t: Optional[Type]) -> bool: return t is not None and t.accept(HasErasedComponentsQuery()) @@ -2832,7 +2853,7 @@ def overload_arg_similarity(actual: Type, formal: Type) -> int: def any_arg_causes_overload_ambiguity(items: List[CallableType], arg_types: List[Type], arg_kinds: List[int], - arg_names: List[Optional[str]]) -> bool: + arg_names: Optional[Sequence[Optional[str]]]) -> bool: """May an Any actual argument cause ambiguous result type on call to overloaded function? Note that this sometimes returns True even if there is no ambiguity, since a correct diff --git a/mypy/constraints.py b/mypy/constraints.py index 7180dd00f25f..4e7c2ecba269 100644 --- a/mypy/constraints.py +++ b/mypy/constraints.py @@ -1,6 +1,6 @@ """Type inference constraints.""" -from typing import Iterable, List, Optional +from typing import Iterable, List, Optional, Sequence from mypy import experiments from mypy.types import ( @@ -42,7 +42,7 @@ def __repr__(self) -> str: def infer_constraints_for_callable( - callee: CallableType, arg_types: List[Optional[Type]], arg_kinds: List[int], + callee: CallableType, arg_types: Sequence[Optional[Type]], arg_kinds: List[int], formal_to_actual: List[List[int]]) -> List[Constraint]: """Infer type variable constraints for a callable and actual arguments. diff --git a/mypy/fastparse.py b/mypy/fastparse.py index d9119c39b361..cb1eeba02c20 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -885,7 +885,8 @@ def visit_JoinedStr(self, n: ast3.JoinedStr) -> Expression: join_method.set_line(empty_string) result_expression = CallExpr(join_method, [strs_to_join], - [ARG_POS]) + [ARG_POS], + [None]) return result_expression # FormattedValue(expr value) @@ -902,7 +903,8 @@ def visit_FormattedValue(self, n: ast3.FormattedValue) -> Expression: format_method.set_line(format_string) result_expression = CallExpr(format_method, [exp], - [ARG_POS]) + [ARG_POS], + [None]) return result_expression # Bytes(bytes s) diff --git a/mypy/infer.py b/mypy/infer.py index 6820a2c05eb4..b7d0dca8b9b4 100644 --- a/mypy/infer.py +++ b/mypy/infer.py @@ -1,6 +1,6 @@ """Utilities for type argument inference.""" -from typing import List, Optional +from typing import List, Optional, Sequence from mypy.constraints import infer_constraints, infer_constraints_for_callable from mypy.types import Type, TypeVarId, CallableType @@ -9,7 +9,7 @@ def infer_function_type_arguments(callee_type: CallableType, - arg_types: List[Optional[Type]], + arg_types: Sequence[Optional[Type]], arg_kinds: List[int], formal_to_actual: List[List[int]], strict: bool = True) -> List[Optional[Type]]: diff --git a/mypy/messages.py b/mypy/messages.py index 51fa0c7d9955..2f3473b3e59d 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -165,7 +165,7 @@ def enable_errors(self) -> None: def is_errors(self) -> bool: return self.errors.is_errors() - def report(self, msg: str, context: Context, severity: str, + def report(self, msg: str, context: Optional[Context], severity: str, file: Optional[str] = None, origin: Optional[Context] = None, offset: int = 0) -> None: """Report an error or note (unless disabled).""" @@ -175,7 +175,7 @@ def report(self, msg: str, context: Context, severity: str, msg.strip(), severity=severity, file=file, offset=offset, origin_line=origin.get_line() if origin else None) - def fail(self, msg: str, context: Context, file: Optional[str] = None, + def fail(self, msg: str, context: Optional[Context], file: Optional[str] = None, origin: Optional[Context] = None) -> None: """Report an error message (unless disabled).""" self.report(msg, context, 'error', file=file, origin=origin) @@ -641,7 +641,7 @@ def invalid_index_type(self, index_type: Type, expected_type: Type, base_str: st self.format(index_type), base_str, self.format(expected_type)), context) def too_few_arguments(self, callee: CallableType, context: Context, - argument_names: List[str]) -> None: + argument_names: Optional[Sequence[Optional[str]]]) -> None: if (argument_names is not None and not all(k is None for k in argument_names) and len(argument_names) >= 1): diff = [k for k in callee.arg_names if k not in argument_names] @@ -695,7 +695,7 @@ def duplicate_argument_value(self, callee: CallableType, index: int, format(capitalize(callable_name(callee)), callee.arg_names[index]), context) - def does_not_return_value(self, callee_type: Type, context: Context) -> None: + def does_not_return_value(self, callee_type: Optional[Type], context: Context) -> None: """Report an error about use of an unusable type.""" name = None # type: Optional[str] if isinstance(callee_type, FunctionLike): diff --git a/mypy/nodes.py b/mypy/nodes.py index 330a03676889..7f7ceb5fb8fe 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -1241,7 +1241,7 @@ def __init__(self, callee: Expression, args: List[Expression], arg_kinds: List[int], - arg_names: Optional[List[Optional[str]]] = None, + arg_names: List[Optional[str]], analyzed: Optional[Expression] = None) -> None: if not arg_names: arg_names = [None] * len(args) @@ -1731,13 +1731,13 @@ class TypeAliasExpr(Expression): type = None # type: mypy.types.Type # Simple fallback type for aliases that are invalid in runtime expressions # (for example Union, Tuple, Callable). - fallback = None # type: Optional[mypy.types.Type] + fallback = None # type: mypy.types.Type # This type alias is subscripted in a runtime expression like Alias[int](42) # (not in a type context like type annotation or base class). in_runtime = False # type: bool def __init__(self, type: 'mypy.types.Type', tvars: List[str], - fallback: 'Optional[mypy.types.Type]' = None, in_runtime: bool = False) -> None: + fallback: 'mypy.types.Type', in_runtime: bool = False) -> None: self.type = type self.fallback = fallback self.in_runtime = in_runtime From 1f7310606644b137ae574157bb98b989b8d055e0 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Thu, 14 Sep 2017 19:44:32 +0200 Subject: [PATCH 3/5] Finish clean-up of checker, checkexpr and myunit --- mypy/binder.py | 2 +- mypy/checker.py | 10 ++++++---- mypy/checkexpr.py | 14 +++++++------- mypy/checkmember.py | 2 +- mypy/myunit/__init__.py | 2 +- mypy/types.py | 3 ++- mypy_self_check.ini | 11 +---------- 7 files changed, 19 insertions(+), 25 deletions(-) diff --git a/mypy/binder.py b/mypy/binder.py index 094d51b912ea..956c950c5394 100644 --- a/mypy/binder.py +++ b/mypy/binder.py @@ -212,7 +212,7 @@ def pop_frame(self, can_skip: bool, fall_through: int) -> Frame: def assign_type(self, expr: Expression, type: Type, - declared_type: Type, + declared_type: Optional[Type], restrict_any: bool = False) -> None: if not isinstance(expr, BindableTypes): return None diff --git a/mypy/checker.py b/mypy/checker.py index 383e76c4c71e..e53964e6345b 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1433,6 +1433,7 @@ def check_compatibility_all_supers(self, lvalue: NameExpr, lvalue_type: Optional base_type, base_node = self.lvalue_type_from_base(lvalue_node, base) if base_type: + assert base_node is not None if not self.check_compatibility_super(lvalue, lvalue_type, rvalue, @@ -1516,6 +1517,7 @@ def lvalue_type_from_base(self, expr_node: Var, if base_type: if not has_no_typevars(base_type): self_type = self.scope.active_self_type() + assert self_type is not None, "Internal error: base lookup outside class" if isinstance(self_type, TupleType): instance = self_type.fallback else: @@ -1864,7 +1866,7 @@ def set_inference_error_fallback_type(self, var: Var, lvalue: Lvalue, type: Type if context.get_line() in self.errors.ignored_lines[self.errors.file]: self.set_inferred_type(var, lvalue, AnyType(TypeOfAny.from_error)) - def check_simple_assignment(self, lvalue_type: Type, rvalue: Expression, + def check_simple_assignment(self, lvalue_type: Optional[Type], rvalue: Expression, context: Context, msg: str = messages.INCOMPATIBLE_TYPES_IN_ASSIGNMENT, lvalue_name: str = 'variable', @@ -1880,7 +1882,7 @@ def check_simple_assignment(self, lvalue_type: Type, rvalue: Expression, self.msg.deleted_as_rvalue(rvalue_type, context) if isinstance(lvalue_type, DeletedType): self.msg.deleted_as_lvalue(lvalue_type, context) - else: + elif lvalue_type: self.check_subtype(rvalue_type, lvalue_type, context, msg, '{} has type'.format(rvalue_name), '{} has type'.format(lvalue_name)) @@ -2770,7 +2772,7 @@ def conditional_type_map(expr: Expression, return {}, {} -def partition_by_callable(type: Optional[Type]) -> Tuple[List[Type], List[Type]]: +def partition_by_callable(type: Type) -> Tuple[List[Type], List[Type]]: """Takes in a type and partitions that type into callable subtypes and uncallable subtypes. @@ -2801,7 +2803,7 @@ def partition_by_callable(type: Optional[Type]) -> Tuple[List[Type], List[Type]] if isinstance(type, Instance): method = type.type.get_method('__call__') - if method: + if method and method.type: callables, uncallables = partition_by_callable(method.type) if len(callables) and not len(uncallables): # Only consider the type callable if its __call__ method is diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index f32d4a0cb852..6849420fd159 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -236,7 +236,7 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type: isinstance(callee_type, CallableType) and callee_type.implicit): return self.msg.untyped_function_call(callee_type, e) - # Figure out the full name of the callee for plugin loopup. + # Figure out the full name of the callee for plugin lookup. object_type = None if not isinstance(e.callee, RefExpr): fullname = None @@ -260,6 +260,7 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type: # Apply plugin signature hook that may generate a better signature. signature_hook = self.plugin.get_method_signature_hook(fullname) if signature_hook: + assert object_type is not None callee_type = self.apply_method_signature_hook( e, callee_type, object_type, signature_hook) ret_type = self.check_call_expr_with_callee_type(callee_type, e, fullname, object_type) @@ -1715,7 +1716,6 @@ def visit_tuple_slice_helper(self, left_type: TupleType, slic: SliceExpr) -> Typ if stride is None: return self.nonliteral_tuple_index_helper(left_type, slic) - assert begin and stride and end return left_type.slice(begin, stride, end) def nonliteral_tuple_index_helper(self, left_type: TupleType, index: Expression) -> Type: @@ -1960,6 +1960,7 @@ def visit_dict_expr(self, e: DictExpr) -> Type: vtdef = TypeVarDef('VT', -2, [], self.object_type()) kt = TypeVarType(ktdef) vt = TypeVarType(vtdef) + rv = None # type: Optional[Type] # Call dict(*args), unless it's empty and stargs is not. if args or not stargs: # The callable type represents a function like this: @@ -1976,7 +1977,7 @@ def visit_dict_expr(self, e: DictExpr) -> Type: rv = self.check_call(constructor, args, [nodes.ARG_POS] * len(args), e)[0] else: # dict(...) will be called below. - rv = None + pass # Call rv.update(arg) for each arg in **stargs, # except if rv isn't set yet, then set rv = dict(arg). if stargs: @@ -2176,8 +2177,7 @@ def analyze_super(self, e: SuperExpr, is_lvalue: bool) -> Type: 'super() requires one or more positional arguments in ' 'enclosing function', e) return AnyType(TypeOfAny.from_error) - declared_self = args[0].variable.type - assert declared_self is not None, "Internal error: type of self is None" + declared_self = args[0].variable.type or fill_typevars(e.info) return analyze_member_access(name=e.name, typ=fill_typevars(e.info), node=e, is_lvalue=False, is_super=True, is_operator=False, builtin_type=self.named_type, @@ -2836,7 +2836,7 @@ def overload_arg_similarity(actual: Type, formal: Type) -> int: item = actual.item if formal.type.fullname() in {"builtins.object", "builtins.type"}: return 2 - elif isinstance(item, Instance): + elif isinstance(item, Instance) and item.type.metaclass_type: # FIX: this does not handle e.g. Union of instances return overload_arg_similarity(item.type.metaclass_type, formal) else: @@ -2900,7 +2900,7 @@ def all_same_types(types: Iterable[Type]) -> bool: def map_formals_to_actuals(caller_kinds: List[int], - caller_names: List[Optional[str]], + caller_names: Optional[Sequence[Optional[str]]], callee_kinds: List[int], callee_names: List[Optional[str]], caller_arg_type: Callable[[int], diff --git a/mypy/checkmember.py b/mypy/checkmember.py index ceb9a4ff00ce..ea8aff82d209 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -630,7 +630,7 @@ class B(A): pass """ if isinstance(method, Overloaded): - return cast(F, Overloaded([bind_self(c, method) for c in method.items()])) + return cast(F, Overloaded([bind_self(c, original_type) for c in method.items()])) assert isinstance(method, CallableType) func = method if not func.arg_types: diff --git a/mypy/myunit/__init__.py b/mypy/myunit/__init__.py index 013353daed2c..92ba802530eb 100644 --- a/mypy/myunit/__init__.py +++ b/mypy/myunit/__init__.py @@ -112,7 +112,7 @@ def __init__(self, name: str, suite: 'Optional[Suite]' = None, self.name = name self.suite = suite self.old_cwd = None # type: Optional[str] - self.tmpdir = None # type: Optional[tempfile.TemporaryDirectory] + self.tmpdir = None # type: Optional[tempfile.TemporaryDirectory[str]] def run(self) -> None: if self.func: diff --git a/mypy/types.py b/mypy/types.py index 904694c81558..a53085a66a36 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -1011,7 +1011,8 @@ def copy_modified(self, *, fallback: Optional[Instance] = None, items = self.items return TupleType(items, fallback, self.line, self.column) - def slice(self, begin: int, stride: int, end: int) -> 'TupleType': + def slice(self, begin: Optional[int], stride: Optional[int], + end: Optional[int]) -> 'TupleType': return TupleType(self.items[begin:end:stride], self.fallback, self.line, self.column, self.implicit) diff --git a/mypy_self_check.ini b/mypy_self_check.ini index aa4683befee4..e97c379d677a 100644 --- a/mypy_self_check.ini +++ b/mypy_self_check.ini @@ -8,15 +8,6 @@ disallow_any = generics, unimported warn_redundant_casts = True warn_unused_ignores = True -; historical exceptions -[mypy-mypy.binder] -disallow_any = unimported - +; historical exception [mypy-mypy.semanal] strict_optional = False - -[mypy-mypy.myunit] -disallow_any = unimported - -[mypy-mypy.nodes] -disallow_any = unimported From 218253a9c8cd8f44df0af0957a3d46aa5f515a25 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Sun, 17 Sep 2017 17:22:29 +0200 Subject: [PATCH 4/5] Address CR --- mypy/checker.py | 10 ++++------ mypy/checkexpr.py | 20 ++++++++++---------- mypy_self_check.ini | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index e53964e6345b..3fcc3c665e12 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -610,11 +610,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str]) # function. In the first case, set up another reference with the # precise type. if isinstance(item, FuncDef): - fdef = item # type: Optional[FuncDef] - else: - fdef = None - - if fdef: + fdef = item # Check if __init__ has an invalid, non-None return type. if (fdef.info and fdef.name() in ('__init__', '__init_subclass__') and not isinstance(typ.ret_type, NoneTyp) and @@ -634,6 +630,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str]) self.msg.unimported_type_becomes_any(prefix, arg_type, fdef) check_for_explicit_any(fdef.type, self.options, self.is_typeshed_stub, self.msg, context=fdef) + if name: # Special method names if name in nodes.reverse_op_method_set: self.check_reverse_op_method(item, typ, name) @@ -641,6 +638,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: Optional[str]) self.check_getattr_method(typ, defn, name) elif name == '__setattr__': self.check_setattr_method(typ, defn) + # Refuse contravariant return type variable if isinstance(typ.ret_type, TypeVarType): if typ.ret_type.variance == CONTRAVARIANT: @@ -1456,7 +1454,7 @@ def check_compatibility_super(self, lvalue: NameExpr, lvalue_type: Optional[Type # lvalue had a type defined; this is handled by other # parts, and all we have to worry about in that case is # that lvalue is compatible with the base class. - compare_node = None # type: Optional[Node] + compare_node = None if lvalue_type: compare_type = lvalue_type compare_node = lvalue.node diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 6849420fd159..36c89b3ceda4 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -21,7 +21,7 @@ ConditionalExpr, ComparisonExpr, TempNode, SetComprehension, DictionaryComprehension, ComplexExpr, EllipsisExpr, StarExpr, AwaitExpr, YieldExpr, YieldFromExpr, TypedDictExpr, PromoteExpr, NewTypeExpr, NamedTupleExpr, TypeVarExpr, - TypeAliasExpr, BackquoteExpr, EnumCallExpr, SymbolTableNode, + TypeAliasExpr, BackquoteExpr, EnumCallExpr, ARG_POS, ARG_NAMED, ARG_STAR, ARG_STAR2, MODULE_REF, TVAR, LITERAL_TYPE, ) from mypy.literals import literal @@ -201,7 +201,7 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type: and len(e.args) == 2): for typ in mypy.checker.flatten(e.args[1]): if isinstance(typ, NameExpr): - node = None # type: Optional[SymbolTableNode] + node = None try: node = self.chk.lookup_qualified(typ.name) except KeyError: @@ -218,7 +218,7 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type: elif typ.node.is_newtype: self.msg.fail(messages.CANNOT_ISINSTANCE_NEWTYPE, e) self.try_infer_partial_type(e) - type_context = None # type: Optional[CallableType] + type_context = None if isinstance(e.callee, LambdaExpr): formal_to_actual = map_actuals_to_formals( e.arg_kinds, e.arg_names, @@ -677,7 +677,7 @@ def infer_arg_types_in_context(self, callee: Optional[CallableType], if callee: fixed = min(fixed, callee.max_fixed_args()) - ctx = None # type: Optional[Type] + ctx = None for i, arg in enumerate(args): if i < fixed: if callee and i < len(callee.arg_types): @@ -908,7 +908,7 @@ def check_argument_count(self, callee: CallableType, actual_types: List[Type], """Check that there is a value for all required arguments to a function. Also check that there are no duplicate values for arguments. Report found errors - using 'messages' if it's not None. + using 'messages' if it's not None. If 'messages' is given, 'context' must also be given. Return False if there were any errors. Otherwise return True """ @@ -1368,7 +1368,7 @@ def visit_comparison_expr(self, e: ComparisonExpr) -> Type: Comparison expressions are type checked consecutive-pair-wise That is, 'a < b > c == d' is check as 'a < b and b > c and c == d' """ - result = None # type: Optional[mypy.types.Type] + result = None # Check each consecutive operand pair and their operator for left, right, operator in zip(e.operands, e.operands[1:], e.operators): @@ -1697,9 +1697,9 @@ def visit_index_expr_helper(self, e: IndexExpr) -> Type: return result def visit_tuple_slice_helper(self, left_type: TupleType, slic: SliceExpr) -> Type: - begin = None # type: Optional[int] - end = None # type: Optional[int] - stride = None # type: Optional[int] + begin = None + end = None + stride = None if slic.begin_index: begin = self._get_value(slic.begin_index) @@ -1960,7 +1960,7 @@ def visit_dict_expr(self, e: DictExpr) -> Type: vtdef = TypeVarDef('VT', -2, [], self.object_type()) kt = TypeVarType(ktdef) vt = TypeVarType(vtdef) - rv = None # type: Optional[Type] + rv = None # Call dict(*args), unless it's empty and stargs is not. if args or not stargs: # The callable type represents a function like this: diff --git a/mypy_self_check.ini b/mypy_self_check.ini index e97c379d677a..6b97ed660d9b 100644 --- a/mypy_self_check.ini +++ b/mypy_self_check.ini @@ -8,6 +8,6 @@ disallow_any = generics, unimported warn_redundant_casts = True warn_unused_ignores = True -; historical exception +# historical exception [mypy-mypy.semanal] strict_optional = False From d461fc12b55c90ab6503a3c4a28aea661b612183 Mon Sep 17 00:00:00 2001 From: Ivan Levkivskyi Date: Mon, 18 Sep 2017 00:22:13 +0200 Subject: [PATCH 5/5] Restart CI builds