diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-01-10 16:48:05 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-01-11 13:06:57 -0500 |
commit | 3a23e8ed29180e914883a263ec83373ecbd02efa (patch) | |
tree | 30775bf16114d0415d1b429dc4df1957e64cf082 /lib/sqlalchemy/sql/base.py | |
parent | 5681d4e4da8ee69d83e9c0103c171d413d4c183e (diff) | |
download | sqlalchemy-3a23e8ed29180e914883a263ec83373ecbd02efa.tar.gz |
remove internal use of metaclasses
All but one metaclass used internally can now
be replaced using __init_subclass__(). Within this
patch we remove:
* events._EventMeta
* sql.visitors.TraversibleType
* sql.visitors.InternalTraversibleType
* testing.fixtures.FindFixture
* testing.fixtures.FindFixtureDeclarative
* langhelpers.EnsureKWArgType
* sql.functions._GenericMeta
* sql.type_api.VisitableCheckKWArg (was a mixture of TraversibleType
and EnsureKWArgType)
The remaining internal class is MetaOptions used by the
sql.Options object which is in turn currently mostly for
ORM internal use, as this type implements class level overrides
for the ``+`` operator.
For declarative, removing DeclarativeMeta in place of
an `__init_subclass__()` class would not be fully feasible as
it would break backwards compatibility with applications that
refer to this class explicitly, but also DeclarativeMeta intercepts
class-level attribute set and delete operations which is a widely
used pattern. An option for declarative base to use
`__init_subclass__()` should be provided but this is out of
scope for this particular change.
Change-Id: I8aa898c7ab59d887739037d34b1cbab36521ab78
References: #6810
Diffstat (limited to 'lib/sqlalchemy/sql/base.py')
-rw-r--r-- | lib/sqlalchemy/sql/base.py | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/lib/sqlalchemy/sql/base.py b/lib/sqlalchemy/sql/base.py index 805f7b1a0..6ab9a75f6 100644 --- a/lib/sqlalchemy/sql/base.py +++ b/lib/sqlalchemy/sql/base.py @@ -20,9 +20,9 @@ import typing from . import roles from . import visitors -from .traversals import HasCacheKey # noqa +from .cache_key import HasCacheKey # noqa +from .cache_key import MemoizedHasCacheKey # noqa from .traversals import HasCopyInternals # noqa -from .traversals import MemoizedHasCacheKey # noqa from .visitors import ClauseVisitor from .visitors import ExtendedInternalTraversal from .visitors import InternalTraversal @@ -37,7 +37,6 @@ try: except ImportError: from ._py_util import prefix_anon_map # noqa - coercions = None elements = None type_api = None @@ -610,18 +609,13 @@ class HasCompileState(Generative): class _MetaOptions(type): - """metaclass for the Options class.""" + """metaclass for the Options class. - def __init__(cls, classname, bases, dict_): - cls._cache_attrs = tuple( - sorted( - d - for d in dict_ - if not d.startswith("__") - and d not in ("_cache_key_traversal",) - ) - ) - type.__init__(cls, classname, bases, dict_) + This metaclass is actually necessary despite the availability of the + ``__init_subclass__()`` hook as this type also provides custom class-level + behavior for the ``__add__()`` method. + + """ def __add__(self, other): o1 = self() @@ -640,6 +634,18 @@ class _MetaOptions(type): class Options(metaclass=_MetaOptions): """A cacheable option dictionary with defaults.""" + def __init_subclass__(cls) -> None: + dict_ = cls.__dict__ + cls._cache_attrs = tuple( + sorted( + d + for d in dict_ + if not d.startswith("__") + and d not in ("_cache_key_traversal",) + ) + ) + super().__init_subclass__() + def __init__(self, **kw): self.__dict__.update(kw) |