]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Fixed indirect regression regarding :func:`.has_inherited_table`,
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 9 Apr 2013 18:21:40 +0000 (14:21 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 9 Apr 2013 18:21:40 +0000 (14:21 -0400)
where since it considers the current class' ``__table__``, was
sensitive to when it was called.  This is 0.7's behavior also,
but in 0.7 things tended to "work out" within events like
``__mapper_args__()``.  :func:`.has_inherited_table` now only
considers superclasses, so should return the same answer
regarding the current class no matter when it's called
(obviously assuming the state of the superclass).
[ticket:2656]

doc/build/changelog/changelog_08.rst
lib/sqlalchemy/ext/declarative/api.py
test/ext/declarative/test_inheritance.py

index 503b8932bca03cff0da74cfde61194f6a7c3f338..cbc84909574eeb0e639c4c694be24bd9c96cfd85 100644 (file)
@@ -6,6 +6,19 @@
 .. changelog::
     :version: 0.8.1
 
+    .. change::
+      :tags: bug, orm, declarative
+      :tickets: 2656
+
+    Fixed indirect regression regarding :func:`.has_inherited_table`,
+    where since it considers the current class' ``__table__``, was
+    sensitive to when it was called.  This is 0.7's behavior also,
+    but in 0.7 things tended to "work out" within events like
+    ``__mapper_args__()``.  :func:`.has_inherited_table` now only
+    considers superclasses, so should return the same answer
+    regarding the current class no matter when it's called
+    (obviously assuming the state of the superclass).
+
     .. change::
       :tags: bug, orm
       :tickets: 2699
index af77919a7fc3ac046783937ffe19956eaa4fdca2..6f3ffddc72bd9b9825c35da9f3c625b3581e9803 100644 (file)
@@ -38,7 +38,7 @@ def has_inherited_table(cls):
     """Given a class, return True if any of the classes it inherits from has a
     mapped table, otherwise return False.
     """
-    for class_ in cls.__mro__:
+    for class_ in cls.__mro__[1:]:
         if getattr(class_, '__table__', None) is not None:
             return True
     return False
index ab78cc3e2ea6e9e21c4e4deb4d1bd4b0488f82bd..f0372e8eeae879b47eb4c732926a546703940e75 100644 (file)
@@ -14,7 +14,8 @@ from sqlalchemy.orm import relationship, create_session, class_mapper, \
     Session
 from sqlalchemy.testing import eq_
 from sqlalchemy.util import classproperty
-from sqlalchemy.ext.declarative import declared_attr, AbstractConcreteBase, ConcreteBase
+from sqlalchemy.ext.declarative import declared_attr, AbstractConcreteBase, \
+            ConcreteBase, has_inherited_table
 from sqlalchemy.testing import fixtures
 
 Base = None
@@ -1112,6 +1113,46 @@ class ConcreteInhTest(_RemoveListeners, DeclarativeTestBase):
                             'concrete':True}
         self._roundtrip(Employee, Manager, Engineer, Boss)
 
+
+    def test_has_inherited_table_doesnt_consider_base(self):
+        class A(Base):
+            __tablename__ = 'a'
+            id = Column(Integer, primary_key=True)
+
+        assert not has_inherited_table(A)
+
+        class B(A):
+            __tablename__ = 'b'
+            id = Column(Integer, ForeignKey('a.id'), primary_key=True)
+
+        assert has_inherited_table(B)
+
+    def test_has_inherited_table_in_mapper_args(self):
+        class Test(Base):
+            __tablename__ = 'test'
+            id = Column(Integer, primary_key=True)
+            type = Column(String(20))
+
+            @declared_attr
+            def __mapper_args__(cls):
+                if not has_inherited_table(cls):
+                    ret = {
+                        'polymorphic_identity': 'default',
+                        'polymorphic_on': cls.type,
+                        }
+                else:
+                    ret = {'polymorphic_identity': cls.__name__}
+                return ret
+
+        class PolyTest(Test):
+            __tablename__ = 'poly_test'
+            id = Column(Integer, ForeignKey(Test.id), primary_key=True)
+
+        configure_mappers()
+
+        assert Test.__mapper__.polymorphic_on is Test.__table__.c.type
+        assert PolyTest.__mapper__.polymorphic_on is Test.__table__.c.type
+
     def test_ok_to_override_type_from_abstract(self):
         class Employee(AbstractConcreteBase, Base, fixtures.ComparableEntity):
             pass