summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/build/changelog/unreleased_13/4412.rst8
-rw-r--r--doc/build/orm/session_api.rst2
-rw-r--r--lib/sqlalchemy/orm/__init__.py1
-rw-r--r--lib/sqlalchemy/orm/session.py27
-rw-r--r--lib/sqlalchemy/testing/fixtures.py4
-rw-r--r--test/ext/declarative/test_basic.py3
-rw-r--r--test/ext/declarative/test_inheritance.py3
-rw-r--r--test/ext/declarative/test_mixin.py3
-rw-r--r--test/orm/test_eager_relations.py3
-rw-r--r--test/orm/test_session.py46
-rw-r--r--test/orm/test_subquery_relations.py3
11 files changed, 94 insertions, 9 deletions
diff --git a/doc/build/changelog/unreleased_13/4412.rst b/doc/build/changelog/unreleased_13/4412.rst
new file mode 100644
index 000000000..3c868ff82
--- /dev/null
+++ b/doc/build/changelog/unreleased_13/4412.rst
@@ -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.
diff --git a/doc/build/orm/session_api.rst b/doc/build/orm/session_api.rst
index 5523422e0..683719945 100644
--- a/doc/build/orm/session_api.rst
+++ b/doc/build/orm/session_api.rst
@@ -20,6 +20,8 @@ Session and sessionmaker()
Session Utilities
-----------------
+.. autofunction:: close_all_sessions
+
.. autofunction:: make_transient
.. autofunction:: make_transient_to_detached
diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py
index c64623da9..a596d1408 100644
--- a/lib/sqlalchemy/orm/__init__.py
+++ b/lib/sqlalchemy/orm/__init__.py
@@ -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
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index 1d405e3fa..e1a1e5577 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -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")
@@ -3220,6 +3225,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`.
diff --git a/lib/sqlalchemy/testing/fixtures.py b/lib/sqlalchemy/testing/fixtures.py
index 64d9328d7..953b229f2 100644
--- a/lib/sqlalchemy/testing/fixtures.py
+++ b/lib/sqlalchemy/testing/fixtures.py
@@ -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()
diff --git a/test/ext/declarative/test_basic.py b/test/ext/declarative/test_basic.py
index 990262f2c..0f0035019 100644
--- a/test/ext/declarative/test_basic.py
+++ b/test/ext/declarative/test_basic.py
@@ -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()
diff --git a/test/ext/declarative/test_inheritance.py b/test/ext/declarative/test_inheritance.py
index 97c7dcd7c..17b915da0 100644
--- a/test/ext/declarative/test_inheritance.py
+++ b/test/ext/declarative/test_inheritance.py
@@ -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()
diff --git a/test/ext/declarative/test_mixin.py b/test/ext/declarative/test_mixin.py
index 7fec77270..ef9bbd354 100644
--- a/test/ext/declarative/test_mixin.py
+++ b/test/ext/declarative/test_mixin.py
@@ -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()
diff --git a/test/orm/test_eager_relations.py b/test/orm/test_eager_relations.py
index 2b53e5ae8..ea8ae764d 100644
--- a/test/orm/test_eager_relations.py
+++ b/test/orm/test_eager_relations.py
@@ -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
diff --git a/test/orm/test_session.py b/test/orm/test_session.py
index 1f36578df..03b18df6a 100644
--- a/test/orm/test_session.py
+++ b/test/orm/test_session.py
@@ -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
diff --git a/test/orm/test_subquery_relations.py b/test/orm/test_subquery_relations.py
index 1374d55d8..a4ee2d804 100644
--- a/test/orm/test_subquery_relations.py
+++ b/test/orm/test_subquery_relations.py
@@ -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