self.callables[key] = callable_
def __fire_trigger(self):
- self.trigger(self.obj(), self.expired_attributes)
+ instance = self.obj()
+ self.trigger(instance, [k for k in self.expired_attributes if k not in self.dict])
for k in self.expired_attributes:
self.callables.pop(k, None)
self.expired_attributes.clear()
strategy = self.parent_property._get_strategy(DeferredColumnLoader)
# full list of ColumnProperty objects to be loaded in the deferred fetch
- props = [p for p in mapper.iterate_properties if isinstance(p.strategy, ColumnLoader) and p.columns[0].table in needs_tables]
+ props = [p.key for p in mapper.iterate_properties if isinstance(p.strategy, ColumnLoader) and p.columns[0].table in needs_tables]
# TODO: we are somewhat duplicating efforts from mapper._get_poly_select_loader
# and should look for ways to simplify.
if props is not None:
group = props
elif self.group is not None:
- group = [p for p in localparent.iterate_properties if isinstance(p.strategy, DeferredColumnLoader) and p.group==self.group]
+ group = [p.key for p in localparent.iterate_properties if isinstance(p.strategy, DeferredColumnLoader) and p.group==self.group]
else:
- group = [self.parent_property]
-
+ group = [self.parent_property.key]
+
+ group = [k for k in group if k not in instance.__dict__]
+
if self._should_log_debug:
self.logger.debug("deferred load %s group %s" % (mapperutil.attribute_str(instance, self.key), group and ','.join([p.key for p in group]) or 'None'))
if create_statement is None:
ident = instance._instance_key[1]
- session.query(localparent)._get(None, ident=ident, only_load_props=[p.key for p in group], refresh_instance=instance)
+ session.query(localparent)._get(None, ident=ident, only_load_props=group, refresh_instance=instance)
else:
statement, params = create_statement(instance)
- session.query(localparent).from_statement(statement).params(params)._get(None, only_load_props=[p.key for p in group], refresh_instance=instance)
+ session.query(localparent).from_statement(statement).params(params)._get(None, only_load_props=group, refresh_instance=instance)
return attributes.ATTR_WAS_SET
return lazyload
sess.flush()
sess.clear()
assert sess.query(User).get(7).name == 'somenewname'
+
+ def test_expire_preserves_changes(self):
+ """test that the expire load operation doesn't revert post-expire changes"""
+
+ mapper(Order, orders)
+ sess = create_session()
+ o = sess.query(Order).get(3)
+ sess.expire(o)
+
+ o.description = "order 3 modified"
+ def go():
+ assert o.isopen == 1
+ self.assert_sql_count(testbase.db, go, 1)
+ assert o.description == 'order 3 modified'
def test_expire_committed(self):
"""test that the committed state of the attribute receives the most recent DB data"""
def go():
sess.flush()
self.assert_sql_count(testbase.db, go, 0)
-
+
+ def test_preserve_changes(self):
+ """test that the deferred load operation doesn't revert modifications on attributes"""
+
+ mapper(Order, orders, properties = {
+ 'userident':deferred(orders.c.user_id, group='primary'),
+ 'description':deferred(orders.c.description, group='primary'),
+ 'opened':deferred(orders.c.isopen, group='primary')
+ })
+ sess = create_session()
+ o = sess.query(Order).get(3)
+ assert 'userident' not in o.__dict__
+ o.description = 'somenewdescription'
+ assert o.description == 'somenewdescription'
+ def go():
+ assert o.opened == 1
+ self.assert_sql_count(testbase.db, go, 1)
+ assert o.description == 'somenewdescription'
+ assert o in sess.dirty
+
+
def test_commitsstate(self):
"""test that when deferred elements are loaded via a group, they get the proper CommittedState
and dont result in changes being committed"""