summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2023-04-10 10:28:44 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2023-04-10 10:33:09 -0400
commitbf51ff3248d1c87cbc7a846e2e6886339d59b9cb (patch)
treef00471bbd6e497de058c6064ac2cdd74dd1d8014
parent1eb72d9725d0df60206151805c927ad3c6566fb7 (diff)
downloadsqlalchemy-bf51ff3248d1c87cbc7a846e2e6886339d59b9cb.tar.gz
include declared_directive as a declared_attr
Fixed issue where the :meth:`_orm.declared_attr.directive` modifier was not correctly honored for subclasses when applied to the ``__mapper_args__`` special method name, as opposed to direct use of :class:`_orm.declared_attr`. The two constructs should have identical runtime behaviors. Fixes: #9625 Change-Id: I0dfe9e73bb45f70dbebc8e94ce280ad3b52e867f
-rw-r--r--doc/build/changelog/unreleased_20/9625.rst9
-rw-r--r--lib/sqlalchemy/orm/decl_base.py4
-rw-r--r--test/orm/declarative/test_inheritance.py41
3 files changed, 52 insertions, 2 deletions
diff --git a/doc/build/changelog/unreleased_20/9625.rst b/doc/build/changelog/unreleased_20/9625.rst
new file mode 100644
index 000000000..edb4c0aa7
--- /dev/null
+++ b/doc/build/changelog/unreleased_20/9625.rst
@@ -0,0 +1,9 @@
+.. change::
+ :tags: bug, orm
+ :tickets: 9625
+
+ Fixed issue where the :meth:`_orm.declared_attr.directive` modifier was not
+ correctly honored for subclasses when applied to the ``__mapper_args__``
+ special method name, as opposed to direct use of
+ :class:`_orm.declared_attr`. The two constructs should have identical
+ runtime behaviors.
diff --git a/lib/sqlalchemy/orm/decl_base.py b/lib/sqlalchemy/orm/decl_base.py
index bd62c3c1b..beede0ddb 100644
--- a/lib/sqlalchemy/orm/decl_base.py
+++ b/lib/sqlalchemy/orm/decl_base.py
@@ -260,9 +260,9 @@ def _mapper(
@util.preload_module("sqlalchemy.orm.decl_api")
def _is_declarative_props(obj: Any) -> bool:
- declared_attr = util.preloaded.orm_decl_api.declared_attr
+ _declared_attr_common = util.preloaded.orm_decl_api._declared_attr_common
- return isinstance(obj, (declared_attr, util.classproperty))
+ return isinstance(obj, (_declared_attr_common, util.classproperty))
def _check_declared_props_nocascade(
diff --git a/test/orm/declarative/test_inheritance.py b/test/orm/declarative/test_inheritance.py
index 4cc086be2..e8658926b 100644
--- a/test/orm/declarative/test_inheritance.py
+++ b/test/orm/declarative/test_inheritance.py
@@ -68,6 +68,47 @@ class DeclarativeInheritanceTest(
assert class_mapper(Engineer).polymorphic_identity is None
assert class_mapper(Engineer).polymorphic_on is Person.__table__.c.type
+ @testing.variation("directive", ["declared_attr", "da_directive"])
+ def test_declared_attr_mapped_args(self, directive):
+ class Employee(Base):
+ __tablename__ = "employee"
+
+ id: Mapped[int] = mapped_column(primary_key=True)
+ type: Mapped[str] = mapped_column(String(50))
+
+ if directive.declared_attr:
+
+ @declared_attr
+ def __mapper_args__(cls):
+ if cls.__name__ == "Employee":
+ return {
+ "polymorphic_on": cls.type,
+ "polymorphic_identity": "Employee",
+ }
+ else:
+ return {"polymorphic_identity": cls.__name__}
+
+ elif directive.da_directive:
+
+ @declared_attr.directive
+ def __mapper_args__(cls):
+ if cls.__name__ == "Employee":
+ return {
+ "polymorphic_on": cls.type,
+ "polymorphic_identity": "Employee",
+ }
+ else:
+ return {"polymorphic_identity": cls.__name__}
+
+ else:
+ directive.fail()
+
+ class Engineer(Employee):
+ pass
+
+ eq_(class_mapper(Engineer).polymorphic_identity, "Engineer")
+ eq_(class_mapper(Employee).polymorphic_identity, "Employee")
+
def test_we_must_only_copy_column_mapper_args(self):
class Person(Base):