are constructed after existing ones have been used
already.
+ - When an open Session is garbage collected, the objects
+ within it which remain are considered detached again
+ when they are add()-ed to a new Session.
+ This is accomplished by an extra check that the previous
+ "session_key" doesn't actually exist among the pool
+ of Sessions. [ticket:2281]
+
- New declarative features:
- __declare_last__() method, establishes an event
listener for the class method that will be called
"present in this session."
% (mapperutil.state_str(state), state.key))
- if state.session_id and state.session_id is not self.hash_key:
+ if state.session_id and \
+ state.session_id is not self.hash_key and \
+ state.session_id in _sessions:
raise sa_exc.InvalidRequestError(
"Object '%s' is already attached to session '%s' "
"(this is '%s')" % (mapperutil.state_str(state),
del u3
gc_collect()
+ def test_auto_detach_on_gc_session(self):
+ users, User = self.tables.users, self.classes.User
+
+ mapper(User, users)
+
+ sess = Session()
+
+ u1 = User(name='u1')
+ sess.add(u1)
+ sess.commit()
+
+ # can't add u1 to Session,
+ # already belongs to u2
+ s2 = Session()
+ assert_raises_message(
+ sa.exc.InvalidRequestError,
+ r".*is already attached to session",
+ s2.add, u1
+ )
+
+ # garbage collect sess
+ del sess
+ gc_collect()
+
+ # s2 lets it in now despite u1 having
+ # session_key
+ s2.add(u1)
+ assert u1 in s2
+
class SessionDataTest(_fixtures.FixtureTest):
def test_expunge_cascade(self):
Address, addresses, users, User = (self.classes.Address,