diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-04-04 19:01:54 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-04-12 15:10:32 -0400 |
commit | 428ea01f00a9cc7f85e435018565eb6da7af1b77 (patch) | |
tree | 8a39510cc038731e2df8f8b536ae1c533bd23351 /lib/sqlalchemy/orm/decl_base.py | |
parent | a45e2284dad17fbbba3bea9d5e5304aab21c8c94 (diff) | |
download | sqlalchemy-428ea01f00a9cc7f85e435018565eb6da7af1b77.tar.gz |
read from cls.__dict__ so init_subclass works
Modified the :class:`.DeclarativeMeta` metaclass to pass ``cls.__dict__``
into the declarative scanning process to look for attributes, rather than
the separate dictionary passed to the type's ``__init__()`` method. This
allows user-defined base classes that add attributes within an
``__init_subclass__()`` to work as expected, as ``__init_subclass__()`` can
only affect the ``cls.__dict__`` itself and not the other dictionary. This
is technically a regression from 1.3 where ``__dict__`` was being used.
Additionally makes the reference between ClassManager and
the declarative configuration object a weak reference, so that it
can be discarded after mappers are set up.
Fixes: #7900
Change-Id: I3c2fd4e227cc1891aa4bb3d7d5b43d5686f9f27c
Diffstat (limited to 'lib/sqlalchemy/orm/decl_base.py')
-rw-r--r-- | lib/sqlalchemy/orm/decl_base.py | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/lib/sqlalchemy/orm/decl_base.py b/lib/sqlalchemy/orm/decl_base.py index 3fb8af80c..804d05ce1 100644 --- a/lib/sqlalchemy/orm/decl_base.py +++ b/lib/sqlalchemy/orm/decl_base.py @@ -161,7 +161,13 @@ def _check_declared_props_nocascade(obj, name, cls): class _MapperConfig: - __slots__ = ("cls", "classname", "properties", "declared_attr_reg") + __slots__ = ( + "cls", + "classname", + "properties", + "declared_attr_reg", + "__weakref__", + ) @classmethod def setup_mapping(cls, registry, cls_, dict_, table, mapper_kw): @@ -311,13 +317,15 @@ class _ClassScanMapperConfig(_MapperConfig): mapper_kw, ): + # grab class dict before the instrumentation manager has been added. + # reduces cycles + self.clsdict_view = ( + util.immutabledict(dict_) if dict_ else util.EMPTY_DICT + ) super(_ClassScanMapperConfig, self).__init__(registry, cls_, mapper_kw) self.registry = registry self.persist_selectable = None - self.clsdict_view = ( - util.immutabledict(dict_) if dict_ else util.EMPTY_DICT - ) self.collected_attributes = {} self.collected_annotations: Dict[str, Tuple[Any, bool]] = {} self.declared_columns = util.OrderedSet() |