def visit_Lambda(self, n: ast3.Lambda) -> LambdaExpr: body = ast3.Return(n.body) body.lineno = n.lineno body.col_offset = n.col_offset e = LambdaExpr(self.transform_args(n.args, n.lineno), self.as_required_block([body], n.lineno)) e.set_line( n.lineno, n.col_offset) # Overrides set_line -- can't use self.set_line return e
def visit_Lambda(self, n: ast27.Lambda) -> LambdaExpr: args, decompose_stmts = self.transform_args(n.args, n.lineno) n_body = ast27.Return(n.body) n_body.lineno = n.lineno n_body.col_offset = n.col_offset body = self.as_required_block([n_body], n.lineno) if decompose_stmts: body.body = decompose_stmts + body.body e = LambdaExpr(args, body) e.set_line(n.lineno, n.col_offset) # Overrides set_line -- can't use self.set_line return e
def visit_Lambda(self, n: ast3.Lambda) -> LambdaExpr: body = ast3.Return(n.body) body.lineno = n.lineno body.col_offset = n.col_offset return LambdaExpr(self.transform_args(n.args, n.lineno), self.as_required_block([body], n.lineno))
def visit_lambda_expr(self, node: LambdaExpr) -> LambdaExpr: new = LambdaExpr([self.copy_argument(arg) for arg in node.arguments], self.block(node.body), cast(Optional[FunctionLike], self.optional_type(node.type))) self.copy_function_attributes(new, node) return new
def visit_Lambda(self, n: ast27.Lambda) -> LambdaExpr: args, decompose_stmts = self.transform_args(n.args, n.lineno) n_body = ast27.Return(n.body) n_body.lineno = n.lineno n_body.col_offset = n.col_offset body = self.as_required_block([n_body], n.lineno) if decompose_stmts: body.body = decompose_stmts + body.body return LambdaExpr(args, body)
def visit_lambda_expr(self, node: LambdaExpr) -> None: node.info = self.fixup(node.info) super().visit_lambda_expr(node)
def _scan_declarative_decorator_stmt( cls: ClassDef, api: SemanticAnalyzerPluginInterface, stmt: Decorator, attributes: List[util.SQLAlchemyAttribute], ) -> 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 util.name_is_dunder(stmt.name): # for dunder names like __table_args__, __tablename__, # __mapper_args__ etc., rewrite these as simple assignment # statements; otherwise mypy doesn't like if the decorated # function has an annotation like ``cls: Type[Foo]`` because # it isn't @classmethod any_ = AnyType(TypeOfAny.special_form) left_node = NameExpr(stmt.var.name) left_node.node = stmt.var new_stmt = AssignmentStmt([left_node], TempNode(any_)) new_stmt.type = left_node.node.type cls.defs.body[dec_index] = new_stmt return elif 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(names.NAMED_TYPE_SQLA_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 rvalue = util.expr_to_mapped_constructor( LambdaExpr(stmt.func.arguments, stmt.func.body)) new_stmt = AssignmentStmt([left_node], rvalue) new_stmt.type = left_node.node.type attributes.append( util.SQLAlchemyAttribute( name=left_node.name, line=stmt.line, column=stmt.column, typ=left_hand_explicit_type, info=cls.info, )) cls.defs.body[dec_index] = new_stmt