diff options
-rw-r--r-- | doc/build/changelog/changelog_11.rst | 8 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/session.py | 6 | ||||
-rw-r--r-- | test/orm/test_session.py | 13 |
3 files changed, 24 insertions, 3 deletions
diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst index 972c1d1df..3fed21b17 100644 --- a/doc/build/changelog/changelog_11.rst +++ b/doc/build/changelog/changelog_11.rst @@ -21,6 +21,14 @@ .. changelog:: :version: 1.1.5 + .. change:: try_finally_for_noautoflush + :tags: bug, orm + + The :attr:`.Session.no_autoflush` context manager now ensures that + the autoflush flag is reset within a "finally" block, so that if + an exception is raised within the block, the state still resets + appropriately. Pull request courtesy Emin Arakelian. + .. change:: 3878 :tags: bug, sql :tickets: 3878 diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index b39ba1465..cb1ebf013 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -1354,8 +1354,10 @@ class Session(_SessionClassMethods): """ autoflush = self.autoflush self.autoflush = False - yield self - self.autoflush = autoflush + try: + yield self + finally: + self.autoflush = autoflush def _autoflush(self): if self.autoflush and not self._flushing: diff --git a/test/orm/test_session.py b/test/orm/test_session.py index 24666d084..5cc8aec20 100644 --- a/test/orm/test_session.py +++ b/test/orm/test_session.py @@ -1,5 +1,5 @@ from sqlalchemy.testing import eq_, assert_raises, \ - assert_raises_message, assertions + assert_raises_message, assertions, is_true from sqlalchemy.testing.util import gc_collect from sqlalchemy.testing import pickleable from sqlalchemy.util import pickle @@ -317,6 +317,17 @@ class SessionStateTest(_fixtures.FixtureTest): assert u in sess.query(User).all() assert u not in sess.new + def test_with_no_autoflush_after_exception(self): + sess = Session(autoflush=True) + + assert_raises( + ZeroDivisionError, + testing.run_as_contextmanager, + sess.no_autoflush, + lambda obj: 1 / 0 + ) + + is_true(sess.autoflush) def test_deleted_flag(self): users, User = self.tables.users, self.classes.User |