From aeeff72e806420bf85e2e6723b1f941df38a3e1a Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 15 Apr 2022 11:05:36 -0400 Subject: pep-484: ORM public API, constructors for the moment, abandoning using @overload with relationship() and mapped_column(). The overloads are very difficult to get working at all, and the overloads that were there all wouldn't pass on mypy. various techniques of getting them to "work", meaning having right hand side dictate what's legal on the left, have mixed success and wont give consistent results; additionally, it's legal to have Optional / non-optional independent of nullable in any case for columns. relationship cases are less ambiguous but mypy was not going along with things. we have a comprehensive system of allowing left side annotations to drive the right side, in the absense of explicit settings on the right. so type-centric SQLAlchemy will be left-side driven just like dataclasses, and the various flags and switches on the right side will just not be needed very much. in other matters, one surprise, forgot to remove string support from orm.join(A, B, "somename") or do deprecations for it in 1.4. This is a really not-directly-used structure barely mentioned in the docs for many years, the example shows a relationship being used, not a string, so we will just change it to raise the usual error here. Change-Id: Iefbbb8d34548b538023890ab8b7c9a5d9496ec6e --- lib/sqlalchemy/orm/decl_base.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'lib/sqlalchemy/orm/decl_base.py') diff --git a/lib/sqlalchemy/orm/decl_base.py b/lib/sqlalchemy/orm/decl_base.py index 804d05ce1..9c79a4172 100644 --- a/lib/sqlalchemy/orm/decl_base.py +++ b/lib/sqlalchemy/orm/decl_base.py @@ -12,6 +12,8 @@ import collections from typing import Any from typing import Dict from typing import Tuple +from typing import Type +from typing import TYPE_CHECKING import weakref from . import attributes @@ -42,6 +44,10 @@ from ..sql.schema import Column from ..sql.schema import Table from ..util import topological +if TYPE_CHECKING: + from ._typing import _O + from ._typing import _RegistryType + def _declared_mapping_info(cls): # deferred mapping @@ -121,7 +127,7 @@ def _dive_for_cls_manager(cls): return None for base in cls.__mro__: - manager = attributes.manager_of_class(base) + manager = attributes.opt_manager_of_class(base) if manager: return manager return None @@ -171,7 +177,7 @@ class _MapperConfig: @classmethod def setup_mapping(cls, registry, cls_, dict_, table, mapper_kw): - manager = attributes.manager_of_class(cls) + manager = attributes.opt_manager_of_class(cls) if manager and manager.class_ is cls_: raise exc.InvalidRequestError( "Class %r already has been " "instrumented declaratively" % cls @@ -191,7 +197,12 @@ class _MapperConfig: return cfg_cls(registry, cls_, dict_, table, mapper_kw) - def __init__(self, registry, cls_, mapper_kw): + def __init__( + self, + registry: _RegistryType, + cls_: Type[Any], + mapper_kw: Dict[str, Any], + ): self.cls = util.assert_arg_type(cls_, type, "cls_") self.classname = cls_.__name__ self.properties = util.OrderedDict() @@ -206,7 +217,7 @@ class _MapperConfig: init_method=registry.constructor, ) else: - manager = attributes.manager_of_class(self.cls) + manager = attributes.opt_manager_of_class(self.cls) if not manager or not manager.is_mapped: raise exc.InvalidRequestError( "Class %s has no primary mapper configured. Configure " -- cgit v1.2.1