From 95e53d0b6072510c7a687e3bcc92246d9b3d7181 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 10 Mar 2015 17:21:46 -0400 Subject: - Fixed bug where using an ``__abstract__`` mixin in the middle of a declarative inheritance hierarchy would prevent attributes and configuration being correctly propagated from the base class to the inheriting class. fixes #3219 fixes #3240 --- lib/sqlalchemy/ext/declarative/base.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'lib') diff --git a/lib/sqlalchemy/ext/declarative/base.py b/lib/sqlalchemy/ext/declarative/base.py index e35ae085a..7d4020b24 100644 --- a/lib/sqlalchemy/ext/declarative/base.py +++ b/lib/sqlalchemy/ext/declarative/base.py @@ -35,6 +35,21 @@ def _declared_mapping_info(cls): return None +def _resolve_for_abstract(cls): + if cls is object: + return None + + if _get_immediate_cls_attr(cls, '__abstract__'): + for sup in cls.__bases__: + sup = _resolve_for_abstract(sup) + if sup is not None: + return sup + else: + return None + else: + return cls + + def _get_immediate_cls_attr(cls, attrname): """return an attribute of the class that is either present directly on the class, e.g. not on a superclass, or is from a superclass but @@ -46,6 +61,9 @@ def _get_immediate_cls_attr(cls, attrname): inherit from. """ + if not issubclass(cls, object): + return None + for base in cls.__mro__: _is_declarative_inherits = hasattr(base, '_decl_class_registry') if attrname in base.__dict__: @@ -389,6 +407,9 @@ class _MapperConfig(object): table_args = self.table_args declared_columns = self.declared_columns for c in cls.__bases__: + c = _resolve_for_abstract(c) + if c is None: + continue if _declared_mapping_info(c) is not None and \ not _get_immediate_cls_attr( c, '_sa_decl_prepare_nocascade'): -- cgit v1.2.1