NO_VALUE = util.symbol('NO_VALUE')
NEVER_SET = util.symbol('NEVER_SET')
-# "passive" get settings
-# TODO: the True/False values need to be factored out
-PASSIVE_NO_INITIALIZE = True #util.symbol('PASSIVE_NO_INITIALIZE')
+PASSIVE_NO_INITIALIZE = util.symbol('PASSIVE_NO_INITIALIZE')
"""Symbol indicating that loader callables should
not be fired off, and a non-initialized attribute
should remain that way."""
-# this is used by backrefs.
PASSIVE_NO_FETCH = util.symbol('PASSIVE_NO_FETCH')
"""Symbol indicating that loader callables should not emit SQL.
Non-initialized attributes should be initialized to an empty value."""
Loads of "previous" values during change events use this flag.
"""
-PASSIVE_OFF = False #util.symbol('PASSIVE_OFF')
+PASSIVE_OFF = util.symbol('PASSIVE_OFF')
"""Symbol indicating that loader callables should be executed."""
def _supports_population(self):
return self.impl.supports_population
- def get_history(self, instance, **kwargs):
+ def get_history(self, instance, passive=PASSIVE_OFF):
return self.impl.get_history(instance_state(instance),
- instance_dict(instance), **kwargs)
+ instance_dict(instance), passive)
def __selectable__(self):
# TODO: conditionally attach this method based on clause_element ?
passive is False, the callable will be executed and the
resulting value will be set as the new value for this attribute.
"""
-
if self.key in dict_:
return dict_[self.key]
else:
HISTORY_BLANK = History(None, None, None)
-def get_history(obj, key, **kwargs):
+def get_history(obj, key, passive=PASSIVE_OFF):
"""Return a :class:`.History` record for the given object
and attribute key.
:param key: string attribute name.
- :param kwargs: Optional keyword arguments currently
- include the ``passive`` flag, which indicates if the attribute should be
+ :param passive: indicates if the attribute should be
loaded from the database if not already present (:attr:`PASSIVE_NO_FETCH`), and
if the attribute should be not initialized to a blank value otherwise
(:attr:`PASSIVE_NO_INITIALIZE`). Default is :attr:`PASSIVE_OFF`.
"""
- return get_state_history(instance_state(obj), key, **kwargs)
+ return get_state_history(instance_state(obj), key, passive)
-def get_state_history(state, key, **kwargs):
- return state.get_history(key, **kwargs)
+def get_state_history(state, key, passive=PASSIVE_OFF):
+ return state.get_history(key, passive)
def has_parent(cls, obj, key, optimistic=False):
self.passive_deletes = prop.passive_deletes
self.passive_updates = prop.passive_updates
self.enable_typechecks = prop.enable_typechecks
- self._passive_delete_flag = self.passive_deletes and \
- attributes.PASSIVE_NO_INITIALIZE or \
- attributes.PASSIVE_OFF
+ if self.passive_deletes:
+ self._passive_delete_flag = attributes.PASSIVE_NO_INITIALIZE
+ else:
+ self._passive_delete_flag = attributes.PASSIVE_OFF
+ if self.passive_updates:
+ self._passive_update_flag = attributes.PASSIVE_NO_INITIALIZE
+ else:
+ self._passive_update_flag= attributes.PASSIVE_OFF
+
self.key = prop.key
if not self.prop.synchronize_pairs:
raise sa_exc.ArgumentError(
history = uowcommit.get_attribute_history(
s,
self.key,
- passive=passive)
+ passive)
if history and not history.empty():
return True
else:
history = uowcommit.get_attribute_history(
state,
self.key,
- passive=self._passive_delete_flag)
+ self._passive_delete_flag)
if history:
for child in history.deleted:
if child is not None and self.hasparent(child) is False:
for state in states:
pks_changed = self._pks_changed(uowcommit, state)
+ if not pks_changed or self.passive_updates:
+ passive = attributes.PASSIVE_NO_INITIALIZE
+ else:
+ passive = attributes.PASSIVE_OFF
+
history = uowcommit.get_attribute_history(
state,
self.key,
- passive=not pks_changed
- or self.passive_updates)
+ passive)
if history:
for child in history.added:
if child is not None:
history = uowcommit.get_attribute_history(
state,
self.key,
- passive=self._passive_delete_flag)
+ self._passive_delete_flag)
if history:
for child in history.deleted:
if child is not None and \
def process_saves(self, uowcommit, states):
for state in states:
- history = uowcommit.get_attribute_history(state,
- self.key,
- passive=True)
+ history = uowcommit.get_attribute_history(
+ state,
+ self.key,
+ attributes.PASSIVE_NO_INITIALIZE)
if history:
for child in history.added:
self._synchronize(state, child, None,
history = uowcommit.get_attribute_history(
state,
self.key,
- passive=self._passive_delete_flag)
+ self._passive_delete_flag)
if history:
if self.cascade.delete_orphan:
todelete = history.sum()
history = uowcommit.get_attribute_history(
state,
self.key,
- passive=self._passive_delete_flag)
+ self._passive_delete_flag)
if history:
ret = True
for child in history.deleted:
history = uowcommit.get_attribute_history(
state,
self.key,
- passive=self._passive_delete_flag)
+ self._passive_delete_flag)
if history:
self._post_update(state, uowcommit, history.sum())
def process_saves(self, uowcommit, states):
for state in states:
- history = uowcommit.get_attribute_history(state,
- self.key,
- passive=True)
+ history = uowcommit.get_attribute_history(
+ state,
+ self.key,
+ attributes.PASSIVE_NO_INITIALIZE)
if history:
for child in history.added:
self._synchronize(state, child, None, False,
continue
dict_ = state.dict
related = state.get_impl(self.key).get(state, dict_,
- passive=self.passive_updates)
+ passive=self._passive_update_flag)
if related is not attributes.PASSIVE_NO_RESULT and \
related is not None:
related_state = attributes.instance_state(dict_[self.key])
history = uowcommit.get_attribute_history(
state,
self.key,
- passive=self._passive_delete_flag)
+ self._passive_delete_flag)
def presort_saves(self, uowcommit, states):
if not self.passive_updates:
history = uowcommit.get_attribute_history(
state,
self.key,
- False)
+ attributes.PASSIVE_OFF)
if not self.cascade.delete_orphan:
return
history = uowcommit.get_attribute_history(
state,
self.key,
- passive=True)
+ attributes.PASSIVE_NO_INITIALIZE)
if history:
for child in history.deleted:
if self.hasparent(child) is False:
history = uowcommit.get_attribute_history(
state,
self.key,
- passive=self._passive_delete_flag)
+ self._passive_delete_flag)
if history:
for child in history.non_added():
if child is None or \
for state in states:
need_cascade_pks = not self.passive_updates and \
self._pks_changed(uowcommit, state)
+ if need_cascade_pks:
+ passive = attributes.PASSIVE_OFF
+ else:
+ passive = attributes.PASSIVE_NO_INITIALIZE
history = uowcommit.get_attribute_history(state, self.key,
- passive=not need_cascade_pks)
+ passive)
if history:
for child in history.added:
if child is None or \
self.key = key
if hasattr(prop, 'get_history'):
- def get_history(self, state, dict_, **kw):
- return prop.get_history(state, dict_, **kw)
+ def get_history(self, state, dict_,
+ passive=attributes.PASSIVE_OFF):
+ return prop.get_history(state, dict_, passive)
if self.descriptor is None:
desc = getattr(mapper.class_, self.key, None)
prop.key for prop in self.props
]
- def get_history(self, state, dict_, **kw):
+ def get_history(self, state, dict_, passive=attributes.PASSIVE_OFF):
"""Provided for userland code that uses attributes.get_history()."""
added = []
else:
self.query_class = mixin_user_query(query_class)
- def get(self, state, dict_, passive=False):
- if passive:
+ def get(self, state, dict_, passive=attributes.PASSIVE_OFF):
+ if passive is not attributes.PASSIVE_OFF:
return self._get_collection_history(state,
- passive=True).added_items
+ attributes.PASSIVE_NO_INITIALIZE).added_items
else:
return self.query_class(self, state)
- def get_collection(self, state, dict_, user_data=None, passive=True):
- if passive:
+ def get_collection(self, state, dict_, user_data=None,
+ passive=attributes.PASSIVE_NO_INITIALIZE):
+ if passive is not attributes.PASSIVE_OFF:
return self._get_collection_history(state,
- passive=passive).added_items
+ passive).added_items
else:
- history = self._get_collection_history(state,
- passive=passive)
+ history = self._get_collection_history(state, passive)
return history.added_items + history.unchanged_items
def fire_append_event(self, state, dict_, value, initiator):
raise NotImplementedError("Dynamic attributes don't support "
"collection population.")
- def get_history(self, state, dict_, passive=False):
+ def get_history(self, state, dict_, passive=attributes.PASSIVE_OFF):
c = self._get_collection_history(state, passive)
return attributes.History(c.added_items, c.unchanged_items,
c.deleted_items)
c.added_items + c.unchanged_items + c.deleted_items
]
- def _get_collection_history(self, state, passive=False):
+ def _get_collection_history(self, state, passive=attributes.PASSIVE_OFF):
if self.key in state.committed_state:
c = state.committed_state[self.key]
else:
c = CollectionHistory(self, state)
- if not passive:
+ if passive is attributes.PASSIVE_OFF:
return CollectionHistory(self, state, apply_to=c)
else:
return c
- def append(self, state, dict_, value, initiator, passive=False):
+ def append(self, state, dict_, value, initiator,
+ passive=attributes.PASSIVE_OFF):
if initiator is not self:
self.fire_append_event(state, dict_, value, initiator)
- def remove(self, state, dict_, value, initiator, passive=False):
+ def remove(self, state, dict_, value, initiator,
+ passive=attributes.PASSIVE_OFF):
if initiator is not self:
self.fire_remove_event(state, dict_, value, initiator)
if sess is None:
return iter(self.attr._get_collection_history(
attributes.instance_state(self.instance),
- passive=True).added_items)
+ attributes.PASSIVE_NO_INITIALIZE).added_items)
else:
return iter(self._clone(sess))
if sess is None:
return self.attr._get_collection_history(
attributes.instance_state(self.instance),
- passive=True).added_items.__getitem__(index)
+ attributes.PASSIVE_NO_INITIALIZE).added_items.\
+ __getitem__(index)
else:
return self._clone(sess).__getitem__(index)
if sess is None:
return len(self.attr._get_collection_history(
attributes.instance_state(self.instance),
- passive=True).added_items)
+ attributes.PASSIVE_NO_INITIALIZE).added_items)
else:
return self._clone(sess).count()
manager = state.manager
return self._identity_class, tuple([
manager[self._columntoproperty[col].key].\
- impl.get(state, dict_, False)
+ impl.get(state, dict_, attributes.PASSIVE_OFF)
for col in self.primary_key
])
manager = state.manager
return [
manager[self._columntoproperty[col].key].\
- impl.get(state, dict_, False)
+ impl.get(state, dict_, attributes.PASSIVE_OFF)
for col in self.primary_key
]
- def _get_state_attr_by_column(self, state, dict_, column, passive=False):
+ def _get_state_attr_by_column(self, state, dict_, column,
+ passive=attributes.PASSIVE_OFF):
prop = self._columntoproperty[column]
return state.manager[prop.key].impl.get(state, dict_, passive=passive)
dict_ = attributes.instance_dict(obj)
return self._get_committed_state_attr_by_column(state, dict_, column)
- def _get_committed_state_attr_by_column(self, state, dict_, column,
- passive=False):
+ def _get_committed_state_attr_by_column(self, state, dict_,
+ column, passive=attributes.PASSIVE_OFF):
prop = self._columntoproperty[column]
return state.manager[prop.key].impl.\
if leftcol.table not in tables:
leftval = self._get_committed_state_attr_by_column(
- state, state.dict,
- leftcol, passive=True)
+ state, state.dict,
+ leftcol,
+ passive=attributes.PASSIVE_NO_INITIALIZE)
if leftval is attributes.PASSIVE_NO_RESULT or leftval is None:
raise ColumnsNotAvailable()
binary.left = sql.bindparam(None, leftval,
type_=binary.right.type)
elif rightcol.table not in tables:
rightval = self._get_committed_state_attr_by_column(
- state, state.dict,
- rightcol, passive=True)
+ state, state.dict,
+ rightcol,
+ passive=attributes.PASSIVE_NO_INITIALIZE)
if rightval is attributes.PASSIVE_NO_RESULT or rightval is None:
raise ColumnsNotAvailable()
binary.right = sql.bindparam(None, rightval,
visited_states = set()
prp, mpp = object(), object()
- visitables = deque([(deque(self._props.values()), prp, state, state.dict)])
+ visitables = deque([(deque(self._props.values()), prp,
+ state, state.dict)])
while visitables:
iterator, item_type, parent_state, parent_dict = visitables[-1]
elif item_type is mpp:
instance, instance_mapper, corresponding_state, \
corresponding_dict = iterator.popleft()
- yield instance, instance_mapper, corresponding_state, corresponding_dict
+ yield instance, instance_mapper, \
+ corresponding_state, corresponding_dict
visitables.append((deque(instance_mapper._props.values()),
- prp, corresponding_state, corresponding_dict))
+ prp, corresponding_state,
+ corresponding_dict))
@_memoized_configured_property
def _compiled_cache(self):
elif col in post_update_cols:
prop = mapper._columntoproperty[col]
history = attributes.get_state_history(
- state, prop.key, passive=True)
+ state, prop.key,
+ attributes.PASSIVE_NO_INITIALIZE)
if history.added:
value = history.added[0]
params[col.key] = value
prop = mapper._columntoproperty[col]
history = attributes.get_state_history(
- state, prop.key, passive=True
+ state, prop.key,
+ attributes.PASSIVE_NO_INITIALIZE
)
if history.added:
params[col.key] = history.added[0]
for prop in mapper._columntoproperty.\
itervalues():
history = attributes.get_state_history(
- state, prop.key,
- passive=True)
+ state, prop.key,
+ attributes.PASSIVE_NO_INITIALIZE)
if history.added:
hasdata = True
else:
prop = mapper._columntoproperty[col]
history = attributes.get_state_history(
- state, prop.key, passive=True)
+ state, prop.key,
+ attributes.PASSIVE_NO_INITIALIZE)
if history.added:
if isinstance(history.added[0],
sql.ClauseElement):
active_history=self.active_history,
*self.columns)
- def _getcommitted(self, state, dict_, column, passive=False):
+ def _getcommitted(self, state, dict_, column,
+ passive=attributes.PASSIVE_OFF):
return state.get_impl(self.key).\
get_committed_value(state, dict_, passive=passive)
elif manytoone_fk:
self.direction = MANYTOONE
if not self.direction:
- raise sa_exc.ArgumentError("Can't determine relationshi"
- "p direction for relationship '%s' - foreign "
+ raise sa_exc.ArgumentError("Can't determine relationship"
+ " direction for relationship '%s' - foreign "
"key columns are present in both the parent "
"and the child's mapped tables. Specify "
"'foreign_keys' argument." % self)
% self)
if self.direction is MANYTOONE and self.passive_deletes:
util.warn("On %s, 'passive_deletes' is normally configured "
- "on one-to-many, one-to-one, many-to-many relationships only."
+ "on one-to-many, one-to-one, many-to-many "
+ "relationships only."
% self)
def _determine_local_remote_pairs(self):
raise
- def is_modified(self, instance, include_collections=True, passive=False):
+ def is_modified(self, instance, include_collections=True, passive=attributes.PASSIVE_OFF):
"""Return ``True`` if instance has modified attributes.
This method retrieves a history instance for each instrumented
manager.dispatch.init_failure(self, args, kwargs)
raise
- def get_history(self, key, **kwargs):
- return self.manager[key].impl.get_history(self, self.dict, **kwargs)
+ def get_history(self, key, passive):
+ return self.manager[key].impl.get_history(self, self.dict, passive)
def get_impl(self, key):
return self.manager[key].impl
self.state = state
self.key = key
- def __call__(self, passive=False):
+ def __call__(self, passive=attributes.PASSIVE_OFF):
state, key = self.state, self.key
localparent = state.manager.mapper
self.state = state
self.key = key
- def __call__(self, passive=False):
+ def __call__(self, passive=attributes.PASSIVE_OFF):
state, key = self.state, self.key
instance_mapper = state.manager.mapper
prop = instance_mapper._props[key]
between instances based on join conditions.
"""
-from sqlalchemy.orm import exc, util as mapperutil
+from sqlalchemy.orm import exc, util as mapperutil, attributes
def populate(source, source_mapper, dest, dest_mapper,
synchronize_pairs, uowcommit, flag_cascaded_pks):
try:
# inline of source_mapper._get_state_attr_by_column
prop = source_mapper._columntoproperty[l]
- value = source.manager[prop.key].impl.get(source, source_dict, False)
+ value = source.manager[prop.key].impl.get(source, source_dict,
+ attributes.PASSIVE_OFF)
except exc.UnmappedColumnError:
_raise_col_to_prop(False, source_mapper, l, dest_mapper, r)
prop = source_mapper._columntoproperty[l]
except exc.UnmappedColumnError:
_raise_col_to_prop(False, source_mapper, l, None, r)
- history = uowcommit.get_attribute_history(source, prop.key, passive=True)
+ history = uowcommit.get_attribute_history(source, prop.key,
+ attributes.PASSIVE_NO_INITIALIZE)
return bool(history.deleted)
else:
return False
self.states[state] = (isdelete, True)
- def get_attribute_history(self, state, key, passive=attributes.PASSIVE_NO_INITIALIZE):
+ def get_attribute_history(self, state, key,
+ passive=attributes.PASSIVE_NO_INITIALIZE):
"""facade to attributes.get_state_history(), including caching of results."""
hashkey = ("history", state, key)
history, state_history, cached_passive = self.attributes[hashkey]
# if the cached lookup was "passive" and now
# we want non-passive, do a non-passive lookup and re-cache
- if cached_passive and not passive:
+ if cached_passive is not attributes.PASSIVE_OFF \
+ and passive is attributes.PASSIVE_OFF:
impl = state.manager[key].impl
- history = impl.get_history(state, state.dict, passive=False)
+ history = impl.get_history(state, state.dict,
+ attributes.PASSIVE_OFF)
if history and impl.uses_objects:
state_history = history.as_state()
else:
impl = state.manager[key].impl
# TODO: store the history as (state, object) tuples
# so we don't have to keep converting here
- history = impl.get_history(state, state.dict, passive=passive)
+ history = impl.get_history(state, state.dict, passive)
if history and impl.uses_objects:
state_history = history.as_state()
else:
return symbol, (self.name,)
def __repr__(self):
return "<symbol '%s>" % self.name
+
_symbol.__name__ = 'symbol'
p4 = Post("post 5")
p4.blog = b
assert called[0] == 0
- eq_(attributes.instance_state(b).get_history('posts'), ([p, p4], [p1, p2, p3], []))
+ eq_(attributes.instance_state(b).
+ get_history('posts', attributes.PASSIVE_OFF),
+ ([p, p4], [p1, p2, p3], []))
assert called[0] == 1
def test_lazy_remove(self):