diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2017-05-26 13:26:40 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2017-05-26 13:28:15 -0400 |
| commit | 8b82369347641d1c9d64406462fa5527132c4880 (patch) | |
| tree | a031040645ba90b6232545f3376419872a8eb00b /lib/sqlalchemy | |
| parent | b1369b47217558779a5b8a17ecd945cedd608dc7 (diff) | |
| download | sqlalchemy-8b82369347641d1c9d64406462fa5527132c4880.tar.gz | |
Don't hard-evaluate non-ORM @declared_attr for AbstractConcreteBase
Fixed bug where using :class:`.declared_attr` on an
:class:`.AbstractConcreteBase` where a particular return value were some
non-mapped symbol, including ``None``, would cause the attribute
to hard-evaluate just once and store the value to the object
dictionary, not allowing it to invoke for subclasses. This behavior
is normal when :class:`.declared_attr` is on a mapped class, and
does not occur on a mixin or abstract class. Since
:class:`.AbstractConcreteBase` is both "abstract" and actually
"mapped", a special exception case is made here so that the
"abstract" behavior takes precedence for :class:`.declared_attr`.
Change-Id: I6160ebb3a52c441d6a4b663c8c9bbac6d37fa417
Fixes: #3848
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/ext/declarative/base.py | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/lib/sqlalchemy/ext/declarative/base.py b/lib/sqlalchemy/ext/declarative/base.py index 95f02ea96..d9433e692 100644 --- a/lib/sqlalchemy/ext/declarative/base.py +++ b/lib/sqlalchemy/ext/declarative/base.py @@ -273,6 +273,9 @@ class _MapperConfig(object): our_stuff = self.properties + late_mapped = _get_immediate_cls_attr( + cls, '_sa_decl_prepare_nocascade', strict=True) + for k in list(dict_): if k in ('__table__', '__tablename__', '__mapper_args__'): @@ -302,7 +305,8 @@ class _MapperConfig(object): # and place the evaluated value onto the class. if not k.startswith('__'): dict_.pop(k) - setattr(cls, k, value) + if not late_mapped: + setattr(cls, k, value) continue # we expect to see the name 'metadata' in some valid cases; # however at this point we see it's assigned to something trying |
