From: Mike Bayer Date: Thu, 26 Jan 2017 21:11:49 +0000 (-0500) Subject: Union the exclude_properties of the inheriting mapper in declarative X-Git-Tag: rel_1_1_6~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9a5943bf76cd436484a85a6d9478507c9bac3b08;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Union the exclude_properties of the inheriting mapper in declarative Fixed bug where the "automatic exclude" feature of declarative that ensures a column local to a single table inheritance subclass does not appear as an attribute on other derivations of the base would not take effect for multiple levels of subclassing from the base. Change-Id: Ibf67b631b4870dd1bd159f7d6085549d299fffe0 Fixes: #3895 --- diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst index 440b8294d6..8ed93ef74c 100644 --- a/doc/build/changelog/changelog_11.rst +++ b/doc/build/changelog/changelog_11.rst @@ -53,6 +53,15 @@ Added :meth:`.baked.Result.scalar` and :meth:`.baked.Result.count` to the "baked" query system. + .. change:: 3895 + :tags: bug, orm, declarative + :tickets: 3895 + + Fixed bug where the "automatic exclude" feature of declarative that + ensures a column local to a single table inheritance subclass does + not appear as an attribute on other derivations of the base would + not take effect for multiple levels of subclassing from the base. + .. change:: 3893 :tags: bug, orm :tickets: 3893 diff --git a/lib/sqlalchemy/ext/declarative/base.py b/lib/sqlalchemy/ext/declarative/base.py index 16cb05e9c2..3beee31910 100644 --- a/lib/sqlalchemy/ext/declarative/base.py +++ b/lib/sqlalchemy/ext/declarative/base.py @@ -492,8 +492,12 @@ class _MapperConfig(object): if 'exclude_properties' not in mapper_args: mapper_args['exclude_properties'] = exclude_properties = \ - set([c.key for c in inherited_table.c - if c not in inherited_mapper._columntoproperty]) + set( + [c.key for c in inherited_table.c + if c not in inherited_mapper._columntoproperty] + ).union( + inherited_mapper.exclude_properties or () + ) exclude_properties.difference_update( [c.key for c in self.declared_columns]) diff --git a/test/ext/declarative/test_inheritance.py b/test/ext/declarative/test_inheritance.py index a5a86b7c6f..375bd6edca 100644 --- a/test/ext/declarative/test_inheritance.py +++ b/test/ext/declarative/test_inheritance.py @@ -1,6 +1,6 @@ from sqlalchemy.testing import eq_, assert_raises, \ - assert_raises_message, is_, is_true + assert_raises_message, is_, is_true, is_false from sqlalchemy.ext import declarative as decl import sqlalchemy as sa from sqlalchemy import testing @@ -485,6 +485,43 @@ class DeclarativeInheritanceTest(DeclarativeTestBase): ).one(), Engineer(name='vlad', primary_language='cobol')) + def test_single_cols_on_sub_base_of_joined(self): + """test [ticket:3895]""" + + class Person(Base): + __tablename__ = "person" + + id = Column(Integer, primary_key=True) + type = Column(String) + + __mapper_args__ = { + "polymorphic_on": type, + } + + class Contractor(Person): + contractor_field = Column(String) + + __mapper_args__ = { + "polymorphic_identity": "contractor", + } + + class Employee(Person): + __tablename__ = "employee" + + id = Column(Integer, ForeignKey(Person.id), primary_key=True) + + class Engineer(Employee): + __mapper_args__ = { + "polymorphic_identity": "engineer", + } + + configure_mappers() + + is_false(hasattr(Person, 'contractor_field')) + is_true(hasattr(Contractor, 'contractor_field')) + is_false(hasattr(Employee, 'contractor_field')) + is_false(hasattr(Engineer, 'contractor_field')) + def test_single_cols_on_sub_to_joined(self): """test [ticket:3797]"""