diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-09-27 11:44:58 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2020-09-27 11:45:49 -0400 |
commit | 17dd7fce6164794f6fd75a9351061f109e3360b1 (patch) | |
tree | ec85112b76a1124c113993d8124c7516134dfae5 | |
parent | ffafbd4b9657a4ee8bec57c0861414144f37bdc5 (diff) | |
download | sqlalchemy-17dd7fce6164794f6fd75a9351061f109e3360b1.tar.gz |
Accommodate for same base class multiple times in inherits list
Improved declarative inheritance scanning to not get tripped up when the
same base class appears multiple times in the base inheritance list.
Fixes: #4699
Change-Id: I932e735cd2e2c1efa935936c84219924225d10f1
-rw-r--r-- | doc/build/changelog/unreleased_14/4699.rst | 7 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/decl_base.py | 3 | ||||
-rw-r--r-- | test/orm/declarative/test_mixin.py | 25 |
3 files changed, 34 insertions, 1 deletions
diff --git a/doc/build/changelog/unreleased_14/4699.rst b/doc/build/changelog/unreleased_14/4699.rst new file mode 100644 index 000000000..e1e1442cf --- /dev/null +++ b/doc/build/changelog/unreleased_14/4699.rst @@ -0,0 +1,7 @@ +.. change:: + :tags: bug, orm + :tickets: 4699 + + Improved declarative inheritance scanning to not get tripped up when the + same base class appears multiple times in the base inheritance list. + diff --git a/lib/sqlalchemy/orm/decl_base.py b/lib/sqlalchemy/orm/decl_base.py index b9c890429..644e4aff6 100644 --- a/lib/sqlalchemy/orm/decl_base.py +++ b/lib/sqlalchemy/orm/decl_base.py @@ -677,7 +677,8 @@ class _ClassScanMapperConfig(_MapperConfig): ) is not None and not _get_immediate_cls_attr( c, "_sa_decl_prepare_nocascade", strict=True ): - inherits_search.append(c) + if c not in inherits_search: + inherits_search.append(c) if inherits_search: if len(inherits_search) > 1: diff --git a/test/orm/declarative/test_mixin.py b/test/orm/declarative/test_mixin.py index eed918572..bc36ee962 100644 --- a/test/orm/declarative/test_mixin.py +++ b/test/orm/declarative/test_mixin.py @@ -218,6 +218,31 @@ class DeclarativeMixinTest(DeclarativeTestBase): eq_(MyModelA.__table__.c.foo.type.__class__, String) eq_(MyModelB.__table__.c.foo.type.__class__, Integer) + def test_same_base_multiple_times(self): + class User(Base): + __tablename__ = "user" + + id = Column(Integer, primary_key=True) + name = Column(String) + surname = Column(String) + + class SpecialUser(User): + __abstract__ = True + + class ConvenienceStuff(User): + __abstract__ = True + + def fullname(self): + return self.name + " " + self.surname + + class Manager(SpecialUser, ConvenienceStuff, User): + __tablename__ = "manager" + + id = Column(Integer, ForeignKey("user.id"), primary_key=True) + title = Column(String) + + eq_(Manager.__table__.name, "manager") + def test_not_allowed(self): class MyMixin: foo = Column(Integer, ForeignKey("bar.id")) |