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/util/langhelpers.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/util/langhelpers.py')
-rw-r--r-- | lib/sqlalchemy/util/langhelpers.py | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/lib/sqlalchemy/util/langhelpers.py b/lib/sqlalchemy/util/langhelpers.py index 1b277cdee..66c530867 100644 --- a/lib/sqlalchemy/util/langhelpers.py +++ b/lib/sqlalchemy/util/langhelpers.py @@ -1743,14 +1743,28 @@ def attrsetter(attrname): return env["set"] -class EnsureKWArgType(type): +class EnsureKWArg: r"""Apply translation of functions to accept \**kw arguments if they don't already. + Used to ensure cross-compatibility with third party legacy code, for things + like compiler visit methods that need to accept ``**kw`` arguments, + but may have been copied from old code that didn't accept them. + + """ + + ensure_kwarg: str + """a regular expression that indicates method names for which the method + should accept ``**kw`` arguments. + + The class will scan for methods matching the name template and decorate + them if necessary to ensure ``**kw`` parameters are accepted. + """ - def __init__(cls, clsname, bases, clsdict): + def __init_subclass__(cls) -> None: fn_reg = cls.ensure_kwarg + clsdict = cls.__dict__ if fn_reg: for key in clsdict: m = re.match(fn_reg, key) @@ -1758,11 +1772,12 @@ class EnsureKWArgType(type): fn = clsdict[key] spec = compat.inspect_getfullargspec(fn) if not spec.varkw: - clsdict[key] = wrapped = cls._wrap_w_kw(fn) + wrapped = cls._wrap_w_kw(fn) setattr(cls, key, wrapped) - super(EnsureKWArgType, cls).__init__(clsname, bases, clsdict) + super().__init_subclass__() - def _wrap_w_kw(self, fn): + @classmethod + def _wrap_w_kw(cls, fn): def wrap(*arg, **kw): return fn(*arg) |