From 24cd39de0fc1b8b8ad80b0503bd48b137e0e152f Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 6 Oct 2014 18:33:05 -0400 Subject: [PATCH] - Fixed "'NoneType' object has no attribute 'concrete'" error when using :class:`.AbstractConcreteBase` in conjunction with a subclass that declares ``__abstract__``. fixes #3185 Conflicts: test/ext/declarative/test_inheritance.py --- doc/build/changelog/changelog_09.rst | 9 +++++++ lib/sqlalchemy/ext/declarative/api.py | 2 +- test/ext/declarative/test_inheritance.py | 30 ++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/doc/build/changelog/changelog_09.rst b/doc/build/changelog/changelog_09.rst index 7dd50739e0..692c6e3925 100644 --- a/doc/build/changelog/changelog_09.rst +++ b/doc/build/changelog/changelog_09.rst @@ -13,6 +13,15 @@ .. changelog:: :version: 0.9.8 + .. change:: + :tags: bug, declarative, orm + :versions: 1.0.0 + :tickets: 3185 + + Fixed "'NoneType' object has no attribute 'concrete'" error + when using :class:`.AbstractConcreteBase` in conjunction with + a subclass that declares ``__abstract__``. + .. change:: :tags: bug, engine :versions: 1.0.0 diff --git a/lib/sqlalchemy/ext/declarative/api.py b/lib/sqlalchemy/ext/declarative/api.py index daf8bffb5c..fe64ee71c7 100644 --- a/lib/sqlalchemy/ext/declarative/api.py +++ b/lib/sqlalchemy/ext/declarative/api.py @@ -396,7 +396,7 @@ class AbstractConcreteBase(ConcreteBase): for scls in cls.__subclasses__(): sm = _mapper_or_none(scls) - if sm.concrete and cls in scls.__bases__: + if sm and sm.concrete and cls in scls.__bases__: sm._set_concrete_base(m) diff --git a/test/ext/declarative/test_inheritance.py b/test/ext/declarative/test_inheritance.py index e450a1c433..b1fbfd3626 100644 --- a/test/ext/declarative/test_inheritance.py +++ b/test/ext/declarative/test_inheritance.py @@ -1303,3 +1303,33 @@ class ConcreteExtensionConfigTest( "b.b_data AS b_data, 'b' AS type FROM b) AS pjoin " "ON pjoin.a_id = a.id" ) + + def test_abstract_in_hierarchy(self): + class Document(Base, AbstractConcreteBase): + doctype = Column(String) + + class ContactDocument(Document): + __abstract__ = True + + send_method = Column(String) + + class ActualDocument(ContactDocument): + __tablename__ = 'actual_documents' + __mapper_args__ = { + 'concrete': True, + 'polymorphic_identity': 'actual'} + + id = Column(Integer, primary_key=True) + + configure_mappers() + session = Session() + self.assert_compile( + session.query(Document), + "SELECT pjoin.doctype AS pjoin_doctype, " + "pjoin.send_method AS pjoin_send_method, " + "pjoin.id AS pjoin_id, pjoin.type AS pjoin_type " + "FROM (SELECT actual_documents.doctype AS doctype, " + "actual_documents.send_method AS send_method, " + "actual_documents.id AS id, 'actual' AS type " + "FROM actual_documents) AS pjoin" + ) -- 2.47.3