]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Add standalone orm.close_all method and deprecate SessionMaker.close_all
authorAugustin Trancart <augustin.trancart@oslandia.com>
Sat, 12 Jan 2019 15:46:01 +0000 (10:46 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 12 Jan 2019 22:19:37 +0000 (17:19 -0500)
Added a new function :func:`.close_all_sessions` which takes
over the task of the :meth:`.Session.close_all` method, which
is now deprecated as this is confusing as a classmethod.
Pull request courtesy Augustin Trancart.

Fixes: #4412
Closes: #4438
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/4438
Pull-request-sha: 7833d12a9898c82d50716427144bf3276c22ab3f

Change-Id: Ib35eaa520ae886f3f8f550f9712fc3b139e00b60

doc/build/changelog/unreleased_13/4412.rst [new file with mode: 0644]
doc/build/orm/session_api.rst
lib/sqlalchemy/orm/__init__.py
lib/sqlalchemy/orm/session.py
lib/sqlalchemy/testing/fixtures.py
test/ext/declarative/test_basic.py
test/ext/declarative/test_inheritance.py
test/ext/declarative/test_mixin.py
test/orm/test_eager_relations.py
test/orm/test_session.py
test/orm/test_subquery_relations.py

diff --git a/doc/build/changelog/unreleased_13/4412.rst b/doc/build/changelog/unreleased_13/4412.rst
new file mode 100644 (file)
index 0000000..3c868ff
--- /dev/null
@@ -0,0 +1,8 @@
+.. change::
+   :tags: change, orm
+   :tickets: 4412
+
+   Added a new function :func:`.close_all_sessions` which takes
+   over the task of the :meth:`.Session.close_all` method, which
+   is now deprecated as this is confusing as a classmethod.
+   Pull request courtesy Augustin Trancart.
index 5523422e01c481582c3471672094bb971a8e47c9..683719945fb787831bb282c6345563bc2700793e 100644 (file)
@@ -20,6 +20,8 @@ Session and sessionmaker()
 Session Utilities
 -----------------
 
+.. autofunction:: close_all_sessions
+
 .. autofunction:: make_transient
 
 .. autofunction:: make_transient_to_detached
index 5c286a71bc1fa765e020a7299e4c236d55ba17bf..1666104d98d425e0e7e9a69efc667c42dd0af7d9 100644 (file)
@@ -40,6 +40,7 @@ from .relationships import foreign  # noqa
 from .relationships import RelationshipProperty  # noqa
 from .relationships import remote  # noqa
 from .scoping import scoped_session  # noqa
+from .session import close_all_sessions  # noqa
 from .session import make_transient  # noqa
 from .session import make_transient_to_detached  # noqa
 from .session import object_session  # noqa
index fbc268e01e6b7867956e1d200afabc1cce9fe015..360e734667152a7526c90968341e94d28dacf4cc 100644 (file)
@@ -59,11 +59,16 @@ class _SessionClassMethods(object):
     """Class-level methods for :class:`.Session`, :class:`.sessionmaker`."""
 
     @classmethod
+    @util.deprecated(
+        "1.3",
+        "The :meth:`.Session.close_all` method is deprecated and will be "
+        "removed in a future release.  Please refer to "
+        ":func:`.session.close_all_sessions`.",
+    )
     def close_all(cls):
         """Close *all* sessions in memory."""
 
-        for sess in _sessions.values():
-            sess.close()
+        close_all_sessions()
 
     @classmethod
     @util.dependencies("sqlalchemy.orm.util")
@@ -3204,6 +3209,24 @@ class sessionmaker(_SessionClassMethods):
         )
 
 
+def close_all_sessions():
+    """Close all sessions in memory.
+
+    This function consults a global registry of all :class:`.Session` objects
+    and calls :meth:`.Session.close` on them, which resets them to a clean
+    state.
+
+    This function is not for general use but may be useful for test suites
+    within the teardown scheme.
+
+    .. versionadded:: 1.3
+
+    """
+
+    for sess in _sessions.values():
+        sess.close()
+
+
 def make_transient(instance):
     """Alter the state of the given instance so that it is :term:`transient`.
 
index 64d9328d72a185e6b4b4b0ef97303e6e08b393b7..953b229f298448adccb19ef0aa1a6b2385a8f469 100644 (file)
@@ -246,7 +246,7 @@ class RemovesEvents(object):
 class _ORMTest(object):
     @classmethod
     def teardown_class(cls):
-        sa.orm.session.Session.close_all()
+        sa.orm.session.close_all_sessions()
         sa.orm.clear_mappers()
 
 
@@ -287,7 +287,7 @@ class MappedTest(_ORMTest, TablesTest, assertions.AssertsExecutionResults):
         self._setup_each_inserts()
 
     def teardown(self):
-        sa.orm.session.Session.close_all()
+        sa.orm.session.close_all_sessions()
         self._teardown_each_mappers()
         self._teardown_each_classes()
         self._teardown_each_tables()
index 990262f2ca0b42273118536064a701f25ff81c95..0f003501906cd828d8275511539eae5776c7997a 100644 (file)
@@ -19,6 +19,7 @@ from sqlalchemy.ext.hybrid import hybrid_property
 from sqlalchemy.orm import backref
 from sqlalchemy.orm import class_mapper
 from sqlalchemy.orm import clear_mappers
+from sqlalchemy.orm import close_all_sessions
 from sqlalchemy.orm import column_property
 from sqlalchemy.orm import composite
 from sqlalchemy.orm import configure_mappers
@@ -60,7 +61,7 @@ class DeclarativeTestBase(
         Base = decl.declarative_base(testing.db)
 
     def teardown(self):
-        Session.close_all()
+        close_all_sessions()
         clear_mappers()
         Base.metadata.drop_all()
 
index 97c7dcd7c8aca0cea72478318053dee0c2cfde84..17b915da074e6add44d02eb1da8c1de50ab421ca 100644 (file)
@@ -10,6 +10,7 @@ from sqlalchemy.ext.declarative import declared_attr
 from sqlalchemy.ext.declarative import has_inherited_table
 from sqlalchemy.orm import class_mapper
 from sqlalchemy.orm import clear_mappers
+from sqlalchemy.orm import close_all_sessions
 from sqlalchemy.orm import configure_mappers
 from sqlalchemy.orm import create_session
 from sqlalchemy.orm import deferred
@@ -39,7 +40,7 @@ class DeclarativeTestBase(fixtures.TestBase, testing.AssertsExecutionResults):
         Base = decl.declarative_base(testing.db)
 
     def teardown(self):
-        Session.close_all()
+        close_all_sessions()
         clear_mappers()
         Base.metadata.drop_all()
 
index 7fec772708aa7d10e6a02818d929e4a45f45e2e6..ef9bbd354d3f69c1365b941ce8cfca1cdf63f253 100644 (file)
@@ -11,6 +11,7 @@ from sqlalchemy.ext.declarative import declared_attr
 from sqlalchemy.orm import base as orm_base
 from sqlalchemy.orm import class_mapper
 from sqlalchemy.orm import clear_mappers
+from sqlalchemy.orm import close_all_sessions
 from sqlalchemy.orm import column_property
 from sqlalchemy.orm import configure_mappers
 from sqlalchemy.orm import create_session
@@ -41,7 +42,7 @@ class DeclarativeTestBase(fixtures.TestBase, testing.AssertsExecutionResults):
         Base = decl.declarative_base(testing.db)
 
     def teardown(self):
-        Session.close_all()
+        close_all_sessions()
         clear_mappers()
         Base.metadata.drop_all()
 
index 2b53e5ae81e314ef1c868cdaf43ad9462fd67b89..ea8ae764d9586efea10665a298cdca2762b6bcd1 100644 (file)
@@ -14,6 +14,7 @@ from sqlalchemy import testing
 from sqlalchemy import text
 from sqlalchemy.orm import aliased
 from sqlalchemy.orm import backref
+from sqlalchemy.orm import close_all_sessions
 from sqlalchemy.orm import column_property
 from sqlalchemy.orm import contains_eager
 from sqlalchemy.orm import create_session
@@ -5054,7 +5055,7 @@ class CyclicalInheritingEagerTestTwo(
         session.add_all([rscott, alien, brunner])
         session.commit()
 
-        session.close_all()
+        close_all_sessions()
         self.d = session.query(Director).options(joinedload("*")).first()
         assert len(list(session)) == 3
 
index 1f36578df924c0f507c381fa660a1507c220840d..03b18df6aac1e9cb18f9102488097f8bbf7af8e0 100644 (file)
@@ -7,6 +7,7 @@ from sqlalchemy import String
 from sqlalchemy import testing
 from sqlalchemy.orm import attributes
 from sqlalchemy.orm import backref
+from sqlalchemy.orm import close_all_sessions
 from sqlalchemy.orm import create_session
 from sqlalchemy.orm import exc as orm_exc
 from sqlalchemy.orm import joinedload
@@ -148,6 +149,51 @@ class TransScopingTest(_fixtures.FixtureTest):
 class SessionUtilTest(_fixtures.FixtureTest):
     run_inserts = None
 
+    def test_close_all_sessions(self):
+        users, User = self.tables.users, self.classes.User
+
+        mapper(User, users)
+
+        s1 = Session()
+        u1 = User()
+        s1.add(u1)
+
+        s2 = Session()
+        u2 = User()
+        s2.add(u2)
+
+        assert u1 in s1
+        assert u2 in s2
+
+        close_all_sessions()
+
+        assert u1 not in s1
+        assert u2 not in s2
+
+    def test_session_close_all_deprecated(self):
+        users, User = self.tables.users, self.classes.User
+
+        mapper(User, users)
+
+        s1 = Session()
+        u1 = User()
+        s1.add(u1)
+
+        s2 = Session()
+        u2 = User()
+        s2.add(u2)
+
+        assert u1 in s1
+        assert u2 in s2
+
+        with assertions.expect_deprecated(
+                r"The Session.close_all\(\) method is deprecated and will "
+                "be removed in a future release. "):
+            Session.close_all()
+
+        assert u1 not in s1
+        assert u2 not in s2
+
     def test_object_session_raises(self):
         User = self.classes.User
 
index 1374d55d8d771bf65b81d3d1004cf59f43e77f9f..a4ee2d804b0c32b0a9e82195c86ea4d9aee20b16 100644 (file)
@@ -7,6 +7,7 @@ from sqlalchemy import String
 from sqlalchemy import testing
 from sqlalchemy.orm import aliased
 from sqlalchemy.orm import clear_mappers
+from sqlalchemy.orm import close_all_sessions
 from sqlalchemy.orm import create_session
 from sqlalchemy.orm import deferred
 from sqlalchemy.orm import joinedload
@@ -2666,7 +2667,7 @@ class CyclicalInheritingEagerTestTwo(
         session.add_all([rscott, alien, brunner])
         session.commit()
 
-        session.close_all()
+        close_all_sessions()
         d = session.query(Director).options(subqueryload("*")).first()
         assert len(list(session)) == 3