diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2006-06-30 03:56:49 +0000 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2006-06-30 03:56:49 +0000 |
commit | 6446bb1360d23bcf4500d7afe63cf84cd1957665 (patch) | |
tree | 782d01a6204e89eef5e08d689bd3255ae18624bd /lib/sqlalchemy/attributes.py | |
parent | a8c2b7b97902fa9dd69a11f696ad2d4e0bf6328b (diff) | |
download | sqlalchemy-6446bb1360d23bcf4500d7afe63cf84cd1957665.tar.gz |
fixes to attributes/related so that get_history with passive=True returns no
AttributeHistory object if an untriggered callable was found (not sure how this used to work
OK....)
Diffstat (limited to 'lib/sqlalchemy/attributes.py')
-rw-r--r-- | lib/sqlalchemy/attributes.py | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/lib/sqlalchemy/attributes.py b/lib/sqlalchemy/attributes.py index 2bf336398..5e2226e9d 100644 --- a/lib/sqlalchemy/attributes.py +++ b/lib/sqlalchemy/attributes.py @@ -10,6 +10,9 @@ import weakref class InstrumentedAttribute(object): """a property object that instruments attribute access on object instances. All methods correspond to a single attribute on a particular class.""" + + PASSIVE_NORESULT = object() + def __init__(self, manager, key, uselist, callable_, typecallable, trackparent=False, extension=None, **kwargs): self.manager = manager self.key = key @@ -40,9 +43,16 @@ class InstrumentedAttribute(object): item._state[('hasparent', self)] = value def get_history(self, obj, passive=False): - """returns a new AttributeHistory object for the given object for this - InstrumentedAttribute's attribute.""" - return AttributeHistory(self, obj, passive=passive) + """return a new AttributeHistory object for the given object/this attribute's key. + + if passive is True, then dont execute any callables; if the attribute's value + can only be achieved via executing a callable, then return None.""" + # get the current state. this may trigger a lazy load if + # passive is False. + current = self.get(obj, passive=passive, raiseerr=False) + if current is InstrumentedAttribute.PASSIVE_NORESULT: + return None + return AttributeHistory(self, obj, current, passive=passive) def set_callable(self, obj, callable_): """sets a callable function on the given object which will be executed when this attribute @@ -123,7 +133,7 @@ class InstrumentedAttribute(object): callable_ = self._get_callable(obj) if callable_ is not None: if passive: - return None + return InstrumentedAttribute.PASSIVE_NORESULT l = InstrumentedList(self, obj, self._adapt_list(callable_()), init=False) # if a callable was executed, then its part of the "committed state" # if any, so commit the newly loaded data @@ -141,7 +151,7 @@ class InstrumentedAttribute(object): callable_ = self._get_callable(obj) if callable_ is not None: if passive: - return None + return InstrumentedAttribute.PASSIVE_NORESULT obj.__dict__[self.key] = callable_() # if a callable was executed, then its part of the "committed state" # if any, so commit the newly loaded data @@ -473,12 +483,9 @@ class CommittedState(object): class AttributeHistory(object): """calculates the "history" of a particular attribute on a particular instance, based on the CommittedState associated with the instance, if any.""" - def __init__(self, attr, obj, passive=False): + def __init__(self, attr, obj, current, passive=False): self.attr = attr - # get the current state. this may trigger a lazy load if - # passive is False. - current = attr.get(obj, passive=passive, raiseerr=False) - + # get the "original" value. if a lazy load was fired when we got # the 'current' value, this "original" was also populated just # now as well (therefore we have to get it second) @@ -492,7 +499,6 @@ class AttributeHistory(object): self._current = current else: self._current = [current] - if attr.uselist: s = util.Set(original or []) self._added_items = [] @@ -592,7 +598,7 @@ class AttributeManager(object): """ attr = getattr(obj.__class__, key) x = attr.get(obj, passive=passive) - if x is None: + if x is InstrumentedAttribute.PASSIVE_NORESULT: return [] elif attr.uselist: return x |