From aeb825fef70e40e02ce4de01e4d1053aafc0ccba Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 12 Mar 2018 12:50:52 -0400 Subject: [PATCH] Ignore non-primary mappers within mutable instrumentation Fixed bug where using :meth:`.Mutable.associate_with` or :meth:`.Mutable.as_mutable` in conjunction with a class that has non- primary mappers set up with alternatively-named attributes would produce an attribute error. Since non-primary mappers are not used for persistence, the mutable extension now excludes non-primary mappers from its instrumentation steps. Change-Id: I2630d9f771a171aece03181ccf9159885f68f25e Fixes: #4215 (cherry picked from commit 0fd508ad32a6f94653757a5ae10c1eae14e099fc) --- doc/build/changelog/unreleased_12/4215.rst | 12 ++++++++++++ lib/sqlalchemy/ext/mutable.py | 4 ++++ test/ext/test_mutable.py | 22 ++++++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 doc/build/changelog/unreleased_12/4215.rst diff --git a/doc/build/changelog/unreleased_12/4215.rst b/doc/build/changelog/unreleased_12/4215.rst new file mode 100644 index 0000000000..e658c5ba87 --- /dev/null +++ b/doc/build/changelog/unreleased_12/4215.rst @@ -0,0 +1,12 @@ +.. change:: + :tags: bug, orm + :tickets: 4215 + :versions: 1.3.0b1 + + Fixed bug where using :meth:`.Mutable.associate_with` or + :meth:`.Mutable.as_mutable` in conjunction with a class that has non- + primary mappers set up with alternatively-named attributes would produce an + attribute error. Since non-primary mappers are not used for persistence, + the mutable extension now excludes non-primary mappers from its + instrumentation steps. + diff --git a/lib/sqlalchemy/ext/mutable.py b/lib/sqlalchemy/ext/mutable.py index 955aa3ae19..014cef3cce 100644 --- a/lib/sqlalchemy/ext/mutable.py +++ b/lib/sqlalchemy/ext/mutable.py @@ -566,6 +566,8 @@ class Mutable(MutableBase): """ def listen_for_type(mapper, class_): + if mapper.non_primary: + return for prop in mapper.column_attrs: if isinstance(prop.columns[0].type, sqltype): cls.associate_with_attribute(getattr(class_, prop.key)) @@ -619,6 +621,8 @@ class Mutable(MutableBase): schema_event_check = False def listen_for_type(mapper, class_): + if mapper.non_primary: + return for prop in mapper.column_attrs: if ( schema_event_check and diff --git a/test/ext/test_mutable.py b/test/ext/test_mutable.py index 16fd52d97b..654a85e745 100644 --- a/test/ext/test_mutable.py +++ b/test/ext/test_mutable.py @@ -801,6 +801,17 @@ class MutableWithScalarJSONTest(_MutableDictTestBase, fixtures.MappedTest): self._test_non_mutable() +class MutableIncludeNonPrimaryTest(MutableWithScalarJSONTest): + @classmethod + def setup_mappers(cls): + foo = cls.tables.foo + + mapper(Foo, foo) + mapper(Foo, foo, non_primary=True, properties={ + "foo_bar": foo.c.data + }) + + class MutableColumnCopyJSONTest(_MutableDictTestBase, fixtures.MappedTest): @classmethod @@ -967,6 +978,17 @@ class MutableAssociationScalarPickleTest(_MutableDictTestBase, ) +class MutableAssocIncludeNonPrimaryTest(MutableAssociationScalarPickleTest): + @classmethod + def setup_mappers(cls): + foo = cls.tables.foo + + mapper(Foo, foo) + mapper(Foo, foo, non_primary=True, properties={ + "foo_bar": foo.c.data + }) + + class MutableAssociationScalarJSONTest(_MutableDictTestBase, fixtures.MappedTest): -- 2.47.2