diff options
| -rw-r--r-- | doc/build/changelog/unreleased_20/9367.rst | 11 | ||||
| -rw-r--r-- | lib/sqlalchemy/ext/automap.py | 20 | ||||
| -rw-r--r-- | test/ext/test_automap.py | 12 |
3 files changed, 38 insertions, 5 deletions
diff --git a/doc/build/changelog/unreleased_20/9367.rst b/doc/build/changelog/unreleased_20/9367.rst new file mode 100644 index 000000000..9355ffdea --- /dev/null +++ b/doc/build/changelog/unreleased_20/9367.rst @@ -0,0 +1,11 @@ +.. change:: + :tags: bug, ext + :tickets: 9367 + + Fixed issue in automap where calling ``.prepare()`` from one of the mapped + classes would not use the correct base class when automap detected new + tables, instead using the given class, leading to mappers trying to + configure inheritance. While one should normally call ``.prepare()`` from + the base in any case, it shouldn't misbehave that badly when called from a + subclass. + diff --git a/lib/sqlalchemy/ext/automap.py b/lib/sqlalchemy/ext/automap.py index 030015284..1861791b7 100644 --- a/lib/sqlalchemy/ext/automap.py +++ b/lib/sqlalchemy/ext/automap.py @@ -1188,6 +1188,14 @@ class AutomapBase: .. versionadded:: 1.4 """ + + for mr in cls.__mro__: + if "_sa_automapbase_bookkeeping" in mr.__dict__: + automap_base = cast("Type[AutomapBase]", mr) + break + else: + assert False, "Can't locate automap base in class hierarchy" + glbls = globals() if classname_for_table is None: classname_for_table = glbls["classname_for_table"] @@ -1237,7 +1245,7 @@ class AutomapBase: ] many_to_many = [] - bookkeeping = cls._sa_automapbase_bookkeeping + bookkeeping = automap_base._sa_automapbase_bookkeeping metadata_tables = cls.metadata.tables for table_key in set(metadata_tables).difference( @@ -1278,7 +1286,7 @@ class AutomapBase: mapped_cls = type( newname, - (cls,), + (automap_base,), clsdict, ) map_config = _DeferredMapperConfig.config_for_cls( @@ -1309,7 +1317,7 @@ class AutomapBase: for map_config in table_to_map_config.values(): _relationships_for_fks( - cls, + automap_base, map_config, table_to_map_config, collection_class, @@ -1320,7 +1328,7 @@ class AutomapBase: for lcl_m2m, rem_m2m, m2m_const, table in many_to_many: _m2m_relationship( - cls, + automap_base, lcl_m2m, rem_m2m, m2m_const, @@ -1332,7 +1340,9 @@ class AutomapBase: generate_relationship, ) - for map_config in _DeferredMapperConfig.classes_for_base(cls): + for map_config in _DeferredMapperConfig.classes_for_base( + automap_base + ): map_config.map() _sa_decl_prepare = True diff --git a/test/ext/test_automap.py b/test/ext/test_automap.py index 6c4aa02c0..dca0bb063 100644 --- a/test/ext/test_automap.py +++ b/test/ext/test_automap.py @@ -65,6 +65,18 @@ class AutomapTest(fixtures.MappedTest): u1 = User(name="u1", addresses_collection={a1}) assert a1.user is u1 + def test_prepare_from_subclass(self): + """test #9367""" + Base = automap_base() + + class User(Base): + __tablename__ = "users" + + User.prepare(testing.db) + + assert not hasattr(Base.classes, "users") + assert hasattr(Base.classes, "addresses") + def test_prepare_w_only(self): Base = automap_base() |
