loading would prevent other eager loads, self referential or not,
from joining to the parent JOIN properly. Thanks to Alex K
for creating a great test case.
+
+ - session.expire() and related methods will not expire() unloaded
+ deferred attributes. This prevents them from being needlessly
+ loaded when the instance is refreshed.
- sql
- Further fixes to the "percent signs and spaces in column/table
if prop is None and raiseerr:
raise sa_exc.InvalidRequestError("Mapper '%s' has no property '%s'" % (str(self), key))
return prop
-
+
+ @util.memoized_property
+ def _deferred_props(self):
+ return [p.key for p in self._props.values() if
+ isinstance(p, ColumnProperty) and getattr(p, 'deferred', False)]
+
@property
def iterate_properties(self):
"""return an iterator of all MapperProperty objects."""
return util.IdentitySet(self._new.values())
-_expire_state = attributes.InstanceState.expire_attributes
+def _expire_state(state, attribute_names):
+ if attribute_names is None:
+ state.expired = True
+ state.modified= False
+ # dont add unloaded deferred attributes to the list of attrs
+ attribute_names = set(state.manager.keys()).\
+ difference([k for k in state.manager.mapper._deferred_props if k not in state.dict])
+ state.expire_attributes(attribute_names)
+
UOWEventHandler = unitofwork.UOWEventHandler
_sessions = weakref.WeakValueDictionary()
import gc
from testlib import sa, testing
from testlib.sa import Table, Column, Integer, String, ForeignKey, exc as sa_exc
-from testlib.sa.orm import mapper, relation, create_session, attributes
+from testlib.sa.orm import mapper, relation, create_session, attributes, deferred
from orm import _base, _fixtures
# but now its back, rollback has occured, the _remove_newly_deleted
# is reverted
self.assertEquals(u.name, 'chuck')
-
+
+ @testing.resolve_artifact_names
+ def test_deferred(self):
+ """test that unloaded, deferred attributes aren't included in the expiry list."""
+
+ mapper(Order, orders, properties={'description':deferred(orders.c.description)})
+
+ s = create_session()
+ o1 = s.query(Order).first()
+ assert 'description' not in o1.__dict__
+ s.expire(o1)
+ assert o1.isopen is not None
+ assert 'description' not in o1.__dict__
+ assert o1.description
+
@testing.resolve_artifact_names
def test_lazyload_autoflushes(self):
mapper(User, users, properties={