diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-01-24 17:04:27 -0500 | 
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-02-13 14:23:04 -0500 | 
| commit | e545298e35ea9f126054b337e4b5ba01988b29f7 (patch) | |
| tree | e64aea159111d5921ff01f08b1c4efb667249dfe /lib/sqlalchemy/ext/mypy/util.py | |
| parent | f1da1623b800cd4de3b71fd1b2ad5ccfde286780 (diff) | |
| download | sqlalchemy-e545298e35ea9f126054b337e4b5ba01988b29f7.tar.gz | |
establish mypy / typing approach for v2.0
large patch to get ORM / typing efforts started.
this is to support adding new test cases to mypy,
support dropping sqlalchemy2-stubs entirely from the
test suite, validate major ORM typing reorganization
to eliminate the need for the mypy plugin.
* New declarative approach which uses annotation
  introspection, fixes: #7535
* Mapped[] is now at the base of all ORM constructs
  that find themselves in classes, to support direct
  typing without plugins
* Mypy plugin updated for new typing structures
* Mypy test suite broken out into "plugin" tests vs.
  "plain" tests, and enhanced to better support test
  structures where we assert that various objects are
  introspected by the type checker as we expect.
  as we go forward with typing, we will
  add new use cases to "plain" where we can assert that
  types are introspected as we expect.
* For typing support, users will be much more exposed to the
  class names of things.  Add these all to "sqlalchemy" import
  space.
* Column(ForeignKey()) no longer needs to be `@declared_attr`
  if the FK refers to a remote table
* composite() attributes mapped to a dataclass no longer
  need to implement a `__composite_values__()` method
* with_variant() accepts multiple dialect names
Change-Id: I22797c0be73a8fbbd2d6f5e0c0b7258b17fe145d
Fixes: #7535
Fixes: #7551
References: #6810
Diffstat (limited to 'lib/sqlalchemy/ext/mypy/util.py')
| -rw-r--r-- | lib/sqlalchemy/ext/mypy/util.py | 36 | 
1 files changed, 23 insertions, 13 deletions
| diff --git a/lib/sqlalchemy/ext/mypy/util.py b/lib/sqlalchemy/ext/mypy/util.py index fa42074c3..741772eac 100644 --- a/lib/sqlalchemy/ext/mypy/util.py +++ b/lib/sqlalchemy/ext/mypy/util.py @@ -10,24 +10,27 @@ from typing import Type as TypingType  from typing import TypeVar  from typing import Union -from mypy.nodes import ARG_POS  from mypy.nodes import CallExpr  from mypy.nodes import ClassDef  from mypy.nodes import CLASSDEF_NO_INFO  from mypy.nodes import Context  from mypy.nodes import Expression +from mypy.nodes import FuncDef  from mypy.nodes import IfStmt  from mypy.nodes import JsonDict  from mypy.nodes import MemberExpr  from mypy.nodes import NameExpr  from mypy.nodes import Statement  from mypy.nodes import SymbolTableNode +from mypy.nodes import TypeAlias  from mypy.nodes import TypeInfo  from mypy.plugin import ClassDefContext  from mypy.plugin import DynamicClassDefContext  from mypy.plugin import SemanticAnalyzerPluginInterface  from mypy.plugins.common import deserialize_and_fixup_type  from mypy.typeops import map_type_from_supertype +from mypy.types import CallableType +from mypy.types import get_proper_type  from mypy.types import Instance  from mypy.types import NoneType  from mypy.types import Type @@ -231,6 +234,25 @@ def flatten_typechecking(stmts: Iterable[Statement]) -> Iterator[Statement]:              yield stmt +def type_for_callee(callee: Expression) -> Optional[Union[Instance, TypeInfo]]: +    if isinstance(callee, (MemberExpr, NameExpr)): +        if isinstance(callee.node, FuncDef): +            if callee.node.type and isinstance(callee.node.type, CallableType): +                ret_type = get_proper_type(callee.node.type.ret_type) + +                if isinstance(ret_type, Instance): +                    return ret_type + +            return None +        elif isinstance(callee.node, TypeAlias): +            target_type = get_proper_type(callee.node.target) +            if isinstance(target_type, Instance): +                return target_type +        elif isinstance(callee.node, TypeInfo): +            return callee.node +    return None + +  def unbound_to_instance(      api: SemanticAnalyzerPluginInterface, typ: Type  ) -> Type: @@ -290,15 +312,3 @@ def info_for_cls(          return sym.node      return cls.info - - -def expr_to_mapped_constructor(expr: Expression) -> CallExpr: -    column_descriptor = NameExpr("__sa_Mapped") -    column_descriptor.fullname = "sqlalchemy.orm.attributes.Mapped" -    member_expr = MemberExpr(column_descriptor, "_empty_constructor") -    return CallExpr( -        member_expr, -        [expr], -        [ARG_POS], -        ["arg1"], -    ) | 
