summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2022-12-05 14:01:12 +0000
committerGerrit Code Review <gerrit@ci3.zzzcomputing.com>2022-12-05 14:01:12 +0000
commit9058593e0b28cee0211251de6604e4601ff69a00 (patch)
treefc39fa7fc6ef9bf4beb44dbfec4674d68a2c9464
parent3497fd1c5b60ac529450fb2aab7c7fbb8da8a9e4 (diff)
parentca46caede4b8d846f3cd48e642922ae821d0be2b (diff)
downloadsqlalchemy-9058593e0b28cee0211251de6604e4601ff69a00.tar.gz
Merge "adjustments for unreliable gc" into main
-rw-r--r--doc/build/orm/queryguide/_deferred_setup.rst1
-rw-r--r--doc/build/orm/queryguide/select.rst4
-rw-r--r--test/aaa_profiling/test_memusage.py54
-rw-r--r--test/orm/test_transaction.py39
-rw-r--r--test/requirements.py1
5 files changed, 60 insertions, 39 deletions
diff --git a/doc/build/orm/queryguide/_deferred_setup.rst b/doc/build/orm/queryguide/_deferred_setup.rst
index e75630c46..2675c9341 100644
--- a/doc/build/orm/queryguide/_deferred_setup.rst
+++ b/doc/build/orm/queryguide/_deferred_setup.rst
@@ -100,5 +100,6 @@ This page illustrates the mappings and fixture data used by the
... )
>>> session.commit()
BEGIN ... COMMIT
+ >>> session.close()
>>> conn.begin()
BEGIN ...
diff --git a/doc/build/orm/queryguide/select.rst b/doc/build/orm/queryguide/select.rst
index 7967bb4d5..55c3ae94e 100644
--- a/doc/build/orm/queryguide/select.rst
+++ b/doc/build/orm/queryguide/select.rst
@@ -1001,6 +1001,10 @@ which belonged to "sandy":
Relationship Instance Comparison Operators
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. comment
+
+ >>> session.expunge_all()
+
The :func:`_orm.relationship`-bound attribute also offers a few SQL construction
implementations that are geared towards filtering a :func:`_orm.relationship`-bound
attribute in terms of a specific instance of a related object, which can unpack
diff --git a/test/aaa_profiling/test_memusage.py b/test/aaa_profiling/test_memusage.py
index 1162a54af..4756a3fd5 100644
--- a/test/aaa_profiling/test_memusage.py
+++ b/test/aaa_profiling/test_memusage.py
@@ -18,6 +18,7 @@ from sqlalchemy import util
from sqlalchemy.engine import result
from sqlalchemy.engine.processors import to_decimal_processor_factory
from sqlalchemy.orm import aliased
+from sqlalchemy.orm import attributes
from sqlalchemy.orm import clear_mappers
from sqlalchemy.orm import configure_mappers
from sqlalchemy.orm import declarative_base
@@ -1724,3 +1725,56 @@ class CycleTest(_fixtures.FixtureTest):
s.close()
go()
+
+
+@testing.add_to_marker.memory_intensive
+class MiscMemoryIntensiveTests(fixtures.TestBase):
+ @testing.fixture
+ def user_fixture(self, decl_base):
+ class User(decl_base):
+ __tablename__ = "user"
+
+ id = Column(Integer, primary_key=True)
+ name = Column(String(50))
+
+ decl_base.metadata.create_all(testing.db)
+ yield User
+
+ @testing.requires.predictable_gc
+ def test_gced_delete_on_rollback(self, user_fixture):
+ User = user_fixture
+
+ s = fixture_session()
+ u1 = User(name="ed")
+ s.add(u1)
+ s.commit()
+
+ s.delete(u1)
+ u1_state = attributes.instance_state(u1)
+ assert u1_state in s.identity_map.all_states()
+ assert u1_state in s._deleted
+ s.flush()
+ assert u1_state not in s.identity_map.all_states()
+ assert u1_state not in s._deleted
+ del u1
+ gc_collect()
+ gc_collect()
+ gc_collect()
+ assert u1_state.obj() is None
+
+ s.rollback()
+ # new in 1.1, not in identity map if the object was
+ # gc'ed and we restore snapshot; we've changed update_impl
+ # to just skip this object
+ assert u1_state not in s.identity_map.all_states()
+
+ # in any version, the state is replaced by the query
+ # because the identity map would switch it
+ u1 = s.query(User).filter_by(name="ed").one()
+ assert u1_state not in s.identity_map.all_states()
+
+ eq_(s.scalar(select(func.count("*")).select_from(User.__table__)), 1)
+ s.delete(u1)
+ s.flush()
+ eq_(s.scalar(select(func.count("*")).select_from(User.__table__)), 0)
+ s.commit()
diff --git a/test/orm/test_transaction.py b/test/orm/test_transaction.py
index 2f08080ad..f66908fc9 100644
--- a/test/orm/test_transaction.py
+++ b/test/orm/test_transaction.py
@@ -1249,45 +1249,6 @@ class AutoExpireTest(_LocalFixture):
assert u1 in s
assert u1 not in s.deleted
- @testing.requires.predictable_gc
- def test_gced_delete_on_rollback(self):
- User, users = self.classes.User, self.tables.users
-
- s = fixture_session()
- u1 = User(name="ed")
- s.add(u1)
- s.commit()
-
- s.delete(u1)
- u1_state = attributes.instance_state(u1)
- assert u1_state in s.identity_map.all_states()
- assert u1_state in s._deleted
- s.flush()
- assert u1_state not in s.identity_map.all_states()
- assert u1_state not in s._deleted
- del u1
- gc_collect()
- gc_collect()
- gc_collect()
- assert u1_state.obj() is None
-
- s.rollback()
- # new in 1.1, not in identity map if the object was
- # gc'ed and we restore snapshot; we've changed update_impl
- # to just skip this object
- assert u1_state not in s.identity_map.all_states()
-
- # in any version, the state is replaced by the query
- # because the identity map would switch it
- u1 = s.query(User).filter_by(name="ed").one()
- assert u1_state not in s.identity_map.all_states()
-
- eq_(s.scalar(select(func.count("*")).select_from(users)), 1)
- s.delete(u1)
- s.flush()
- eq_(s.scalar(select(func.count("*")).select_from(users)), 0)
- s.commit()
-
def test_trans_deleted_cleared_on_rollback(self):
User = self.classes.User
s = fixture_session()
diff --git a/test/requirements.py b/test/requirements.py
index e56c944ff..5276593c9 100644
--- a/test/requirements.py
+++ b/test/requirements.py
@@ -397,6 +397,7 @@ class DefaultRequirements(SuiteRequirements):
[
no_support("oracle", "Oracle XE usually can't handle these"),
no_support("mssql+pyodbc", "MS ODBC drivers struggle"),
+ no_support("+aiosqlite", "very unreliable driver"),
self._running_on_windows(),
]
)