From c53a1c461484fa8bb451a468bbe5c30090e10674 Mon Sep 17 00:00:00 2001 From: Elazar Gershuni Date: Sat, 3 Sep 2016 20:51:27 +0300 Subject: [PATCH 1/3] NewType+namedtuple: common method for typeinfo --- mypy/nodes.py | 10 ---------- mypy/semanal.py | 35 +++++++++++++++++------------------ 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/mypy/nodes.py b/mypy/nodes.py index 764d94771416..dec269bf0489 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -2037,16 +2037,6 @@ def deserialize(cls, data: JsonDict) -> 'TypeInfo': return ti -def namedtuple_type_info(tup: 'mypy.types.TupleType', names: 'SymbolTable', - defn: ClassDef, module_name: str) -> TypeInfo: - info = TypeInfo(names, defn, module_name) - info.tuple_type = tup - info.bases = [tup.fallback] - info.is_named_tuple = True - info.mro = [info] + tup.fallback.type.mro - return info - - class SymbolTableNode: # Kind of node. Possible values: # - LDEF: local definition (of any kind) diff --git a/mypy/semanal.py b/mypy/semanal.py index c2ae263d1684..2237f497ba1c 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -63,8 +63,7 @@ YieldFromExpr, NamedTupleExpr, NonlocalDecl, SetComprehension, DictionaryComprehension, TYPE_ALIAS, TypeAliasExpr, YieldExpr, ExecStmt, Argument, BackquoteExpr, ImportBase, AwaitExpr, - IntExpr, FloatExpr, UnicodeExpr, - Expression, EllipsisExpr, namedtuple_type_info, + IntExpr, FloatExpr, UnicodeExpr, EllipsisExpr, COVARIANT, CONTRAVARIANT, INVARIANT, UNBOUND_IMPORTED, LITERAL_YES, ) from mypy.visitor import NodeVisitor @@ -1413,13 +1412,7 @@ def check_newtype_args(self, name: str, call: CallExpr, context: Context) -> Opt return None if has_failed else old_type def build_newtype_typeinfo(self, name: str, old_type: Type, base_type: Instance) -> TypeInfo: - class_def = ClassDef(name, Block([])) - class_def.fullname = self.qualified_name(name) - - symbols = SymbolTable() - info = TypeInfo(symbols, class_def, self.cur_mod_id) - info.mro = [info] + base_type.type.mro - info.bases = [base_type] + info = self.basic_new_typeinfo(name, base_type) info.is_newtype = True # Add __init__ method @@ -1434,7 +1427,7 @@ def build_newtype_typeinfo(self, name: str, old_type: Type, base_type: Instance) name=name) init_func = FuncDef('__init__', args, Block([]), typ=signature) init_func.info = info - symbols['__init__'] = SymbolTableNode(MDEF, init_func) + info.names['__init__'] = SymbolTableNode(MDEF, init_func) return info @@ -1686,6 +1679,15 @@ def fail_namedtuple_arg(self, message: str, self.fail(message, context) return [], [], False + def basic_new_typeinfo(self, name: str, basetype_or_fallback: Instance) -> TypeInfo: + class_def = ClassDef(name, Block([])) + class_def.fullname = self.qualified_name(name) + + info = TypeInfo(SymbolTable(), class_def, self.cur_mod_id) + info.mro = [info] + basetype_or_fallback.type.mro + info.bases = [basetype_or_fallback] + return info + def build_namedtuple_typeinfo(self, name: str, items: List[str], types: List[Type]) -> TypeInfo: strtype = self.named_type('__builtins__.str') # type: Type @@ -1700,20 +1702,17 @@ def build_namedtuple_typeinfo(self, name: str, items: List[str], # but it can't be expressed. 'new' and 'len' should be callable types. iterable_type = self.named_type_or_none('typing.Iterable', [AnyType()]) function_type = self.named_type('__builtins__.function') - fullname = self.qualified_name(name) - symbols = SymbolTable() - class_def = ClassDef(name, Block([])) - class_def.fullname = fullname - info = namedtuple_type_info(TupleType(types, fallback), symbols, - class_def, self.cur_mod_id) + info = self.basic_new_typeinfo(name, fallback) + info.is_named_tuple = True + info.tuple_type = TupleType(types, fallback) def add_field(var: Var, is_initialized_in_class: bool = False, is_property: bool = False) -> None: var.info = info var.is_initialized_in_class = is_initialized_in_class var.is_property = is_property - symbols[var.name()] = SymbolTableNode(MDEF, var) + info.names[var.name()] = SymbolTableNode(MDEF, var) vars = [Var(item, typ) for item, typ in zip(items, types)] for var in vars: @@ -1740,7 +1739,7 @@ def add_method(funcname: str, ret: Type, args: List[Argument], name=None, func = FuncDef(funcname, args, Block([]), typ=signature) func.info = info func.is_class = is_classmethod - symbols[funcname] = SymbolTableNode(MDEF, func) + info.names[funcname] = SymbolTableNode(MDEF, func) add_method('_replace', ret=this_type, args=[Argument(var, var.type, EllipsisExpr(), ARG_NAMED) for var in vars]) From 6ad4d56122544f51add1c6a0ff228a33d98ae113 Mon Sep 17 00:00:00 2001 From: Elazar Gershuni Date: Sun, 2 Oct 2016 02:51:33 +0300 Subject: [PATCH 2/3] Tighten types for semanal --- mypy/nodes.py | 1 + mypy/semanal.py | 50 ++++++++++++++++++++++++------------------------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/mypy/nodes.py b/mypy/nodes.py index 8f931ba57a87..b8e27926a266 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -137,6 +137,7 @@ def accept(self, visitor: NodeVisitor[T]) -> T: # fields of Node subtypes are expected to contain. Statement = Node Expression = Node +Lvalue = Expression class SymbolNode(Node): diff --git a/mypy/semanal.py b/mypy/semanal.py index cac77af31634..c57188ce2157 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -49,7 +49,7 @@ from mypy.nodes import ( MypyFile, TypeInfo, Node, AssignmentStmt, FuncDef, OverloadedFuncDef, - ClassDef, Var, GDEF, MODULE_REF, FuncItem, Import, + ClassDef, Var, GDEF, MODULE_REF, FuncItem, Import, Expression, Lvalue, ImportFrom, ImportAll, Block, LDEF, NameExpr, MemberExpr, IndexExpr, TupleExpr, ListExpr, ExpressionStmt, ReturnStmt, RaiseStmt, AssertStmt, OperatorAssignmentStmt, WhileStmt, @@ -405,7 +405,7 @@ def find_type_variables_in_type( assert False, 'Unsupported type %s' % type return result - def is_defined_type_var(self, tvar: str, context: Node) -> bool: + def is_defined_type_var(self, tvar: str, context: Context) -> bool: return self.lookup_qualified(tvar, context).kind == BOUND_TVAR def visit_overloaded_func_def(self, defn: OverloadedFuncDef) -> None: @@ -606,7 +606,7 @@ def unbind_class_type_vars(self) -> None: if self.bound_tvars: enable_typevars(self.bound_tvars) - def analyze_class_decorator(self, defn: ClassDef, decorator: Node) -> None: + def analyze_class_decorator(self, defn: ClassDef, decorator: Expression) -> None: decorator.accept(self) def setup_is_builtinclass(self, defn: ClassDef) -> None: @@ -801,7 +801,7 @@ def analyze_base_classes(self, defn: ClassDef) -> None: if info.mro and info.mro[-1].fullname() != 'builtins.object': info.mro.append(self.object_type().type) - def expr_to_analyzed_type(self, expr: Node) -> Type: + def expr_to_analyzed_type(self, expr: Expression) -> Type: if isinstance(expr, CallExpr): expr.accept(self) info = self.check_namedtuple(expr) @@ -1135,7 +1135,7 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None: isinstance(s.rvalue, (ListExpr, TupleExpr))): self.add_exports(*s.rvalue.items) - def analyze_simple_literal_type(self, rvalue: Node) -> Optional[Type]: + def analyze_simple_literal_type(self, rvalue: Expression) -> Optional[Type]: """Return builtins.int if rvalue is an int literal, etc.""" if self.weak_opts or self.options.semantic_analysis_only or self.function_stack: # Skip this if any weak options are set. @@ -1177,7 +1177,7 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> None: # just an alias for the type. self.globals[lvalue.name].node = node - def analyze_lvalue(self, lval: Node, nested: bool = False, + def analyze_lvalue(self, lval: Lvalue, nested: bool = False, add_global: bool = False, explicit_type: bool = False) -> None: """Analyze an lvalue or assignment target. @@ -1300,11 +1300,11 @@ def is_self_member_ref(self, memberexpr: MemberExpr) -> bool: node = memberexpr.expr.node return isinstance(node, Var) and node.is_self - def check_lvalue_validity(self, node: Node, ctx: Context) -> None: + def check_lvalue_validity(self, node: Expression, ctx: Context) -> None: if isinstance(node, (TypeInfo, TypeVarExpr)): self.fail('Invalid assignment target', ctx) - def store_declared_types(self, lvalue: Node, typ: Type) -> None: + def store_declared_types(self, lvalue: Lvalue, typ: Type) -> None: if isinstance(typ, StarType) and not isinstance(lvalue, StarExpr): self.fail('Star type only allowed for starred expressions', lvalue) if isinstance(lvalue, RefExpr): @@ -1508,7 +1508,7 @@ def get_typevar_declaration(self, s: AssignmentStmt) -> Optional[CallExpr]: return None return call - def process_typevar_parameters(self, args: List[Node], + def process_typevar_parameters(self, args: List[Expression], names: List[Optional[str]], kinds: List[int], has_values: bool, @@ -1585,7 +1585,7 @@ def process_namedtuple_definition(self, s: AssignmentStmt) -> None: # TODO call.analyzed node.node = named_tuple - def check_namedtuple(self, node: Node, var_name: str = None) -> TypeInfo: + def check_namedtuple(self, node: Expression, var_name: str = None) -> TypeInfo: """Check if a call defines a namedtuple. The optional var_name argument is the name of the variable to @@ -1665,7 +1665,7 @@ def parse_namedtuple_args(self, call: CallExpr, + ', '.join(underscore), call) return items, types, ok - def parse_namedtuple_fields_with_types(self, nodes: List[Node], + def parse_namedtuple_fields_with_types(self, nodes: List[Expression], context: Context) -> Tuple[List[str], List[Type], bool]: items = [] # type: List[str] types = [] # type: List[Type] @@ -1770,7 +1770,7 @@ def add_method(funcname: str, ret: Type, args: List[Argument], name=None, def make_argument(self, name: str, type: Type) -> Argument: return Argument(Var(name), type, None, ARG_POS) - def analyze_types(self, items: List[Node]) -> List[Type]: + def analyze_types(self, items: List[Expression]) -> List[Type]: result = [] # type: List[Type] for node in items: try: @@ -1931,7 +1931,7 @@ def visit_del_stmt(self, s: DelStmt) -> None: if not self.is_valid_del_target(s.expr): self.fail('Invalid delete target', s) - def is_valid_del_target(self, s: Node) -> bool: + def is_valid_del_target(self, s: Expression) -> bool: if isinstance(s, (IndexExpr, NameExpr, MemberExpr)): return True elif isinstance(s, TupleExpr): @@ -2502,7 +2502,7 @@ def add_local(self, node: Union[Var, FuncBase], ctx: Context) -> None: node._fullname = name self.locals[-1][name] = SymbolTableNode(LDEF, node) - def add_exports(self, *exps: Node) -> None: + def add_exports(self, *exps: Expression) -> None: for exp in exps: if isinstance(exp, StrExpr): self.all_exports.add(exp.value) @@ -2753,7 +2753,7 @@ def visit_if_stmt(self, s: IfStmt) -> None: def visit_try_stmt(self, s: TryStmt) -> None: self.sem.analyze_try_stmt(s, self, add_global=True) - def analyze_lvalue(self, lvalue: Node, explicit_type: bool = False) -> None: + def analyze_lvalue(self, lvalue: Lvalue, explicit_type: bool = False) -> None: self.sem.analyze_lvalue(lvalue, add_global=True, explicit_type=explicit_type) @@ -2919,12 +2919,12 @@ def set_callable_name(sig: Type, fdef: FuncDef) -> Type: return sig -def refers_to_fullname(node: Node, fullname: str) -> bool: +def refers_to_fullname(node: Expression, fullname: str) -> bool: """Is node a name or member expression with the given full name?""" return isinstance(node, RefExpr) and node.fullname == fullname -def refers_to_class_or_function(node: Node) -> bool: +def refers_to_class_or_function(node: Expression) -> bool: """Does semantically analyzed node refer to a class?""" return (isinstance(node, RefExpr) and isinstance(node.node, (TypeInfo, FuncDef, OverloadedFuncDef))) @@ -2997,7 +2997,7 @@ def infer_reachability_of_if_statement(s: IfStmt, break -def infer_if_condition_value(expr: Node, pyversion: Tuple[int, int], platform: str) -> int: +def infer_if_condition_value(expr: Expression, pyversion: Tuple[int, int], platform: str) -> int: """Infer whether if condition is always true/false. Return ALWAYS_TRUE if always true, ALWAYS_FALSE if always false, @@ -3034,7 +3034,7 @@ def infer_if_condition_value(expr: Node, pyversion: Tuple[int, int], platform: s return result -def consider_sys_version_info(expr: Node, pyversion: Tuple[int, ...]) -> int: +def consider_sys_version_info(expr: Expression, pyversion: Tuple[int, ...]) -> int: """Consider whether expr is a comparison involving sys.version_info. Return ALWAYS_TRUE, ALWAYS_FALSE, or TRUTH_VALUE_UNKNOWN. @@ -3076,7 +3076,7 @@ def consider_sys_version_info(expr: Node, pyversion: Tuple[int, ...]) -> int: return TRUTH_VALUE_UNKNOWN -def consider_sys_platform(expr: Node, platform: str) -> int: +def consider_sys_platform(expr: Expression, platform: str) -> int: """Consider whether expr is a comparison involving sys.platform. Return ALWAYS_TRUE, ALWAYS_FALSE, or TRUTH_VALUE_UNKNOWN. @@ -3135,7 +3135,7 @@ def fixed_comparison(left: Targ, op: str, right: Targ) -> int: return TRUTH_VALUE_UNKNOWN -def contains_int_or_tuple_of_ints(expr: Node) -> Union[None, int, Tuple[int], Tuple[int, ...]]: +def contains_int_or_tuple_of_ints(expr: Expression) -> Union[None, int, Tuple[int], Tuple[int, ...]]: if isinstance(expr, IntExpr): return expr.value if isinstance(expr, TupleExpr): @@ -3149,7 +3149,7 @@ def contains_int_or_tuple_of_ints(expr: Node) -> Union[None, int, Tuple[int], Tu return None -def contains_sys_version_info(expr: Node) -> Union[None, int, Tuple[Optional[int], Optional[int]]]: +def contains_sys_version_info(expr: Expression) -> Union[None, int, Tuple[Optional[int], Optional[int]]]: if is_sys_attr(expr, 'version_info'): return (None, None) # Same as sys.version_info[:] if isinstance(expr, IndexExpr) and is_sys_attr(expr.base, 'version_info'): @@ -3173,7 +3173,7 @@ def contains_sys_version_info(expr: Node) -> Union[None, int, Tuple[Optional[int return None -def is_sys_attr(expr: Node, name: str) -> bool: +def is_sys_attr(expr: Expression, name: str) -> bool: # TODO: This currently doesn't work with code like this: # - import sys as _sys # - from sys import version_info @@ -3211,7 +3211,7 @@ def is_identity_signature(sig: Type) -> bool: return False -def returns_any_if_called(expr: Node) -> bool: +def returns_any_if_called(expr: Expression) -> bool: """Return True if we can predict that expr will return Any if called. This only uses information available during semantic analysis so this @@ -3234,7 +3234,7 @@ def returns_any_if_called(expr: Node) -> bool: return False -def find_fixed_callable_return(expr: Node) -> Optional[CallableType]: +def find_fixed_callable_return(expr: Expression) -> Optional[CallableType]: if isinstance(expr, RefExpr): if isinstance(expr.node, FuncDef): typ = expr.node.type From caabcba8ca363ac04332808fd95714ae1f75839b Mon Sep 17 00:00:00 2001 From: Elazar Gershuni Date: Sun, 2 Oct 2016 02:51:33 +0300 Subject: [PATCH 3/3] Tighten types for semanal --- mypy/nodes.py | 1 + mypy/semanal.py | 52 +++++++++++++++++++++++++------------------------ 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/mypy/nodes.py b/mypy/nodes.py index 8f931ba57a87..b8e27926a266 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -137,6 +137,7 @@ def accept(self, visitor: NodeVisitor[T]) -> T: # fields of Node subtypes are expected to contain. Statement = Node Expression = Node +Lvalue = Expression class SymbolNode(Node): diff --git a/mypy/semanal.py b/mypy/semanal.py index cac77af31634..0f777e4c6361 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -49,7 +49,7 @@ from mypy.nodes import ( MypyFile, TypeInfo, Node, AssignmentStmt, FuncDef, OverloadedFuncDef, - ClassDef, Var, GDEF, MODULE_REF, FuncItem, Import, + ClassDef, Var, GDEF, MODULE_REF, FuncItem, Import, Expression, Lvalue, ImportFrom, ImportAll, Block, LDEF, NameExpr, MemberExpr, IndexExpr, TupleExpr, ListExpr, ExpressionStmt, ReturnStmt, RaiseStmt, AssertStmt, OperatorAssignmentStmt, WhileStmt, @@ -405,7 +405,7 @@ def find_type_variables_in_type( assert False, 'Unsupported type %s' % type return result - def is_defined_type_var(self, tvar: str, context: Node) -> bool: + def is_defined_type_var(self, tvar: str, context: Context) -> bool: return self.lookup_qualified(tvar, context).kind == BOUND_TVAR def visit_overloaded_func_def(self, defn: OverloadedFuncDef) -> None: @@ -606,7 +606,7 @@ def unbind_class_type_vars(self) -> None: if self.bound_tvars: enable_typevars(self.bound_tvars) - def analyze_class_decorator(self, defn: ClassDef, decorator: Node) -> None: + def analyze_class_decorator(self, defn: ClassDef, decorator: Expression) -> None: decorator.accept(self) def setup_is_builtinclass(self, defn: ClassDef) -> None: @@ -801,7 +801,7 @@ def analyze_base_classes(self, defn: ClassDef) -> None: if info.mro and info.mro[-1].fullname() != 'builtins.object': info.mro.append(self.object_type().type) - def expr_to_analyzed_type(self, expr: Node) -> Type: + def expr_to_analyzed_type(self, expr: Expression) -> Type: if isinstance(expr, CallExpr): expr.accept(self) info = self.check_namedtuple(expr) @@ -1135,7 +1135,7 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None: isinstance(s.rvalue, (ListExpr, TupleExpr))): self.add_exports(*s.rvalue.items) - def analyze_simple_literal_type(self, rvalue: Node) -> Optional[Type]: + def analyze_simple_literal_type(self, rvalue: Expression) -> Optional[Type]: """Return builtins.int if rvalue is an int literal, etc.""" if self.weak_opts or self.options.semantic_analysis_only or self.function_stack: # Skip this if any weak options are set. @@ -1177,7 +1177,7 @@ def check_and_set_up_type_alias(self, s: AssignmentStmt) -> None: # just an alias for the type. self.globals[lvalue.name].node = node - def analyze_lvalue(self, lval: Node, nested: bool = False, + def analyze_lvalue(self, lval: Lvalue, nested: bool = False, add_global: bool = False, explicit_type: bool = False) -> None: """Analyze an lvalue or assignment target. @@ -1300,11 +1300,11 @@ def is_self_member_ref(self, memberexpr: MemberExpr) -> bool: node = memberexpr.expr.node return isinstance(node, Var) and node.is_self - def check_lvalue_validity(self, node: Node, ctx: Context) -> None: + def check_lvalue_validity(self, node: Expression, ctx: Context) -> None: if isinstance(node, (TypeInfo, TypeVarExpr)): self.fail('Invalid assignment target', ctx) - def store_declared_types(self, lvalue: Node, typ: Type) -> None: + def store_declared_types(self, lvalue: Lvalue, typ: Type) -> None: if isinstance(typ, StarType) and not isinstance(lvalue, StarExpr): self.fail('Star type only allowed for starred expressions', lvalue) if isinstance(lvalue, RefExpr): @@ -1508,7 +1508,7 @@ def get_typevar_declaration(self, s: AssignmentStmt) -> Optional[CallExpr]: return None return call - def process_typevar_parameters(self, args: List[Node], + def process_typevar_parameters(self, args: List[Expression], names: List[Optional[str]], kinds: List[int], has_values: bool, @@ -1585,7 +1585,7 @@ def process_namedtuple_definition(self, s: AssignmentStmt) -> None: # TODO call.analyzed node.node = named_tuple - def check_namedtuple(self, node: Node, var_name: str = None) -> TypeInfo: + def check_namedtuple(self, node: Expression, var_name: str = None) -> TypeInfo: """Check if a call defines a namedtuple. The optional var_name argument is the name of the variable to @@ -1665,7 +1665,7 @@ def parse_namedtuple_args(self, call: CallExpr, + ', '.join(underscore), call) return items, types, ok - def parse_namedtuple_fields_with_types(self, nodes: List[Node], + def parse_namedtuple_fields_with_types(self, nodes: List[Expression], context: Context) -> Tuple[List[str], List[Type], bool]: items = [] # type: List[str] types = [] # type: List[Type] @@ -1770,7 +1770,7 @@ def add_method(funcname: str, ret: Type, args: List[Argument], name=None, def make_argument(self, name: str, type: Type) -> Argument: return Argument(Var(name), type, None, ARG_POS) - def analyze_types(self, items: List[Node]) -> List[Type]: + def analyze_types(self, items: List[Expression]) -> List[Type]: result = [] # type: List[Type] for node in items: try: @@ -1931,7 +1931,7 @@ def visit_del_stmt(self, s: DelStmt) -> None: if not self.is_valid_del_target(s.expr): self.fail('Invalid delete target', s) - def is_valid_del_target(self, s: Node) -> bool: + def is_valid_del_target(self, s: Expression) -> bool: if isinstance(s, (IndexExpr, NameExpr, MemberExpr)): return True elif isinstance(s, TupleExpr): @@ -2502,7 +2502,7 @@ def add_local(self, node: Union[Var, FuncBase], ctx: Context) -> None: node._fullname = name self.locals[-1][name] = SymbolTableNode(LDEF, node) - def add_exports(self, *exps: Node) -> None: + def add_exports(self, *exps: Expression) -> None: for exp in exps: if isinstance(exp, StrExpr): self.all_exports.add(exp.value) @@ -2753,7 +2753,7 @@ def visit_if_stmt(self, s: IfStmt) -> None: def visit_try_stmt(self, s: TryStmt) -> None: self.sem.analyze_try_stmt(s, self, add_global=True) - def analyze_lvalue(self, lvalue: Node, explicit_type: bool = False) -> None: + def analyze_lvalue(self, lvalue: Lvalue, explicit_type: bool = False) -> None: self.sem.analyze_lvalue(lvalue, add_global=True, explicit_type=explicit_type) @@ -2919,12 +2919,12 @@ def set_callable_name(sig: Type, fdef: FuncDef) -> Type: return sig -def refers_to_fullname(node: Node, fullname: str) -> bool: +def refers_to_fullname(node: Expression, fullname: str) -> bool: """Is node a name or member expression with the given full name?""" return isinstance(node, RefExpr) and node.fullname == fullname -def refers_to_class_or_function(node: Node) -> bool: +def refers_to_class_or_function(node: Expression) -> bool: """Does semantically analyzed node refer to a class?""" return (isinstance(node, RefExpr) and isinstance(node.node, (TypeInfo, FuncDef, OverloadedFuncDef))) @@ -2997,7 +2997,7 @@ def infer_reachability_of_if_statement(s: IfStmt, break -def infer_if_condition_value(expr: Node, pyversion: Tuple[int, int], platform: str) -> int: +def infer_if_condition_value(expr: Expression, pyversion: Tuple[int, int], platform: str) -> int: """Infer whether if condition is always true/false. Return ALWAYS_TRUE if always true, ALWAYS_FALSE if always false, @@ -3034,7 +3034,7 @@ def infer_if_condition_value(expr: Node, pyversion: Tuple[int, int], platform: s return result -def consider_sys_version_info(expr: Node, pyversion: Tuple[int, ...]) -> int: +def consider_sys_version_info(expr: Expression, pyversion: Tuple[int, ...]) -> int: """Consider whether expr is a comparison involving sys.version_info. Return ALWAYS_TRUE, ALWAYS_FALSE, or TRUTH_VALUE_UNKNOWN. @@ -3076,7 +3076,7 @@ def consider_sys_version_info(expr: Node, pyversion: Tuple[int, ...]) -> int: return TRUTH_VALUE_UNKNOWN -def consider_sys_platform(expr: Node, platform: str) -> int: +def consider_sys_platform(expr: Expression, platform: str) -> int: """Consider whether expr is a comparison involving sys.platform. Return ALWAYS_TRUE, ALWAYS_FALSE, or TRUTH_VALUE_UNKNOWN. @@ -3135,7 +3135,8 @@ def fixed_comparison(left: Targ, op: str, right: Targ) -> int: return TRUTH_VALUE_UNKNOWN -def contains_int_or_tuple_of_ints(expr: Node) -> Union[None, int, Tuple[int], Tuple[int, ...]]: +def contains_int_or_tuple_of_ints(expr: Expression + ) -> Union[None, int, Tuple[int], Tuple[int, ...]]: if isinstance(expr, IntExpr): return expr.value if isinstance(expr, TupleExpr): @@ -3149,7 +3150,8 @@ def contains_int_or_tuple_of_ints(expr: Node) -> Union[None, int, Tuple[int], Tu return None -def contains_sys_version_info(expr: Node) -> Union[None, int, Tuple[Optional[int], Optional[int]]]: +def contains_sys_version_info(expr: Expression + ) -> Union[None, int, Tuple[Optional[int], Optional[int]]]: if is_sys_attr(expr, 'version_info'): return (None, None) # Same as sys.version_info[:] if isinstance(expr, IndexExpr) and is_sys_attr(expr.base, 'version_info'): @@ -3173,7 +3175,7 @@ def contains_sys_version_info(expr: Node) -> Union[None, int, Tuple[Optional[int return None -def is_sys_attr(expr: Node, name: str) -> bool: +def is_sys_attr(expr: Expression, name: str) -> bool: # TODO: This currently doesn't work with code like this: # - import sys as _sys # - from sys import version_info @@ -3211,7 +3213,7 @@ def is_identity_signature(sig: Type) -> bool: return False -def returns_any_if_called(expr: Node) -> bool: +def returns_any_if_called(expr: Expression) -> bool: """Return True if we can predict that expr will return Any if called. This only uses information available during semantic analysis so this @@ -3234,7 +3236,7 @@ def returns_any_if_called(expr: Node) -> bool: return False -def find_fixed_callable_return(expr: Node) -> Optional[CallableType]: +def find_fixed_callable_return(expr: Expression) -> Optional[CallableType]: if isinstance(expr, RefExpr): if isinstance(expr.node, FuncDef): typ = expr.node.type