diff options
| author | mike bayer <mike_mp@zzzcomputing.com> | 2023-02-06 17:01:50 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit@bbpush.zzzcomputing.com> | 2023-02-06 17:01:50 +0000 |
| commit | 3c46f2cbab092135f2ca7c63ca7e47cf1a7f0a9c (patch) | |
| tree | 44cdf485bbd1c3a54fd6b949e581e9004eba900b | |
| parent | a7434ecb339554ba095ddddf1978f8606633299c (diff) | |
| parent | b927d95d075c4cdf027f784e759c9904416fb73a (diff) | |
| download | sqlalchemy-3c46f2cbab092135f2ca7c63ca7e47cf1a7f0a9c.tar.gz | |
Merge "check for superclasses of user defined init" into main
| -rw-r--r-- | doc/build/changelog/unreleased_20/9249.rst | 13 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/decl_api.py | 2 | ||||
| -rw-r--r-- | test/orm/declarative/test_basic.py | 23 |
3 files changed, 35 insertions, 3 deletions
diff --git a/doc/build/changelog/unreleased_20/9249.rst b/doc/build/changelog/unreleased_20/9249.rst new file mode 100644 index 000000000..1ffd63a01 --- /dev/null +++ b/doc/build/changelog/unreleased_20/9249.rst @@ -0,0 +1,13 @@ +.. change:: + :tags: bug, orm + :tickets: 9249 + + Fixed regression caused by the fix for :ticket:`9171`, which itself was + fixing a regression, involving the mechanics of ``__init__()`` on classes + that extend from :class:`_orm.DeclarativeBase`. The change made it such + that ``__init__()`` was applied to the user-defined base if there were no + ``__init__()`` method directly on the class. This has been adjusted so that + ``__init__()`` is applied only if no other class in the hierarchy of the + user-defined base has an ``__init__()`` method. This again allows + user-defined base classes based on :class:`_orm.DeclarativeBase` to include + mixins that themselves include a custom ``__init__()`` method. diff --git a/lib/sqlalchemy/orm/decl_api.py b/lib/sqlalchemy/orm/decl_api.py index e3e2611da..5f2b3c696 100644 --- a/lib/sqlalchemy/orm/decl_api.py +++ b/lib/sqlalchemy/orm/decl_api.py @@ -567,7 +567,7 @@ def _setup_declarative_base(cls: Type[Any]) -> None: if "metadata" not in cls.__dict__: cls.metadata = cls.registry.metadata # type: ignore - if "__init__" not in cls.__dict__: + if getattr(cls, "__init__", object.__init__) is object.__init__: cls.__init__ = cls.registry.constructor diff --git a/test/orm/declarative/test_basic.py b/test/orm/declarative/test_basic.py index 45f0d4200..d4890a781 100644 --- a/test/orm/declarative/test_basic.py +++ b/test/orm/declarative/test_basic.py @@ -134,7 +134,13 @@ class DeclarativeBaseSetupsTest(fixtures.TestBase): @testing.variation( "base_type", - ["declbase", "declbasenometa", "declbasefn", "asdeclarative"], + [ + "declbase", + "declbasenometa", + "declbasefn", + "asdeclarative", + "mixinonbase", + ], ) def test_reg_constructor_custom_init(self, base_type): """test for #9171 testing what an explicit __init__ does. @@ -165,6 +171,15 @@ class DeclarativeBaseSetupsTest(fixtures.TestBase): m1.init(x) Base = declarative_base(cls=_B) + elif base_type.mixinonbase: + + class Mixin: + def __init__(self, x=None): + m1.init(x) + + class Base(Mixin, DeclarativeBase): + pass + elif base_type.asdeclarative: @as_declarative() @@ -180,7 +195,11 @@ class DeclarativeBaseSetupsTest(fixtures.TestBase): fs = fakeself() - if base_type.declbase or base_type.declbasenometa: + if ( + base_type.declbase + or base_type.declbasenometa + or base_type.mixinonbase + ): Base.__init__(fs, x=5) eq_(m1.mock_calls, [mock.call.init(5)]) else: |
