Example #1
0
 def duplicate_assignment(self, node: AssignmentStmt) -> AssignmentStmt:
     new = AssignmentStmt(self.expressions(node.lvalues),
                          self.expr(node.rvalue),
                          self.optional_type(node.type))
     new.line = node.line
     new.is_final_def = node.is_final_def
     return new
Example #2
0
 def duplicate_assignment(self, node: AssignmentStmt) -> AssignmentStmt:
     new = AssignmentStmt(self.expressions(node.lvalues),
                          self.expr(node.rvalue),
                          self.optional_type(node.type))
     new.line = node.line
     new.is_final_def = node.is_final_def
     return new
Example #3
0
 def visit_assignment_stmt(self, node: AssignmentStmt) -> None:
     node.type = node.unanalyzed_type
     node.is_final_def = False
     if self.type and not self.is_class_body:
         for lvalue in node.lvalues:
             self.process_lvalue_in_method(lvalue)
     super().visit_assignment_stmt(node)
Example #4
0
 def visit_assignment_stmt(self, node: AssignmentStmt) -> None:
     node.type = node.unanalyzed_type
     node.is_final_def = False
     if self.type and not self.is_class_body:
         for lvalue in node.lvalues:
             self.process_lvalue_in_method(lvalue)
     super().visit_assignment_stmt(node)
Example #5
0
 def convert_arg(index: int, arg: ast27.expr) -> Var:
     if isinstance(arg, ast27.Name):
         v = arg.id
     elif isinstance(arg, ast27.Tuple):
         v = '__tuple_arg_{}'.format(index + 1)
         rvalue = NameExpr(v)
         rvalue.set_line(line)
         assignment = AssignmentStmt([self.visit(arg)], rvalue)
         assignment.set_line(line)
         decompose_stmts.append(assignment)
     else:
         raise RuntimeError("'{}' is not a valid argument.".format(ast27.dump(arg)))
     return Var(v)
Example #6
0
 def convert_arg(index: int, arg: ast27.expr) -> Var:
     if isinstance(arg, ast27.Name):
         v = arg.id
     elif isinstance(arg, ast27.Tuple):
         v = '__tuple_arg_{}'.format(index + 1)
         rvalue = NameExpr(v)
         rvalue.set_line(line)
         assignment = AssignmentStmt([self.visit(arg)], rvalue)
         assignment.set_line(line)
         decompose_stmts.append(assignment)
     else:
         raise RuntimeError("'{}' is not a valid argument.".format(ast27.dump(arg)))
     return Var(v)
Example #7
0
 def visit_Assign(self, n: ast35.Assign) -> AssignmentStmt:
     typ = None
     if hasattr(n,
                'annotation') and n.annotation is not None:  # type: ignore
         new_syntax = True
     else:
         new_syntax = False
     if new_syntax and self.pyversion < (3, 6):
         raise TypeCommentParseError(
             'Variable annotation syntax is only '
             'suppoted in Python 3.6, use type '
             'comment instead', n.lineno, n.col_offset)
     # typed_ast prevents having both type_comment and annotation.
     if n.type_comment is not None:
         typ = parse_type_comment(n.type_comment, n.lineno)
     elif new_syntax:
         typ = TypeConverter(line=n.lineno).visit(
             n.annotation)  # type: ignore
         typ.column = n.annotation.col_offset
     if n.value is None:  # always allow 'x: int'
         rvalue = TempNode(AnyType())  # type: Expression
     else:
         rvalue = self.visit(n.value)
     lvalues = self.translate_expr_list(n.targets)
     return AssignmentStmt(lvalues, rvalue, type=typ, new_syntax=new_syntax)
Example #8
0
def _apply_type_to_mapped_statement(
    api: SemanticAnalyzerPluginInterface,
    stmt: AssignmentStmt,
    lvalue: NameExpr,
    left_hand_explicit_type: Optional[Union[Instance, UnionType]],
    python_type_for_type: Union[Instance, UnionType],
) -> None:
    """Apply the Mapped[<type>] annotation and right hand object to a
    declarative assignment statement.

    This converts a Python declarative class statement such as::

        class User(Base):
            # ...

            attrname = Column(Integer)

    To one that describes the final Python behavior to Mypy::

        class User(Base):
            # ...

            attrname : Mapped[Optional[int]] = <meaningless temp node>

    """
    descriptor = api.modules["sqlalchemy.orm.attributes"].names["Mapped"]

    left_node = lvalue.node

    inst = Instance(descriptor.node, [python_type_for_type])

    if left_hand_explicit_type is not None:
        left_node.type = Instance(descriptor.node, [left_hand_explicit_type])
    else:
        lvalue.is_inferred_def = False
        left_node.type = inst

    # so to have it skip the right side totally, we can do this:
    # stmt.rvalue = TempNode(AnyType(TypeOfAny.special_form))

    # however, if we instead manufacture a new node that uses the old
    # one, then we can still get type checking for the call itself,
    # e.g. the Column, relationship() call, etc.

    # rewrite the node as:
    # <attr> : Mapped[<typ>] =
    # _sa_Mapped._empty_constructor(<original CallExpr from rvalue>)
    # the original right-hand side is maintained so it gets type checked
    # internally
    api.add_symbol_table_node("_sa_Mapped", descriptor)
    column_descriptor = nodes.NameExpr("_sa_Mapped")
    column_descriptor.fullname = "sqlalchemy.orm.Mapped"
    mm = nodes.MemberExpr(column_descriptor, "_empty_constructor")
    orig_call_expr = stmt.rvalue
    stmt.rvalue = CallExpr(
        mm,
        [orig_call_expr],
        [nodes.ARG_POS],
        ["arg1"],
    )
Example #9
0
    def copy_argument(self, argument: Argument) -> Argument:
        init_stmt = None  # type: AssignmentStmt

        if argument.initialization_statement:
            init_lvalue = cast(
                NameExpr,
                self.node(argument.initialization_statement.lvalues[0]),
            )
            init_lvalue.set_line(argument.line)
            init_stmt = AssignmentStmt(
                [init_lvalue],
                self.node(argument.initialization_statement.rvalue),
                self.optional_type(argument.initialization_statement.type),
            )

        arg = Argument(
            self.visit_var(argument.variable),
            argument.type_annotation,
            argument.initializer,
            argument.kind,
            init_stmt,
        )

        # Refresh lines of the inner things
        arg.set_line(argument.line)

        return arg
Example #10
0
    def make_setter_wrapper(self, name: str, typ: Type) -> FuncDef:
        """Create a setter wrapper for a data attribute.

        The setter will be of this form:
        
        . def set$name(self: C, name: typ) -> None:
        .     self.name! = name
        """
        scope = self.make_scope()
        selft = self.self_type()
        selfv = scope.add('self', selft)
        namev = scope.add(name, typ)
        
        lvalue = MemberExpr(scope.name_expr('self'), name, direct=True)
        rvalue = scope.name_expr(name)
        ret = AssignmentStmt([lvalue], rvalue)

        wrapper_name = 'set$' + name
        sig = Callable([selft, typ],
                       [nodes.ARG_POS, nodes.ARG_POS],
                       [None, None],
                       Void(), False)
        fdef = FuncDef(wrapper_name,
                       [selfv, namev],
                       [nodes.ARG_POS, nodes.ARG_POS],
                       [None, None],
                       Block([ret]), sig)
        fdef.info = self.tf.type_context()
        return fdef
Example #11
0
    def _field_from_field_def(
        self,
        stmt: nodes.AssignmentStmt,
        name: nodes.NameExpr,
        sym: nodes.SymbolTableNode,
    ):
        field = super()._field_from_field_def(stmt, name, sym)
        if field is None:
            return None
        else:
            assert isinstance(sym.node, nodes.Var)
            sym.node.is_initialized_in_class = False

            name.is_inferred_def = False

            rhs = stmt.rvalue
            if not isinstance(rhs, nodes.CastExpr):
                stmt.rvalue = nodes.CastExpr(
                    typ=field.type,
                    expr=rhs,
                )
                stmt.rvalue.line = rhs.line
                stmt.rvalue.column = rhs.column

            return field
Example #12
0
 def visit_AnnAssign(self, n: ast3.AnnAssign) -> AssignmentStmt:
     if n.value is None:  # always allow 'x: int'
         rvalue = TempNode(AnyType())  # type: Expression
     else:
         rvalue = self.visit(n.value)
     typ = TypeConverter(self.errors, line=n.lineno).visit(n.annotation)
     typ.column = n.annotation.col_offset
     return AssignmentStmt([self.visit(n.target)], rvalue, type=typ, new_syntax=True)
Example #13
0
 def visit_Assign(self, n: ast3.Assign) -> AssignmentStmt:
     lvalues = self.translate_expr_list(n.targets)
     rvalue = self.visit(n.value)
     if n.type_comment is not None:
         typ = parse_type_comment(n.type_comment, n.lineno, self.errors)
     else:
         typ = None
     return AssignmentStmt(lvalues, rvalue, type=typ, new_syntax=False)
Example #14
0
    def visit_Assign(self, n: ast27.Assign) -> AssignmentStmt:
        typ = None
        if n.type_comment:
            typ = parse_type_comment(n.type_comment, n.lineno, self.errors)

        return AssignmentStmt(self.translate_expr_list(n.targets),
                              self.visit(n.value),
                              type=typ)
Example #15
0
    def visit_Assign(self, n: ast35.Assign) -> Node:
        typ = None
        if n.type_comment:
            typ = parse_type_comment(n.type_comment, n.lineno)

        return AssignmentStmt(self.visit_list(n.targets),
                              self.visit(n.value),
                              type=typ)
Example #16
0
    def visit_Assign(self, n: ast27.Assign) -> AssignmentStmt:
        typ = None
        if n.type_comment:
            typ = parse_type_comment(n.type_comment, n.lineno, self.errors,
                                     assume_str_is_unicode=self.unicode_literals)

        stmt = AssignmentStmt(self.translate_expr_list(n.targets),
                              self.visit(n.value),
                              type=typ)
        return self.set_line(stmt, n)
Example #17
0
 def visit_assignment_stmt(self, node: AssignmentStmt) -> None:
     node.type = node.unanalyzed_type
     if self.type and not self.is_class_body:
         # TODO: Handle multiple assignment
         if len(node.lvalues) == 1:
             lvalue = node.lvalues[0]
             if isinstance(lvalue, MemberExpr) and lvalue.is_new_def:
                 # Remove defined attribute from the class symbol table. If is_new_def is
                 # true for a MemberExpr, we know that it must be an assignment through
                 # self, since only those can define new attributes.
                 del self.type.names[lvalue.name]
     super().visit_assignment_stmt(node)
Example #18
0
def apply_type_to_mapped_statement(
    api: SemanticAnalyzerPluginInterface,
    stmt: AssignmentStmt,
    lvalue: NameExpr,
    left_hand_explicit_type: Optional[ProperType],
    python_type_for_type: Optional[ProperType],
) -> None:
    """Apply the Mapped[<type>] annotation and right hand object to a
    declarative assignment statement.

    This converts a Python declarative class statement such as::

        class User(Base):
            # ...

            attrname = Column(Integer)

    To one that describes the final Python behavior to Mypy::

        class User(Base):
            # ...

            attrname : Mapped[Optional[int]] = <meaningless temp node>

    """
    left_node = lvalue.node
    assert isinstance(left_node, Var)

    if left_hand_explicit_type is not None:
        left_node.type = api.named_type(
            "__sa_Mapped", [left_hand_explicit_type]
        )
    else:
        lvalue.is_inferred_def = False
        left_node.type = api.named_type(
            "__sa_Mapped",
            [] if python_type_for_type is None else [python_type_for_type],
        )

    # so to have it skip the right side totally, we can do this:
    # stmt.rvalue = TempNode(AnyType(TypeOfAny.special_form))

    # however, if we instead manufacture a new node that uses the old
    # one, then we can still get type checking for the call itself,
    # e.g. the Column, relationship() call, etc.

    # rewrite the node as:
    # <attr> : Mapped[<typ>] =
    # _sa_Mapped._empty_constructor(<original CallExpr from rvalue>)
    # the original right-hand side is maintained so it gets type checked
    # internally
    stmt.rvalue = util.expr_to_mapped_constructor(stmt.rvalue)
Example #19
0
 def visit_AnnAssign(self, n: ast3.AnnAssign) -> AssignmentStmt:
     if n.value is None:  # always allow 'x: int'
         rvalue = TempNode(AnyType(TypeOfAny.special_form),
                           no_rhs=True)  # type: Expression
     else:
         rvalue = self.visit(n.value)
     typ = TypeConverter(self.errors, line=n.lineno).visit(n.annotation)
     assert typ is not None
     typ.column = n.annotation.col_offset
     s = AssignmentStmt([self.visit(n.target)],
                        rvalue,
                        type=typ,
                        new_syntax=True)
     return self.set_line(s, n)
Example #20
0
 def visit_assignment_stmt(self, node: AssignmentStmt) -> None:
     node.type = node.unanalyzed_type
     if node.type and self.is_class_body:
         # Remove attribute defined in the class body from the class namespace to avoid
         # bogus "Name already defined" errors.
         #
         # TODO: Handle multiple assignment, other lvalues
         # TODO: What about assignments without type annotations?
         assert len(node.lvalues) == 1
         lvalue = node.lvalues[0]
         assert isinstance(lvalue, NameExpr)
         assert self.type is not None  # Because self.is_class_body is True
         del self.type.names[lvalue.name]
     super().visit_assignment_stmt(node)
Example #21
0
    def make_instance_tvar_initializer(self, creat: FuncDef) -> None:
        """Add type variable member initialization code to a constructor.

        Modify the constructor body directly.
        """
        for n in range(num_slots(creat.info)):
            rvalue = self.make_tvar_init_expression(creat.info, n)
            init = AssignmentStmt([MemberExpr(self_expr(),
                                              tvar_slot_name(n),
                                              direct=True)],
                                  rvalue)
            self.tf.set_type(init.lvalues[0], AnyType())
            self.tf.set_type(init.rvalue, AnyType())
            creat.body.body.insert(n, init)
Example #22
0
 def visit_assignment_stmt(self, node: AssignmentStmt) -> None:
     node.type = node.unanalyzed_type
     if node.type and self.is_class_body:
         # Remove attribute defined in the class body from the class namespace to avoid
         # bogus "Name already defined" errors.
         #
         # TODO: Handle multiple assignment, other lvalues
         # TODO: What about assignments without type annotations?
         assert len(node.lvalues) == 1
         lvalue = node.lvalues[0]
         assert isinstance(lvalue, NameExpr)
         assert self.type is not None  # Because self.is_class_body is True
         del self.type.names[lvalue.name]
     super().visit_assignment_stmt(node)
Example #23
0
    def make_generic_wrapper_init(self, info: TypeInfo) -> FuncDef:
        """Build constructor of a generic wrapper class."""
        nslots = num_slots(info)
        
        cdefs = [] # type: List[Node]
        
        # Build superclass constructor call.
        base = info.mro[1]
        if base.fullname() != 'builtins.object' and self.tf.is_java:
            s = SuperExpr('__init__')
            cargs = [NameExpr('__o')] # type: List[Node]
            for n in range(num_slots(base)):
                cargs.append(NameExpr(tvar_arg_name(n + 1)))
            for n in range(num_slots(base)):
                cargs.append(NameExpr(tvar_arg_name(n + 1, BOUND_VAR)))
            c = CallExpr(s, cargs, [nodes.ARG_POS] * len(cargs))
            cdefs.append(ExpressionStmt(c))
        
        # Create initialization of the wrapped object.
        cdefs.append(AssignmentStmt([MemberExpr(
                                         self_expr(),
                                         self.object_member_name(info),
                                         direct=True)],
                                    NameExpr('__o')))
        
        # Build constructor arguments.
        args = [Var('self'), Var('__o')]
        init = [None, None] # type: List[Node]
        
        for alt in [False, BOUND_VAR]:
            for n in range(nslots):
                args.append(Var(tvar_arg_name(n + 1, alt)))
                init.append(None)

        nargs = nslots * 2 + 2
        fdef = FuncDef('__init__',
                       args,
                       [nodes.ARG_POS] * nargs,
                       init,
                       Block(cdefs),
                       Callable( [AnyType()] * nargs,
                                [nodes.ARG_POS] * nargs, [None] * nargs,
                                Void(),
                                is_type_obj=False))
        fdef.info = info
        
        self.make_wrapper_slot_initializer(fdef)
        
        return fdef
Example #24
0
    def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
        super().visit_assignment_stmt(s)
        if isinstance(s.lvalues[0], IndexExpr):
            index = cast(IndexExpr, s.lvalues[0])
            method_type = index.method_type
            if self.dynamic_funcs[-1] or isinstance(method_type, AnyType):
                lvalue_type = AnyType()  # type: Type
            else:
                method_callable = cast(Callable, method_type)
                # TODO arg_types[1] may not be reliable
                lvalue_type = method_callable.arg_types[1]
        else:
            lvalue_type = self.get_type(s.lvalues[0])

        s.rvalue = self.coerce2(s.rvalue, lvalue_type, self.get_type(s.rvalue), self.type_context())
Example #25
0
    def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
        super().visit_assignment_stmt(s)
        if isinstance(s.lvalues[0], IndexExpr):
            index = cast(IndexExpr, s.lvalues[0])
            method_type = index.method_type
            if self.dynamic_funcs[-1] or isinstance(method_type, AnyType):
                lvalue_type = AnyType()  # type: Type
            else:
                method_callable = cast(Callable, method_type)
                # TODO arg_types[1] may not be reliable
                lvalue_type = method_callable.arg_types[1]
        else:
            lvalue_type = self.get_type(s.lvalues[0])

        s.rvalue = self.coerce2(s.rvalue, lvalue_type, self.get_type(s.rvalue),
                                self.type_context())
Example #26
0
    def make_wrapper_slot_initializer(self, creat: FuncDef) -> None:
        """Add type variable member initializations to a wrapper constructor.

        The function must be a constructor of a generic wrapper class. Modify
        the constructor body directly.
        """
        for alt in [BOUND_VAR, False]:
            for n in range(num_slots(creat.info)):
                rvalue = TypeExpr(
                    RuntimeTypeVar(NameExpr(tvar_slot_name(n, alt))))
                init = AssignmentStmt(
                    [MemberExpr(self_expr(),
                                tvar_slot_name(n, alt), direct=True)],
                    rvalue)
                self.tf.set_type(init.lvalues[0], AnyType())
                self.tf.set_type(init.rvalue, AnyType())
                creat.body.body.insert(n, init)
Example #27
0
    def make_dynamic_setter_wrapper(self, name: str, typ: Type) -> FuncDef:
        """Create a dynamically-typed setter wrapper for a data attribute.

        The setter will be of this form:
        
        . def set$name*(self: C, name; Any) -> None:
        .     self.name! = {typ name}
        """
        lvalue = MemberExpr(self_expr(), name, direct=True)
        name_expr = NameExpr(name)
        rvalue = coerce(name_expr, typ, AnyType(), self.tf.type_context())
        ret = AssignmentStmt([lvalue], rvalue)

        wrapper_name = 'set$' + name + self.tf.dynamic_suffix()
        selft = self_type(self.tf.type_context())            
        sig = Callable([selft, AnyType()],
                       [nodes.ARG_POS, nodes.ARG_POS],
                       [None, None],
                       Void(), False)
        return FuncDef(wrapper_name,
                       [Var('self'), Var(name)],
                       [nodes.ARG_POS, nodes.ARG_POS],
                       [None, None],
                       Block([ret]), sig)
Example #28
0
 def visit_Assign(self, n: ast27.Assign) -> AssignmentStmt:
     typ = self.translate_type_comment(n, n.type_comment)
     stmt = AssignmentStmt(self.translate_expr_list(n.targets),
                           self.visit(n.value),
                           type=typ)
     return self.set_line(stmt, n)
Example #29
0
 def duplicate_assignment(self, node: AssignmentStmt) -> AssignmentStmt:
     new = AssignmentStmt(self.nodes(node.lvalues), self.node(node.rvalue),
                          self.optional_type(node.type))
     new.line = node.line
     return new
Example #30
0
def _scan_declarative_decorator_stmt(
    cls: ClassDef,
    api: SemanticAnalyzerPluginInterface,
    stmt: Decorator,
    cls_metadata: util.DeclClassApplied,
) -> None:
    """Extract mapping information from a @declared_attr in a declarative
    class.

    E.g.::

        @reg.mapped
        class MyClass:
            # ...

            @declared_attr
            def updated_at(cls) -> Column[DateTime]:
                return Column(DateTime)

    Will resolve in mypy as::

        @reg.mapped
        class MyClass:
            # ...

            updated_at: Mapped[Optional[datetime.datetime]]

    """
    for dec in stmt.decorators:
        if (
            isinstance(dec, (NameExpr, MemberExpr, SymbolNode))
            and names._type_id_for_named_node(dec) is names.DECLARED_ATTR
        ):
            break
    else:
        return

    dec_index = cls.defs.body.index(stmt)

    left_hand_explicit_type: Optional[ProperType] = None

    if isinstance(stmt.func.type, CallableType):
        func_type = stmt.func.type.ret_type
        if isinstance(func_type, UnboundType):
            type_id = names._type_id_for_unbound_type(func_type, cls, api)
        else:
            # this does not seem to occur unless the type argument is
            # incorrect
            return

        if (
            type_id
            in {
                names.MAPPED,
                names.RELATIONSHIP,
                names.COMPOSITE_PROPERTY,
                names.MAPPER_PROPERTY,
                names.SYNONYM_PROPERTY,
                names.COLUMN_PROPERTY,
            }
            and func_type.args
        ):
            left_hand_explicit_type = get_proper_type(func_type.args[0])
        elif type_id is names.COLUMN and func_type.args:
            typeengine_arg = func_type.args[0]
            if isinstance(typeengine_arg, UnboundType):
                sym = api.lookup_qualified(typeengine_arg.name, typeengine_arg)
                if sym is not None and isinstance(sym.node, TypeInfo):
                    if names._has_base_type_id(sym.node, names.TYPEENGINE):
                        left_hand_explicit_type = UnionType(
                            [
                                infer._extract_python_type_from_typeengine(
                                    api, sym.node, []
                                ),
                                NoneType(),
                            ]
                        )
                    else:
                        util.fail(
                            api,
                            "Column type should be a TypeEngine "
                            "subclass not '{}'".format(sym.node.fullname),
                            func_type,
                        )

    if left_hand_explicit_type is None:
        # no type on the decorated function.  our option here is to
        # dig into the function body and get the return type, but they
        # should just have an annotation.
        msg = (
            "Can't infer type from @declared_attr on function '{}';  "
            "please specify a return type from this function that is "
            "one of: Mapped[<python type>], relationship[<target class>], "
            "Column[<TypeEngine>], MapperProperty[<python type>]"
        )
        util.fail(api, msg.format(stmt.var.name), stmt)

        left_hand_explicit_type = AnyType(TypeOfAny.special_form)

    left_node = NameExpr(stmt.var.name)
    left_node.node = stmt.var

    # totally feeling around in the dark here as I don't totally understand
    # the significance of UnboundType.  It seems to be something that is
    # not going to do what's expected when it is applied as the type of
    # an AssignmentStatement.  So do a feeling-around-in-the-dark version
    # of converting it to the regular Instance/TypeInfo/UnionType structures
    # we see everywhere else.
    if isinstance(left_hand_explicit_type, UnboundType):
        left_hand_explicit_type = get_proper_type(
            util._unbound_to_instance(api, left_hand_explicit_type)
        )

    left_node.node.type = api.named_type(
        "__sa_Mapped", [left_hand_explicit_type]
    )

    # this will ignore the rvalue entirely
    # rvalue = TempNode(AnyType(TypeOfAny.special_form))

    # rewrite the node as:
    # <attr> : Mapped[<typ>] =
    # _sa_Mapped._empty_constructor(lambda: <function body>)
    # the function body is maintained so it gets type checked internally
    column_descriptor = nodes.NameExpr("__sa_Mapped")
    column_descriptor.fullname = "sqlalchemy.orm.attributes.Mapped"
    mm = nodes.MemberExpr(column_descriptor, "_empty_constructor")

    arg = nodes.LambdaExpr(stmt.func.arguments, stmt.func.body)
    rvalue = CallExpr(
        mm,
        [arg],
        [nodes.ARG_POS],
        ["arg1"],
    )

    new_stmt = AssignmentStmt([left_node], rvalue)
    new_stmt.type = left_node.node.type

    cls_metadata.mapped_attr_names.append(
        (left_node.name, left_hand_explicit_type)
    )
    cls.defs.body[dec_index] = new_stmt
Example #31
0
 def duplicate_assignment(self, node: AssignmentStmt) -> AssignmentStmt:
     new = AssignmentStmt(self.nodes(node.lvalues),
                          self.node(node.rvalue),
                          self.optional_type(node.type))
     new.line = node.line
     return new
Example #32
0
 def visit_assignment_stmt(self, node: AssignmentStmt) -> None:
     node.type = node.unanalyzed_type
     super().visit_assignment_stmt(node)