diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-08-02 19:25:43 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2014-08-02 19:25:43 -0400 |
commit | f22ed46dd241a9261d2eec1bec12e0685582e101 (patch) | |
tree | 620f398ab272e6da89c5b8f04974abcc59c460ac | |
parent | beaefd799dcc8954cbbbc9c8df9ede55cbee1e1c (diff) | |
download | sqlalchemy-3149.tar.gz |
dev3149
-rw-r--r-- | lib/sqlalchemy/ext/declarative/api.py | 25 | ||||
-rw-r--r-- | lib/sqlalchemy/ext/declarative/base.py | 11 |
2 files changed, 25 insertions, 11 deletions
diff --git a/lib/sqlalchemy/ext/declarative/api.py b/lib/sqlalchemy/ext/declarative/api.py index 251b06fed..d4450da58 100644 --- a/lib/sqlalchemy/ext/declarative/api.py +++ b/lib/sqlalchemy/ext/declarative/api.py @@ -172,7 +172,7 @@ class declared_attr(interfaces._MappedAttribute, property): def property(cls): return _declared_property - defer_defer_defer = False + should_resolve_late = False class _memoized_declared_attr(declared_attr): @@ -182,7 +182,7 @@ class _memoized_declared_attr(declared_attr): self._cascading = cascading def __get__(desc, self, cls): - if desc.defer_defer_defer: + if desc.should_resolve_late: return desc elif cls in desc.reg: return desc.reg[cls] @@ -190,6 +190,18 @@ class _memoized_declared_attr(declared_attr): desc.reg[cls] = obj = desc.fget(cls) return obj + def resolve_early(self, cls, name): + if not self._cascading: + return getattr(cls, name) + else: + return self.__get__(self, cls) + + def resolve_late(self, cls, name): + if self.should_resolve_late: + return self.fget(cls) + else: + raise NotImplementedError() + @classproperty def cascading(cls): return lambda decorated: cls(decorated, cascading=True) @@ -200,8 +212,7 @@ class _declared_column(_memoized_declared_attr): class _declared_property(_memoized_declared_attr): - defer_defer_defer = True - + should_resolve_late = True def declarative_base(bind=None, metadata=None, mapper=None, cls=object, @@ -433,6 +444,12 @@ class AbstractConcreteBase(ConcreteBase): pjoin = cls._create_polymorphic_union(mappers) cls.__mapper__ = m = mapper(cls, pjoin, polymorphic_on=pjoin.c.type) + for base in cls.__mro__: + for name, obj in vars(base).items(): + if isinstance(obj, _memoized_declared_attr) \ + and obj._cascading: + m.add_property(name, obj.resolve_late(cls, name)) + for scls in cls.__subclasses__(): sm = _mapper_or_none(scls) if sm.concrete and cls in scls.__bases__: diff --git a/lib/sqlalchemy/ext/declarative/base.py b/lib/sqlalchemy/ext/declarative/base.py index cee22637d..d17338bcb 100644 --- a/lib/sqlalchemy/ext/declarative/base.py +++ b/lib/sqlalchemy/ext/declarative/base.py @@ -132,11 +132,8 @@ def _as_declarative(cls, classname, dict_): "column_property(), relationship(), etc.) must " "be declared as @declared_attr callables " "on declarative mixin classes.") - elif isinstance(obj, _memoized_declared_attr): # and \ - if obj._cascading: - dict_[name] = ret = obj.__get__(obj, cls) - else: - dict_[name] = ret = getattr(cls, name) + elif isinstance(obj, _memoized_declared_attr): + dict_[name] = ret = obj.resolve_early(cls, name) if isinstance(ret, (Column, MapperProperty)) and \ ret.doc is None: ret.doc = obj.__doc__ @@ -166,7 +163,7 @@ def _as_declarative(cls, classname, dict_): value = dict_[k] if isinstance(value, declarative_props): - if value.defer_defer_defer: + if value.should_resolve_late: add_later[k] = value else: value = getattr(cls, k) @@ -426,7 +423,7 @@ class _MapperConfig(object): **mapper_args ) for k, v in self.add_later.items(): - setattr(self.cls, k, v.fget(self.cls)) + setattr(self.cls, k, v.resolve_late(self.cls, k)) class _DeferredMapperConfig(_MapperConfig): |