From 1983a03dca3cf1b0024583d02edb0f08134da9a6 Mon Sep 17 00:00:00 2001 From: Elazar Gershuni Date: Mon, 12 Sep 2016 03:15:34 +0300 Subject: [PATCH 01/11] Make Statement a proper subclass of Node --- mypy/fastparse.py | 18 ++++++++++-------- mypy/fastparse2.py | 22 +++++++++++----------- mypy/nodes.py | 21 ++++++++++++++------- mypy/parse.py | 31 ++++++++++++++++--------------- mypy/treetransform.py | 11 +++++++---- 5 files changed, 58 insertions(+), 45 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 7ad71be62462..112b89d88544 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -14,11 +14,9 @@ UnaryExpr, FuncExpr, ComparisonExpr, StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension, SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, - AwaitExpr, - ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2 -) + AwaitExpr, ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2, Statement) from mypy.types import ( - Type, CallableType, FunctionLike, AnyType, UnboundType, TupleType, TypeList, EllipsisType, + Type, CallableType, AnyType, UnboundType, TupleType, TypeList, EllipsisType, ) from mypy import defaults from mypy import experiments @@ -128,6 +126,9 @@ def visit_NoneType(self, n: Any) -> Optional[Node]: def visit_list(self, l: Sequence[ast35.AST]) -> List[Node]: return [self.visit(e) for e in l] + def visit_statement_list(self, l: Sequence[ast35.AST]) -> List[Statement]: + return [self.visit(e) for e in l] + op_map = { ast35.Add: '+', ast35.Sub: '-', @@ -176,12 +177,13 @@ def from_comp_operator(self, op: ast35.cmpop) -> str: def as_block(self, stmts: List[ast35.stmt], lineno: int) -> Block: b = None if stmts: - b = Block(self.fix_function_overloads(self.visit_list(stmts))) + stmt_list = self.visit_statement_list(stmts) + b = Block(self.fix_function_overloads(stmt_list)) b.set_line(lineno) return b - def fix_function_overloads(self, stmts: List[Node]) -> List[Node]: - ret = [] # type: List[Node] + def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: + ret = [] # type: List[Statement] current_overload = [] current_overload_name = None # mypy doesn't actually check that the decorator is literally @overload @@ -225,7 +227,7 @@ def translate_module_id(self, id: str) -> str: return id def visit_Module(self, mod: ast35.Module) -> Node: - body = self.fix_function_overloads(self.visit_list(mod.body)) + body = self.fix_function_overloads(self.visit_statement_list(mod.body)) return MypyFile(body, self.imports, diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 25e5bcb78fbc..216dfa2d5352 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -27,14 +27,12 @@ TupleExpr, GeneratorExpr, ListComprehension, ListExpr, ConditionalExpr, DictExpr, SetExpr, NameExpr, IntExpr, StrExpr, BytesExpr, UnicodeExpr, FloatExpr, CallExpr, SuperExpr, MemberExpr, IndexExpr, SliceExpr, OpExpr, - UnaryExpr, FuncExpr, ComparisonExpr, - StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension, - SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, - AwaitExpr, Expression, - ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2 + UnaryExpr, FuncExpr, ComparisonExpr, DictionaryComprehension, + SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, Expression, + ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2, Statement ) from mypy.types import ( - Type, CallableType, FunctionLike, AnyType, UnboundType, TupleType, TypeList, EllipsisType, + Type, CallableType, AnyType, UnboundType, ) from mypy import defaults from mypy import experiments @@ -44,7 +42,6 @@ try: from typed_ast import ast27 from typed_ast import ast35 - from typed_ast import conversions except ImportError: if sys.version_info.minor > 2: print('You must install the typed_ast package before you can run mypy' @@ -147,6 +144,9 @@ def visit_NoneType(self, n: Any) -> Optional[Node]: def visit_list(self, l: Sequence[ast27.AST]) -> List[Node]: return [self.visit(e) for e in l] + def visit_statement_list(self, l: Sequence[ast27.AST]) -> List[Statement]: + return [self.visit(e) for e in l] + op_map = { ast27.Add: '+', ast27.Sub: '-', @@ -194,12 +194,12 @@ def from_comp_operator(self, op: ast27.cmpop) -> str: def as_block(self, stmts: List[ast27.stmt], lineno: int) -> Block: b = None if stmts: - b = Block(self.fix_function_overloads(self.visit_list(stmts))) + b = Block(self.fix_function_overloads(self.visit_statement_list(stmts))) b.set_line(lineno) return b - def fix_function_overloads(self, stmts: List[Node]) -> List[Node]: - ret = [] # type: List[Node] + def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: + ret = [] # type: List[Statement] current_overload = [] current_overload_name = None # mypy doesn't actually check that the decorator is literally @overload @@ -243,7 +243,7 @@ def translate_module_id(self, id: str) -> str: return id def visit_Module(self, mod: ast27.Module) -> Node: - body = self.fix_function_overloads(self.visit_list(mod.body)) + body = self.fix_function_overloads(self.visit_statement_list(mod.body)) return MypyFile(body, self.imports, diff --git a/mypy/nodes.py b/mypy/nodes.py index d989cf680f9c..27aa749df9ae 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -1,11 +1,10 @@ """Abstract syntax tree node classes (i.e. parse tree).""" import os -import re -from abc import abstractmethod, ABCMeta +from abc import abstractmethod from typing import ( - Any, TypeVar, List, Tuple, cast, Set, Dict, Union, Optional + Any, TypeVar, List, Tuple, cast, Set, Dict, Union, Optional, NewType ) from mypy.lex import Token @@ -117,13 +116,21 @@ def accept(self, visitor: NodeVisitor[T]) -> T: raise RuntimeError('Not implemented') -# These are placeholders for a future refactoring; see #1783. -# For now they serve as (unchecked) documentation of what various +# This is a placeholder for a future refactoring; see #1783. +# For now it serves as (unchecked) documentation of what various # fields of Node subtypes are expected to contain. -Statement = Node Expression = Node +class Statement(Node): + pass + + +# For now, only Var is a declaration +class Declaration(Node): + pass + + class SymbolNode(Node): # Nodes that can be stored in a symbol table. @@ -572,7 +579,7 @@ def deserialize(cls, data: JsonDict) -> 'Decorator': return dec -class Var(SymbolNode, Statement): +class Var(SymbolNode, Declaration): """A variable. It can refer to global/local variable or a data attribute. diff --git a/mypy/parse.py b/mypy/parse.py index 39979d7126b8..c6638e6cb2a7 100644 --- a/mypy/parse.py +++ b/mypy/parse.py @@ -14,7 +14,6 @@ UnicodeLit, FloatLit, Op, Indent, Keyword, Punct, LexError, ComplexLit, EllipsisToken ) -import mypy.types from mypy.nodes import ( MypyFile, Import, Node, ImportAll, ImportFrom, FuncDef, OverloadedFuncDef, ClassDef, Decorator, Block, Var, OperatorAssignmentStmt, @@ -27,14 +26,14 @@ UnaryExpr, FuncExpr, PrintStmt, ImportBase, ComparisonExpr, StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension, SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, ExecStmt, Argument, - BackquoteExpr + BackquoteExpr, Statement ) from mypy import defaults from mypy import nodes from mypy.errors import Errors, CompileError from mypy.types import Type, CallableType, AnyType, UnboundType from mypy.parsetype import ( - parse_type, parse_types, parse_signature, TypeParseError, parse_str_as_signature + parse_type, parse_types, parse_signature, TypeParseError ) from mypy.options import Options @@ -235,7 +234,7 @@ def translate_module_id(self, id: str) -> str: return 'builtins' return id - def parse_import_from(self) -> Node: + def parse_import_from(self) -> Statement: self.expect('from') # Build the list of beginning relative tokens. @@ -318,8 +317,8 @@ def parse_qualified_name(self) -> str: # Parsing global definitions - def parse_defs(self) -> List[Node]: - defs = [] # type: List[Node] + def parse_defs(self) -> List[Statement]: + defs = [] # type: List[Statement] while not self.eof(): try: defn, is_simple = self.parse_statement() @@ -394,7 +393,7 @@ def parse_class_keywords(self) -> Optional[str]: def parse_super_type(self) -> Node: return self.parse_expression(precedence[',']) - def parse_decorated_function_or_class(self) -> Node: + def parse_decorated_function_or_class(self) -> Statement: decorators = [] no_type_checks = False while self.current_str() == '@': @@ -868,7 +867,7 @@ def parse_block(self, allow_type: bool = False) -> Tuple[Block, Type]: brk = self.expect_break() type = self.parse_type_comment(brk, signature=True) self.expect_indent() - stmt_list = [] # type: List[Node] + stmt_list = [] # type: List[Statement] while (not isinstance(self.current(), Dedent) and not isinstance(self.current(), Eof)): try: @@ -886,7 +885,7 @@ def parse_block(self, allow_type: bool = False) -> Tuple[Block, Type]: node.set_line(colon) return node, type - def try_combine_overloads(self, s: Node, stmt: List[Node]) -> bool: + def try_combine_overloads(self, s: Node, stmt: List[Statement]) -> bool: if isinstance(s, Decorator) and stmt: fdef = s n = fdef.func.name() @@ -898,8 +897,8 @@ def try_combine_overloads(self, s: Node, stmt: List[Node]) -> bool: return True return False - def parse_statement(self) -> Tuple[Node, bool]: - stmt = None # type: Node + def parse_statement(self) -> Tuple[Statement, bool]: + stmt = None # type: Statement t = self.current() ts = self.current_str() is_simple = True # Is this a non-block statement? @@ -964,7 +963,7 @@ def parse_statement(self) -> Tuple[Node, bool]: stmt.set_line(t) return stmt, is_simple - def parse_expression_or_assignment(self) -> Node: + def parse_expression_or_assignment(self) -> Statement: expr = self.parse_expression(star_expr_allowed=True) if self.current_str() == '=': return self.parse_assignment(expr) @@ -978,7 +977,7 @@ def parse_expression_or_assignment(self) -> Node: # Expression statement. return ExpressionStmt(expr) - def parse_assignment(self, lvalue: Any) -> Node: + def parse_assignment(self, lvalue: Any) -> AssignmentStmt: """Parse an assignment statement. Assume that lvalue has been parsed already, and the current token is '='. @@ -1184,7 +1183,7 @@ def parse_if_stmt(self) -> IfStmt: else: return None - def parse_try_stmt(self) -> Node: + def parse_try_stmt(self) -> Statement: self.expect('try') body, _ = self.parse_block() is_error = False @@ -1813,7 +1812,9 @@ def parse_lambda_expr(self) -> FuncExpr: expr = self.parse_expression(precedence[',']) - nodes = [ReturnStmt(expr).set_line(lambda_tok)] + ret = ReturnStmt(expr) + ret.set_line(lambda_tok) + nodes = [ret] # type: List[Statement] # Potentially insert extra assignment statements to the beginning of the # body, used to decompose Python 2 tuple arguments. nodes[:0] = extra_stmts diff --git a/mypy/treetransform.py b/mypy/treetransform.py index b6143d4a7fef..02a031053870 100644 --- a/mypy/treetransform.py +++ b/mypy/treetransform.py @@ -19,9 +19,9 @@ ComparisonExpr, TempNode, StarExpr, YieldFromExpr, NamedTupleExpr, NonlocalDecl, SetComprehension, DictionaryComprehension, ComplexExpr, TypeAliasExpr, EllipsisExpr, - YieldExpr, ExecStmt, Argument, BackquoteExpr, AwaitExpr, + YieldExpr, ExecStmt, Argument, BackquoteExpr, AwaitExpr, Statement ) -from mypy.types import Type, FunctionLike, Instance +from mypy.types import Type, FunctionLike from mypy.traverser import TraverserVisitor from mypy.visitor import NodeVisitor @@ -57,7 +57,7 @@ def __init__(self) -> None: def visit_mypy_file(self, node: MypyFile) -> Node: # NOTE: The 'names' and 'imports' instance variables will be empty! - new = MypyFile(self.nodes(node.defs), [], node.is_bom, + new = MypyFile(self.statements(node.defs), [], node.is_bom, ignored_lines=set(node.ignored_lines)) new._name = node._name new._fullname = node._fullname @@ -200,7 +200,7 @@ def visit_nonlocal_decl(self, node: NonlocalDecl) -> Node: return NonlocalDecl(node.names[:]) def visit_block(self, node: Block) -> Block: - return Block(self.nodes(node.body)) + return Block(self.statements(node.body)) def visit_decorator(self, node: Decorator) -> Decorator: # Note that a Decorator must be transformed to a Decorator. @@ -524,6 +524,9 @@ def optional_block(self, block: Block) -> Block: def nodes(self, nodes: List[Node]) -> List[Node]: return [self.node(node) for node in nodes] + def statements(self, nodes: List[Statement]) -> List[Statement]: + return [cast(Statement, self.node(node)) for node in nodes] + def optional_nodes(self, nodes: List[Node]) -> List[Node]: return [self.optional_node(node) for node in nodes] From 9c59230d46301980a945e1d1fc5fd42697ee3869 Mon Sep 17 00:00:00 2001 From: Elazar Date: Mon, 12 Sep 2016 03:36:06 +0300 Subject: [PATCH 02/11] remove NewType from import list --- mypy/nodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/nodes.py b/mypy/nodes.py index 27aa749df9ae..a310ddadd603 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -4,7 +4,7 @@ from abc import abstractmethod from typing import ( - Any, TypeVar, List, Tuple, cast, Set, Dict, Union, Optional, NewType + Any, TypeVar, List, Tuple, cast, Set, Dict, Union, Optional ) from mypy.lex import Token From 3aeb5f16e72e3e998854ac31b825bdb6c807ccde Mon Sep 17 00:00:00 2001 From: Elazar Gershuni Date: Mon, 12 Sep 2016 05:15:19 +0300 Subject: [PATCH 03/11] Make Expression a proper subclass of Node --- mypy/checker.py | 86 +++++++++++++------------ mypy/checkexpr.py | 34 +++++----- mypy/fastparse.py | 131 +++++++++++++++++++------------------- mypy/fastparse2.py | 122 +++++++++++++++++------------------ mypy/nodes.py | 7 ++- mypy/parse.py | 97 ++++++++++++++-------------- mypy/semanal.py | 19 +++--- mypy/treetransform.py | 143 +++++++++++++++++++++--------------------- 8 files changed, 325 insertions(+), 314 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 9231cd73b0a6..6026ffc3d861 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -7,12 +7,12 @@ import os.path from typing import ( - Any, Dict, Set, List, cast, Tuple, TypeVar, Union, Optional, NamedTuple + Any, Dict, Set, List, cast, Tuple, TypeVar, Union, Optional, NamedTuple, Mapping ) from mypy.errors import Errors, report_internal_error from mypy.nodes import ( - SymbolTable, Node, MypyFile, Var, Expression, + SymbolTable, Node, Statement, MypyFile, Var, Expression, OverloadedFuncDef, FuncDef, FuncItem, FuncBase, TypeInfo, ClassDef, GDEF, Block, AssignmentStmt, NameExpr, MemberExpr, IndexExpr, TupleExpr, ListExpr, ExpressionStmt, ReturnStmt, IfStmt, @@ -229,7 +229,7 @@ def accept(self, node: Node, type_context: Type = None) -> Type: else: return typ - def accept_loop(self, body: Node, else_body: Node = None) -> Type: + def accept_loop(self, body: Statement, else_body: Statement = None) -> Type: """Repeatedly type check a loop body until the frame doesn't change. Then check the else_body. @@ -1039,7 +1039,7 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> Type: for lv in s.lvalues[:-1]: self.check_assignment(lv, rvalue, s.type is None) - def check_assignment(self, lvalue: Node, rvalue: Node, infer_lvalue_type: bool = True) -> None: + def check_assignment(self, lvalue: Expression, rvalue: Expression, infer_lvalue_type: bool = True) -> None: """Type check a single assignment: lvalue = rvalue.""" if isinstance(lvalue, TupleExpr) or isinstance(lvalue, ListExpr): self.check_assignment_to_multiple_lvalues(lvalue.items, rvalue, lvalue, @@ -1094,7 +1094,7 @@ def check_assignment(self, lvalue: Node, rvalue: Node, infer_lvalue_type: bool = self.infer_variable_type(inferred, lvalue, self.accept(rvalue), rvalue) - def check_assignment_to_multiple_lvalues(self, lvalues: List[Node], rvalue: Node, + def check_assignment_to_multiple_lvalues(self, lvalues: List[Expression], rvalue: Expression, context: Context, infer_lvalue_type: bool = True) -> None: if isinstance(rvalue, TupleExpr) or isinstance(rvalue, ListExpr): @@ -1129,7 +1129,7 @@ def check_assignment_to_multiple_lvalues(self, lvalues: List[Node], rvalue: Node else: self.check_multi_assignment(lvalues, rvalue, context, infer_lvalue_type) - def check_rvalue_count_in_assignment(self, lvalues: List[Node], rvalue_count: int, + def check_rvalue_count_in_assignment(self, lvalues: List[Expression], rvalue_count: int, context: Context) -> bool: if any(isinstance(lvalue, StarExpr) for lvalue in lvalues): if len(lvalues) - 1 > rvalue_count: @@ -1142,8 +1142,8 @@ def check_rvalue_count_in_assignment(self, lvalues: List[Node], rvalue_count: in return False return True - def check_multi_assignment(self, lvalues: List[Node], - rvalue: Node, + def check_multi_assignment(self, lvalues: List[Expression], + rvalue: Expression, context: Context, infer_lvalue_type: bool = True, msg: str = None) -> None: @@ -1165,7 +1165,7 @@ def check_multi_assignment(self, lvalues: List[Node], self.check_multi_assignment_from_iterable(lvalues, rvalue_type, context, infer_lvalue_type) - def check_multi_assignment_from_tuple(self, lvalues: List[Node], rvalue: Node, + def check_multi_assignment_from_tuple(self, lvalues: List[Expression], rvalue: Expression, rvalue_type: TupleType, context: Context, undefined_rvalue: bool, infer_lvalue_type: bool = True) -> None: @@ -1195,7 +1195,7 @@ def check_multi_assignment_from_tuple(self, lvalues: List[Node], rvalue: Node, for lv, rv_type in zip(right_lvs, right_rv_types): self.check_assignment(lv, self.temp_node(rv_type, context), infer_lvalue_type) - def lvalue_type_for_inference(self, lvalues: List[Node], rvalue_type: TupleType) -> Type: + def lvalue_type_for_inference(self, lvalues: List[Expression], rvalue_type: TupleType) -> Type: star_index = next((i for i, lv in enumerate(lvalues) if isinstance(lv, StarExpr)), len(lvalues)) left_lvs = lvalues[:star_index] @@ -1206,7 +1206,7 @@ def lvalue_type_for_inference(self, lvalues: List[Node], rvalue_type: TupleType) type_parameters = [] # type: List[Type] - def append_types_for_inference(lvs: List[Node], rv_types: List[Type]) -> None: + def append_types_for_inference(lvs: List[Expression], rv_types: List[Type]) -> None: for lv, rv_type in zip(lvs, rv_types): sub_lvalue_type, index_expr, inferred = self.check_lvalue(lv) if sub_lvalue_type: @@ -1251,7 +1251,7 @@ def type_is_iterable(self, type: Type) -> bool: [AnyType()])) and isinstance(type, Instance)) - def check_multi_assignment_from_iterable(self, lvalues: List[Node], rvalue_type: Type, + def check_multi_assignment_from_iterable(self, lvalues: List[Expression], rvalue_type: Type, context: Context, infer_lvalue_type: bool = True) -> None: if self.type_is_iterable(rvalue_type): @@ -1266,7 +1266,7 @@ def check_multi_assignment_from_iterable(self, lvalues: List[Node], rvalue_type: else: self.msg.type_not_iterable(rvalue_type, context) - def check_lvalue(self, lvalue: Node) -> Tuple[Type, IndexExpr, Var]: + def check_lvalue(self, lvalue: Expression) -> Tuple[Type, IndexExpr, Var]: lvalue_type = None # type: Type index_lvalue = None # type: IndexExpr inferred = None # type: Var @@ -1296,7 +1296,7 @@ def check_lvalue(self, lvalue: Node) -> Tuple[Type, IndexExpr, Var]: return lvalue_type, index_lvalue, inferred - def is_definition(self, s: Node) -> bool: + def is_definition(self, s: Expression) -> bool: if isinstance(s, NameExpr): if s.is_def: return True @@ -1312,7 +1312,7 @@ def is_definition(self, s: Node) -> bool: return s.is_def return False - def infer_variable_type(self, name: Var, lvalue: Node, + def infer_variable_type(self, name: Var, lvalue: Expression, init_type: Type, context: Context) -> None: """Infer the type of initialized variables from initializer type.""" if self.typing_mode_weak(): @@ -1339,7 +1339,7 @@ def infer_variable_type(self, name: Var, lvalue: Node, self.set_inferred_type(name, lvalue, init_type) - def infer_partial_type(self, name: Var, lvalue: Node, init_type: Type) -> bool: + def infer_partial_type(self, name: Var, lvalue: Expression, init_type: Type) -> bool: if isinstance(init_type, (NoneTyp, UninhabitedType)): partial_type = PartialType(None, name, [init_type]) elif isinstance(init_type, Instance): @@ -1358,7 +1358,7 @@ def infer_partial_type(self, name: Var, lvalue: Node, init_type: Type) -> bool: self.partial_types[-1][name] = lvalue return True - def set_inferred_type(self, var: Var, lvalue: Node, type: Type) -> None: + def set_inferred_type(self, var: Var, lvalue: Expression, type: Type) -> None: """Store inferred variable type. Store the type to both the variable node and the expression node that @@ -1368,7 +1368,7 @@ def set_inferred_type(self, var: Var, lvalue: Node, type: Type) -> None: var.type = type self.store_type(lvalue, type) - def set_inference_error_fallback_type(self, var: Var, lvalue: Node, type: Type, + def set_inference_error_fallback_type(self, var: Var, lvalue: Expression, type: Type, context: Context) -> None: """If errors on context line are ignored, store dummy type for variable. @@ -1383,7 +1383,7 @@ def set_inference_error_fallback_type(self, var: Var, lvalue: Node, type: Type, if context.get_line() in self.errors.ignored_lines[self.errors.file]: self.set_inferred_type(var, lvalue, AnyType()) - def narrow_type_from_binder(self, expr: Node, known_type: Type) -> Type: + def narrow_type_from_binder(self, expr: Expression, known_type: Type) -> Type: if expr.literal >= LITERAL_TYPE: restriction = self.binder.get(expr) if restriction: @@ -1391,8 +1391,8 @@ def narrow_type_from_binder(self, expr: Node, known_type: Type) -> Type: return ans return known_type - def check_simple_assignment(self, lvalue_type: Type, rvalue: Node, - context: Node, + def check_simple_assignment(self, lvalue_type: Type, rvalue: Expression, + context: Union[Expression, ImportBase], msg: str = messages.INCOMPATIBLE_TYPES_IN_ASSIGNMENT, lvalue_name: str = 'variable', rvalue_name: str = 'expression') -> Type: @@ -1414,7 +1414,7 @@ def check_simple_assignment(self, lvalue_type: Type, rvalue: Node, return rvalue_type def check_indexed_assignment(self, lvalue: IndexExpr, - rvalue: Node, context: Context) -> None: + rvalue: Expression, context: Context) -> None: """Type check indexed assignment base[index] = rvalue. The lvalue argument is the base[index] expression. @@ -1429,7 +1429,7 @@ def check_indexed_assignment(self, lvalue: IndexExpr, context) def try_infer_partial_type_from_indexed_assignment( - self, lvalue: IndexExpr, rvalue: Node) -> None: + self, lvalue: IndexExpr, rvalue: Expression) -> None: # TODO: Should we share some of this with try_infer_partial_type? if isinstance(lvalue.base, RefExpr) and isinstance(lvalue.base.node, Var): var = lvalue.base.node @@ -1610,7 +1610,7 @@ def visit_raise_stmt(self, s: RaiseStmt) -> Type: if s.from_expr: self.type_check_raise(s.from_expr, s) - def type_check_raise(self, e: Node, s: RaiseStmt) -> None: + def type_check_raise(self, e: Expression, s: RaiseStmt) -> None: typ = self.accept(e) if isinstance(typ, FunctionLike): if typ.is_type_obj(): @@ -1701,7 +1701,7 @@ def visit_try_without_finally(self, s: TryStmt) -> bool: breaking_out = breaking_out and self.binder.last_pop_breaking_out return breaking_out - def visit_except_handler_test(self, n: Node) -> Type: + def visit_except_handler_test(self, n: Expression) -> Type: """Type check an exception handler test clause.""" type = self.accept(n) @@ -1737,7 +1737,7 @@ def visit_for_stmt(self, s: ForStmt) -> Type: self.analyze_index_variables(s.index, item_type, s) self.accept_loop(s.body, s.else_body) - def analyze_async_iterable_item_type(self, expr: Node) -> Type: + def analyze_async_iterable_item_type(self, expr: Expression) -> Type: """Analyse async iterable expression and return iterator item type.""" iterable = self.accept(expr) @@ -1756,7 +1756,7 @@ def analyze_async_iterable_item_type(self, expr: Node) -> Type: return self.check_awaitable_expr(awaitable, expr, messages.INCOMPATIBLE_TYPES_IN_ASYNC_FOR) - def analyze_iterable_item_type(self, expr: Node) -> Type: + def analyze_iterable_item_type(self, expr: Expression) -> Type: """Analyse iterable expression and return iterator item type.""" iterable = self.accept(expr) @@ -1791,7 +1791,7 @@ def analyze_iterable_item_type(self, expr: Node) -> Type: expr) return echk.check_call(method, [], [], expr)[0] - def analyze_index_variables(self, index: Node, item_type: Type, + def analyze_index_variables(self, index: Expression, item_type: Type, context: Context) -> None: """Type check or infer for loop or list comprehension index vars.""" self.check_assignment(index, self.temp_node(item_type, context)) @@ -1805,7 +1805,7 @@ def visit_del_stmt(self, s: DelStmt) -> Type: c.line = s.line return c.accept(self) else: - def flatten(t: Node) -> List[Node]: + def flatten(t: Expression) -> List[Expression]: """Flatten a nested sequence of tuples/lists into one list of nodes.""" if isinstance(t, TupleExpr) or isinstance(t, ListExpr): return [b for a in t.items for b in flatten(a)] @@ -2330,7 +2330,7 @@ def check_usable_type(self, typ: Type, context: Context) -> None: if self.is_unusable_type(typ): self.msg.does_not_return_value(typ, context) - def temp_node(self, t: Type, context: Context = None) -> Node: + def temp_node(self, t: Type, context: Context = None) -> Expression: """Create a temporary node with the given, fixed type.""" temp = TempNode(t) if context: @@ -2368,12 +2368,12 @@ def method_type(self, func: FuncBase) -> FunctionLike: # probably be better to have the dict keyed by the nodes' literal_hash # field instead. -# NB: This should be `TypeMap = Optional[Dict[Node, Type]]`! +# NB: This should be `TypeMap = Optional[Dict[Expression, Type]]`! # But see https://github.com/python/mypy/issues/1637 -TypeMap = Dict[Node, Type] +TypeMap = Dict[Expression, Type] -def conditional_type_map(expr: Node, +def conditional_type_map(expr: Expression, current_type: Optional[Type], proposed_type: Optional[Type], *, @@ -2405,7 +2405,7 @@ def conditional_type_map(expr: Node, return {}, {} -def is_literal_none(n: Node) -> bool: +def is_literal_none(n: Expression) -> bool: return isinstance(n, NameExpr) and n.fullname == 'builtins.None' @@ -2453,8 +2453,8 @@ def or_conditional_maps(m1: TypeMap, m2: TypeMap) -> TypeMap: return result -def find_isinstance_check(node: Node, - type_map: Dict[Node, Type], +def find_isinstance_check(node: Expression, + type_map: Mapping[Node, Type], weak: bool=False ) -> Tuple[TypeMap, TypeMap]: """Find any isinstance checks (within a chain of ands). Includes @@ -2473,15 +2473,15 @@ def find_isinstance_check(node: Node, expr = node.args[0] if expr.literal == LITERAL_TYPE: vartype = type_map[expr] - type = get_isinstance_type(node.args[1], type_map) + type = get_isinstance_type(node.args[1], type_map[node.args[1]]) return conditional_type_map(expr, vartype, type, weak=weak) elif (isinstance(node, ComparisonExpr) and any(is_literal_none(n) for n in node.operands) and experiments.STRICT_OPTIONAL): # Check for `x is None` and `x is not None`. is_not = node.operators == ['is not'] if is_not or node.operators == ['is']: - if_vars = {} # type: Dict[Node, Type] - else_vars = {} # type: Dict[Node, Type] + if_vars = {} # type: Dict[Expression, Type] + else_vars = {} # type: Dict[Expression, Type] 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 @@ -2500,7 +2500,7 @@ def find_isinstance_check(node: Node, vartype = type_map[node] if_type = true_only(vartype) else_type = false_only(vartype) - ref = node # type: Node + ref = node # type: Expression if_map = {ref: if_type} if not isinstance(if_type, UninhabitedType) else None else_map = {ref: else_type} if not isinstance(else_type, UninhabitedType) else None return if_map, else_map @@ -2546,9 +2546,7 @@ def find_isinstance_check(node: Node, return {}, {} -def get_isinstance_type(node: Node, type_map: Dict[Node, Type]) -> Type: - type = type_map[node] - +def get_isinstance_type(node: Expression, type: Type) -> Type: if isinstance(type, TupleType): all_types = type.items else: @@ -2573,7 +2571,7 @@ def get_isinstance_type(node: Node, type_map: Dict[Node, Type]) -> Type: return UnionType(types) -def expand_node(defn: Node, map: Dict[TypeVarId, Type]) -> Node: +def expand_node(defn: FuncItem, map: Dict[TypeVarId, Type]) -> Node: visitor = TypeTransformVisitor(map) return defn.accept(visitor) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 178a21429a73..e0a54ef6a558 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -10,7 +10,7 @@ ) from mypy.nodes import ( NameExpr, RefExpr, Var, FuncDef, OverloadedFuncDef, TypeInfo, CallExpr, - Node, MemberExpr, IntExpr, StrExpr, BytesExpr, UnicodeExpr, FloatExpr, + Expression, MemberExpr, IntExpr, StrExpr, BytesExpr, UnicodeExpr, FloatExpr, OpExpr, UnaryExpr, IndexExpr, CastExpr, RevealTypeExpr, TypeApplication, ListExpr, TupleExpr, DictExpr, FuncExpr, SuperExpr, SliceExpr, Context, ListComprehension, GeneratorExpr, SetExpr, MypyFile, Decorator, @@ -234,10 +234,10 @@ def check_call_expr_with_callee_type(self, callee_type: Type, return self.check_call(callee_type, e.args, e.arg_kinds, e, e.arg_names, callable_node=e.callee)[0] - def check_call(self, callee: Type, args: List[Node], + def check_call(self, callee: Type, args: List[Expression], arg_kinds: List[int], context: Context, arg_names: List[str] = None, - callable_node: Node = None, + callable_node: Expression = None, arg_messages: MessageBuilder = None) -> Tuple[Type, Type]: """Type check a call. @@ -370,7 +370,7 @@ def analyze_type_type_callee(self, item: Type, context: Context) -> Type: return AnyType() def infer_arg_types_in_context(self, callee: Optional[CallableType], - args: List[Node]) -> List[Type]: + args: List[Expression]) -> List[Type]: """Infer argument expression types using a callable type as context. For example, if callee argument 2 has type List[int], infer the @@ -402,7 +402,7 @@ def infer_arg_types_in_context(self, callee: Optional[CallableType], return res def infer_arg_types_in_context2( - self, callee: CallableType, args: List[Node], arg_kinds: List[int], + self, callee: CallableType, args: List[Expression], arg_kinds: List[int], formal_to_actual: List[List[int]]) -> List[Type]: """Infer argument expression types using a callable type as context. @@ -468,7 +468,7 @@ def infer_function_type_arguments_using_context( error_context)) def infer_function_type_arguments(self, callee_type: CallableType, - args: List[Node], + args: List[Expression], arg_kinds: List[int], formal_to_actual: List[List[int]], context: Context) -> CallableType: @@ -533,7 +533,7 @@ def infer_function_type_arguments(self, callee_type: CallableType, def infer_function_type_arguments_pass2( self, callee_type: CallableType, - args: List[Node], + args: List[Expression], arg_kinds: List[int], formal_to_actual: List[List[int]], inferred_args: List[Type], @@ -1048,7 +1048,7 @@ def get_operator_method(self, op: str) -> str: else: return nodes.op_methods[op] - def _check_op_for_errors(self, method: str, base_type: Type, arg: Node, + def _check_op_for_errors(self, method: str, base_type: Type, arg: Expression, context: Context ) -> Tuple[Tuple[Type, Type], MessageBuilder]: """Type check a binary operation which maps to a method call. @@ -1062,7 +1062,7 @@ def _check_op_for_errors(self, method: str, base_type: Type, arg: Node, local_errors) return result, local_errors - def check_op_local(self, method: str, base_type: Type, arg: Node, + def check_op_local(self, method: str, base_type: Type, arg: Expression, context: Context, local_errors: MessageBuilder) -> Tuple[Type, Type]: """Type check a binary operation which maps to a method call. @@ -1074,7 +1074,7 @@ def check_op_local(self, method: str, base_type: Type, arg: Node, return self.check_call(method_type, [arg], [nodes.ARG_POS], context, arg_messages=local_errors) - def check_op(self, method: str, base_type: Type, arg: Node, + def check_op(self, method: str, base_type: Type, arg: Expression, context: Context, allow_reverse: bool = False) -> Tuple[Type, Type]: """Type check a binary operation which maps to a method call. @@ -1336,7 +1336,7 @@ def visit_tuple_slice_helper(self, left_type: TupleType, slic: SliceExpr) -> Typ return left_type.slice(begin, stride, end) - def _get_value(self, index: Node) -> Optional[int]: + def _get_value(self, index: Expression) -> Optional[int]: if isinstance(index, IntExpr): return index.value elif isinstance(index, UnaryExpr): @@ -1383,7 +1383,7 @@ def visit_list_expr(self, e: ListExpr) -> Type: def visit_set_expr(self, e: SetExpr) -> Type: return self.check_lst_expr(e.items, 'builtins.set', '', e) - def check_lst_expr(self, items: List[Node], fullname: str, + def check_lst_expr(self, items: List[Expression], fullname: str, tag: str, context: Context) -> Type: # Translate into type checking a generic function call. # Used for list and set expressions, as well as for tuples @@ -1472,8 +1472,8 @@ def visit_dict_expr(self, e: DictExpr) -> Type: Translate it into a call to dict(), with provisions for **expr. """ # Collect function arguments, watching out for **expr. - args = [] # type: List[Node] # Regular "key: value" - stargs = [] # type: List[Node] # For "**expr" + args = [] # type: List[Expression] # Regular "key: value" + stargs = [] # type: List[Expression] # For "**expr" for key, value in e.items: if key is None: stargs.append(value) @@ -1734,8 +1734,8 @@ def visit_conditional_expr(self, e: ConditionalExpr) -> Type: return res - def analyze_cond_branch(self, map: Optional[Dict[Node, Type]], - node: Node, context: Optional[Type]) -> Type: + def analyze_cond_branch(self, map: Optional[Dict[Expression, Type]], + node: Expression, context: Optional[Type]) -> Type: with self.chk.binder.frame_context(): if map: for var, type in map.items(): @@ -1750,7 +1750,7 @@ def visit_backquote_expr(self, e: BackquoteExpr) -> Type: # Helpers # - def accept(self, node: Node, context: Type = None) -> Type: + def accept(self, node: Expression, context: Type = None) -> Type: """Type check a node. Alias for TypeChecker.accept.""" return self.chk.accept(node, context) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 112b89d88544..28921e0e4b2a 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -11,7 +11,7 @@ TupleExpr, GeneratorExpr, ListComprehension, ListExpr, ConditionalExpr, DictExpr, SetExpr, NameExpr, IntExpr, StrExpr, BytesExpr, UnicodeExpr, FloatExpr, CallExpr, SuperExpr, MemberExpr, IndexExpr, SliceExpr, OpExpr, - UnaryExpr, FuncExpr, ComparisonExpr, + UnaryExpr, FuncExpr, ComparisonExpr, Expression, StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension, SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, AwaitExpr, ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2, Statement) @@ -123,7 +123,7 @@ def generic_visit(self, node: ast35.AST) -> None: def visit_NoneType(self, n: Any) -> Optional[Node]: return None - def visit_list(self, l: Sequence[ast35.AST]) -> List[Node]: + def visit_list_expression(self, l: Sequence[ast35.AST]) -> List[Expression]: return [self.visit(e) for e in l] def visit_statement_list(self, l: Sequence[ast35.AST]) -> List[Statement]: @@ -241,17 +241,17 @@ def visit_Module(self, mod: ast35.Module) -> Node: # arguments = (arg* args, arg? vararg, arg* kwonlyargs, expr* kw_defaults, # arg? kwarg, expr* defaults) @with_line - def visit_FunctionDef(self, n: ast35.FunctionDef) -> Node: + def visit_FunctionDef(self, n: ast35.FunctionDef) -> Union[FuncDef, Decorator]: return self.do_func_def(n) # AsyncFunctionDef(identifier name, arguments args, # stmt* body, expr* decorator_list, expr? returns, string? type_comment) @with_line - def visit_AsyncFunctionDef(self, n: ast35.AsyncFunctionDef) -> Node: + def visit_AsyncFunctionDef(self, n: ast35.AsyncFunctionDef) -> Union[FuncDef, Decorator]: return self.do_func_def(n, is_coroutine=True) def do_func_def(self, n: Union[ast35.FunctionDef, ast35.AsyncFunctionDef], - is_coroutine: bool = False) -> Node: + is_coroutine: bool = False) -> Union[FuncDef, Decorator]: """Helper shared between visit_FunctionDef and visit_AsyncFunctionDef.""" args = self.transform_args(n.args, n.lineno) @@ -314,11 +314,11 @@ def do_func_def(self, n: Union[ast35.FunctionDef, ast35.AsyncFunctionDef], func_def.is_decorated = True func_def.set_line(n.lineno + len(n.decorator_list)) func_def.body.set_line(func_def.get_line()) - return Decorator(func_def, self.visit_list(n.decorator_list), var) + return Decorator(func_def, self.visit_list_expression(n.decorator_list), var) else: return func_def - def set_type_optional(self, type: Type, initializer: Node) -> None: + def set_type_optional(self, type: Type, initializer: Expression) -> None: if not experiments.STRICT_OPTIONAL: return # Indicate that type should be wrapped in an Optional if arg is initialized to None. @@ -374,7 +374,7 @@ def stringify_name(self, n: ast35.AST) -> str: # stmt* body, # expr* decorator_list) @with_line - def visit_ClassDef(self, n: ast35.ClassDef) -> Node: + def visit_ClassDef(self, n: ast35.ClassDef) -> ClassDef: self.class_nesting += 1 metaclass_arg = find(lambda x: x.arg == 'metaclass', n.keywords) metaclass = None @@ -384,22 +384,22 @@ def visit_ClassDef(self, n: ast35.ClassDef) -> Node: cdef = ClassDef(n.name, self.as_block(n.body, n.lineno), None, - self.visit_list(n.bases), + self.visit_list_expression(n.bases), metaclass=metaclass) - cdef.decorators = self.visit_list(n.decorator_list) + cdef.decorators = self.visit_list_expression(n.decorator_list) self.class_nesting -= 1 return cdef # Return(expr? value) @with_line - def visit_Return(self, n: ast35.Return) -> Node: + def visit_Return(self, n: ast35.Return) -> ReturnStmt: return ReturnStmt(self.visit(n.value)) # Delete(expr* targets) @with_line - def visit_Delete(self, n: ast35.Delete) -> Node: + def visit_Delete(self, n: ast35.Delete) -> DelStmt: if len(n.targets) > 1: - tup = TupleExpr(self.visit_list(n.targets)) + tup = TupleExpr(self.visit_list_expression(n.targets)) tup.set_line(n.lineno) return DelStmt(tup) else: @@ -407,25 +407,25 @@ def visit_Delete(self, n: ast35.Delete) -> Node: # Assign(expr* targets, expr value, string? type_comment) @with_line - def visit_Assign(self, n: ast35.Assign) -> Node: + def visit_Assign(self, n: ast35.Assign) -> AssignmentStmt: typ = None if n.type_comment: typ = parse_type_comment(n.type_comment, n.lineno) - return AssignmentStmt(self.visit_list(n.targets), + return AssignmentStmt(self.visit_list_expression(n.targets), self.visit(n.value), type=typ) # AugAssign(expr target, operator op, expr value) @with_line - def visit_AugAssign(self, n: ast35.AugAssign) -> Node: + def visit_AugAssign(self, n: ast35.AugAssign) -> OperatorAssignmentStmt: return OperatorAssignmentStmt(self.from_operator(n.op), self.visit(n.target), self.visit(n.value)) # For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment) @with_line - def visit_For(self, n: ast35.For) -> Node: + def visit_For(self, n: ast35.For) -> ForStmt: return ForStmt(self.visit(n.target), self.visit(n.iter), self.as_block(n.body, n.lineno), @@ -433,7 +433,7 @@ def visit_For(self, n: ast35.For) -> Node: # AsyncFor(expr target, expr iter, stmt* body, stmt* orelse) @with_line - def visit_AsyncFor(self, n: ast35.AsyncFor) -> Node: + def visit_AsyncFor(self, n: ast35.AsyncFor) -> ForStmt: r = ForStmt(self.visit(n.target), self.visit(n.iter), self.as_block(n.body, n.lineno), @@ -443,28 +443,28 @@ def visit_AsyncFor(self, n: ast35.AsyncFor) -> Node: # While(expr test, stmt* body, stmt* orelse) @with_line - def visit_While(self, n: ast35.While) -> Node: + def visit_While(self, n: ast35.While) -> WhileStmt: return WhileStmt(self.visit(n.test), self.as_block(n.body, n.lineno), self.as_block(n.orelse, n.lineno)) # If(expr test, stmt* body, stmt* orelse) @with_line - def visit_If(self, n: ast35.If) -> Node: + def visit_If(self, n: ast35.If) -> IfStmt: return IfStmt([self.visit(n.test)], [self.as_block(n.body, n.lineno)], self.as_block(n.orelse, n.lineno)) # With(withitem* items, stmt* body, string? type_comment) @with_line - def visit_With(self, n: ast35.With) -> Node: + def visit_With(self, n: ast35.With) -> WithStmt: return WithStmt([self.visit(i.context_expr) for i in n.items], [self.visit(i.optional_vars) for i in n.items], self.as_block(n.body, n.lineno)) # AsyncWith(withitem* items, stmt* body) @with_line - def visit_AsyncWith(self, n: ast35.AsyncWith) -> Node: + def visit_AsyncWith(self, n: ast35.AsyncWith) -> WithStmt: r = WithStmt([self.visit(i.context_expr) for i in n.items], [self.visit(i.optional_vars) for i in n.items], self.as_block(n.body, n.lineno)) @@ -473,12 +473,12 @@ def visit_AsyncWith(self, n: ast35.AsyncWith) -> Node: # Raise(expr? exc, expr? cause) @with_line - def visit_Raise(self, n: ast35.Raise) -> Node: + def visit_Raise(self, n: ast35.Raise) -> RaiseStmt: return RaiseStmt(self.visit(n.exc), self.visit(n.cause)) # Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody) @with_line - def visit_Try(self, n: ast35.Try) -> Node: + def visit_Try(self, n: ast35.Try) -> TryStmt: vs = [NameExpr(h.name) if h.name is not None else None for h in n.handlers] types = [self.visit(h.type) for h in n.handlers] handlers = [self.as_block(h.body, h.lineno) for h in n.handlers] @@ -492,12 +492,12 @@ def visit_Try(self, n: ast35.Try) -> Node: # Assert(expr test, expr? msg) @with_line - def visit_Assert(self, n: ast35.Assert) -> Node: + def visit_Assert(self, n: ast35.Assert) -> AssertStmt: return AssertStmt(self.visit(n.test)) # Import(alias* names) @with_line - def visit_Import(self, n: ast35.Import) -> Node: + def visit_Import(self, n: ast35.Import) -> Import: i = Import([(self.translate_module_id(a.name), a.asname) for a in n.names]) self.imports.append(i) return i @@ -517,39 +517,39 @@ def visit_ImportFrom(self, n: ast35.ImportFrom) -> Node: # Global(identifier* names) @with_line - def visit_Global(self, n: ast35.Global) -> Node: + def visit_Global(self, n: ast35.Global) -> GlobalDecl: return GlobalDecl(n.names) # Nonlocal(identifier* names) @with_line - def visit_Nonlocal(self, n: ast35.Nonlocal) -> Node: + def visit_Nonlocal(self, n: ast35.Nonlocal) -> NonlocalDecl: return NonlocalDecl(n.names) # Expr(expr value) @with_line - def visit_Expr(self, n: ast35.Expr) -> Node: + def visit_Expr(self, n: ast35.Expr) -> ExpressionStmt: value = self.visit(n.value) return ExpressionStmt(value) # Pass @with_line - def visit_Pass(self, n: ast35.Pass) -> Node: + def visit_Pass(self, n: ast35.Pass) -> PassStmt: return PassStmt() # Break @with_line - def visit_Break(self, n: ast35.Break) -> Node: + def visit_Break(self, n: ast35.Break) -> BreakStmt: return BreakStmt() # Continue @with_line - def visit_Continue(self, n: ast35.Continue) -> Node: + def visit_Continue(self, n: ast35.Continue) -> ContinueStmt: return ContinueStmt() # --- expr --- # BoolOp(boolop op, expr* values) @with_line - def visit_BoolOp(self, n: ast35.BoolOp) -> Node: + def visit_BoolOp(self, n: ast35.BoolOp) -> OpExpr: # mypy translates (1 and 2 and 3) as (1 and (2 and 3)) assert len(n.values) >= 2 op = None @@ -561,17 +561,17 @@ def visit_BoolOp(self, n: ast35.BoolOp) -> Node: raise RuntimeError('unknown BoolOp ' + str(type(n))) # potentially inefficient! - def group(vals: List[Node]) -> Node: + def group(vals: List[Expression]) -> OpExpr: if len(vals) == 2: return OpExpr(op, vals[0], vals[1]) else: return OpExpr(op, vals[0], group(vals[1:])) - return group(self.visit_list(n.values)) + return group(self.visit_list_expression(n.values)) # BinOp(expr left, operator op, expr right) @with_line - def visit_BinOp(self, n: ast35.BinOp) -> Node: + def visit_BinOp(self, n: ast35.BinOp) -> OpExpr: op = self.from_operator(n.op) if op is None: @@ -581,7 +581,7 @@ def visit_BinOp(self, n: ast35.BinOp) -> Node: # UnaryOp(unaryop op, expr operand) @with_line - def visit_UnaryOp(self, n: ast35.UnaryOp) -> Node: + def visit_UnaryOp(self, n: ast35.UnaryOp) -> UnaryExpr: op = None if isinstance(n.op, ast35.Invert): op = '~' @@ -599,7 +599,7 @@ def visit_UnaryOp(self, n: ast35.UnaryOp) -> Node: # Lambda(arguments args, expr body) @with_line - def visit_Lambda(self, n: ast35.Lambda) -> Node: + def visit_Lambda(self, n: ast35.Lambda) -> FuncExpr: body = ast35.Return(n.body) body.lineno = n.lineno @@ -608,37 +608,38 @@ def visit_Lambda(self, n: ast35.Lambda) -> Node: # IfExp(expr test, expr body, expr orelse) @with_line - def visit_IfExp(self, n: ast35.IfExp) -> Node: + def visit_IfExp(self, n: ast35.IfExp) -> ConditionalExpr: return ConditionalExpr(self.visit(n.test), self.visit(n.body), self.visit(n.orelse)) # Dict(expr* keys, expr* values) @with_line - def visit_Dict(self, n: ast35.Dict) -> Node: - return DictExpr(list(zip(self.visit_list(n.keys), self.visit_list(n.values)))) + def visit_Dict(self, n: ast35.Dict) -> DictExpr: + return DictExpr(list(zip(self.visit_list_expression(n.keys), + self.visit_list_expression(n.values)))) # Set(expr* elts) @with_line - def visit_Set(self, n: ast35.Set) -> Node: - return SetExpr(self.visit_list(n.elts)) + def visit_Set(self, n: ast35.Set) -> SetExpr: + return SetExpr(self.visit_list_expression(n.elts)) # ListComp(expr elt, comprehension* generators) @with_line - def visit_ListComp(self, n: ast35.ListComp) -> Node: + def visit_ListComp(self, n: ast35.ListComp) -> ListComprehension: return ListComprehension(self.visit_GeneratorExp(cast(ast35.GeneratorExp, n))) # SetComp(expr elt, comprehension* generators) @with_line - def visit_SetComp(self, n: ast35.SetComp) -> Node: + def visit_SetComp(self, n: ast35.SetComp) -> SetComprehension: return SetComprehension(self.visit_GeneratorExp(cast(ast35.GeneratorExp, n))) # DictComp(expr key, expr value, comprehension* generators) @with_line - def visit_DictComp(self, n: ast35.DictComp) -> Node: + def visit_DictComp(self, n: ast35.DictComp) -> DictionaryComprehension: targets = [self.visit(c.target) for c in n.generators] iters = [self.visit(c.iter) for c in n.generators] - ifs_list = [self.visit_list(c.ifs) for c in n.generators] + ifs_list = [self.visit_list_expression(c.ifs) for c in n.generators] return DictionaryComprehension(self.visit(n.key), self.visit(n.value), targets, @@ -650,7 +651,7 @@ def visit_DictComp(self, n: ast35.DictComp) -> Node: def visit_GeneratorExp(self, n: ast35.GeneratorExp) -> GeneratorExpr: targets = [self.visit(c.target) for c in n.generators] iters = [self.visit(c.iter) for c in n.generators] - ifs_list = [self.visit_list(c.ifs) for c in n.generators] + ifs_list = [self.visit_list_expression(c.ifs) for c in n.generators] return GeneratorExpr(self.visit(n.elt), targets, iters, @@ -664,29 +665,29 @@ def visit_Await(self, n: ast35.Await) -> Node: # Yield(expr? value) @with_line - def visit_Yield(self, n: ast35.Yield) -> Node: + def visit_Yield(self, n: ast35.Yield) -> YieldExpr: return YieldExpr(self.visit(n.value)) # YieldFrom(expr value) @with_line - def visit_YieldFrom(self, n: ast35.YieldFrom) -> Node: + def visit_YieldFrom(self, n: ast35.YieldFrom) -> YieldFromExpr: return YieldFromExpr(self.visit(n.value)) # Compare(expr left, cmpop* ops, expr* comparators) @with_line - def visit_Compare(self, n: ast35.Compare) -> Node: + def visit_Compare(self, n: ast35.Compare) -> ComparisonExpr: operators = [self.from_comp_operator(o) for o in n.ops] - operands = self.visit_list([n.left] + n.comparators) + operands = self.visit_list_expression([n.left] + n.comparators) return ComparisonExpr(operators, operands) # Call(expr func, expr* args, keyword* keywords) # keyword = (identifier? arg, expr value) @with_line - def visit_Call(self, n: ast35.Call) -> Node: + def visit_Call(self, n: ast35.Call) -> CallExpr: def is_star2arg(k: ast35.keyword) -> bool: return k.arg is None - arg_types = self.visit_list( + arg_types = self.visit_list_expression( [a.value if isinstance(a, ast35.Starred) else a for a in n.args] + [k.value for k in n.keywords]) arg_kinds = ([ARG_STAR if isinstance(a, ast35.Starred) else ARG_POS for a in n.args] + @@ -735,12 +736,12 @@ def visit_Bytes(self, n: ast35.Bytes) -> Node: return StrExpr(contents) # NameConstant(singleton value) - def visit_NameConstant(self, n: ast35.NameConstant) -> Node: + def visit_NameConstant(self, n: ast35.NameConstant) -> NameExpr: return NameExpr(str(n.value)) # Ellipsis @with_line - def visit_Ellipsis(self, n: ast35.Ellipsis) -> Node: + def visit_Ellipsis(self, n: ast35.Ellipsis) -> EllipsisExpr: return EllipsisExpr() # Attribute(expr value, identifier attr, expr_context ctx) @@ -755,43 +756,43 @@ def visit_Attribute(self, n: ast35.Attribute) -> Node: # Subscript(expr value, slice slice, expr_context ctx) @with_line - def visit_Subscript(self, n: ast35.Subscript) -> Node: + def visit_Subscript(self, n: ast35.Subscript) -> IndexExpr: return IndexExpr(self.visit(n.value), self.visit(n.slice)) # Starred(expr value, expr_context ctx) @with_line - def visit_Starred(self, n: ast35.Starred) -> Node: + def visit_Starred(self, n: ast35.Starred) -> StarExpr: return StarExpr(self.visit(n.value)) # Name(identifier id, expr_context ctx) @with_line - def visit_Name(self, n: ast35.Name) -> Node: + def visit_Name(self, n: ast35.Name) -> NameExpr: return NameExpr(n.id) # List(expr* elts, expr_context ctx) @with_line - def visit_List(self, n: ast35.List) -> Node: + def visit_List(self, n: ast35.List) -> ListExpr: return ListExpr([self.visit(e) for e in n.elts]) # Tuple(expr* elts, expr_context ctx) @with_line - def visit_Tuple(self, n: ast35.Tuple) -> Node: + def visit_Tuple(self, n: ast35.Tuple) -> TupleExpr: return TupleExpr([self.visit(e) for e in n.elts]) # --- slice --- # Slice(expr? lower, expr? upper, expr? step) - def visit_Slice(self, n: ast35.Slice) -> Node: + def visit_Slice(self, n: ast35.Slice) -> SliceExpr: return SliceExpr(self.visit(n.lower), self.visit(n.upper), self.visit(n.step)) # ExtSlice(slice* dims) - def visit_ExtSlice(self, n: ast35.ExtSlice) -> Node: - return TupleExpr(self.visit_list(n.dims)) + def visit_ExtSlice(self, n: ast35.ExtSlice) -> TupleExpr: + return TupleExpr(self.visit_list_expression(n.dims)) # Index(expr value) - def visit_Index(self, n: ast35.Index) -> Node: + def visit_Index(self, n: ast35.Index) -> IndexExpr: return self.visit(n.value) diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 216dfa2d5352..1416eaefa457 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -141,7 +141,7 @@ def generic_visit(self, node: ast27.AST) -> None: def visit_NoneType(self, n: Any) -> Optional[Node]: return None - def visit_list(self, l: Sequence[ast27.AST]) -> List[Node]: + def visit_list_expression(self, l: Sequence[ast27.AST]) -> List[Expression]: return [self.visit(e) for e in l] def visit_statement_list(self, l: Sequence[ast27.AST]) -> List[Statement]: @@ -242,7 +242,7 @@ def translate_module_id(self, id: str) -> str: return 'builtins' return id - def visit_Module(self, mod: ast27.Module) -> Node: + def visit_Module(self, mod: ast27.Module) -> MypyFile: body = self.fix_function_overloads(self.visit_statement_list(mod.body)) return MypyFile(body, @@ -257,7 +257,7 @@ def visit_Module(self, mod: ast27.Module) -> Node: # arguments = (arg* args, arg? vararg, arg* kwonlyargs, expr* kw_defaults, # arg? kwarg, expr* defaults) @with_line - def visit_FunctionDef(self, n: ast27.FunctionDef) -> Node: + def visit_FunctionDef(self, n: ast27.FunctionDef) -> Union[FuncDef, Decorator]: converter = TypeConverter(line=n.lineno) args = self.transform_args(n.args, n.lineno) @@ -317,7 +317,7 @@ def visit_FunctionDef(self, n: ast27.FunctionDef) -> Node: func_def.is_decorated = True func_def.set_line(n.lineno + len(n.decorator_list)) func_def.body.set_line(func_def.get_line()) - return Decorator(func_def, self.visit_list(n.decorator_list), var) + return Decorator(func_def, self.visit_list_expression(n.decorator_list), var) else: return func_def @@ -356,7 +356,7 @@ def get_type(i: int) -> Optional[Type]: return None args = [(convert_arg(arg), get_type(i)) for i, arg in enumerate(n.args)] - defaults = self.visit_list(n.defaults) + defaults = self.visit_list_expression(n.defaults) new_args = [] # type: List[Argument] num_no_defaults = len(args) - len(defaults) @@ -393,28 +393,28 @@ def stringify_name(self, n: ast27.AST) -> str: # stmt* body, # expr* decorator_list) @with_line - def visit_ClassDef(self, n: ast27.ClassDef) -> Node: + def visit_ClassDef(self, n: ast27.ClassDef) -> ClassDef: self.class_nesting += 1 cdef = ClassDef(n.name, self.as_block(n.body, n.lineno), None, - self.visit_list(n.bases), + self.visit_list_expression(n.bases), metaclass=None) - cdef.decorators = self.visit_list(n.decorator_list) + cdef.decorators = self.visit_list_expression(n.decorator_list) self.class_nesting -= 1 return cdef # Return(expr? value) @with_line - def visit_Return(self, n: ast27.Return) -> Node: + def visit_Return(self, n: ast27.Return) -> ReturnStmt: return ReturnStmt(self.visit(n.value)) # Delete(expr* targets) @with_line def visit_Delete(self, n: ast27.Delete) -> Node: if len(n.targets) > 1: - tup = TupleExpr(self.visit_list(n.targets)) + tup = TupleExpr(self.visit_list_expression(n.targets)) tup.set_line(n.lineno) return DelStmt(tup) else: @@ -422,25 +422,25 @@ def visit_Delete(self, n: ast27.Delete) -> Node: # Assign(expr* targets, expr value, string? type_comment) @with_line - def visit_Assign(self, n: ast27.Assign) -> Node: + def visit_Assign(self, n: ast27.Assign) -> AssignmentStmt: typ = None if n.type_comment: typ = parse_type_comment(n.type_comment, n.lineno) - return AssignmentStmt(self.visit_list(n.targets), + return AssignmentStmt(self.visit_list_expression(n.targets), self.visit(n.value), type=typ) # AugAssign(expr target, operator op, expr value) @with_line - def visit_AugAssign(self, n: ast27.AugAssign) -> Node: + def visit_AugAssign(self, n: ast27.AugAssign) -> OperatorAssignmentStmt: return OperatorAssignmentStmt(self.from_operator(n.op), self.visit(n.target), self.visit(n.value)) # For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment) @with_line - def visit_For(self, n: ast27.For) -> Node: + def visit_For(self, n: ast27.For) -> ForStmt: return ForStmt(self.visit(n.target), self.visit(n.iter), self.as_block(n.body, n.lineno), @@ -448,27 +448,27 @@ def visit_For(self, n: ast27.For) -> Node: # While(expr test, stmt* body, stmt* orelse) @with_line - def visit_While(self, n: ast27.While) -> Node: + def visit_While(self, n: ast27.While) -> WhileStmt: return WhileStmt(self.visit(n.test), self.as_block(n.body, n.lineno), self.as_block(n.orelse, n.lineno)) # If(expr test, stmt* body, stmt* orelse) @with_line - def visit_If(self, n: ast27.If) -> Node: + def visit_If(self, n: ast27.If) -> IfStmt: return IfStmt([self.visit(n.test)], [self.as_block(n.body, n.lineno)], self.as_block(n.orelse, n.lineno)) # With(withitem* items, stmt* body, string? type_comment) @with_line - def visit_With(self, n: ast27.With) -> Node: + def visit_With(self, n: ast27.With) -> WithStmt: return WithStmt([self.visit(n.context_expr)], [self.visit(n.optional_vars)], self.as_block(n.body, n.lineno)) @with_line - def visit_Raise(self, n: ast27.Raise) -> Node: + def visit_Raise(self, n: ast27.Raise) -> RaiseStmt: e = None if n.type is not None: e = n.type @@ -484,11 +484,11 @@ def visit_Raise(self, n: ast27.Raise) -> Node: # TryExcept(stmt* body, excepthandler* handlers, stmt* orelse) @with_line - def visit_TryExcept(self, n: ast27.TryExcept) -> Node: + def visit_TryExcept(self, n: ast27.TryExcept) -> TryStmt: return self.try_handler(n.body, n.handlers, n.orelse, [], n.lineno) @with_line - def visit_TryFinally(self, n: ast27.TryFinally) -> Node: + def visit_TryFinally(self, n: ast27.TryFinally) -> TryStmt: if len(n.body) == 1 and isinstance(n.body[0], ast27.TryExcept): return self.try_handler([n.body[0]], [], [], n.finalbody, n.lineno) else: @@ -499,7 +499,7 @@ def try_handler(self, handlers: List[ast27.ExceptHandler], orelse: List[ast27.stmt], finalbody: List[ast27.stmt], - lineno: int) -> Node: + lineno: int) -> TryStmt: def produce_name(item: ast27.ExceptHandler) -> Optional[NameExpr]: if item.name is None: return None @@ -520,7 +520,7 @@ def produce_name(item: ast27.ExceptHandler) -> Optional[NameExpr]: self.as_block(finalbody, lineno)) @with_line - def visit_Print(self, n: ast27.Print) -> Node: + def visit_Print(self, n: ast27.Print) -> CallExpr: keywords = [] if n.dest is not None: keywords.append(ast27.keyword("file", n.dest)) @@ -537,7 +537,7 @@ def visit_Print(self, n: ast27.Print) -> Node: return self.visit(ast27.Expr(call, lineno=n.lineno, col_offset=-1)) @with_line - def visit_Exec(self, n: ast27.Exec) -> Node: + def visit_Exec(self, n: ast27.Exec) -> CallExpr: new_globals = n.globals new_locals = n.locals @@ -556,7 +556,7 @@ def visit_Exec(self, n: ast27.Exec) -> Node: lineno=n.lineno, col_offset=-1)) @with_line - def visit_Repr(self, n: ast27.Repr) -> Node: + def visit_Repr(self, n: ast27.Repr) -> CallExpr: # TODO: Comment in visit_Print also applies here return self.visit(ast27.Call( ast27.Name("repr", ast27.Load(), lineno=n.lineno, col_offset=-1), @@ -566,7 +566,7 @@ def visit_Repr(self, n: ast27.Repr) -> Node: # Assert(expr test, expr? msg) @with_line - def visit_Assert(self, n: ast27.Assert) -> Node: + def visit_Assert(self, n: ast27.Assert) -> AssertStmt: return AssertStmt(self.visit(n.test)) # Import(alias* names) @@ -578,7 +578,7 @@ def visit_Import(self, n: ast27.Import) -> Node: # ImportFrom(identifier? module, alias* names, int? level) @with_line - def visit_ImportFrom(self, n: ast27.ImportFrom) -> Node: + def visit_ImportFrom(self, n: ast27.ImportFrom) -> ImportBase: i = None # type: ImportBase if len(n.names) == 1 and n.names[0].name == '*': i = ImportAll(n.module, n.level) @@ -591,34 +591,34 @@ def visit_ImportFrom(self, n: ast27.ImportFrom) -> Node: # Global(identifier* names) @with_line - def visit_Global(self, n: ast27.Global) -> Node: + def visit_Global(self, n: ast27.Global) -> GlobalDecl: return GlobalDecl(n.names) # Expr(expr value) @with_line - def visit_Expr(self, n: ast27.Expr) -> Node: + def visit_Expr(self, n: ast27.Expr) -> ExpressionStmt: value = self.visit(n.value) return ExpressionStmt(value) # Pass @with_line - def visit_Pass(self, n: ast27.Pass) -> Node: + def visit_Pass(self, n: ast27.Pass) -> PassStmt: return PassStmt() # Break @with_line - def visit_Break(self, n: ast27.Break) -> Node: + def visit_Break(self, n: ast27.Break) -> BreakStmt: return BreakStmt() # Continue @with_line - def visit_Continue(self, n: ast27.Continue) -> Node: + def visit_Continue(self, n: ast27.Continue) -> ContinueStmt: return ContinueStmt() # --- expr --- # BoolOp(boolop op, expr* values) @with_line - def visit_BoolOp(self, n: ast27.BoolOp) -> Node: + def visit_BoolOp(self, n: ast27.BoolOp) -> OpExpr: # mypy translates (1 and 2 and 3) as (1 and (2 and 3)) assert len(n.values) >= 2 op = None @@ -630,17 +630,17 @@ def visit_BoolOp(self, n: ast27.BoolOp) -> Node: raise RuntimeError('unknown BoolOp ' + str(type(n))) # potentially inefficient! - def group(vals: List[Node]) -> Node: + def group(vals: List[Expression]) -> OpExpr: if len(vals) == 2: return OpExpr(op, vals[0], vals[1]) else: return OpExpr(op, vals[0], group(vals[1:])) - return group(self.visit_list(n.values)) + return group(self.visit_list_expression(n.values)) # BinOp(expr left, operator op, expr right) @with_line - def visit_BinOp(self, n: ast27.BinOp) -> Node: + def visit_BinOp(self, n: ast27.BinOp) -> OpExpr: op = self.from_operator(n.op) if op is None: @@ -650,7 +650,7 @@ def visit_BinOp(self, n: ast27.BinOp) -> Node: # UnaryOp(unaryop op, expr operand) @with_line - def visit_UnaryOp(self, n: ast27.UnaryOp) -> Node: + def visit_UnaryOp(self, n: ast27.UnaryOp) -> UnaryExpr: op = None if isinstance(n.op, ast27.Invert): op = '~' @@ -668,7 +668,7 @@ def visit_UnaryOp(self, n: ast27.UnaryOp) -> Node: # Lambda(arguments args, expr body) @with_line - def visit_Lambda(self, n: ast27.Lambda) -> Node: + def visit_Lambda(self, n: ast27.Lambda) -> FuncExpr: body = ast27.Return(n.body) body.lineno = n.lineno @@ -677,37 +677,37 @@ def visit_Lambda(self, n: ast27.Lambda) -> Node: # IfExp(expr test, expr body, expr orelse) @with_line - def visit_IfExp(self, n: ast27.IfExp) -> Node: + def visit_IfExp(self, n: ast27.IfExp) -> ConditionalExpr: return ConditionalExpr(self.visit(n.test), self.visit(n.body), self.visit(n.orelse)) # Dict(expr* keys, expr* values) @with_line - def visit_Dict(self, n: ast27.Dict) -> Node: - return DictExpr(list(zip(self.visit_list(n.keys), self.visit_list(n.values)))) + def visit_Dict(self, n: ast27.Dict) -> DictExpr: + return DictExpr(list(zip(self.visit_list_expression(n.keys), self.visit_list_expression(n.values)))) # Set(expr* elts) @with_line - def visit_Set(self, n: ast27.Set) -> Node: - return SetExpr(self.visit_list(n.elts)) + def visit_Set(self, n: ast27.Set) -> SetExpr: + return SetExpr(self.visit_list_expression(n.elts)) # ListComp(expr elt, comprehension* generators) @with_line - def visit_ListComp(self, n: ast27.ListComp) -> Node: + def visit_ListComp(self, n: ast27.ListComp) -> ListComprehension: return ListComprehension(self.visit_GeneratorExp(cast(ast27.GeneratorExp, n))) # SetComp(expr elt, comprehension* generators) @with_line - def visit_SetComp(self, n: ast27.SetComp) -> Node: + def visit_SetComp(self, n: ast27.SetComp) -> SetComprehension: return SetComprehension(self.visit_GeneratorExp(cast(ast27.GeneratorExp, n))) # DictComp(expr key, expr value, comprehension* generators) @with_line - def visit_DictComp(self, n: ast27.DictComp) -> Node: + def visit_DictComp(self, n: ast27.DictComp) -> DictionaryComprehension: targets = [self.visit(c.target) for c in n.generators] iters = [self.visit(c.iter) for c in n.generators] - ifs_list = [self.visit_list(c.ifs) for c in n.generators] + ifs_list = [self.visit_list_expression(c.ifs) for c in n.generators] return DictionaryComprehension(self.visit(n.key), self.visit(n.value), targets, @@ -719,7 +719,7 @@ def visit_DictComp(self, n: ast27.DictComp) -> Node: def visit_GeneratorExp(self, n: ast27.GeneratorExp) -> GeneratorExpr: targets = [self.visit(c.target) for c in n.generators] iters = [self.visit(c.iter) for c in n.generators] - ifs_list = [self.visit_list(c.ifs) for c in n.generators] + ifs_list = [self.visit_list_expression(c.ifs) for c in n.generators] return GeneratorExpr(self.visit(n.elt), targets, iters, @@ -727,20 +727,20 @@ def visit_GeneratorExp(self, n: ast27.GeneratorExp) -> GeneratorExpr: # Yield(expr? value) @with_line - def visit_Yield(self, n: ast27.Yield) -> Node: + def visit_Yield(self, n: ast27.Yield) -> YieldExpr: return YieldExpr(self.visit(n.value)) # Compare(expr left, cmpop* ops, expr* comparators) @with_line - def visit_Compare(self, n: ast27.Compare) -> Node: + def visit_Compare(self, n: ast27.Compare) -> ComparisonExpr: operators = [self.from_comp_operator(o) for o in n.ops] - operands = self.visit_list([n.left] + n.comparators) + operands = self.visit_list_expression([n.left] + n.comparators) return ComparisonExpr(operators, operands) # Call(expr func, expr* args, keyword* keywords) # keyword = (identifier? arg, expr value) @with_line - def visit_Call(self, n: ast27.Call) -> Node: + def visit_Call(self, n: ast27.Call) -> CallExpr: arg_types = [] # type: List[ast27.expr] arg_kinds = [] # type: List[int] signature = [] # type: List[Optional[str]] @@ -764,13 +764,13 @@ def visit_Call(self, n: ast27.Call) -> Node: signature.append(None) return CallExpr(self.visit(n.func), - self.visit_list(arg_types), + self.visit_list_expression(arg_types), arg_kinds, cast("List[str]", signature)) # Num(object n) -- a number as a PyObject. @with_line - def visit_Num(self, new: ast27.Num) -> Node: + def visit_Num(self, new: ast27.Num) -> Expression: value = new.n is_inverse = False if new.n < 0: @@ -818,7 +818,7 @@ def visit_Str(self, s: ast27.Str) -> Node: return UnicodeExpr(s.s) # Ellipsis - def visit_Ellipsis(self, n: ast27.Ellipsis) -> Node: + def visit_Ellipsis(self, n: ast27.Ellipsis) -> EllipsisExpr: return EllipsisExpr() # Attribute(expr value, identifier attr, expr_context ctx) @@ -833,35 +833,35 @@ def visit_Attribute(self, n: ast27.Attribute) -> Node: # Subscript(expr value, slice slice, expr_context ctx) @with_line - def visit_Subscript(self, n: ast27.Subscript) -> Node: + def visit_Subscript(self, n: ast27.Subscript) -> IndexExpr: return IndexExpr(self.visit(n.value), self.visit(n.slice)) # Name(identifier id, expr_context ctx) @with_line - def visit_Name(self, n: ast27.Name) -> Node: + def visit_Name(self, n: ast27.Name) -> NameExpr: return NameExpr(n.id) # List(expr* elts, expr_context ctx) @with_line - def visit_List(self, n: ast27.List) -> Node: + def visit_List(self, n: ast27.List) -> ListExpr: return ListExpr([self.visit(e) for e in n.elts]) # Tuple(expr* elts, expr_context ctx) @with_line - def visit_Tuple(self, n: ast27.Tuple) -> Node: + def visit_Tuple(self, n: ast27.Tuple) -> TupleExpr: return TupleExpr([self.visit(e) for e in n.elts]) # --- slice --- # Slice(expr? lower, expr? upper, expr? step) - def visit_Slice(self, n: ast27.Slice) -> Node: + def visit_Slice(self, n: ast27.Slice) -> SliceExpr: return SliceExpr(self.visit(n.lower), self.visit(n.upper), self.visit(n.step)) # ExtSlice(slice* dims) - def visit_ExtSlice(self, n: ast27.ExtSlice) -> Node: - return TupleExpr(self.visit_list(n.dims)) + def visit_ExtSlice(self, n: ast27.ExtSlice) -> TupleExpr: + return TupleExpr(self.visit_list_expression(n.dims)) # Index(expr value) def visit_Index(self, n: ast27.Index) -> Node: diff --git a/mypy/nodes.py b/mypy/nodes.py index a310ddadd603..f0d7de75970a 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -119,7 +119,8 @@ def accept(self, visitor: NodeVisitor[T]) -> T: # This is a placeholder for a future refactoring; see #1783. # For now it serves as (unchecked) documentation of what various # fields of Node subtypes are expected to contain. -Expression = Node +class Expression(Node): + pass class Statement(Node): @@ -1747,9 +1748,9 @@ def accept(self, visitor: NodeVisitor[T]) -> T: class AwaitExpr(Node): """Await expression (await ...).""" - expr = None # type: Node + expr = None # type: Expression - def __init__(self, expr: Node) -> None: + def __init__(self, expr: Expression) -> None: self.expr = expr def accept(self, visitor: NodeVisitor[T]) -> T: diff --git a/mypy/parse.py b/mypy/parse.py index c6638e6cb2a7..d680500d4d88 100644 --- a/mypy/parse.py +++ b/mypy/parse.py @@ -15,11 +15,11 @@ EllipsisToken ) from mypy.nodes import ( - MypyFile, Import, Node, ImportAll, ImportFrom, FuncDef, OverloadedFuncDef, + MypyFile, Import, ImportAll, ImportFrom, FuncDef, OverloadedFuncDef, ClassDef, Decorator, Block, Var, OperatorAssignmentStmt, ExpressionStmt, AssignmentStmt, ReturnStmt, RaiseStmt, AssertStmt, DelStmt, BreakStmt, ContinueStmt, PassStmt, GlobalDecl, - WhileStmt, ForStmt, IfStmt, TryStmt, WithStmt, + WhileStmt, ForStmt, IfStmt, TryStmt, WithStmt, Expression, TupleExpr, GeneratorExpr, ListComprehension, ListExpr, ConditionalExpr, DictExpr, SetExpr, NameExpr, IntExpr, StrExpr, BytesExpr, UnicodeExpr, FloatExpr, CallExpr, SuperExpr, MemberExpr, IndexExpr, SliceExpr, OpExpr, @@ -339,7 +339,7 @@ def parse_class_def(self) -> ClassDef: metaclass = None try: - base_types = [] # type: List[Node] + base_types = [] # type: List[Expression] try: name_tok = self.expect_type(Name) name = name_tok.string @@ -390,7 +390,7 @@ def parse_class_keywords(self) -> Optional[str]: break return metaclass - def parse_super_type(self) -> Node: + def parse_super_type(self) -> Expression: return self.parse_expression(precedence[',']) def parse_decorated_function_or_class(self) -> Statement: @@ -417,7 +417,7 @@ def parse_decorated_function_or_class(self) -> Statement: cls.decorators = decorators return cls - def is_no_type_check_decorator(self, expr: Node) -> bool: + def is_no_type_check_decorator(self, expr: Expression) -> bool: if isinstance(expr, NameExpr): return expr.name == 'no_type_check' elif isinstance(expr, MemberExpr): @@ -749,7 +749,7 @@ def parse_tuple_arg(self, index: int) -> Tuple[Argument, AssignmentStmt, List[st arg_names = self.find_tuple_arg_argument_names(paren_arg) return Argument(var, None, initializer, kind), decompose, arg_names - def verify_tuple_arg(self, paren_arg: Node) -> None: + def verify_tuple_arg(self, paren_arg: Expression) -> None: if isinstance(paren_arg, TupleExpr): if not paren_arg.items: self.fail('Empty tuple not valid as an argument', paren_arg.line) @@ -758,7 +758,7 @@ def verify_tuple_arg(self, paren_arg: Node) -> None: elif not isinstance(paren_arg, NameExpr): self.fail('Invalid item in tuple argument', paren_arg.line) - def find_tuple_arg_argument_names(self, node: Node) -> List[str]: + def find_tuple_arg_argument_names(self, node: Expression) -> List[str]: result = [] # type: List[str] if isinstance(node, TupleExpr): for item in node.items: @@ -779,7 +779,7 @@ def parse_normal_arg(self, require_named: bool, else: type = self.parse_arg_type(allow_signature) - initializer = None # type: Node + initializer = None # type: Expression if self.current_str() == '=': self.expect('=') initializer = self.parse_expression(precedence[',']) @@ -795,7 +795,7 @@ def parse_normal_arg(self, require_named: bool, return Argument(variable, type, initializer, kind), require_named - def set_type_optional(self, type: Type, initializer: Node) -> None: + def set_type_optional(self, type: Type, initializer: Expression) -> None: if not experiments.STRICT_OPTIONAL: return # Indicate that type should be wrapped in an Optional if arg is initialized to None. @@ -803,7 +803,7 @@ def set_type_optional(self, type: Type, initializer: Node) -> None: if isinstance(type, UnboundType): type.optional = optional - def parse_parameter_annotation(self) -> Node: + def parse_parameter_annotation(self) -> Expression: if self.current_str() == ':': self.skip() return self.parse_expression(precedence[',']) @@ -885,7 +885,7 @@ def parse_block(self, allow_type: bool = False) -> Tuple[Block, Type]: node.set_line(colon) return node, type - def try_combine_overloads(self, s: Node, stmt: List[Statement]) -> bool: + def try_combine_overloads(self, s: Statement, stmt: List[Statement]) -> bool: if isinstance(s, Decorator) and stmt: fdef = s n = fdef.func.name() @@ -1127,7 +1127,7 @@ def parse_for_stmt(self) -> ForStmt: node = ForStmt(index, expr, body, else_body) return node - def parse_for_index_variables(self) -> Node: + def parse_for_index_variables(self) -> Expression: # Parse index variables of a 'for' statement. index_items = [] force_tuple = False @@ -1188,14 +1188,16 @@ def parse_try_stmt(self) -> Statement: body, _ = self.parse_block() is_error = False vars = [] # type: List[NameExpr] - types = [] # type: List[Node] + types = [] # type: List[Expression] handlers = [] # type: List[Block] while self.current_str() == 'except': self.expect('except') if not isinstance(self.current(), Colon): try: t = self.current() - types.append(self.parse_expression(precedence[',']).set_line(t)) + exp = self.parse_expression(precedence[',']) + exp.set_line(t) + types.append(exp) if self.current_str() == 'as': self.expect('as') vars.append(self.parse_name_expr()) @@ -1286,9 +1288,9 @@ def parse_exec_stmt(self) -> ExecStmt: # Parsing expressions - def parse_expression(self, prec: int = 0, star_expr_allowed: bool = False) -> Node: + def parse_expression(self, prec: int = 0, star_expr_allowed: bool = False) -> Expression: """Parse a subexpression within a specific precedence context.""" - expr = None # type: Node + expr = None # type: Expression current = self.current() # Remember token for setting the line number. # Parse a "value" expression or unary operator expression and store @@ -1408,18 +1410,18 @@ def parse_expression(self, prec: int = 0, star_expr_allowed: bool = False) -> No return expr - def parse_parentheses(self) -> Node: + def parse_parentheses(self) -> Expression: self.skip() if self.current_str() == ')': # Empty tuple (). - expr = self.parse_empty_tuple_expr() # type: Node + expr = self.parse_empty_tuple_expr() # type: Expression else: # Parenthesised expression. expr = self.parse_expression(0, star_expr_allowed=True) self.expect(')') return expr - def parse_star_expr(self) -> Node: + def parse_star_expr(self) -> Expression: star = self.expect('*') expr = self.parse_expression(precedence['*u']) expr = StarExpr(expr) @@ -1432,7 +1434,7 @@ def parse_empty_tuple_expr(self) -> TupleExpr: node = TupleExpr([]) return node - def parse_list_expr(self) -> Node: + def parse_list_expr(self) -> Expression: """Parse list literal or list comprehension.""" items = [] self.expect('[') @@ -1450,7 +1452,7 @@ def parse_list_expr(self) -> Node: expr = ListExpr(items) return expr - def parse_generator_expr(self, left_expr: Node) -> GeneratorExpr: + def parse_generator_expr(self, left_expr: Expression) -> GeneratorExpr: tok = self.current() indices, sequences, condlists = self.parse_comp_for() @@ -1458,10 +1460,10 @@ def parse_generator_expr(self, left_expr: Node) -> GeneratorExpr: gen.set_line(tok) return gen - def parse_comp_for(self) -> Tuple[List[Node], List[Node], List[List[Node]]]: + def parse_comp_for(self) -> Tuple[List[Expression], List[Expression], List[List[Expression]]]: indices = [] sequences = [] - condlists = [] # type: List[List[Node]] + condlists = [] # type: List[List[Expression]] while self.current_str() == 'for': conds = [] self.expect('for') @@ -1480,24 +1482,26 @@ def parse_comp_for(self) -> Tuple[List[Node], List[Node], List[List[Node]]]: return indices, sequences, condlists - def parse_expression_list(self) -> Node: + def parse_expression_list(self) -> Expression: prec = precedence[''] expr = self.parse_expression(prec) if self.current_str() != ',': return expr else: t = self.current() - return self.parse_tuple_expr(expr, prec).set_line(t) + exp = self.parse_tuple_expr(expr, prec) + exp.set_line(t) + return exp - def parse_conditional_expr(self, left_expr: Node) -> ConditionalExpr: + def parse_conditional_expr(self, left_expr: Expression) -> ConditionalExpr: self.expect('if') cond = self.parse_expression(precedence['']) self.expect('else') else_expr = self.parse_expression(precedence['']) return ConditionalExpr(cond, left_expr, else_expr) - def parse_dict_or_set_expr(self) -> Node: - items = [] # type: List[Tuple[Node, Node]] + def parse_dict_or_set_expr(self) -> Expression: + items = [] # type: List[Tuple[Expression, Expression]] self.expect('{') while self.current_str() != '}' and not self.eol(): key = self.parse_expression(precedence['']) @@ -1519,7 +1523,7 @@ def parse_dict_or_set_expr(self) -> Node: node = DictExpr(items) return node - def parse_set_expr(self, first: Node) -> SetExpr: + def parse_set_expr(self, first: Expression) -> SetExpr: items = [first] while self.current_str() != '}' and not self.eol(): self.expect(',') @@ -1530,13 +1534,13 @@ def parse_set_expr(self, first: Node) -> SetExpr: expr = SetExpr(items) return expr - def parse_set_comprehension(self, expr: Node) -> SetComprehension: + def parse_set_comprehension(self, expr: Expression) -> SetComprehension: gen = self.parse_generator_expr(expr) self.expect('}') set_comp = SetComprehension(gen) return set_comp - def parse_dict_comprehension(self, key: Node, value: Node, + def parse_dict_comprehension(self, key: Expression, value: Expression, colon: Token) -> DictionaryComprehension: indices, sequences, condlists = self.parse_comp_for() dic = DictionaryComprehension(key, value, indices, sequences, condlists) @@ -1544,7 +1548,7 @@ def parse_dict_comprehension(self, key: Node, value: Node, self.expect('}') return dic - def parse_tuple_expr(self, expr: Node, + def parse_tuple_expr(self, expr: Expression, prec: int = precedence[',']) -> TupleExpr: items = [expr] while True: @@ -1581,7 +1585,7 @@ def parse_int_expr(self) -> IntExpr: node = IntExpr(value) return node - def parse_str_expr(self) -> Node: + def parse_str_expr(self) -> Expression: # XXX \uxxxx literals token = self.expect_type(StrLit) value = cast(StrLit, token).parsed() @@ -1594,12 +1598,12 @@ def parse_str_expr(self) -> Node: value += token.parsed() is_unicode = True if is_unicode or (self.pyversion[0] == 2 and 'unicode_literals' in self.future_options): - node = UnicodeExpr(value) # type: Node + node = UnicodeExpr(value) # type: Expression else: node = StrExpr(value) return node - def parse_bytes_literal(self) -> Node: + def parse_bytes_literal(self) -> Expression: # XXX \uxxxx literals tok = [self.expect_type(BytesLit)] value = (cast(BytesLit, tok[0])).parsed() @@ -1607,12 +1611,12 @@ def parse_bytes_literal(self) -> Node: t = cast(BytesLit, self.skip()) value += t.parsed() if self.pyversion[0] >= 3: - node = BytesExpr(value) # type: Node + node = BytesExpr(value) # type: Expression else: node = StrExpr(value) return node - def parse_unicode_literal(self) -> Node: + def parse_unicode_literal(self) -> Expression: # XXX \uxxxx literals token = self.expect_type(UnicodeLit) value = cast(UnicodeLit, token).parsed() @@ -1621,7 +1625,7 @@ def parse_unicode_literal(self) -> Node: value += token.parsed() if self.pyversion[0] >= 3: # Python 3.3 supports u'...' as an alias of '...'. - node = StrExpr(value) # type: Node + node = StrExpr(value) # type: Expression else: node = UnicodeExpr(value) return node @@ -1643,7 +1647,7 @@ def parse_call_expr(self, callee: Any) -> CallExpr: node = CallExpr(callee, args, kinds, names) return node - def parse_arg_expr(self) -> Tuple[List[Node], List[int], List[str]]: + def parse_arg_expr(self) -> Tuple[List[Expression], List[int], List[str]]: """Parse arguments in a call expression (within '(' and ')'). Return a tuple with these items: @@ -1651,7 +1655,7 @@ def parse_arg_expr(self) -> Tuple[List[Node], List[int], List[str]]: argument kinds argument names (for named arguments; None for ordinary args) """ - args = [] # type: List[Node] + args = [] # type: List[Expression] kinds = [] # type: List[int] names = [] # type: List[str] var_arg = False @@ -1689,13 +1693,13 @@ def parse_arg_expr(self) -> Tuple[List[Node], List[int], List[str]]: self.expect(',') return args, kinds, names - def parse_member_expr(self, expr: Any) -> Node: + def parse_member_expr(self, expr: Any) -> Expression: self.expect('.') name = self.expect_type(Name) if (isinstance(expr, CallExpr) and isinstance(expr.callee, NameExpr) and expr.callee.name == 'super'): # super() expression - node = SuperExpr(name.string) # type: Node + node = SuperExpr(name.string) # type: Expression else: node = MemberExpr(expr, name.string) return node @@ -1717,7 +1721,7 @@ def parse_index_expr(self, base: Any) -> IndexExpr: node = IndexExpr(base, index) return node - def parse_slice_item(self) -> Node: + def parse_slice_item(self) -> Expression: if self.current_str() != ':': if self.current_str() == '...': # Ellipsis is valid here even in Python 2 (but not elsewhere). @@ -1742,10 +1746,11 @@ def parse_slice_item(self) -> Node: self.expect(':') if self.current_str() not in (']', ','): stride = self.parse_expression(precedence[',']) - item = SliceExpr(index, end_index, stride).set_line(colon.line) + item = SliceExpr(index, end_index, stride) + item.set_line(colon.line) return item - def parse_bin_op_expr(self, left: Node, prec: int) -> OpExpr: + def parse_bin_op_expr(self, left: Expression, prec: int) -> OpExpr: op = self.expect_type(Op) op_str = op.string if op_str == '~': @@ -1755,7 +1760,7 @@ def parse_bin_op_expr(self, left: Node, prec: int) -> OpExpr: node = OpExpr(op_str, left, right) return node - def parse_comparison_expr(self, left: Node, prec: int) -> ComparisonExpr: + def parse_comparison_expr(self, left: Expression, prec: int) -> ComparisonExpr: operators_str = [] operands = [left] diff --git a/mypy/semanal.py b/mypy/semanal.py index eb81f1878d08..02fd0e082b74 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -44,13 +44,13 @@ """ from typing import ( - List, Dict, Set, Tuple, cast, Any, TypeVar, Union, Optional, Callable + List, Dict, Set, Tuple, cast, Any, TypeVar, Union, Optional, Callable, Iterable ) from mypy.nodes import ( MypyFile, TypeInfo, Node, AssignmentStmt, FuncDef, OverloadedFuncDef, ClassDef, Var, GDEF, MODULE_REF, FuncItem, Import, - ImportFrom, ImportAll, Block, LDEF, NameExpr, MemberExpr, + ImportFrom, ImportAll, Block, LDEF, NameExpr, MemberExpr, Expression, IndexExpr, TupleExpr, ListExpr, ExpressionStmt, ReturnStmt, RaiseStmt, AssertStmt, OperatorAssignmentStmt, WhileStmt, ForStmt, BreakStmt, ContinueStmt, IfStmt, TryStmt, WithStmt, DelStmt, @@ -1361,7 +1361,8 @@ def process_newtype_declaration(self, s: AssignmentStmt) -> None: # TODO: why does NewType work in local scopes despite always being of kind GDEF? node.kind = GDEF node.node = newtype_class_info - call.analyzed = NewTypeExpr(newtype_class_info).set_line(call.line) + call.analyzed = NewTypeExpr(newtype_class_info) + call.analyzed.set_line(call.line) def analyze_newtype_declaration(self, s: AssignmentStmt) -> Tuple[Optional[str], Optional[CallExpr]]: @@ -1384,7 +1385,8 @@ def analyze_newtype_declaration(self, # overwritten later with a fully complete NewTypeExpr if there are no other # errors with the NewType() call. call = s.rvalue - call.analyzed = NewTypeExpr(None).set_line(call.line) + call.analyzed = NewTypeExpr(None) + call.analyzed.set_line(call.line) return name, call @@ -1505,7 +1507,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, @@ -1614,7 +1616,8 @@ def check_namedtuple(self, node: Node, var_name: str = None) -> TypeInfo: info = self.build_namedtuple_typeinfo(name, items, types) # Store it as a global just in case it would remain anonymous. self.globals[name] = SymbolTableNode(GDEF, info, self.cur_mod_id) - call.analyzed = NamedTupleExpr(info).set_line(call.line) + call.analyzed = NamedTupleExpr(info) + call.analyzed.set_line(call.line) return info def parse_namedtuple_args(self, call: CallExpr, @@ -1661,7 +1664,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] @@ -1766,7 +1769,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: Iterable[Node]) -> List[Type]: result = [] # type: List[Type] for node in items: try: diff --git a/mypy/treetransform.py b/mypy/treetransform.py index 02a031053870..19429b6943fb 100644 --- a/mypy/treetransform.py +++ b/mypy/treetransform.py @@ -3,10 +3,10 @@ Subclass TransformVisitor to perform non-trivial transformations. """ -from typing import List, Dict, cast +from typing import List, Dict, cast, TypeVar, Iterable from mypy.nodes import ( - MypyFile, Import, Node, ImportAll, ImportFrom, FuncItem, FuncDef, + MypyFile, Import, Node, Expression, ImportAll, ImportFrom, FuncItem, FuncDef, OverloadedFuncDef, ClassDef, Decorator, Block, Var, OperatorAssignmentStmt, ExpressionStmt, AssignmentStmt, ReturnStmt, RaiseStmt, AssertStmt, DelStmt, BreakStmt, ContinueStmt, @@ -26,6 +26,9 @@ from mypy.visitor import NodeVisitor +T = TypeVar('T', Expression, Statement) + + class TransformVisitor(NodeVisitor[Node]): """Transform a semantically analyzed AST (or subtree) to an identical copy. @@ -55,7 +58,7 @@ def __init__(self) -> None: # transformed node). self.func_placeholder_map = {} # type: Dict[FuncDef, FuncDef] - def visit_mypy_file(self, node: MypyFile) -> Node: + def visit_mypy_file(self, node: MypyFile) -> Statement: # NOTE: The 'names' and 'imports' instance variables will be empty! new = MypyFile(self.statements(node.defs), [], node.is_bom, ignored_lines=set(node.ignored_lines)) @@ -65,13 +68,13 @@ def visit_mypy_file(self, node: MypyFile) -> Node: new.names = SymbolTable() return new - def visit_import(self, node: Import) -> Node: + def visit_import(self, node: Import) -> Statement: return Import(node.ids[:]) - def visit_import_from(self, node: ImportFrom) -> Node: + def visit_import_from(self, node: ImportFrom) -> Statement: return ImportFrom(node.id, node.relative, node.names[:]) - def visit_import_all(self, node: ImportAll) -> Node: + def visit_import_all(self, node: ImportAll) -> Statement: return ImportAll(node.id, node.relative) def copy_argument(self, argument: Argument) -> Argument: @@ -143,7 +146,7 @@ def visit_func_def(self, node: FuncDef) -> FuncDef: else: return new - def visit_func_expr(self, node: FuncExpr) -> Node: + def visit_func_expr(self, node: FuncExpr) -> Expression: new = FuncExpr([self.copy_argument(arg) for arg in node.arguments], self.block(node.body), cast(FunctionLike, self.optional_type(node.type))) @@ -169,7 +172,7 @@ def duplicate_inits(self, result.append(None) return result - def visit_overloaded_func_def(self, node: OverloadedFuncDef) -> Node: + def visit_overloaded_func_def(self, node: OverloadedFuncDef) -> OverloadedFuncDef: items = [self.visit_decorator(decorator) for decorator in node.items] for newitem, olditem in zip(items, node.items): @@ -180,7 +183,7 @@ def visit_overloaded_func_def(self, node: OverloadedFuncDef) -> Node: new.info = node.info return new - def visit_class_def(self, node: ClassDef) -> Node: + def visit_class_def(self, node: ClassDef) -> ClassDef: new = ClassDef(node.name, self.block(node.defs), node.type_vars, @@ -188,15 +191,15 @@ def visit_class_def(self, node: ClassDef) -> Node: node.metaclass) new.fullname = node.fullname new.info = node.info - new.decorators = [decorator.accept(self) + new.decorators = [cast(Expression, decorator.accept(self)) for decorator in node.decorators] new.is_builtinclass = node.is_builtinclass return new - def visit_global_decl(self, node: GlobalDecl) -> Node: + def visit_global_decl(self, node: GlobalDecl) -> GlobalDecl: return GlobalDecl(node.names[:]) - def visit_nonlocal_decl(self, node: NonlocalDecl) -> Node: + def visit_nonlocal_decl(self, node: NonlocalDecl) -> NonlocalDecl: return NonlocalDecl(node.names[:]) def visit_block(self, node: Block) -> Block: @@ -229,10 +232,10 @@ def visit_var(self, node: Var) -> Var: self.var_map[node] = new return new - def visit_expression_stmt(self, node: ExpressionStmt) -> Node: + def visit_expression_stmt(self, node: ExpressionStmt) -> ExpressionStmt: return ExpressionStmt(self.node(node.expr)) - def visit_assignment_stmt(self, node: AssignmentStmt) -> Node: + def visit_assignment_stmt(self, node: AssignmentStmt) -> AssignmentStmt: return self.duplicate_assignment(node) def duplicate_assignment(self, node: AssignmentStmt) -> AssignmentStmt: @@ -243,50 +246,50 @@ def duplicate_assignment(self, node: AssignmentStmt) -> AssignmentStmt: return new def visit_operator_assignment_stmt(self, - node: OperatorAssignmentStmt) -> Node: + node: OperatorAssignmentStmt) -> OperatorAssignmentStmt: return OperatorAssignmentStmt(node.op, self.node(node.lvalue), self.node(node.rvalue)) - def visit_while_stmt(self, node: WhileStmt) -> Node: + def visit_while_stmt(self, node: WhileStmt) -> WhileStmt: return WhileStmt(self.node(node.expr), self.block(node.body), self.optional_block(node.else_body)) - def visit_for_stmt(self, node: ForStmt) -> Node: + def visit_for_stmt(self, node: ForStmt) -> ForStmt: return ForStmt(self.node(node.index), self.node(node.expr), self.block(node.body), self.optional_block(node.else_body)) - def visit_return_stmt(self, node: ReturnStmt) -> Node: + def visit_return_stmt(self, node: ReturnStmt) -> ReturnStmt: return ReturnStmt(self.optional_node(node.expr)) - def visit_assert_stmt(self, node: AssertStmt) -> Node: + def visit_assert_stmt(self, node: AssertStmt) -> AssertStmt: return AssertStmt(self.node(node.expr)) - def visit_del_stmt(self, node: DelStmt) -> Node: + def visit_del_stmt(self, node: DelStmt) -> DelStmt: return DelStmt(self.node(node.expr)) - def visit_if_stmt(self, node: IfStmt) -> Node: + def visit_if_stmt(self, node: IfStmt) -> IfStmt: return IfStmt(self.nodes(node.expr), self.blocks(node.body), self.optional_block(node.else_body)) - def visit_break_stmt(self, node: BreakStmt) -> Node: + def visit_break_stmt(self, node: BreakStmt) -> BreakStmt: return BreakStmt() - def visit_continue_stmt(self, node: ContinueStmt) -> Node: + def visit_continue_stmt(self, node: ContinueStmt) -> ContinueStmt: return ContinueStmt() - def visit_pass_stmt(self, node: PassStmt) -> Node: + def visit_pass_stmt(self, node: PassStmt) -> PassStmt: return PassStmt() - def visit_raise_stmt(self, node: RaiseStmt) -> Node: + def visit_raise_stmt(self, node: RaiseStmt) -> RaiseStmt: return RaiseStmt(self.optional_node(node.expr), self.optional_node(node.from_expr)) - def visit_try_stmt(self, node: TryStmt) -> Node: + def visit_try_stmt(self, node: TryStmt) -> TryStmt: return TryStmt(self.block(node.body), self.optional_names(node.vars), self.optional_nodes(node.types), @@ -294,46 +297,46 @@ def visit_try_stmt(self, node: TryStmt) -> Node: self.optional_block(node.else_body), self.optional_block(node.finally_body)) - def visit_with_stmt(self, node: WithStmt) -> Node: + def visit_with_stmt(self, node: WithStmt) -> WithStmt: return WithStmt(self.nodes(node.expr), self.optional_nodes(node.target), self.block(node.body)) - def visit_print_stmt(self, node: PrintStmt) -> Node: + def visit_print_stmt(self, node: PrintStmt) -> PrintStmt: return PrintStmt(self.nodes(node.args), node.newline, self.optional_node(node.target)) - def visit_exec_stmt(self, node: ExecStmt) -> Node: + def visit_exec_stmt(self, node: ExecStmt) -> ExecStmt: return ExecStmt(self.node(node.expr), self.optional_node(node.variables1), self.optional_node(node.variables2)) - def visit_star_expr(self, node: StarExpr) -> Node: + def visit_star_expr(self, node: StarExpr) -> StarExpr: return StarExpr(node.expr) - def visit_int_expr(self, node: IntExpr) -> Node: + def visit_int_expr(self, node: IntExpr) -> IntExpr: return IntExpr(node.value) - def visit_str_expr(self, node: StrExpr) -> Node: + def visit_str_expr(self, node: StrExpr) -> StrExpr: return StrExpr(node.value) - def visit_bytes_expr(self, node: BytesExpr) -> Node: + def visit_bytes_expr(self, node: BytesExpr) -> BytesExpr: return BytesExpr(node.value) - def visit_unicode_expr(self, node: UnicodeExpr) -> Node: + def visit_unicode_expr(self, node: UnicodeExpr) -> UnicodeExpr: return UnicodeExpr(node.value) - def visit_float_expr(self, node: FloatExpr) -> Node: + def visit_float_expr(self, node: FloatExpr) -> Expression: return FloatExpr(node.value) - def visit_complex_expr(self, node: ComplexExpr) -> Node: + def visit_complex_expr(self, node: ComplexExpr) -> Expression: return ComplexExpr(node.value) - def visit_ellipsis(self, node: EllipsisExpr) -> Node: + def visit_ellipsis(self, node: EllipsisExpr) -> Expression: return EllipsisExpr() - def visit_name_expr(self, node: NameExpr) -> Node: + def visit_name_expr(self, node: NameExpr) -> Expression: return self.duplicate_name(node) def duplicate_name(self, node: NameExpr) -> NameExpr: @@ -343,7 +346,7 @@ def duplicate_name(self, node: NameExpr) -> NameExpr: self.copy_ref(new, node) return new - def visit_member_expr(self, node: MemberExpr) -> Node: + def visit_member_expr(self, node: MemberExpr) -> Expression: member = MemberExpr(self.node(node.expr), node.name) if node.def_var: @@ -363,63 +366,63 @@ def copy_ref(self, new: RefExpr, original: RefExpr) -> None: new.node = target new.is_def = original.is_def - def visit_yield_from_expr(self, node: YieldFromExpr) -> Node: + def visit_yield_from_expr(self, node: YieldFromExpr) -> YieldFromExpr: return YieldFromExpr(self.node(node.expr)) - def visit_yield_expr(self, node: YieldExpr) -> Node: + def visit_yield_expr(self, node: YieldExpr) -> YieldExpr: return YieldExpr(self.node(node.expr)) - def visit_await_expr(self, node: AwaitExpr) -> Node: + def visit_await_expr(self, node: AwaitExpr) -> AwaitExpr: return AwaitExpr(self.node(node.expr)) - def visit_call_expr(self, node: CallExpr) -> Node: + def visit_call_expr(self, node: CallExpr) -> Expression: return CallExpr(self.node(node.callee), self.nodes(node.args), node.arg_kinds[:], node.arg_names[:], self.optional_node(node.analyzed)) - def visit_op_expr(self, node: OpExpr) -> Node: + def visit_op_expr(self, node: OpExpr) -> OpExpr: new = OpExpr(node.op, self.node(node.left), self.node(node.right)) new.method_type = self.optional_type(node.method_type) return new - def visit_comparison_expr(self, node: ComparisonExpr) -> Node: + def visit_comparison_expr(self, node: ComparisonExpr) -> ComparisonExpr: new = ComparisonExpr(node.operators, self.nodes(node.operands)) new.method_types = [self.optional_type(t) for t in node.method_types] return new - def visit_cast_expr(self, node: CastExpr) -> Node: + def visit_cast_expr(self, node: CastExpr) -> Expression: return CastExpr(self.node(node.expr), self.type(node.type)) - def visit_reveal_type_expr(self, node: RevealTypeExpr) -> Node: + def visit_reveal_type_expr(self, node: RevealTypeExpr) -> Expression: return RevealTypeExpr(self.node(node.expr)) - def visit_super_expr(self, node: SuperExpr) -> Node: + def visit_super_expr(self, node: SuperExpr) -> SuperExpr: new = SuperExpr(node.name) new.info = node.info return new - def visit_unary_expr(self, node: UnaryExpr) -> Node: + def visit_unary_expr(self, node: UnaryExpr) -> UnaryExpr: new = UnaryExpr(node.op, self.node(node.expr)) new.method_type = self.optional_type(node.method_type) return new - def visit_list_expr(self, node: ListExpr) -> Node: + def visit_list_expr(self, node: ListExpr) -> ListExpr: return ListExpr(self.nodes(node.items)) - def visit_dict_expr(self, node: DictExpr) -> Node: + def visit_dict_expr(self, node: DictExpr) -> DictExpr: return DictExpr([(self.node(key), self.node(value)) for key, value in node.items]) - def visit_tuple_expr(self, node: TupleExpr) -> Node: + def visit_tuple_expr(self, node: TupleExpr) -> TupleExpr: return TupleExpr(self.nodes(node.items)) - def visit_set_expr(self, node: SetExpr) -> Node: + def visit_set_expr(self, node: SetExpr) -> SetExpr: return SetExpr(self.nodes(node.items)) - def visit_index_expr(self, node: IndexExpr) -> Node: + def visit_index_expr(self, node: IndexExpr) -> IndexExpr: new = IndexExpr(self.node(node.base), self.node(node.index)) if node.method_type: new.method_type = self.type(node.method_type) @@ -435,24 +438,24 @@ def visit_type_application(self, node: TypeApplication) -> TypeApplication: return TypeApplication(self.node(node.expr), self.types(node.types)) - def visit_list_comprehension(self, node: ListComprehension) -> Node: + def visit_list_comprehension(self, node: ListComprehension) -> ListComprehension: generator = self.duplicate_generator(node.generator) generator.set_line(node.generator.line) return ListComprehension(generator) - def visit_set_comprehension(self, node: SetComprehension) -> Node: + def visit_set_comprehension(self, node: SetComprehension) -> SetComprehension: generator = self.duplicate_generator(node.generator) generator.set_line(node.generator.line) return SetComprehension(generator) - def visit_dictionary_comprehension(self, node: DictionaryComprehension) -> Node: + def visit_dictionary_comprehension(self, node: DictionaryComprehension) -> DictionaryComprehension: return DictionaryComprehension(self.node(node.key), self.node(node.value), [self.node(index) for index in node.indices], [self.node(s) for s in node.sequences], [[self.node(cond) for cond in conditions] for conditions in node.condlists]) - def visit_generator_expr(self, node: GeneratorExpr) -> Node: + def visit_generator_expr(self, node: GeneratorExpr) -> Expression: return self.duplicate_generator(node) def duplicate_generator(self, node: GeneratorExpr) -> GeneratorExpr: @@ -462,20 +465,20 @@ def duplicate_generator(self, node: GeneratorExpr) -> GeneratorExpr: [[self.node(cond) for cond in conditions] for conditions in node.condlists]) - def visit_slice_expr(self, node: SliceExpr) -> Node: + def visit_slice_expr(self, node: SliceExpr) -> SliceExpr: return SliceExpr(self.optional_node(node.begin_index), self.optional_node(node.end_index), self.optional_node(node.stride)) - def visit_conditional_expr(self, node: ConditionalExpr) -> Node: + def visit_conditional_expr(self, node: ConditionalExpr) -> ConditionalExpr: return ConditionalExpr(self.node(node.cond), self.node(node.if_expr), self.node(node.else_expr)) - def visit_backquote_expr(self, node: BackquoteExpr) -> Node: + def visit_backquote_expr(self, node: BackquoteExpr) -> BackquoteExpr: return BackquoteExpr(self.node(node.expr)) - def visit_type_var_expr(self, node: TypeVarExpr) -> Node: + def visit_type_var_expr(self, node: TypeVarExpr) -> TypeVarExpr: return TypeVarExpr(node.name(), node.fullname(), self.types(node.values), self.type(node.upper_bound), variance=node.variance) @@ -486,17 +489,17 @@ def visit_type_alias_expr(self, node: TypeAliasExpr) -> TypeAliasExpr: def visit_newtype_expr(self, node: NewTypeExpr) -> NewTypeExpr: return NewTypeExpr(node.info) - def visit_namedtuple_expr(self, node: NamedTupleExpr) -> Node: + def visit_namedtuple_expr(self, node: NamedTupleExpr) -> NamedTupleExpr: return NamedTupleExpr(node.info) - def visit__promote_expr(self, node: PromoteExpr) -> Node: + def visit__promote_expr(self, node: PromoteExpr) -> PromoteExpr: return PromoteExpr(node.type) - def visit_temp_node(self, node: TempNode) -> Node: + def visit_temp_node(self, node: TempNode) -> TempNode: return TempNode(self.type(node.type)) - def node(self, node: Node) -> Node: - new = node.accept(self) + def node(self, node: T) -> T: + new = cast(T, node.accept(self)) new.set_line(node.line) return new @@ -504,7 +507,7 @@ def node(self, node: Node) -> Node: # # All the node helpers also propagate line numbers. - def optional_node(self, node: Node) -> Node: + def optional_node(self, node: Expression) -> Expression: if node: return self.node(node) else: @@ -521,13 +524,13 @@ def optional_block(self, block: Block) -> Block: else: return None - def nodes(self, nodes: List[Node]) -> List[Node]: + def nodes(self, nodes: Iterable[T]) -> List[T]: return [self.node(node) for node in nodes] def statements(self, nodes: List[Statement]) -> List[Statement]: return [cast(Statement, self.node(node)) for node in nodes] - def optional_nodes(self, nodes: List[Node]) -> List[Node]: + def optional_nodes(self, nodes: List[Expression]) -> List[Expression]: return [self.optional_node(node) for node in nodes] def blocks(self, blocks: List[Block]) -> List[Block]: From c08eb96cea580422f4ef41723c57e95990bcb010 Mon Sep 17 00:00:00 2001 From: Elazar Gershuni Date: Mon, 12 Sep 2016 05:23:39 +0300 Subject: [PATCH 04/11] lint --- mypy/checker.py | 3 ++- mypy/fastparse2.py | 3 ++- mypy/treetransform.py | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 6026ffc3d861..9a72b6a6e795 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -1039,7 +1039,8 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> Type: for lv in s.lvalues[:-1]: self.check_assignment(lv, rvalue, s.type is None) - def check_assignment(self, lvalue: Expression, rvalue: Expression, infer_lvalue_type: bool = True) -> None: + def check_assignment(self, lvalue: Expression, rvalue: Expression, + infer_lvalue_type: bool = True) -> None: """Type check a single assignment: lvalue = rvalue.""" if isinstance(lvalue, TupleExpr) or isinstance(lvalue, ListExpr): self.check_assignment_to_multiple_lvalues(lvalue.items, rvalue, lvalue, diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 1416eaefa457..371d46112faa 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -685,7 +685,8 @@ def visit_IfExp(self, n: ast27.IfExp) -> ConditionalExpr: # Dict(expr* keys, expr* values) @with_line def visit_Dict(self, n: ast27.Dict) -> DictExpr: - return DictExpr(list(zip(self.visit_list_expression(n.keys), self.visit_list_expression(n.values)))) + return DictExpr(list(zip(self.visit_list_expression(n.keys), + self.visit_list_expression(n.values)))) # Set(expr* elts) @with_line diff --git a/mypy/treetransform.py b/mypy/treetransform.py index 19429b6943fb..9673b4180514 100644 --- a/mypy/treetransform.py +++ b/mypy/treetransform.py @@ -448,7 +448,9 @@ def visit_set_comprehension(self, node: SetComprehension) -> SetComprehension: generator.set_line(node.generator.line) return SetComprehension(generator) - def visit_dictionary_comprehension(self, node: DictionaryComprehension) -> DictionaryComprehension: + def visit_dictionary_comprehension(self, + node: DictionaryComprehension + ) -> DictionaryComprehension: return DictionaryComprehension(self.node(node.key), self.node(node.value), [self.node(index) for index in node.indices], [self.node(s) for s in node.sequences], From 6a9e94c991366176ad4b3ce34a5f53c4fbc9610e Mon Sep 17 00:00:00 2001 From: Elazar Gershuni Date: Mon, 12 Sep 2016 12:18:58 +0300 Subject: [PATCH 05/11] Tighten expression types --- mypy/fastparse.py | 6 ++++-- mypy/fastparse2.py | 5 +++-- mypy/nodes.py | 16 +++++++------- mypy/parse.py | 14 ++++++------ mypy/treetransform.py | 50 +++++++++++++++++++++---------------------- 5 files changed, 46 insertions(+), 45 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 28921e0e4b2a..39c462434482 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -14,7 +14,8 @@ UnaryExpr, FuncExpr, ComparisonExpr, Expression, StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension, SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, - AwaitExpr, ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2, Statement) + AwaitExpr, ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2, Statement, + LvalueExpr) from mypy.types import ( Type, CallableType, AnyType, UnboundType, TupleType, TypeList, EllipsisType, ) @@ -412,7 +413,8 @@ def visit_Assign(self, n: ast35.Assign) -> AssignmentStmt: if n.type_comment: typ = parse_type_comment(n.type_comment, n.lineno) - return AssignmentStmt(self.visit_list_expression(n.targets), + lvalues = cast(List[LvalueExpr], self.visit_list_expression(n.targets)) + return AssignmentStmt(lvalues, self.visit(n.value), type=typ) diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index 371d46112faa..b099b3e4335e 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -28,7 +28,7 @@ DictExpr, SetExpr, NameExpr, IntExpr, StrExpr, BytesExpr, UnicodeExpr, FloatExpr, CallExpr, SuperExpr, MemberExpr, IndexExpr, SliceExpr, OpExpr, UnaryExpr, FuncExpr, ComparisonExpr, DictionaryComprehension, - SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, Expression, + SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, Expression, LvalueExpr, ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2, Statement ) from mypy.types import ( @@ -427,7 +427,8 @@ def visit_Assign(self, n: ast27.Assign) -> AssignmentStmt: if n.type_comment: typ = parse_type_comment(n.type_comment, n.lineno) - return AssignmentStmt(self.visit_list_expression(n.targets), + lvalues = cast(List[LvalueExpr], self.visit_list_expression(n.targets)) + return AssignmentStmt(lvalues, self.visit(n.value), type=typ) diff --git a/mypy/nodes.py b/mypy/nodes.py index f0d7de75970a..c4cf80a2f65e 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -116,9 +116,6 @@ def accept(self, visitor: NodeVisitor[T]) -> T: raise RuntimeError('Not implemented') -# This is a placeholder for a future refactoring; see #1783. -# For now it serves as (unchecked) documentation of what various -# fields of Node subtypes are expected to contain. class Expression(Node): pass @@ -292,7 +289,7 @@ class FuncBase(SymbolNode): """Abstract base class for function-like nodes""" # Type signature. This is usually CallableType or Overloaded, but it can be something else for - # decorated functions/ + # decorated functions type = None # type: mypy.types.Type # If method, reference to TypeInfo info = None # type: TypeInfo @@ -353,7 +350,7 @@ class Argument(Node): variable = None # type: Var type_annotation = None # type: Optional[mypy.types.Type] - initializater = None # type: Optional[Expression] + initializer = None # type: Optional[Expression] kind = None # type: int initialization_statement = None # type: Optional[AssignmentStmt] @@ -756,6 +753,9 @@ def accept(self, visitor: NodeVisitor[T]) -> T: return visitor.visit_expression_stmt(self) +LvalueExpr = Union['NameExpr', 'TupleExpr', 'ListExpr', 'MemberExpr', 'IndexExpr'] + + class AssignmentStmt(Statement): """Assignment statement The same node class is used for single assignment, multiple assignment @@ -765,12 +765,12 @@ class AssignmentStmt(Statement): An lvalue can be NameExpr, TupleExpr, ListExpr, MemberExpr, IndexExpr. """ - lvalues = None # type: List[Expression] + lvalues = None # type: List[LvalueExpr] rvalue = None # type: Expression # Declared type in a comment, may be None. type = None # type: mypy.types.Type - def __init__(self, lvalues: List[Expression], rvalue: Expression, + def __init__(self, lvalues: List[LvalueExpr], rvalue: Expression, type: 'mypy.types.Type' = None) -> None: self.lvalues = lvalues self.rvalue = rvalue @@ -1745,7 +1745,7 @@ def accept(self, visitor: NodeVisitor[T]) -> T: return visitor.visit_newtype_expr(self) -class AwaitExpr(Node): +class AwaitExpr(Expression): """Await expression (await ...).""" expr = None # type: Expression diff --git a/mypy/parse.py b/mypy/parse.py index d680500d4d88..c305fd19a011 100644 --- a/mypy/parse.py +++ b/mypy/parse.py @@ -26,8 +26,7 @@ UnaryExpr, FuncExpr, PrintStmt, ImportBase, ComparisonExpr, StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension, SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, ExecStmt, Argument, - BackquoteExpr, Statement -) + BackquoteExpr, Statement) from mypy import defaults from mypy import nodes from mypy.errors import Errors, CompileError @@ -728,8 +727,7 @@ def parse_tuple_arg(self, index: int) -> Tuple[Argument, AssignmentStmt, List[st arg_name = '__tuple_arg_{}'.format(index + 1) if self.pyversion[0] >= 3: self.fail('Tuples in argument lists only supported in Python 2 mode', line) - paren_arg = self.parse_parentheses() - self.verify_tuple_arg(paren_arg) + paren_arg = self.verify_tuple_arg(self.parse_parentheses()) if isinstance(paren_arg, NameExpr): # This isn't a tuple. Revert to a normal argument. arg_name = paren_arg.name @@ -749,14 +747,16 @@ def parse_tuple_arg(self, index: int) -> Tuple[Argument, AssignmentStmt, List[st arg_names = self.find_tuple_arg_argument_names(paren_arg) return Argument(var, None, initializer, kind), decompose, arg_names - def verify_tuple_arg(self, paren_arg: Expression) -> None: + def verify_tuple_arg(self, paren_arg: Expression) -> Union[TupleExpr, NameExpr]: + if isinstance(paren_arg, NameExpr): + return paren_arg if isinstance(paren_arg, TupleExpr): if not paren_arg.items: self.fail('Empty tuple not valid as an argument', paren_arg.line) for item in paren_arg.items: self.verify_tuple_arg(item) - elif not isinstance(paren_arg, NameExpr): - self.fail('Invalid item in tuple argument', paren_arg.line) + return paren_arg + self.fail('Invalid item in tuple argument', paren_arg.line) def find_tuple_arg_argument_names(self, node: Expression) -> List[str]: result = [] # type: List[str] diff --git a/mypy/treetransform.py b/mypy/treetransform.py index 9673b4180514..270a57f17129 100644 --- a/mypy/treetransform.py +++ b/mypy/treetransform.py @@ -3,7 +3,7 @@ Subclass TransformVisitor to perform non-trivial transformations. """ -from typing import List, Dict, cast, TypeVar, Iterable +from typing import List, Dict, cast, TypeVar, Iterable, Optional from mypy.nodes import ( MypyFile, Import, Node, Expression, ImportAll, ImportFrom, FuncItem, FuncDef, @@ -16,7 +16,7 @@ UnicodeExpr, FloatExpr, CallExpr, SuperExpr, MemberExpr, IndexExpr, SliceExpr, OpExpr, UnaryExpr, FuncExpr, TypeApplication, PrintStmt, SymbolTable, RefExpr, TypeVarExpr, NewTypeExpr, PromoteExpr, - ComparisonExpr, TempNode, StarExpr, + ComparisonExpr, TempNode, StarExpr, LvalueExpr, YieldFromExpr, NamedTupleExpr, NonlocalDecl, SetComprehension, DictionaryComprehension, ComplexExpr, TypeAliasExpr, EllipsisExpr, YieldExpr, ExecStmt, Argument, BackquoteExpr, AwaitExpr, Statement @@ -58,9 +58,9 @@ def __init__(self) -> None: # transformed node). self.func_placeholder_map = {} # type: Dict[FuncDef, FuncDef] - def visit_mypy_file(self, node: MypyFile) -> Statement: + def visit_mypy_file(self, node: MypyFile) -> MypyFile: # NOTE: The 'names' and 'imports' instance variables will be empty! - new = MypyFile(self.statements(node.defs), [], node.is_bom, + new = MypyFile(self.nodes(node.defs), [], node.is_bom, ignored_lines=set(node.ignored_lines)) new._name = node._name new._fullname = node._fullname @@ -68,13 +68,13 @@ def visit_mypy_file(self, node: MypyFile) -> Statement: new.names = SymbolTable() return new - def visit_import(self, node: Import) -> Statement: + def visit_import(self, node: Import) -> Import: return Import(node.ids[:]) - def visit_import_from(self, node: ImportFrom) -> Statement: + def visit_import_from(self, node: ImportFrom) -> ImportFrom: return ImportFrom(node.id, node.relative, node.names[:]) - def visit_import_all(self, node: ImportAll) -> Statement: + def visit_import_all(self, node: ImportAll) -> ImportAll: return ImportAll(node.id, node.relative) def copy_argument(self, argument: Argument) -> Argument: @@ -146,7 +146,7 @@ def visit_func_def(self, node: FuncDef) -> FuncDef: else: return new - def visit_func_expr(self, node: FuncExpr) -> Expression: + def visit_func_expr(self, node: FuncExpr) -> FuncExpr: new = FuncExpr([self.copy_argument(arg) for arg in node.arguments], self.block(node.body), cast(FunctionLike, self.optional_type(node.type))) @@ -203,7 +203,7 @@ def visit_nonlocal_decl(self, node: NonlocalDecl) -> NonlocalDecl: return NonlocalDecl(node.names[:]) def visit_block(self, node: Block) -> Block: - return Block(self.statements(node.body)) + return Block(self.nodes(node.body)) def visit_decorator(self, node: Decorator) -> Decorator: # Note that a Decorator must be transformed to a Decorator. @@ -239,7 +239,8 @@ def visit_assignment_stmt(self, node: AssignmentStmt) -> AssignmentStmt: return self.duplicate_assignment(node) def duplicate_assignment(self, node: AssignmentStmt) -> AssignmentStmt: - new = AssignmentStmt(self.nodes(node.lvalues), + lvalues = cast(List[LvalueExpr], self.nodes(node.lvalues)) + new = AssignmentStmt(lvalues, self.node(node.rvalue), self.optional_type(node.type)) new.line = node.line @@ -327,16 +328,16 @@ def visit_bytes_expr(self, node: BytesExpr) -> BytesExpr: def visit_unicode_expr(self, node: UnicodeExpr) -> UnicodeExpr: return UnicodeExpr(node.value) - def visit_float_expr(self, node: FloatExpr) -> Expression: + def visit_float_expr(self, node: FloatExpr) -> FloatExpr: return FloatExpr(node.value) - def visit_complex_expr(self, node: ComplexExpr) -> Expression: + def visit_complex_expr(self, node: ComplexExpr) -> ComplexExpr: return ComplexExpr(node.value) - def visit_ellipsis(self, node: EllipsisExpr) -> Expression: + def visit_ellipsis(self, node: EllipsisExpr) -> EllipsisExpr: return EllipsisExpr() - def visit_name_expr(self, node: NameExpr) -> Expression: + def visit_name_expr(self, node: NameExpr) -> NameExpr: return self.duplicate_name(node) def duplicate_name(self, node: NameExpr) -> NameExpr: @@ -346,7 +347,7 @@ def duplicate_name(self, node: NameExpr) -> NameExpr: self.copy_ref(new, node) return new - def visit_member_expr(self, node: MemberExpr) -> Expression: + def visit_member_expr(self, node: MemberExpr) -> MemberExpr: member = MemberExpr(self.node(node.expr), node.name) if node.def_var: @@ -375,7 +376,7 @@ def visit_yield_expr(self, node: YieldExpr) -> YieldExpr: def visit_await_expr(self, node: AwaitExpr) -> AwaitExpr: return AwaitExpr(self.node(node.expr)) - def visit_call_expr(self, node: CallExpr) -> Expression: + def visit_call_expr(self, node: CallExpr) -> CallExpr: return CallExpr(self.node(node.callee), self.nodes(node.args), node.arg_kinds[:], @@ -396,7 +397,7 @@ def visit_cast_expr(self, node: CastExpr) -> Expression: return CastExpr(self.node(node.expr), self.type(node.type)) - def visit_reveal_type_expr(self, node: RevealTypeExpr) -> Expression: + def visit_reveal_type_expr(self, node: RevealTypeExpr) -> RevealTypeExpr: return RevealTypeExpr(self.node(node.expr)) def visit_super_expr(self, node: SuperExpr) -> SuperExpr: @@ -457,7 +458,7 @@ def visit_dictionary_comprehension(self, [[self.node(cond) for cond in conditions] for conditions in node.condlists]) - def visit_generator_expr(self, node: GeneratorExpr) -> Expression: + def visit_generator_expr(self, node: GeneratorExpr) -> GeneratorExpr: return self.duplicate_generator(node) def duplicate_generator(self, node: GeneratorExpr) -> GeneratorExpr: @@ -509,7 +510,7 @@ def node(self, node: T) -> T: # # All the node helpers also propagate line numbers. - def optional_node(self, node: Expression) -> Expression: + def optional_node(self, node: T) -> Optional[T]: if node: return self.node(node) else: @@ -529,10 +530,7 @@ def optional_block(self, block: Block) -> Block: def nodes(self, nodes: Iterable[T]) -> List[T]: return [self.node(node) for node in nodes] - def statements(self, nodes: List[Statement]) -> List[Statement]: - return [cast(Statement, self.node(node)) for node in nodes] - - def optional_nodes(self, nodes: List[Expression]) -> List[Expression]: + def optional_nodes(self, nodes: List[T]) -> List[Optional[T]]: return [self.optional_node(node) for node in nodes] def blocks(self, blocks: List[Block]) -> List[Block]: @@ -541,7 +539,7 @@ def blocks(self, blocks: List[Block]) -> List[Block]: def names(self, names: List[NameExpr]) -> List[NameExpr]: return [self.duplicate_name(name) for name in names] - def optional_names(self, names: List[NameExpr]) -> List[NameExpr]: + def optional_names(self, names: List[NameExpr]) -> List[Optional[NameExpr]]: result = [] # type: List[NameExpr] for name in names: if name: @@ -554,7 +552,7 @@ def type(self, type: Type) -> Type: # Override this method to transform types. return type - def optional_type(self, type: Type) -> Type: + def optional_type(self, type: Type) -> Optional[Type]: if type: return self.type(type) else: @@ -563,7 +561,7 @@ def optional_type(self, type: Type) -> Type: def types(self, types: List[Type]) -> List[Type]: return [self.type(type) for type in types] - def optional_types(self, types: List[Type]) -> List[Type]: + def optional_types(self, types: List[Type]) -> List[Optional[Type]]: return [self.optional_type(type) for type in types] From 95fd2cdbc5660ace1a619641a9bbeef27d99cfbf Mon Sep 17 00:00:00 2001 From: Elazar Gershuni Date: Wed, 14 Sep 2016 22:51:29 +0300 Subject: [PATCH 06/11] remove LvalueExpression --- mypy/fastparse.py | 5 ++--- mypy/fastparse2.py | 4 ++-- mypy/nodes.py | 7 ++----- mypy/treetransform.py | 4 ++-- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index 39c462434482..f1abe4aff0eb 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -14,8 +14,7 @@ UnaryExpr, FuncExpr, ComparisonExpr, Expression, StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension, SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, - AwaitExpr, ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2, Statement, - LvalueExpr) + AwaitExpr, ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2, Statement) from mypy.types import ( Type, CallableType, AnyType, UnboundType, TupleType, TypeList, EllipsisType, ) @@ -413,7 +412,7 @@ def visit_Assign(self, n: ast35.Assign) -> AssignmentStmt: if n.type_comment: typ = parse_type_comment(n.type_comment, n.lineno) - lvalues = cast(List[LvalueExpr], self.visit_list_expression(n.targets)) + lvalues = self.visit_list_expression(n.targets) return AssignmentStmt(lvalues, self.visit(n.value), type=typ) diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index b099b3e4335e..f00c72646f75 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -28,7 +28,7 @@ DictExpr, SetExpr, NameExpr, IntExpr, StrExpr, BytesExpr, UnicodeExpr, FloatExpr, CallExpr, SuperExpr, MemberExpr, IndexExpr, SliceExpr, OpExpr, UnaryExpr, FuncExpr, ComparisonExpr, DictionaryComprehension, - SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, Expression, LvalueExpr, + SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, Expression, ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2, Statement ) from mypy.types import ( @@ -427,7 +427,7 @@ def visit_Assign(self, n: ast27.Assign) -> AssignmentStmt: if n.type_comment: typ = parse_type_comment(n.type_comment, n.lineno) - lvalues = cast(List[LvalueExpr], self.visit_list_expression(n.targets)) + lvalues = self.visit_list_expression(n.targets) return AssignmentStmt(lvalues, self.visit(n.value), type=typ) diff --git a/mypy/nodes.py b/mypy/nodes.py index c4cf80a2f65e..146e88f0ae1d 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -753,9 +753,6 @@ def accept(self, visitor: NodeVisitor[T]) -> T: return visitor.visit_expression_stmt(self) -LvalueExpr = Union['NameExpr', 'TupleExpr', 'ListExpr', 'MemberExpr', 'IndexExpr'] - - class AssignmentStmt(Statement): """Assignment statement The same node class is used for single assignment, multiple assignment @@ -765,12 +762,12 @@ class AssignmentStmt(Statement): An lvalue can be NameExpr, TupleExpr, ListExpr, MemberExpr, IndexExpr. """ - lvalues = None # type: List[LvalueExpr] + lvalues = None # type: List[Expression] rvalue = None # type: Expression # Declared type in a comment, may be None. type = None # type: mypy.types.Type - def __init__(self, lvalues: List[LvalueExpr], rvalue: Expression, + def __init__(self, lvalues: List[Expression], rvalue: Expression, type: 'mypy.types.Type' = None) -> None: self.lvalues = lvalues self.rvalue = rvalue diff --git a/mypy/treetransform.py b/mypy/treetransform.py index 270a57f17129..8ef96081c13c 100644 --- a/mypy/treetransform.py +++ b/mypy/treetransform.py @@ -16,7 +16,7 @@ UnicodeExpr, FloatExpr, CallExpr, SuperExpr, MemberExpr, IndexExpr, SliceExpr, OpExpr, UnaryExpr, FuncExpr, TypeApplication, PrintStmt, SymbolTable, RefExpr, TypeVarExpr, NewTypeExpr, PromoteExpr, - ComparisonExpr, TempNode, StarExpr, LvalueExpr, + ComparisonExpr, TempNode, StarExpr, YieldFromExpr, NamedTupleExpr, NonlocalDecl, SetComprehension, DictionaryComprehension, ComplexExpr, TypeAliasExpr, EllipsisExpr, YieldExpr, ExecStmt, Argument, BackquoteExpr, AwaitExpr, Statement @@ -239,7 +239,7 @@ def visit_assignment_stmt(self, node: AssignmentStmt) -> AssignmentStmt: return self.duplicate_assignment(node) def duplicate_assignment(self, node: AssignmentStmt) -> AssignmentStmt: - lvalues = cast(List[LvalueExpr], self.nodes(node.lvalues)) + lvalues = self.nodes(node.lvalues) new = AssignmentStmt(lvalues, self.node(node.rvalue), self.optional_type(node.type)) From b73a1ff1cd73f404a9d11ea0401270dde48524cc Mon Sep 17 00:00:00 2001 From: Elazar Gershuni Date: Wed, 14 Sep 2016 23:03:50 +0300 Subject: [PATCH 07/11] TypeMap as Optional[Dict] --- mypy/checker.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mypy/checker.py b/mypy/checker.py index 9a72b6a6e795..22b3b1cded1f 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -2369,9 +2369,7 @@ def method_type(self, func: FuncBase) -> FunctionLike: # probably be better to have the dict keyed by the nodes' literal_hash # field instead. -# NB: This should be `TypeMap = Optional[Dict[Expression, Type]]`! -# But see https://github.com/python/mypy/issues/1637 -TypeMap = Dict[Expression, Type] +TypeMap = Optional[Dict[Expression, Type]] def conditional_type_map(expr: Expression, From 9a0e532422f7cf41238c5440ec8cb38c6d8decbd Mon Sep 17 00:00:00 2001 From: Elazar Gershuni Date: Wed, 14 Sep 2016 23:07:22 +0300 Subject: [PATCH 08/11] Revert Expression/Statement to be aliases again --- mypy/nodes.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/mypy/nodes.py b/mypy/nodes.py index 146e88f0ae1d..c5290dfe8a92 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -116,17 +116,12 @@ def accept(self, visitor: NodeVisitor[T]) -> T: raise RuntimeError('Not implemented') -class Expression(Node): - pass - - -class Statement(Node): - pass - - -# For now, only Var is a declaration -class Declaration(Node): - pass +# These are placeholders for a future refactoring; see #1783. +# For now they serve as (unchecked) documentation of what various +# fields of Node subtypes are expected to contain. +Statement = Node +Expression = Node +Declaration = Node class SymbolNode(Node): From bb9d203b92b67b94d1b4837bd6ba1bd4fce6c2ce Mon Sep 17 00:00:00 2001 From: Elazar Gershuni Date: Wed, 14 Sep 2016 23:11:39 +0300 Subject: [PATCH 09/11] revert parse-related files --- mypy/fastparse.py | 150 +++++++++++++++++++-------------------- mypy/fastparse2.py | 146 +++++++++++++++++++------------------- mypy/parse.py | 136 +++++++++++++++++------------------- mypy/treetransform.py | 158 ++++++++++++++++++++---------------------- 4 files changed, 286 insertions(+), 304 deletions(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index f1abe4aff0eb..7ad71be62462 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -11,12 +11,14 @@ TupleExpr, GeneratorExpr, ListComprehension, ListExpr, ConditionalExpr, DictExpr, SetExpr, NameExpr, IntExpr, StrExpr, BytesExpr, UnicodeExpr, FloatExpr, CallExpr, SuperExpr, MemberExpr, IndexExpr, SliceExpr, OpExpr, - UnaryExpr, FuncExpr, ComparisonExpr, Expression, + UnaryExpr, FuncExpr, ComparisonExpr, StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension, SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, - AwaitExpr, ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2, Statement) + AwaitExpr, + ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2 +) from mypy.types import ( - Type, CallableType, AnyType, UnboundType, TupleType, TypeList, EllipsisType, + Type, CallableType, FunctionLike, AnyType, UnboundType, TupleType, TypeList, EllipsisType, ) from mypy import defaults from mypy import experiments @@ -123,10 +125,7 @@ def generic_visit(self, node: ast35.AST) -> None: def visit_NoneType(self, n: Any) -> Optional[Node]: return None - def visit_list_expression(self, l: Sequence[ast35.AST]) -> List[Expression]: - return [self.visit(e) for e in l] - - def visit_statement_list(self, l: Sequence[ast35.AST]) -> List[Statement]: + def visit_list(self, l: Sequence[ast35.AST]) -> List[Node]: return [self.visit(e) for e in l] op_map = { @@ -177,13 +176,12 @@ def from_comp_operator(self, op: ast35.cmpop) -> str: def as_block(self, stmts: List[ast35.stmt], lineno: int) -> Block: b = None if stmts: - stmt_list = self.visit_statement_list(stmts) - b = Block(self.fix_function_overloads(stmt_list)) + b = Block(self.fix_function_overloads(self.visit_list(stmts))) b.set_line(lineno) return b - def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: - ret = [] # type: List[Statement] + def fix_function_overloads(self, stmts: List[Node]) -> List[Node]: + ret = [] # type: List[Node] current_overload = [] current_overload_name = None # mypy doesn't actually check that the decorator is literally @overload @@ -227,7 +225,7 @@ def translate_module_id(self, id: str) -> str: return id def visit_Module(self, mod: ast35.Module) -> Node: - body = self.fix_function_overloads(self.visit_statement_list(mod.body)) + body = self.fix_function_overloads(self.visit_list(mod.body)) return MypyFile(body, self.imports, @@ -241,17 +239,17 @@ def visit_Module(self, mod: ast35.Module) -> Node: # arguments = (arg* args, arg? vararg, arg* kwonlyargs, expr* kw_defaults, # arg? kwarg, expr* defaults) @with_line - def visit_FunctionDef(self, n: ast35.FunctionDef) -> Union[FuncDef, Decorator]: + def visit_FunctionDef(self, n: ast35.FunctionDef) -> Node: return self.do_func_def(n) # AsyncFunctionDef(identifier name, arguments args, # stmt* body, expr* decorator_list, expr? returns, string? type_comment) @with_line - def visit_AsyncFunctionDef(self, n: ast35.AsyncFunctionDef) -> Union[FuncDef, Decorator]: + def visit_AsyncFunctionDef(self, n: ast35.AsyncFunctionDef) -> Node: return self.do_func_def(n, is_coroutine=True) def do_func_def(self, n: Union[ast35.FunctionDef, ast35.AsyncFunctionDef], - is_coroutine: bool = False) -> Union[FuncDef, Decorator]: + is_coroutine: bool = False) -> Node: """Helper shared between visit_FunctionDef and visit_AsyncFunctionDef.""" args = self.transform_args(n.args, n.lineno) @@ -314,11 +312,11 @@ def do_func_def(self, n: Union[ast35.FunctionDef, ast35.AsyncFunctionDef], func_def.is_decorated = True func_def.set_line(n.lineno + len(n.decorator_list)) func_def.body.set_line(func_def.get_line()) - return Decorator(func_def, self.visit_list_expression(n.decorator_list), var) + return Decorator(func_def, self.visit_list(n.decorator_list), var) else: return func_def - def set_type_optional(self, type: Type, initializer: Expression) -> None: + def set_type_optional(self, type: Type, initializer: Node) -> None: if not experiments.STRICT_OPTIONAL: return # Indicate that type should be wrapped in an Optional if arg is initialized to None. @@ -374,7 +372,7 @@ def stringify_name(self, n: ast35.AST) -> str: # stmt* body, # expr* decorator_list) @with_line - def visit_ClassDef(self, n: ast35.ClassDef) -> ClassDef: + def visit_ClassDef(self, n: ast35.ClassDef) -> Node: self.class_nesting += 1 metaclass_arg = find(lambda x: x.arg == 'metaclass', n.keywords) metaclass = None @@ -384,22 +382,22 @@ def visit_ClassDef(self, n: ast35.ClassDef) -> ClassDef: cdef = ClassDef(n.name, self.as_block(n.body, n.lineno), None, - self.visit_list_expression(n.bases), + self.visit_list(n.bases), metaclass=metaclass) - cdef.decorators = self.visit_list_expression(n.decorator_list) + cdef.decorators = self.visit_list(n.decorator_list) self.class_nesting -= 1 return cdef # Return(expr? value) @with_line - def visit_Return(self, n: ast35.Return) -> ReturnStmt: + def visit_Return(self, n: ast35.Return) -> Node: return ReturnStmt(self.visit(n.value)) # Delete(expr* targets) @with_line - def visit_Delete(self, n: ast35.Delete) -> DelStmt: + def visit_Delete(self, n: ast35.Delete) -> Node: if len(n.targets) > 1: - tup = TupleExpr(self.visit_list_expression(n.targets)) + tup = TupleExpr(self.visit_list(n.targets)) tup.set_line(n.lineno) return DelStmt(tup) else: @@ -407,26 +405,25 @@ def visit_Delete(self, n: ast35.Delete) -> DelStmt: # Assign(expr* targets, expr value, string? type_comment) @with_line - def visit_Assign(self, n: ast35.Assign) -> AssignmentStmt: + def visit_Assign(self, n: ast35.Assign) -> Node: typ = None if n.type_comment: typ = parse_type_comment(n.type_comment, n.lineno) - lvalues = self.visit_list_expression(n.targets) - return AssignmentStmt(lvalues, + return AssignmentStmt(self.visit_list(n.targets), self.visit(n.value), type=typ) # AugAssign(expr target, operator op, expr value) @with_line - def visit_AugAssign(self, n: ast35.AugAssign) -> OperatorAssignmentStmt: + def visit_AugAssign(self, n: ast35.AugAssign) -> Node: return OperatorAssignmentStmt(self.from_operator(n.op), self.visit(n.target), self.visit(n.value)) # For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment) @with_line - def visit_For(self, n: ast35.For) -> ForStmt: + def visit_For(self, n: ast35.For) -> Node: return ForStmt(self.visit(n.target), self.visit(n.iter), self.as_block(n.body, n.lineno), @@ -434,7 +431,7 @@ def visit_For(self, n: ast35.For) -> ForStmt: # AsyncFor(expr target, expr iter, stmt* body, stmt* orelse) @with_line - def visit_AsyncFor(self, n: ast35.AsyncFor) -> ForStmt: + def visit_AsyncFor(self, n: ast35.AsyncFor) -> Node: r = ForStmt(self.visit(n.target), self.visit(n.iter), self.as_block(n.body, n.lineno), @@ -444,28 +441,28 @@ def visit_AsyncFor(self, n: ast35.AsyncFor) -> ForStmt: # While(expr test, stmt* body, stmt* orelse) @with_line - def visit_While(self, n: ast35.While) -> WhileStmt: + def visit_While(self, n: ast35.While) -> Node: return WhileStmt(self.visit(n.test), self.as_block(n.body, n.lineno), self.as_block(n.orelse, n.lineno)) # If(expr test, stmt* body, stmt* orelse) @with_line - def visit_If(self, n: ast35.If) -> IfStmt: + def visit_If(self, n: ast35.If) -> Node: return IfStmt([self.visit(n.test)], [self.as_block(n.body, n.lineno)], self.as_block(n.orelse, n.lineno)) # With(withitem* items, stmt* body, string? type_comment) @with_line - def visit_With(self, n: ast35.With) -> WithStmt: + def visit_With(self, n: ast35.With) -> Node: return WithStmt([self.visit(i.context_expr) for i in n.items], [self.visit(i.optional_vars) for i in n.items], self.as_block(n.body, n.lineno)) # AsyncWith(withitem* items, stmt* body) @with_line - def visit_AsyncWith(self, n: ast35.AsyncWith) -> WithStmt: + def visit_AsyncWith(self, n: ast35.AsyncWith) -> Node: r = WithStmt([self.visit(i.context_expr) for i in n.items], [self.visit(i.optional_vars) for i in n.items], self.as_block(n.body, n.lineno)) @@ -474,12 +471,12 @@ def visit_AsyncWith(self, n: ast35.AsyncWith) -> WithStmt: # Raise(expr? exc, expr? cause) @with_line - def visit_Raise(self, n: ast35.Raise) -> RaiseStmt: + def visit_Raise(self, n: ast35.Raise) -> Node: return RaiseStmt(self.visit(n.exc), self.visit(n.cause)) # Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody) @with_line - def visit_Try(self, n: ast35.Try) -> TryStmt: + def visit_Try(self, n: ast35.Try) -> Node: vs = [NameExpr(h.name) if h.name is not None else None for h in n.handlers] types = [self.visit(h.type) for h in n.handlers] handlers = [self.as_block(h.body, h.lineno) for h in n.handlers] @@ -493,12 +490,12 @@ def visit_Try(self, n: ast35.Try) -> TryStmt: # Assert(expr test, expr? msg) @with_line - def visit_Assert(self, n: ast35.Assert) -> AssertStmt: + def visit_Assert(self, n: ast35.Assert) -> Node: return AssertStmt(self.visit(n.test)) # Import(alias* names) @with_line - def visit_Import(self, n: ast35.Import) -> Import: + def visit_Import(self, n: ast35.Import) -> Node: i = Import([(self.translate_module_id(a.name), a.asname) for a in n.names]) self.imports.append(i) return i @@ -518,39 +515,39 @@ def visit_ImportFrom(self, n: ast35.ImportFrom) -> Node: # Global(identifier* names) @with_line - def visit_Global(self, n: ast35.Global) -> GlobalDecl: + def visit_Global(self, n: ast35.Global) -> Node: return GlobalDecl(n.names) # Nonlocal(identifier* names) @with_line - def visit_Nonlocal(self, n: ast35.Nonlocal) -> NonlocalDecl: + def visit_Nonlocal(self, n: ast35.Nonlocal) -> Node: return NonlocalDecl(n.names) # Expr(expr value) @with_line - def visit_Expr(self, n: ast35.Expr) -> ExpressionStmt: + def visit_Expr(self, n: ast35.Expr) -> Node: value = self.visit(n.value) return ExpressionStmt(value) # Pass @with_line - def visit_Pass(self, n: ast35.Pass) -> PassStmt: + def visit_Pass(self, n: ast35.Pass) -> Node: return PassStmt() # Break @with_line - def visit_Break(self, n: ast35.Break) -> BreakStmt: + def visit_Break(self, n: ast35.Break) -> Node: return BreakStmt() # Continue @with_line - def visit_Continue(self, n: ast35.Continue) -> ContinueStmt: + def visit_Continue(self, n: ast35.Continue) -> Node: return ContinueStmt() # --- expr --- # BoolOp(boolop op, expr* values) @with_line - def visit_BoolOp(self, n: ast35.BoolOp) -> OpExpr: + def visit_BoolOp(self, n: ast35.BoolOp) -> Node: # mypy translates (1 and 2 and 3) as (1 and (2 and 3)) assert len(n.values) >= 2 op = None @@ -562,17 +559,17 @@ def visit_BoolOp(self, n: ast35.BoolOp) -> OpExpr: raise RuntimeError('unknown BoolOp ' + str(type(n))) # potentially inefficient! - def group(vals: List[Expression]) -> OpExpr: + def group(vals: List[Node]) -> Node: if len(vals) == 2: return OpExpr(op, vals[0], vals[1]) else: return OpExpr(op, vals[0], group(vals[1:])) - return group(self.visit_list_expression(n.values)) + return group(self.visit_list(n.values)) # BinOp(expr left, operator op, expr right) @with_line - def visit_BinOp(self, n: ast35.BinOp) -> OpExpr: + def visit_BinOp(self, n: ast35.BinOp) -> Node: op = self.from_operator(n.op) if op is None: @@ -582,7 +579,7 @@ def visit_BinOp(self, n: ast35.BinOp) -> OpExpr: # UnaryOp(unaryop op, expr operand) @with_line - def visit_UnaryOp(self, n: ast35.UnaryOp) -> UnaryExpr: + def visit_UnaryOp(self, n: ast35.UnaryOp) -> Node: op = None if isinstance(n.op, ast35.Invert): op = '~' @@ -600,7 +597,7 @@ def visit_UnaryOp(self, n: ast35.UnaryOp) -> UnaryExpr: # Lambda(arguments args, expr body) @with_line - def visit_Lambda(self, n: ast35.Lambda) -> FuncExpr: + def visit_Lambda(self, n: ast35.Lambda) -> Node: body = ast35.Return(n.body) body.lineno = n.lineno @@ -609,38 +606,37 @@ def visit_Lambda(self, n: ast35.Lambda) -> FuncExpr: # IfExp(expr test, expr body, expr orelse) @with_line - def visit_IfExp(self, n: ast35.IfExp) -> ConditionalExpr: + def visit_IfExp(self, n: ast35.IfExp) -> Node: return ConditionalExpr(self.visit(n.test), self.visit(n.body), self.visit(n.orelse)) # Dict(expr* keys, expr* values) @with_line - def visit_Dict(self, n: ast35.Dict) -> DictExpr: - return DictExpr(list(zip(self.visit_list_expression(n.keys), - self.visit_list_expression(n.values)))) + def visit_Dict(self, n: ast35.Dict) -> Node: + return DictExpr(list(zip(self.visit_list(n.keys), self.visit_list(n.values)))) # Set(expr* elts) @with_line - def visit_Set(self, n: ast35.Set) -> SetExpr: - return SetExpr(self.visit_list_expression(n.elts)) + def visit_Set(self, n: ast35.Set) -> Node: + return SetExpr(self.visit_list(n.elts)) # ListComp(expr elt, comprehension* generators) @with_line - def visit_ListComp(self, n: ast35.ListComp) -> ListComprehension: + def visit_ListComp(self, n: ast35.ListComp) -> Node: return ListComprehension(self.visit_GeneratorExp(cast(ast35.GeneratorExp, n))) # SetComp(expr elt, comprehension* generators) @with_line - def visit_SetComp(self, n: ast35.SetComp) -> SetComprehension: + def visit_SetComp(self, n: ast35.SetComp) -> Node: return SetComprehension(self.visit_GeneratorExp(cast(ast35.GeneratorExp, n))) # DictComp(expr key, expr value, comprehension* generators) @with_line - def visit_DictComp(self, n: ast35.DictComp) -> DictionaryComprehension: + def visit_DictComp(self, n: ast35.DictComp) -> Node: targets = [self.visit(c.target) for c in n.generators] iters = [self.visit(c.iter) for c in n.generators] - ifs_list = [self.visit_list_expression(c.ifs) for c in n.generators] + ifs_list = [self.visit_list(c.ifs) for c in n.generators] return DictionaryComprehension(self.visit(n.key), self.visit(n.value), targets, @@ -652,7 +648,7 @@ def visit_DictComp(self, n: ast35.DictComp) -> DictionaryComprehension: def visit_GeneratorExp(self, n: ast35.GeneratorExp) -> GeneratorExpr: targets = [self.visit(c.target) for c in n.generators] iters = [self.visit(c.iter) for c in n.generators] - ifs_list = [self.visit_list_expression(c.ifs) for c in n.generators] + ifs_list = [self.visit_list(c.ifs) for c in n.generators] return GeneratorExpr(self.visit(n.elt), targets, iters, @@ -666,29 +662,29 @@ def visit_Await(self, n: ast35.Await) -> Node: # Yield(expr? value) @with_line - def visit_Yield(self, n: ast35.Yield) -> YieldExpr: + def visit_Yield(self, n: ast35.Yield) -> Node: return YieldExpr(self.visit(n.value)) # YieldFrom(expr value) @with_line - def visit_YieldFrom(self, n: ast35.YieldFrom) -> YieldFromExpr: + def visit_YieldFrom(self, n: ast35.YieldFrom) -> Node: return YieldFromExpr(self.visit(n.value)) # Compare(expr left, cmpop* ops, expr* comparators) @with_line - def visit_Compare(self, n: ast35.Compare) -> ComparisonExpr: + def visit_Compare(self, n: ast35.Compare) -> Node: operators = [self.from_comp_operator(o) for o in n.ops] - operands = self.visit_list_expression([n.left] + n.comparators) + operands = self.visit_list([n.left] + n.comparators) return ComparisonExpr(operators, operands) # Call(expr func, expr* args, keyword* keywords) # keyword = (identifier? arg, expr value) @with_line - def visit_Call(self, n: ast35.Call) -> CallExpr: + def visit_Call(self, n: ast35.Call) -> Node: def is_star2arg(k: ast35.keyword) -> bool: return k.arg is None - arg_types = self.visit_list_expression( + arg_types = self.visit_list( [a.value if isinstance(a, ast35.Starred) else a for a in n.args] + [k.value for k in n.keywords]) arg_kinds = ([ARG_STAR if isinstance(a, ast35.Starred) else ARG_POS for a in n.args] + @@ -737,12 +733,12 @@ def visit_Bytes(self, n: ast35.Bytes) -> Node: return StrExpr(contents) # NameConstant(singleton value) - def visit_NameConstant(self, n: ast35.NameConstant) -> NameExpr: + def visit_NameConstant(self, n: ast35.NameConstant) -> Node: return NameExpr(str(n.value)) # Ellipsis @with_line - def visit_Ellipsis(self, n: ast35.Ellipsis) -> EllipsisExpr: + def visit_Ellipsis(self, n: ast35.Ellipsis) -> Node: return EllipsisExpr() # Attribute(expr value, identifier attr, expr_context ctx) @@ -757,43 +753,43 @@ def visit_Attribute(self, n: ast35.Attribute) -> Node: # Subscript(expr value, slice slice, expr_context ctx) @with_line - def visit_Subscript(self, n: ast35.Subscript) -> IndexExpr: + def visit_Subscript(self, n: ast35.Subscript) -> Node: return IndexExpr(self.visit(n.value), self.visit(n.slice)) # Starred(expr value, expr_context ctx) @with_line - def visit_Starred(self, n: ast35.Starred) -> StarExpr: + def visit_Starred(self, n: ast35.Starred) -> Node: return StarExpr(self.visit(n.value)) # Name(identifier id, expr_context ctx) @with_line - def visit_Name(self, n: ast35.Name) -> NameExpr: + def visit_Name(self, n: ast35.Name) -> Node: return NameExpr(n.id) # List(expr* elts, expr_context ctx) @with_line - def visit_List(self, n: ast35.List) -> ListExpr: + def visit_List(self, n: ast35.List) -> Node: return ListExpr([self.visit(e) for e in n.elts]) # Tuple(expr* elts, expr_context ctx) @with_line - def visit_Tuple(self, n: ast35.Tuple) -> TupleExpr: + def visit_Tuple(self, n: ast35.Tuple) -> Node: return TupleExpr([self.visit(e) for e in n.elts]) # --- slice --- # Slice(expr? lower, expr? upper, expr? step) - def visit_Slice(self, n: ast35.Slice) -> SliceExpr: + def visit_Slice(self, n: ast35.Slice) -> Node: return SliceExpr(self.visit(n.lower), self.visit(n.upper), self.visit(n.step)) # ExtSlice(slice* dims) - def visit_ExtSlice(self, n: ast35.ExtSlice) -> TupleExpr: - return TupleExpr(self.visit_list_expression(n.dims)) + def visit_ExtSlice(self, n: ast35.ExtSlice) -> Node: + return TupleExpr(self.visit_list(n.dims)) # Index(expr value) - def visit_Index(self, n: ast35.Index) -> IndexExpr: + def visit_Index(self, n: ast35.Index) -> Node: return self.visit(n.value) diff --git a/mypy/fastparse2.py b/mypy/fastparse2.py index f00c72646f75..25e5bcb78fbc 100644 --- a/mypy/fastparse2.py +++ b/mypy/fastparse2.py @@ -27,12 +27,14 @@ TupleExpr, GeneratorExpr, ListComprehension, ListExpr, ConditionalExpr, DictExpr, SetExpr, NameExpr, IntExpr, StrExpr, BytesExpr, UnicodeExpr, FloatExpr, CallExpr, SuperExpr, MemberExpr, IndexExpr, SliceExpr, OpExpr, - UnaryExpr, FuncExpr, ComparisonExpr, DictionaryComprehension, - SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, Expression, - ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2, Statement + UnaryExpr, FuncExpr, ComparisonExpr, + StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension, + SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, Argument, + AwaitExpr, Expression, + ARG_POS, ARG_OPT, ARG_STAR, ARG_NAMED, ARG_STAR2 ) from mypy.types import ( - Type, CallableType, AnyType, UnboundType, + Type, CallableType, FunctionLike, AnyType, UnboundType, TupleType, TypeList, EllipsisType, ) from mypy import defaults from mypy import experiments @@ -42,6 +44,7 @@ try: from typed_ast import ast27 from typed_ast import ast35 + from typed_ast import conversions except ImportError: if sys.version_info.minor > 2: print('You must install the typed_ast package before you can run mypy' @@ -141,10 +144,7 @@ def generic_visit(self, node: ast27.AST) -> None: def visit_NoneType(self, n: Any) -> Optional[Node]: return None - def visit_list_expression(self, l: Sequence[ast27.AST]) -> List[Expression]: - return [self.visit(e) for e in l] - - def visit_statement_list(self, l: Sequence[ast27.AST]) -> List[Statement]: + def visit_list(self, l: Sequence[ast27.AST]) -> List[Node]: return [self.visit(e) for e in l] op_map = { @@ -194,12 +194,12 @@ def from_comp_operator(self, op: ast27.cmpop) -> str: def as_block(self, stmts: List[ast27.stmt], lineno: int) -> Block: b = None if stmts: - b = Block(self.fix_function_overloads(self.visit_statement_list(stmts))) + b = Block(self.fix_function_overloads(self.visit_list(stmts))) b.set_line(lineno) return b - def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]: - ret = [] # type: List[Statement] + def fix_function_overloads(self, stmts: List[Node]) -> List[Node]: + ret = [] # type: List[Node] current_overload = [] current_overload_name = None # mypy doesn't actually check that the decorator is literally @overload @@ -242,8 +242,8 @@ def translate_module_id(self, id: str) -> str: return 'builtins' return id - def visit_Module(self, mod: ast27.Module) -> MypyFile: - body = self.fix_function_overloads(self.visit_statement_list(mod.body)) + def visit_Module(self, mod: ast27.Module) -> Node: + body = self.fix_function_overloads(self.visit_list(mod.body)) return MypyFile(body, self.imports, @@ -257,7 +257,7 @@ def visit_Module(self, mod: ast27.Module) -> MypyFile: # arguments = (arg* args, arg? vararg, arg* kwonlyargs, expr* kw_defaults, # arg? kwarg, expr* defaults) @with_line - def visit_FunctionDef(self, n: ast27.FunctionDef) -> Union[FuncDef, Decorator]: + def visit_FunctionDef(self, n: ast27.FunctionDef) -> Node: converter = TypeConverter(line=n.lineno) args = self.transform_args(n.args, n.lineno) @@ -317,7 +317,7 @@ def visit_FunctionDef(self, n: ast27.FunctionDef) -> Union[FuncDef, Decorator]: func_def.is_decorated = True func_def.set_line(n.lineno + len(n.decorator_list)) func_def.body.set_line(func_def.get_line()) - return Decorator(func_def, self.visit_list_expression(n.decorator_list), var) + return Decorator(func_def, self.visit_list(n.decorator_list), var) else: return func_def @@ -356,7 +356,7 @@ def get_type(i: int) -> Optional[Type]: return None args = [(convert_arg(arg), get_type(i)) for i, arg in enumerate(n.args)] - defaults = self.visit_list_expression(n.defaults) + defaults = self.visit_list(n.defaults) new_args = [] # type: List[Argument] num_no_defaults = len(args) - len(defaults) @@ -393,28 +393,28 @@ def stringify_name(self, n: ast27.AST) -> str: # stmt* body, # expr* decorator_list) @with_line - def visit_ClassDef(self, n: ast27.ClassDef) -> ClassDef: + def visit_ClassDef(self, n: ast27.ClassDef) -> Node: self.class_nesting += 1 cdef = ClassDef(n.name, self.as_block(n.body, n.lineno), None, - self.visit_list_expression(n.bases), + self.visit_list(n.bases), metaclass=None) - cdef.decorators = self.visit_list_expression(n.decorator_list) + cdef.decorators = self.visit_list(n.decorator_list) self.class_nesting -= 1 return cdef # Return(expr? value) @with_line - def visit_Return(self, n: ast27.Return) -> ReturnStmt: + def visit_Return(self, n: ast27.Return) -> Node: return ReturnStmt(self.visit(n.value)) # Delete(expr* targets) @with_line def visit_Delete(self, n: ast27.Delete) -> Node: if len(n.targets) > 1: - tup = TupleExpr(self.visit_list_expression(n.targets)) + tup = TupleExpr(self.visit_list(n.targets)) tup.set_line(n.lineno) return DelStmt(tup) else: @@ -422,26 +422,25 @@ def visit_Delete(self, n: ast27.Delete) -> Node: # Assign(expr* targets, expr value, string? type_comment) @with_line - def visit_Assign(self, n: ast27.Assign) -> AssignmentStmt: + def visit_Assign(self, n: ast27.Assign) -> Node: typ = None if n.type_comment: typ = parse_type_comment(n.type_comment, n.lineno) - lvalues = self.visit_list_expression(n.targets) - return AssignmentStmt(lvalues, + return AssignmentStmt(self.visit_list(n.targets), self.visit(n.value), type=typ) # AugAssign(expr target, operator op, expr value) @with_line - def visit_AugAssign(self, n: ast27.AugAssign) -> OperatorAssignmentStmt: + def visit_AugAssign(self, n: ast27.AugAssign) -> Node: return OperatorAssignmentStmt(self.from_operator(n.op), self.visit(n.target), self.visit(n.value)) # For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment) @with_line - def visit_For(self, n: ast27.For) -> ForStmt: + def visit_For(self, n: ast27.For) -> Node: return ForStmt(self.visit(n.target), self.visit(n.iter), self.as_block(n.body, n.lineno), @@ -449,27 +448,27 @@ def visit_For(self, n: ast27.For) -> ForStmt: # While(expr test, stmt* body, stmt* orelse) @with_line - def visit_While(self, n: ast27.While) -> WhileStmt: + def visit_While(self, n: ast27.While) -> Node: return WhileStmt(self.visit(n.test), self.as_block(n.body, n.lineno), self.as_block(n.orelse, n.lineno)) # If(expr test, stmt* body, stmt* orelse) @with_line - def visit_If(self, n: ast27.If) -> IfStmt: + def visit_If(self, n: ast27.If) -> Node: return IfStmt([self.visit(n.test)], [self.as_block(n.body, n.lineno)], self.as_block(n.orelse, n.lineno)) # With(withitem* items, stmt* body, string? type_comment) @with_line - def visit_With(self, n: ast27.With) -> WithStmt: + def visit_With(self, n: ast27.With) -> Node: return WithStmt([self.visit(n.context_expr)], [self.visit(n.optional_vars)], self.as_block(n.body, n.lineno)) @with_line - def visit_Raise(self, n: ast27.Raise) -> RaiseStmt: + def visit_Raise(self, n: ast27.Raise) -> Node: e = None if n.type is not None: e = n.type @@ -485,11 +484,11 @@ def visit_Raise(self, n: ast27.Raise) -> RaiseStmt: # TryExcept(stmt* body, excepthandler* handlers, stmt* orelse) @with_line - def visit_TryExcept(self, n: ast27.TryExcept) -> TryStmt: + def visit_TryExcept(self, n: ast27.TryExcept) -> Node: return self.try_handler(n.body, n.handlers, n.orelse, [], n.lineno) @with_line - def visit_TryFinally(self, n: ast27.TryFinally) -> TryStmt: + def visit_TryFinally(self, n: ast27.TryFinally) -> Node: if len(n.body) == 1 and isinstance(n.body[0], ast27.TryExcept): return self.try_handler([n.body[0]], [], [], n.finalbody, n.lineno) else: @@ -500,7 +499,7 @@ def try_handler(self, handlers: List[ast27.ExceptHandler], orelse: List[ast27.stmt], finalbody: List[ast27.stmt], - lineno: int) -> TryStmt: + lineno: int) -> Node: def produce_name(item: ast27.ExceptHandler) -> Optional[NameExpr]: if item.name is None: return None @@ -521,7 +520,7 @@ def produce_name(item: ast27.ExceptHandler) -> Optional[NameExpr]: self.as_block(finalbody, lineno)) @with_line - def visit_Print(self, n: ast27.Print) -> CallExpr: + def visit_Print(self, n: ast27.Print) -> Node: keywords = [] if n.dest is not None: keywords.append(ast27.keyword("file", n.dest)) @@ -538,7 +537,7 @@ def visit_Print(self, n: ast27.Print) -> CallExpr: return self.visit(ast27.Expr(call, lineno=n.lineno, col_offset=-1)) @with_line - def visit_Exec(self, n: ast27.Exec) -> CallExpr: + def visit_Exec(self, n: ast27.Exec) -> Node: new_globals = n.globals new_locals = n.locals @@ -557,7 +556,7 @@ def visit_Exec(self, n: ast27.Exec) -> CallExpr: lineno=n.lineno, col_offset=-1)) @with_line - def visit_Repr(self, n: ast27.Repr) -> CallExpr: + def visit_Repr(self, n: ast27.Repr) -> Node: # TODO: Comment in visit_Print also applies here return self.visit(ast27.Call( ast27.Name("repr", ast27.Load(), lineno=n.lineno, col_offset=-1), @@ -567,7 +566,7 @@ def visit_Repr(self, n: ast27.Repr) -> CallExpr: # Assert(expr test, expr? msg) @with_line - def visit_Assert(self, n: ast27.Assert) -> AssertStmt: + def visit_Assert(self, n: ast27.Assert) -> Node: return AssertStmt(self.visit(n.test)) # Import(alias* names) @@ -579,7 +578,7 @@ def visit_Import(self, n: ast27.Import) -> Node: # ImportFrom(identifier? module, alias* names, int? level) @with_line - def visit_ImportFrom(self, n: ast27.ImportFrom) -> ImportBase: + def visit_ImportFrom(self, n: ast27.ImportFrom) -> Node: i = None # type: ImportBase if len(n.names) == 1 and n.names[0].name == '*': i = ImportAll(n.module, n.level) @@ -592,34 +591,34 @@ def visit_ImportFrom(self, n: ast27.ImportFrom) -> ImportBase: # Global(identifier* names) @with_line - def visit_Global(self, n: ast27.Global) -> GlobalDecl: + def visit_Global(self, n: ast27.Global) -> Node: return GlobalDecl(n.names) # Expr(expr value) @with_line - def visit_Expr(self, n: ast27.Expr) -> ExpressionStmt: + def visit_Expr(self, n: ast27.Expr) -> Node: value = self.visit(n.value) return ExpressionStmt(value) # Pass @with_line - def visit_Pass(self, n: ast27.Pass) -> PassStmt: + def visit_Pass(self, n: ast27.Pass) -> Node: return PassStmt() # Break @with_line - def visit_Break(self, n: ast27.Break) -> BreakStmt: + def visit_Break(self, n: ast27.Break) -> Node: return BreakStmt() # Continue @with_line - def visit_Continue(self, n: ast27.Continue) -> ContinueStmt: + def visit_Continue(self, n: ast27.Continue) -> Node: return ContinueStmt() # --- expr --- # BoolOp(boolop op, expr* values) @with_line - def visit_BoolOp(self, n: ast27.BoolOp) -> OpExpr: + def visit_BoolOp(self, n: ast27.BoolOp) -> Node: # mypy translates (1 and 2 and 3) as (1 and (2 and 3)) assert len(n.values) >= 2 op = None @@ -631,17 +630,17 @@ def visit_BoolOp(self, n: ast27.BoolOp) -> OpExpr: raise RuntimeError('unknown BoolOp ' + str(type(n))) # potentially inefficient! - def group(vals: List[Expression]) -> OpExpr: + def group(vals: List[Node]) -> Node: if len(vals) == 2: return OpExpr(op, vals[0], vals[1]) else: return OpExpr(op, vals[0], group(vals[1:])) - return group(self.visit_list_expression(n.values)) + return group(self.visit_list(n.values)) # BinOp(expr left, operator op, expr right) @with_line - def visit_BinOp(self, n: ast27.BinOp) -> OpExpr: + def visit_BinOp(self, n: ast27.BinOp) -> Node: op = self.from_operator(n.op) if op is None: @@ -651,7 +650,7 @@ def visit_BinOp(self, n: ast27.BinOp) -> OpExpr: # UnaryOp(unaryop op, expr operand) @with_line - def visit_UnaryOp(self, n: ast27.UnaryOp) -> UnaryExpr: + def visit_UnaryOp(self, n: ast27.UnaryOp) -> Node: op = None if isinstance(n.op, ast27.Invert): op = '~' @@ -669,7 +668,7 @@ def visit_UnaryOp(self, n: ast27.UnaryOp) -> UnaryExpr: # Lambda(arguments args, expr body) @with_line - def visit_Lambda(self, n: ast27.Lambda) -> FuncExpr: + def visit_Lambda(self, n: ast27.Lambda) -> Node: body = ast27.Return(n.body) body.lineno = n.lineno @@ -678,38 +677,37 @@ def visit_Lambda(self, n: ast27.Lambda) -> FuncExpr: # IfExp(expr test, expr body, expr orelse) @with_line - def visit_IfExp(self, n: ast27.IfExp) -> ConditionalExpr: + def visit_IfExp(self, n: ast27.IfExp) -> Node: return ConditionalExpr(self.visit(n.test), self.visit(n.body), self.visit(n.orelse)) # Dict(expr* keys, expr* values) @with_line - def visit_Dict(self, n: ast27.Dict) -> DictExpr: - return DictExpr(list(zip(self.visit_list_expression(n.keys), - self.visit_list_expression(n.values)))) + def visit_Dict(self, n: ast27.Dict) -> Node: + return DictExpr(list(zip(self.visit_list(n.keys), self.visit_list(n.values)))) # Set(expr* elts) @with_line - def visit_Set(self, n: ast27.Set) -> SetExpr: - return SetExpr(self.visit_list_expression(n.elts)) + def visit_Set(self, n: ast27.Set) -> Node: + return SetExpr(self.visit_list(n.elts)) # ListComp(expr elt, comprehension* generators) @with_line - def visit_ListComp(self, n: ast27.ListComp) -> ListComprehension: + def visit_ListComp(self, n: ast27.ListComp) -> Node: return ListComprehension(self.visit_GeneratorExp(cast(ast27.GeneratorExp, n))) # SetComp(expr elt, comprehension* generators) @with_line - def visit_SetComp(self, n: ast27.SetComp) -> SetComprehension: + def visit_SetComp(self, n: ast27.SetComp) -> Node: return SetComprehension(self.visit_GeneratorExp(cast(ast27.GeneratorExp, n))) # DictComp(expr key, expr value, comprehension* generators) @with_line - def visit_DictComp(self, n: ast27.DictComp) -> DictionaryComprehension: + def visit_DictComp(self, n: ast27.DictComp) -> Node: targets = [self.visit(c.target) for c in n.generators] iters = [self.visit(c.iter) for c in n.generators] - ifs_list = [self.visit_list_expression(c.ifs) for c in n.generators] + ifs_list = [self.visit_list(c.ifs) for c in n.generators] return DictionaryComprehension(self.visit(n.key), self.visit(n.value), targets, @@ -721,7 +719,7 @@ def visit_DictComp(self, n: ast27.DictComp) -> DictionaryComprehension: def visit_GeneratorExp(self, n: ast27.GeneratorExp) -> GeneratorExpr: targets = [self.visit(c.target) for c in n.generators] iters = [self.visit(c.iter) for c in n.generators] - ifs_list = [self.visit_list_expression(c.ifs) for c in n.generators] + ifs_list = [self.visit_list(c.ifs) for c in n.generators] return GeneratorExpr(self.visit(n.elt), targets, iters, @@ -729,20 +727,20 @@ def visit_GeneratorExp(self, n: ast27.GeneratorExp) -> GeneratorExpr: # Yield(expr? value) @with_line - def visit_Yield(self, n: ast27.Yield) -> YieldExpr: + def visit_Yield(self, n: ast27.Yield) -> Node: return YieldExpr(self.visit(n.value)) # Compare(expr left, cmpop* ops, expr* comparators) @with_line - def visit_Compare(self, n: ast27.Compare) -> ComparisonExpr: + def visit_Compare(self, n: ast27.Compare) -> Node: operators = [self.from_comp_operator(o) for o in n.ops] - operands = self.visit_list_expression([n.left] + n.comparators) + operands = self.visit_list([n.left] + n.comparators) return ComparisonExpr(operators, operands) # Call(expr func, expr* args, keyword* keywords) # keyword = (identifier? arg, expr value) @with_line - def visit_Call(self, n: ast27.Call) -> CallExpr: + def visit_Call(self, n: ast27.Call) -> Node: arg_types = [] # type: List[ast27.expr] arg_kinds = [] # type: List[int] signature = [] # type: List[Optional[str]] @@ -766,13 +764,13 @@ def visit_Call(self, n: ast27.Call) -> CallExpr: signature.append(None) return CallExpr(self.visit(n.func), - self.visit_list_expression(arg_types), + self.visit_list(arg_types), arg_kinds, cast("List[str]", signature)) # Num(object n) -- a number as a PyObject. @with_line - def visit_Num(self, new: ast27.Num) -> Expression: + def visit_Num(self, new: ast27.Num) -> Node: value = new.n is_inverse = False if new.n < 0: @@ -820,7 +818,7 @@ def visit_Str(self, s: ast27.Str) -> Node: return UnicodeExpr(s.s) # Ellipsis - def visit_Ellipsis(self, n: ast27.Ellipsis) -> EllipsisExpr: + def visit_Ellipsis(self, n: ast27.Ellipsis) -> Node: return EllipsisExpr() # Attribute(expr value, identifier attr, expr_context ctx) @@ -835,35 +833,35 @@ def visit_Attribute(self, n: ast27.Attribute) -> Node: # Subscript(expr value, slice slice, expr_context ctx) @with_line - def visit_Subscript(self, n: ast27.Subscript) -> IndexExpr: + def visit_Subscript(self, n: ast27.Subscript) -> Node: return IndexExpr(self.visit(n.value), self.visit(n.slice)) # Name(identifier id, expr_context ctx) @with_line - def visit_Name(self, n: ast27.Name) -> NameExpr: + def visit_Name(self, n: ast27.Name) -> Node: return NameExpr(n.id) # List(expr* elts, expr_context ctx) @with_line - def visit_List(self, n: ast27.List) -> ListExpr: + def visit_List(self, n: ast27.List) -> Node: return ListExpr([self.visit(e) for e in n.elts]) # Tuple(expr* elts, expr_context ctx) @with_line - def visit_Tuple(self, n: ast27.Tuple) -> TupleExpr: + def visit_Tuple(self, n: ast27.Tuple) -> Node: return TupleExpr([self.visit(e) for e in n.elts]) # --- slice --- # Slice(expr? lower, expr? upper, expr? step) - def visit_Slice(self, n: ast27.Slice) -> SliceExpr: + def visit_Slice(self, n: ast27.Slice) -> Node: return SliceExpr(self.visit(n.lower), self.visit(n.upper), self.visit(n.step)) # ExtSlice(slice* dims) - def visit_ExtSlice(self, n: ast27.ExtSlice) -> TupleExpr: - return TupleExpr(self.visit_list_expression(n.dims)) + def visit_ExtSlice(self, n: ast27.ExtSlice) -> Node: + return TupleExpr(self.visit_list(n.dims)) # Index(expr value) def visit_Index(self, n: ast27.Index) -> Node: diff --git a/mypy/parse.py b/mypy/parse.py index c305fd19a011..39979d7126b8 100644 --- a/mypy/parse.py +++ b/mypy/parse.py @@ -14,25 +14,27 @@ UnicodeLit, FloatLit, Op, Indent, Keyword, Punct, LexError, ComplexLit, EllipsisToken ) +import mypy.types from mypy.nodes import ( - MypyFile, Import, ImportAll, ImportFrom, FuncDef, OverloadedFuncDef, + MypyFile, Import, Node, ImportAll, ImportFrom, FuncDef, OverloadedFuncDef, ClassDef, Decorator, Block, Var, OperatorAssignmentStmt, ExpressionStmt, AssignmentStmt, ReturnStmt, RaiseStmt, AssertStmt, DelStmt, BreakStmt, ContinueStmt, PassStmt, GlobalDecl, - WhileStmt, ForStmt, IfStmt, TryStmt, WithStmt, Expression, + WhileStmt, ForStmt, IfStmt, TryStmt, WithStmt, TupleExpr, GeneratorExpr, ListComprehension, ListExpr, ConditionalExpr, DictExpr, SetExpr, NameExpr, IntExpr, StrExpr, BytesExpr, UnicodeExpr, FloatExpr, CallExpr, SuperExpr, MemberExpr, IndexExpr, SliceExpr, OpExpr, UnaryExpr, FuncExpr, PrintStmt, ImportBase, ComparisonExpr, StarExpr, YieldFromExpr, NonlocalDecl, DictionaryComprehension, SetComprehension, ComplexExpr, EllipsisExpr, YieldExpr, ExecStmt, Argument, - BackquoteExpr, Statement) + BackquoteExpr +) from mypy import defaults from mypy import nodes from mypy.errors import Errors, CompileError from mypy.types import Type, CallableType, AnyType, UnboundType from mypy.parsetype import ( - parse_type, parse_types, parse_signature, TypeParseError + parse_type, parse_types, parse_signature, TypeParseError, parse_str_as_signature ) from mypy.options import Options @@ -233,7 +235,7 @@ def translate_module_id(self, id: str) -> str: return 'builtins' return id - def parse_import_from(self) -> Statement: + def parse_import_from(self) -> Node: self.expect('from') # Build the list of beginning relative tokens. @@ -316,8 +318,8 @@ def parse_qualified_name(self) -> str: # Parsing global definitions - def parse_defs(self) -> List[Statement]: - defs = [] # type: List[Statement] + def parse_defs(self) -> List[Node]: + defs = [] # type: List[Node] while not self.eof(): try: defn, is_simple = self.parse_statement() @@ -338,7 +340,7 @@ def parse_class_def(self) -> ClassDef: metaclass = None try: - base_types = [] # type: List[Expression] + base_types = [] # type: List[Node] try: name_tok = self.expect_type(Name) name = name_tok.string @@ -389,10 +391,10 @@ def parse_class_keywords(self) -> Optional[str]: break return metaclass - def parse_super_type(self) -> Expression: + def parse_super_type(self) -> Node: return self.parse_expression(precedence[',']) - def parse_decorated_function_or_class(self) -> Statement: + def parse_decorated_function_or_class(self) -> Node: decorators = [] no_type_checks = False while self.current_str() == '@': @@ -416,7 +418,7 @@ def parse_decorated_function_or_class(self) -> Statement: cls.decorators = decorators return cls - def is_no_type_check_decorator(self, expr: Expression) -> bool: + def is_no_type_check_decorator(self, expr: Node) -> bool: if isinstance(expr, NameExpr): return expr.name == 'no_type_check' elif isinstance(expr, MemberExpr): @@ -727,7 +729,8 @@ def parse_tuple_arg(self, index: int) -> Tuple[Argument, AssignmentStmt, List[st arg_name = '__tuple_arg_{}'.format(index + 1) if self.pyversion[0] >= 3: self.fail('Tuples in argument lists only supported in Python 2 mode', line) - paren_arg = self.verify_tuple_arg(self.parse_parentheses()) + paren_arg = self.parse_parentheses() + self.verify_tuple_arg(paren_arg) if isinstance(paren_arg, NameExpr): # This isn't a tuple. Revert to a normal argument. arg_name = paren_arg.name @@ -747,18 +750,16 @@ def parse_tuple_arg(self, index: int) -> Tuple[Argument, AssignmentStmt, List[st arg_names = self.find_tuple_arg_argument_names(paren_arg) return Argument(var, None, initializer, kind), decompose, arg_names - def verify_tuple_arg(self, paren_arg: Expression) -> Union[TupleExpr, NameExpr]: - if isinstance(paren_arg, NameExpr): - return paren_arg + def verify_tuple_arg(self, paren_arg: Node) -> None: if isinstance(paren_arg, TupleExpr): if not paren_arg.items: self.fail('Empty tuple not valid as an argument', paren_arg.line) for item in paren_arg.items: self.verify_tuple_arg(item) - return paren_arg - self.fail('Invalid item in tuple argument', paren_arg.line) + elif not isinstance(paren_arg, NameExpr): + self.fail('Invalid item in tuple argument', paren_arg.line) - def find_tuple_arg_argument_names(self, node: Expression) -> List[str]: + def find_tuple_arg_argument_names(self, node: Node) -> List[str]: result = [] # type: List[str] if isinstance(node, TupleExpr): for item in node.items: @@ -779,7 +780,7 @@ def parse_normal_arg(self, require_named: bool, else: type = self.parse_arg_type(allow_signature) - initializer = None # type: Expression + initializer = None # type: Node if self.current_str() == '=': self.expect('=') initializer = self.parse_expression(precedence[',']) @@ -795,7 +796,7 @@ def parse_normal_arg(self, require_named: bool, return Argument(variable, type, initializer, kind), require_named - def set_type_optional(self, type: Type, initializer: Expression) -> None: + def set_type_optional(self, type: Type, initializer: Node) -> None: if not experiments.STRICT_OPTIONAL: return # Indicate that type should be wrapped in an Optional if arg is initialized to None. @@ -803,7 +804,7 @@ def set_type_optional(self, type: Type, initializer: Expression) -> None: if isinstance(type, UnboundType): type.optional = optional - def parse_parameter_annotation(self) -> Expression: + def parse_parameter_annotation(self) -> Node: if self.current_str() == ':': self.skip() return self.parse_expression(precedence[',']) @@ -867,7 +868,7 @@ def parse_block(self, allow_type: bool = False) -> Tuple[Block, Type]: brk = self.expect_break() type = self.parse_type_comment(brk, signature=True) self.expect_indent() - stmt_list = [] # type: List[Statement] + stmt_list = [] # type: List[Node] while (not isinstance(self.current(), Dedent) and not isinstance(self.current(), Eof)): try: @@ -885,7 +886,7 @@ def parse_block(self, allow_type: bool = False) -> Tuple[Block, Type]: node.set_line(colon) return node, type - def try_combine_overloads(self, s: Statement, stmt: List[Statement]) -> bool: + def try_combine_overloads(self, s: Node, stmt: List[Node]) -> bool: if isinstance(s, Decorator) and stmt: fdef = s n = fdef.func.name() @@ -897,8 +898,8 @@ def try_combine_overloads(self, s: Statement, stmt: List[Statement]) -> bool: return True return False - def parse_statement(self) -> Tuple[Statement, bool]: - stmt = None # type: Statement + def parse_statement(self) -> Tuple[Node, bool]: + stmt = None # type: Node t = self.current() ts = self.current_str() is_simple = True # Is this a non-block statement? @@ -963,7 +964,7 @@ def parse_statement(self) -> Tuple[Statement, bool]: stmt.set_line(t) return stmt, is_simple - def parse_expression_or_assignment(self) -> Statement: + def parse_expression_or_assignment(self) -> Node: expr = self.parse_expression(star_expr_allowed=True) if self.current_str() == '=': return self.parse_assignment(expr) @@ -977,7 +978,7 @@ def parse_expression_or_assignment(self) -> Statement: # Expression statement. return ExpressionStmt(expr) - def parse_assignment(self, lvalue: Any) -> AssignmentStmt: + def parse_assignment(self, lvalue: Any) -> Node: """Parse an assignment statement. Assume that lvalue has been parsed already, and the current token is '='. @@ -1127,7 +1128,7 @@ def parse_for_stmt(self) -> ForStmt: node = ForStmt(index, expr, body, else_body) return node - def parse_for_index_variables(self) -> Expression: + def parse_for_index_variables(self) -> Node: # Parse index variables of a 'for' statement. index_items = [] force_tuple = False @@ -1183,21 +1184,19 @@ def parse_if_stmt(self) -> IfStmt: else: return None - def parse_try_stmt(self) -> Statement: + def parse_try_stmt(self) -> Node: self.expect('try') body, _ = self.parse_block() is_error = False vars = [] # type: List[NameExpr] - types = [] # type: List[Expression] + types = [] # type: List[Node] handlers = [] # type: List[Block] while self.current_str() == 'except': self.expect('except') if not isinstance(self.current(), Colon): try: t = self.current() - exp = self.parse_expression(precedence[',']) - exp.set_line(t) - types.append(exp) + types.append(self.parse_expression(precedence[',']).set_line(t)) if self.current_str() == 'as': self.expect('as') vars.append(self.parse_name_expr()) @@ -1288,9 +1287,9 @@ def parse_exec_stmt(self) -> ExecStmt: # Parsing expressions - def parse_expression(self, prec: int = 0, star_expr_allowed: bool = False) -> Expression: + def parse_expression(self, prec: int = 0, star_expr_allowed: bool = False) -> Node: """Parse a subexpression within a specific precedence context.""" - expr = None # type: Expression + expr = None # type: Node current = self.current() # Remember token for setting the line number. # Parse a "value" expression or unary operator expression and store @@ -1410,18 +1409,18 @@ def parse_expression(self, prec: int = 0, star_expr_allowed: bool = False) -> Ex return expr - def parse_parentheses(self) -> Expression: + def parse_parentheses(self) -> Node: self.skip() if self.current_str() == ')': # Empty tuple (). - expr = self.parse_empty_tuple_expr() # type: Expression + expr = self.parse_empty_tuple_expr() # type: Node else: # Parenthesised expression. expr = self.parse_expression(0, star_expr_allowed=True) self.expect(')') return expr - def parse_star_expr(self) -> Expression: + def parse_star_expr(self) -> Node: star = self.expect('*') expr = self.parse_expression(precedence['*u']) expr = StarExpr(expr) @@ -1434,7 +1433,7 @@ def parse_empty_tuple_expr(self) -> TupleExpr: node = TupleExpr([]) return node - def parse_list_expr(self) -> Expression: + def parse_list_expr(self) -> Node: """Parse list literal or list comprehension.""" items = [] self.expect('[') @@ -1452,7 +1451,7 @@ def parse_list_expr(self) -> Expression: expr = ListExpr(items) return expr - def parse_generator_expr(self, left_expr: Expression) -> GeneratorExpr: + def parse_generator_expr(self, left_expr: Node) -> GeneratorExpr: tok = self.current() indices, sequences, condlists = self.parse_comp_for() @@ -1460,10 +1459,10 @@ def parse_generator_expr(self, left_expr: Expression) -> GeneratorExpr: gen.set_line(tok) return gen - def parse_comp_for(self) -> Tuple[List[Expression], List[Expression], List[List[Expression]]]: + def parse_comp_for(self) -> Tuple[List[Node], List[Node], List[List[Node]]]: indices = [] sequences = [] - condlists = [] # type: List[List[Expression]] + condlists = [] # type: List[List[Node]] while self.current_str() == 'for': conds = [] self.expect('for') @@ -1482,26 +1481,24 @@ def parse_comp_for(self) -> Tuple[List[Expression], List[Expression], List[List[ return indices, sequences, condlists - def parse_expression_list(self) -> Expression: + def parse_expression_list(self) -> Node: prec = precedence[''] expr = self.parse_expression(prec) if self.current_str() != ',': return expr else: t = self.current() - exp = self.parse_tuple_expr(expr, prec) - exp.set_line(t) - return exp + return self.parse_tuple_expr(expr, prec).set_line(t) - def parse_conditional_expr(self, left_expr: Expression) -> ConditionalExpr: + def parse_conditional_expr(self, left_expr: Node) -> ConditionalExpr: self.expect('if') cond = self.parse_expression(precedence['']) self.expect('else') else_expr = self.parse_expression(precedence['']) return ConditionalExpr(cond, left_expr, else_expr) - def parse_dict_or_set_expr(self) -> Expression: - items = [] # type: List[Tuple[Expression, Expression]] + def parse_dict_or_set_expr(self) -> Node: + items = [] # type: List[Tuple[Node, Node]] self.expect('{') while self.current_str() != '}' and not self.eol(): key = self.parse_expression(precedence['']) @@ -1523,7 +1520,7 @@ def parse_dict_or_set_expr(self) -> Expression: node = DictExpr(items) return node - def parse_set_expr(self, first: Expression) -> SetExpr: + def parse_set_expr(self, first: Node) -> SetExpr: items = [first] while self.current_str() != '}' and not self.eol(): self.expect(',') @@ -1534,13 +1531,13 @@ def parse_set_expr(self, first: Expression) -> SetExpr: expr = SetExpr(items) return expr - def parse_set_comprehension(self, expr: Expression) -> SetComprehension: + def parse_set_comprehension(self, expr: Node) -> SetComprehension: gen = self.parse_generator_expr(expr) self.expect('}') set_comp = SetComprehension(gen) return set_comp - def parse_dict_comprehension(self, key: Expression, value: Expression, + def parse_dict_comprehension(self, key: Node, value: Node, colon: Token) -> DictionaryComprehension: indices, sequences, condlists = self.parse_comp_for() dic = DictionaryComprehension(key, value, indices, sequences, condlists) @@ -1548,7 +1545,7 @@ def parse_dict_comprehension(self, key: Expression, value: Expression, self.expect('}') return dic - def parse_tuple_expr(self, expr: Expression, + def parse_tuple_expr(self, expr: Node, prec: int = precedence[',']) -> TupleExpr: items = [expr] while True: @@ -1585,7 +1582,7 @@ def parse_int_expr(self) -> IntExpr: node = IntExpr(value) return node - def parse_str_expr(self) -> Expression: + def parse_str_expr(self) -> Node: # XXX \uxxxx literals token = self.expect_type(StrLit) value = cast(StrLit, token).parsed() @@ -1598,12 +1595,12 @@ def parse_str_expr(self) -> Expression: value += token.parsed() is_unicode = True if is_unicode or (self.pyversion[0] == 2 and 'unicode_literals' in self.future_options): - node = UnicodeExpr(value) # type: Expression + node = UnicodeExpr(value) # type: Node else: node = StrExpr(value) return node - def parse_bytes_literal(self) -> Expression: + def parse_bytes_literal(self) -> Node: # XXX \uxxxx literals tok = [self.expect_type(BytesLit)] value = (cast(BytesLit, tok[0])).parsed() @@ -1611,12 +1608,12 @@ def parse_bytes_literal(self) -> Expression: t = cast(BytesLit, self.skip()) value += t.parsed() if self.pyversion[0] >= 3: - node = BytesExpr(value) # type: Expression + node = BytesExpr(value) # type: Node else: node = StrExpr(value) return node - def parse_unicode_literal(self) -> Expression: + def parse_unicode_literal(self) -> Node: # XXX \uxxxx literals token = self.expect_type(UnicodeLit) value = cast(UnicodeLit, token).parsed() @@ -1625,7 +1622,7 @@ def parse_unicode_literal(self) -> Expression: value += token.parsed() if self.pyversion[0] >= 3: # Python 3.3 supports u'...' as an alias of '...'. - node = StrExpr(value) # type: Expression + node = StrExpr(value) # type: Node else: node = UnicodeExpr(value) return node @@ -1647,7 +1644,7 @@ def parse_call_expr(self, callee: Any) -> CallExpr: node = CallExpr(callee, args, kinds, names) return node - def parse_arg_expr(self) -> Tuple[List[Expression], List[int], List[str]]: + def parse_arg_expr(self) -> Tuple[List[Node], List[int], List[str]]: """Parse arguments in a call expression (within '(' and ')'). Return a tuple with these items: @@ -1655,7 +1652,7 @@ def parse_arg_expr(self) -> Tuple[List[Expression], List[int], List[str]]: argument kinds argument names (for named arguments; None for ordinary args) """ - args = [] # type: List[Expression] + args = [] # type: List[Node] kinds = [] # type: List[int] names = [] # type: List[str] var_arg = False @@ -1693,13 +1690,13 @@ def parse_arg_expr(self) -> Tuple[List[Expression], List[int], List[str]]: self.expect(',') return args, kinds, names - def parse_member_expr(self, expr: Any) -> Expression: + def parse_member_expr(self, expr: Any) -> Node: self.expect('.') name = self.expect_type(Name) if (isinstance(expr, CallExpr) and isinstance(expr.callee, NameExpr) and expr.callee.name == 'super'): # super() expression - node = SuperExpr(name.string) # type: Expression + node = SuperExpr(name.string) # type: Node else: node = MemberExpr(expr, name.string) return node @@ -1721,7 +1718,7 @@ def parse_index_expr(self, base: Any) -> IndexExpr: node = IndexExpr(base, index) return node - def parse_slice_item(self) -> Expression: + def parse_slice_item(self) -> Node: if self.current_str() != ':': if self.current_str() == '...': # Ellipsis is valid here even in Python 2 (but not elsewhere). @@ -1746,11 +1743,10 @@ def parse_slice_item(self) -> Expression: self.expect(':') if self.current_str() not in (']', ','): stride = self.parse_expression(precedence[',']) - item = SliceExpr(index, end_index, stride) - item.set_line(colon.line) + item = SliceExpr(index, end_index, stride).set_line(colon.line) return item - def parse_bin_op_expr(self, left: Expression, prec: int) -> OpExpr: + def parse_bin_op_expr(self, left: Node, prec: int) -> OpExpr: op = self.expect_type(Op) op_str = op.string if op_str == '~': @@ -1760,7 +1756,7 @@ def parse_bin_op_expr(self, left: Expression, prec: int) -> OpExpr: node = OpExpr(op_str, left, right) return node - def parse_comparison_expr(self, left: Expression, prec: int) -> ComparisonExpr: + def parse_comparison_expr(self, left: Node, prec: int) -> ComparisonExpr: operators_str = [] operands = [left] @@ -1817,9 +1813,7 @@ def parse_lambda_expr(self) -> FuncExpr: expr = self.parse_expression(precedence[',']) - ret = ReturnStmt(expr) - ret.set_line(lambda_tok) - nodes = [ret] # type: List[Statement] + nodes = [ReturnStmt(expr).set_line(lambda_tok)] # Potentially insert extra assignment statements to the beginning of the # body, used to decompose Python 2 tuple arguments. nodes[:0] = extra_stmts diff --git a/mypy/treetransform.py b/mypy/treetransform.py index 8ef96081c13c..b6143d4a7fef 100644 --- a/mypy/treetransform.py +++ b/mypy/treetransform.py @@ -3,10 +3,10 @@ Subclass TransformVisitor to perform non-trivial transformations. """ -from typing import List, Dict, cast, TypeVar, Iterable, Optional +from typing import List, Dict, cast from mypy.nodes import ( - MypyFile, Import, Node, Expression, ImportAll, ImportFrom, FuncItem, FuncDef, + MypyFile, Import, Node, ImportAll, ImportFrom, FuncItem, FuncDef, OverloadedFuncDef, ClassDef, Decorator, Block, Var, OperatorAssignmentStmt, ExpressionStmt, AssignmentStmt, ReturnStmt, RaiseStmt, AssertStmt, DelStmt, BreakStmt, ContinueStmt, @@ -19,16 +19,13 @@ ComparisonExpr, TempNode, StarExpr, YieldFromExpr, NamedTupleExpr, NonlocalDecl, SetComprehension, DictionaryComprehension, ComplexExpr, TypeAliasExpr, EllipsisExpr, - YieldExpr, ExecStmt, Argument, BackquoteExpr, AwaitExpr, Statement + YieldExpr, ExecStmt, Argument, BackquoteExpr, AwaitExpr, ) -from mypy.types import Type, FunctionLike +from mypy.types import Type, FunctionLike, Instance from mypy.traverser import TraverserVisitor from mypy.visitor import NodeVisitor -T = TypeVar('T', Expression, Statement) - - class TransformVisitor(NodeVisitor[Node]): """Transform a semantically analyzed AST (or subtree) to an identical copy. @@ -58,7 +55,7 @@ def __init__(self) -> None: # transformed node). self.func_placeholder_map = {} # type: Dict[FuncDef, FuncDef] - def visit_mypy_file(self, node: MypyFile) -> MypyFile: + def visit_mypy_file(self, node: MypyFile) -> Node: # NOTE: The 'names' and 'imports' instance variables will be empty! new = MypyFile(self.nodes(node.defs), [], node.is_bom, ignored_lines=set(node.ignored_lines)) @@ -68,13 +65,13 @@ def visit_mypy_file(self, node: MypyFile) -> MypyFile: new.names = SymbolTable() return new - def visit_import(self, node: Import) -> Import: + def visit_import(self, node: Import) -> Node: return Import(node.ids[:]) - def visit_import_from(self, node: ImportFrom) -> ImportFrom: + def visit_import_from(self, node: ImportFrom) -> Node: return ImportFrom(node.id, node.relative, node.names[:]) - def visit_import_all(self, node: ImportAll) -> ImportAll: + def visit_import_all(self, node: ImportAll) -> Node: return ImportAll(node.id, node.relative) def copy_argument(self, argument: Argument) -> Argument: @@ -146,7 +143,7 @@ def visit_func_def(self, node: FuncDef) -> FuncDef: else: return new - def visit_func_expr(self, node: FuncExpr) -> FuncExpr: + def visit_func_expr(self, node: FuncExpr) -> Node: new = FuncExpr([self.copy_argument(arg) for arg in node.arguments], self.block(node.body), cast(FunctionLike, self.optional_type(node.type))) @@ -172,7 +169,7 @@ def duplicate_inits(self, result.append(None) return result - def visit_overloaded_func_def(self, node: OverloadedFuncDef) -> OverloadedFuncDef: + def visit_overloaded_func_def(self, node: OverloadedFuncDef) -> Node: items = [self.visit_decorator(decorator) for decorator in node.items] for newitem, olditem in zip(items, node.items): @@ -183,7 +180,7 @@ def visit_overloaded_func_def(self, node: OverloadedFuncDef) -> OverloadedFuncDe new.info = node.info return new - def visit_class_def(self, node: ClassDef) -> ClassDef: + def visit_class_def(self, node: ClassDef) -> Node: new = ClassDef(node.name, self.block(node.defs), node.type_vars, @@ -191,15 +188,15 @@ def visit_class_def(self, node: ClassDef) -> ClassDef: node.metaclass) new.fullname = node.fullname new.info = node.info - new.decorators = [cast(Expression, decorator.accept(self)) + new.decorators = [decorator.accept(self) for decorator in node.decorators] new.is_builtinclass = node.is_builtinclass return new - def visit_global_decl(self, node: GlobalDecl) -> GlobalDecl: + def visit_global_decl(self, node: GlobalDecl) -> Node: return GlobalDecl(node.names[:]) - def visit_nonlocal_decl(self, node: NonlocalDecl) -> NonlocalDecl: + def visit_nonlocal_decl(self, node: NonlocalDecl) -> Node: return NonlocalDecl(node.names[:]) def visit_block(self, node: Block) -> Block: @@ -232,65 +229,64 @@ def visit_var(self, node: Var) -> Var: self.var_map[node] = new return new - def visit_expression_stmt(self, node: ExpressionStmt) -> ExpressionStmt: + def visit_expression_stmt(self, node: ExpressionStmt) -> Node: return ExpressionStmt(self.node(node.expr)) - def visit_assignment_stmt(self, node: AssignmentStmt) -> AssignmentStmt: + def visit_assignment_stmt(self, node: AssignmentStmt) -> Node: return self.duplicate_assignment(node) def duplicate_assignment(self, node: AssignmentStmt) -> AssignmentStmt: - lvalues = self.nodes(node.lvalues) - new = AssignmentStmt(lvalues, + new = AssignmentStmt(self.nodes(node.lvalues), self.node(node.rvalue), self.optional_type(node.type)) new.line = node.line return new def visit_operator_assignment_stmt(self, - node: OperatorAssignmentStmt) -> OperatorAssignmentStmt: + node: OperatorAssignmentStmt) -> Node: return OperatorAssignmentStmt(node.op, self.node(node.lvalue), self.node(node.rvalue)) - def visit_while_stmt(self, node: WhileStmt) -> WhileStmt: + def visit_while_stmt(self, node: WhileStmt) -> Node: return WhileStmt(self.node(node.expr), self.block(node.body), self.optional_block(node.else_body)) - def visit_for_stmt(self, node: ForStmt) -> ForStmt: + def visit_for_stmt(self, node: ForStmt) -> Node: return ForStmt(self.node(node.index), self.node(node.expr), self.block(node.body), self.optional_block(node.else_body)) - def visit_return_stmt(self, node: ReturnStmt) -> ReturnStmt: + def visit_return_stmt(self, node: ReturnStmt) -> Node: return ReturnStmt(self.optional_node(node.expr)) - def visit_assert_stmt(self, node: AssertStmt) -> AssertStmt: + def visit_assert_stmt(self, node: AssertStmt) -> Node: return AssertStmt(self.node(node.expr)) - def visit_del_stmt(self, node: DelStmt) -> DelStmt: + def visit_del_stmt(self, node: DelStmt) -> Node: return DelStmt(self.node(node.expr)) - def visit_if_stmt(self, node: IfStmt) -> IfStmt: + def visit_if_stmt(self, node: IfStmt) -> Node: return IfStmt(self.nodes(node.expr), self.blocks(node.body), self.optional_block(node.else_body)) - def visit_break_stmt(self, node: BreakStmt) -> BreakStmt: + def visit_break_stmt(self, node: BreakStmt) -> Node: return BreakStmt() - def visit_continue_stmt(self, node: ContinueStmt) -> ContinueStmt: + def visit_continue_stmt(self, node: ContinueStmt) -> Node: return ContinueStmt() - def visit_pass_stmt(self, node: PassStmt) -> PassStmt: + def visit_pass_stmt(self, node: PassStmt) -> Node: return PassStmt() - def visit_raise_stmt(self, node: RaiseStmt) -> RaiseStmt: + def visit_raise_stmt(self, node: RaiseStmt) -> Node: return RaiseStmt(self.optional_node(node.expr), self.optional_node(node.from_expr)) - def visit_try_stmt(self, node: TryStmt) -> TryStmt: + def visit_try_stmt(self, node: TryStmt) -> Node: return TryStmt(self.block(node.body), self.optional_names(node.vars), self.optional_nodes(node.types), @@ -298,46 +294,46 @@ def visit_try_stmt(self, node: TryStmt) -> TryStmt: self.optional_block(node.else_body), self.optional_block(node.finally_body)) - def visit_with_stmt(self, node: WithStmt) -> WithStmt: + def visit_with_stmt(self, node: WithStmt) -> Node: return WithStmt(self.nodes(node.expr), self.optional_nodes(node.target), self.block(node.body)) - def visit_print_stmt(self, node: PrintStmt) -> PrintStmt: + def visit_print_stmt(self, node: PrintStmt) -> Node: return PrintStmt(self.nodes(node.args), node.newline, self.optional_node(node.target)) - def visit_exec_stmt(self, node: ExecStmt) -> ExecStmt: + def visit_exec_stmt(self, node: ExecStmt) -> Node: return ExecStmt(self.node(node.expr), self.optional_node(node.variables1), self.optional_node(node.variables2)) - def visit_star_expr(self, node: StarExpr) -> StarExpr: + def visit_star_expr(self, node: StarExpr) -> Node: return StarExpr(node.expr) - def visit_int_expr(self, node: IntExpr) -> IntExpr: + def visit_int_expr(self, node: IntExpr) -> Node: return IntExpr(node.value) - def visit_str_expr(self, node: StrExpr) -> StrExpr: + def visit_str_expr(self, node: StrExpr) -> Node: return StrExpr(node.value) - def visit_bytes_expr(self, node: BytesExpr) -> BytesExpr: + def visit_bytes_expr(self, node: BytesExpr) -> Node: return BytesExpr(node.value) - def visit_unicode_expr(self, node: UnicodeExpr) -> UnicodeExpr: + def visit_unicode_expr(self, node: UnicodeExpr) -> Node: return UnicodeExpr(node.value) - def visit_float_expr(self, node: FloatExpr) -> FloatExpr: + def visit_float_expr(self, node: FloatExpr) -> Node: return FloatExpr(node.value) - def visit_complex_expr(self, node: ComplexExpr) -> ComplexExpr: + def visit_complex_expr(self, node: ComplexExpr) -> Node: return ComplexExpr(node.value) - def visit_ellipsis(self, node: EllipsisExpr) -> EllipsisExpr: + def visit_ellipsis(self, node: EllipsisExpr) -> Node: return EllipsisExpr() - def visit_name_expr(self, node: NameExpr) -> NameExpr: + def visit_name_expr(self, node: NameExpr) -> Node: return self.duplicate_name(node) def duplicate_name(self, node: NameExpr) -> NameExpr: @@ -347,7 +343,7 @@ def duplicate_name(self, node: NameExpr) -> NameExpr: self.copy_ref(new, node) return new - def visit_member_expr(self, node: MemberExpr) -> MemberExpr: + def visit_member_expr(self, node: MemberExpr) -> Node: member = MemberExpr(self.node(node.expr), node.name) if node.def_var: @@ -367,63 +363,63 @@ def copy_ref(self, new: RefExpr, original: RefExpr) -> None: new.node = target new.is_def = original.is_def - def visit_yield_from_expr(self, node: YieldFromExpr) -> YieldFromExpr: + def visit_yield_from_expr(self, node: YieldFromExpr) -> Node: return YieldFromExpr(self.node(node.expr)) - def visit_yield_expr(self, node: YieldExpr) -> YieldExpr: + def visit_yield_expr(self, node: YieldExpr) -> Node: return YieldExpr(self.node(node.expr)) - def visit_await_expr(self, node: AwaitExpr) -> AwaitExpr: + def visit_await_expr(self, node: AwaitExpr) -> Node: return AwaitExpr(self.node(node.expr)) - def visit_call_expr(self, node: CallExpr) -> CallExpr: + def visit_call_expr(self, node: CallExpr) -> Node: return CallExpr(self.node(node.callee), self.nodes(node.args), node.arg_kinds[:], node.arg_names[:], self.optional_node(node.analyzed)) - def visit_op_expr(self, node: OpExpr) -> OpExpr: + def visit_op_expr(self, node: OpExpr) -> Node: new = OpExpr(node.op, self.node(node.left), self.node(node.right)) new.method_type = self.optional_type(node.method_type) return new - def visit_comparison_expr(self, node: ComparisonExpr) -> ComparisonExpr: + def visit_comparison_expr(self, node: ComparisonExpr) -> Node: new = ComparisonExpr(node.operators, self.nodes(node.operands)) new.method_types = [self.optional_type(t) for t in node.method_types] return new - def visit_cast_expr(self, node: CastExpr) -> Expression: + def visit_cast_expr(self, node: CastExpr) -> Node: return CastExpr(self.node(node.expr), self.type(node.type)) - def visit_reveal_type_expr(self, node: RevealTypeExpr) -> RevealTypeExpr: + def visit_reveal_type_expr(self, node: RevealTypeExpr) -> Node: return RevealTypeExpr(self.node(node.expr)) - def visit_super_expr(self, node: SuperExpr) -> SuperExpr: + def visit_super_expr(self, node: SuperExpr) -> Node: new = SuperExpr(node.name) new.info = node.info return new - def visit_unary_expr(self, node: UnaryExpr) -> UnaryExpr: + def visit_unary_expr(self, node: UnaryExpr) -> Node: new = UnaryExpr(node.op, self.node(node.expr)) new.method_type = self.optional_type(node.method_type) return new - def visit_list_expr(self, node: ListExpr) -> ListExpr: + def visit_list_expr(self, node: ListExpr) -> Node: return ListExpr(self.nodes(node.items)) - def visit_dict_expr(self, node: DictExpr) -> DictExpr: + def visit_dict_expr(self, node: DictExpr) -> Node: return DictExpr([(self.node(key), self.node(value)) for key, value in node.items]) - def visit_tuple_expr(self, node: TupleExpr) -> TupleExpr: + def visit_tuple_expr(self, node: TupleExpr) -> Node: return TupleExpr(self.nodes(node.items)) - def visit_set_expr(self, node: SetExpr) -> SetExpr: + def visit_set_expr(self, node: SetExpr) -> Node: return SetExpr(self.nodes(node.items)) - def visit_index_expr(self, node: IndexExpr) -> IndexExpr: + def visit_index_expr(self, node: IndexExpr) -> Node: new = IndexExpr(self.node(node.base), self.node(node.index)) if node.method_type: new.method_type = self.type(node.method_type) @@ -439,26 +435,24 @@ def visit_type_application(self, node: TypeApplication) -> TypeApplication: return TypeApplication(self.node(node.expr), self.types(node.types)) - def visit_list_comprehension(self, node: ListComprehension) -> ListComprehension: + def visit_list_comprehension(self, node: ListComprehension) -> Node: generator = self.duplicate_generator(node.generator) generator.set_line(node.generator.line) return ListComprehension(generator) - def visit_set_comprehension(self, node: SetComprehension) -> SetComprehension: + def visit_set_comprehension(self, node: SetComprehension) -> Node: generator = self.duplicate_generator(node.generator) generator.set_line(node.generator.line) return SetComprehension(generator) - def visit_dictionary_comprehension(self, - node: DictionaryComprehension - ) -> DictionaryComprehension: + def visit_dictionary_comprehension(self, node: DictionaryComprehension) -> Node: return DictionaryComprehension(self.node(node.key), self.node(node.value), [self.node(index) for index in node.indices], [self.node(s) for s in node.sequences], [[self.node(cond) for cond in conditions] for conditions in node.condlists]) - def visit_generator_expr(self, node: GeneratorExpr) -> GeneratorExpr: + def visit_generator_expr(self, node: GeneratorExpr) -> Node: return self.duplicate_generator(node) def duplicate_generator(self, node: GeneratorExpr) -> GeneratorExpr: @@ -468,20 +462,20 @@ def duplicate_generator(self, node: GeneratorExpr) -> GeneratorExpr: [[self.node(cond) for cond in conditions] for conditions in node.condlists]) - def visit_slice_expr(self, node: SliceExpr) -> SliceExpr: + def visit_slice_expr(self, node: SliceExpr) -> Node: return SliceExpr(self.optional_node(node.begin_index), self.optional_node(node.end_index), self.optional_node(node.stride)) - def visit_conditional_expr(self, node: ConditionalExpr) -> ConditionalExpr: + def visit_conditional_expr(self, node: ConditionalExpr) -> Node: return ConditionalExpr(self.node(node.cond), self.node(node.if_expr), self.node(node.else_expr)) - def visit_backquote_expr(self, node: BackquoteExpr) -> BackquoteExpr: + def visit_backquote_expr(self, node: BackquoteExpr) -> Node: return BackquoteExpr(self.node(node.expr)) - def visit_type_var_expr(self, node: TypeVarExpr) -> TypeVarExpr: + def visit_type_var_expr(self, node: TypeVarExpr) -> Node: return TypeVarExpr(node.name(), node.fullname(), self.types(node.values), self.type(node.upper_bound), variance=node.variance) @@ -492,17 +486,17 @@ def visit_type_alias_expr(self, node: TypeAliasExpr) -> TypeAliasExpr: def visit_newtype_expr(self, node: NewTypeExpr) -> NewTypeExpr: return NewTypeExpr(node.info) - def visit_namedtuple_expr(self, node: NamedTupleExpr) -> NamedTupleExpr: + def visit_namedtuple_expr(self, node: NamedTupleExpr) -> Node: return NamedTupleExpr(node.info) - def visit__promote_expr(self, node: PromoteExpr) -> PromoteExpr: + def visit__promote_expr(self, node: PromoteExpr) -> Node: return PromoteExpr(node.type) - def visit_temp_node(self, node: TempNode) -> TempNode: + def visit_temp_node(self, node: TempNode) -> Node: return TempNode(self.type(node.type)) - def node(self, node: T) -> T: - new = cast(T, node.accept(self)) + def node(self, node: Node) -> Node: + new = node.accept(self) new.set_line(node.line) return new @@ -510,7 +504,7 @@ def node(self, node: T) -> T: # # All the node helpers also propagate line numbers. - def optional_node(self, node: T) -> Optional[T]: + def optional_node(self, node: Node) -> Node: if node: return self.node(node) else: @@ -527,10 +521,10 @@ def optional_block(self, block: Block) -> Block: else: return None - def nodes(self, nodes: Iterable[T]) -> List[T]: + def nodes(self, nodes: List[Node]) -> List[Node]: return [self.node(node) for node in nodes] - def optional_nodes(self, nodes: List[T]) -> List[Optional[T]]: + def optional_nodes(self, nodes: List[Node]) -> List[Node]: return [self.optional_node(node) for node in nodes] def blocks(self, blocks: List[Block]) -> List[Block]: @@ -539,7 +533,7 @@ def blocks(self, blocks: List[Block]) -> List[Block]: def names(self, names: List[NameExpr]) -> List[NameExpr]: return [self.duplicate_name(name) for name in names] - def optional_names(self, names: List[NameExpr]) -> List[Optional[NameExpr]]: + def optional_names(self, names: List[NameExpr]) -> List[NameExpr]: result = [] # type: List[NameExpr] for name in names: if name: @@ -552,7 +546,7 @@ def type(self, type: Type) -> Type: # Override this method to transform types. return type - def optional_type(self, type: Type) -> Optional[Type]: + def optional_type(self, type: Type) -> Type: if type: return self.type(type) else: @@ -561,7 +555,7 @@ def optional_type(self, type: Type) -> Optional[Type]: def types(self, types: List[Type]) -> List[Type]: return [self.type(type) for type in types] - def optional_types(self, types: List[Type]) -> List[Optional[Type]]: + def optional_types(self, types: List[Type]) -> List[Type]: return [self.optional_type(type) for type in types] From 7a46e7a52ec9f89071e1ef4742b6948e32053c3d Mon Sep 17 00:00:00 2001 From: Elazar Gershuni Date: Wed, 14 Sep 2016 23:28:42 +0300 Subject: [PATCH 10/11] Argument <: Declaration --- mypy/nodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/nodes.py b/mypy/nodes.py index c5290dfe8a92..8f2e9c45dcf9 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -340,7 +340,7 @@ def deserialize(cls, data: JsonDict) -> 'OverloadedFuncDef': return res -class Argument(Node): +class Argument(Declaration): """A single argument in a FuncItem.""" variable = None # type: Var From 171eca5c862eca452110b20aaa6005a5307a0631 Mon Sep 17 00:00:00 2001 From: Elazar Date: Thu, 15 Sep 2016 02:15:25 +0300 Subject: [PATCH 11/11] revert `Declaration` (which was alias anyway) --- mypy/nodes.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mypy/nodes.py b/mypy/nodes.py index 8f2e9c45dcf9..d243c6b10611 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -121,7 +121,6 @@ def accept(self, visitor: NodeVisitor[T]) -> T: # fields of Node subtypes are expected to contain. Statement = Node Expression = Node -Declaration = Node class SymbolNode(Node): @@ -340,7 +339,7 @@ def deserialize(cls, data: JsonDict) -> 'OverloadedFuncDef': return res -class Argument(Declaration): +class Argument(Node): """A single argument in a FuncItem.""" variable = None # type: Var @@ -572,7 +571,7 @@ def deserialize(cls, data: JsonDict) -> 'Decorator': return dec -class Var(SymbolNode, Declaration): +class Var(SymbolNode, Node): """A variable. It can refer to global/local variable or a data attribute.