--- /dev/null
+.. 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.
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
@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.
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()
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: