From b2741d8b77e630552c6d5749f5f427860976bb8d Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 19 Mar 2010 13:10:13 -0400 Subject: [PATCH] - added "lockmode" kw argument to Session.refresh(), will pass through the string value to Query the same as in with_lockmode(), will also do version check for a version_id_col-enabled mapping. --- CHANGES | 5 +++++ lib/sqlalchemy/orm/session.py | 13 +++++++++---- test/orm/test_versioning.py | 15 ++++++++++++++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index d7103893ff..2e11bd38a1 100644 --- a/CHANGES +++ b/CHANGES @@ -20,6 +20,11 @@ CHANGES callable that, given the current value of the "version_id_col", returns the next version number. Can be used for alternate versioning schemes such as uuid, timestamps. [ticket:1692] + + - added "lockmode" kw argument to Session.refresh(), will + pass through the string value to Query the same as + in with_lockmode(), will also do version check for a + version_id_col-enabled mapping. - Fixed bug in session.rollback() which involved not removing formerly "pending" objects from the session before diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index 0543cd38dd..0a3fbe79e2 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -882,7 +882,7 @@ class Session(object): for state, dict_ in states.items(): state.commit_all(dict_, self.identity_map) - def refresh(self, instance, attribute_names=None): + def refresh(self, instance, attribute_names=None, lockmode=None): """Refresh the attributes on the given instance. A query will be issued to the database and all attributes will be @@ -895,9 +895,13 @@ class Session(object): Eagerly-loaded relational attributes will eagerly load within the single refresh operation. - The ``attribute_names`` argument is an iterable collection of - attribute names indicating a subset of attributes to be refreshed. - + :param attribute_names: optional. An iterable collection of + string attribute names indicating a subset of attributes to + be refreshed. + + :param lockmode: Passed to the :class:`~sqlalchemy.orm.query.Query` + as used by :meth:`~sqlalchemy.orm.query.Query.with_lockmode`. + """ try: state = attributes.instance_state(instance) @@ -906,6 +910,7 @@ class Session(object): self._validate_persistent(state) if self.query(_object_mapper(instance))._get( state.key, refresh_state=state, + lockmode=lockmode, only_load_props=attribute_names) is None: raise sa_exc.InvalidRequestError( "Could not refresh instance '%s'" % diff --git a/test/orm/test_versioning.py b/test/orm/test_versioning.py index d10a4c2bbb..f146e57b8a 100644 --- a/test/orm/test_versioning.py +++ b/test/orm/test_versioning.py @@ -125,16 +125,29 @@ class VersioningTest(_base.MappedTest): s2.commit() # load, version is wrong - assert_raises(sa.orm.exc.ConcurrentModificationError, s1.query(Foo).with_lockmode('read').get, f1s1.id) + assert_raises( + sa.orm.exc.ConcurrentModificationError, + s1.query(Foo).with_lockmode('read').get, f1s1.id + ) + + # load, version is wrong + assert_raises( + sa.orm.exc.ConcurrentModificationError, + s1.refresh, f1s1, lockmode='read' + ) # reload it s1.query(Foo).populate_existing().get(f1s1.id) + # now assert version OK s1.query(Foo).with_lockmode('read').get(f1s1.id) # assert brand new load is OK too s1.close() s1.query(Foo).with_lockmode('read').get(f1s1.id) + + + @testing.emits_warning(r'.*does not support updated rowcount') @engines.close_open_connections -- 2.47.3