From: Mike Bayer Date: Tue, 2 Jul 2024 17:57:47 +0000 (-0400) Subject: call iter() on detached/transient dynamic session X-Git-Tag: rel_1_4_53~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc240eeb4c5755ceb587c60f3125a4864c29fecc;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git call iter() on detached/transient dynamic session Fixed regression going back to 1.4 where accessing a collection using the "dynamic" strategy on a transient object and attempting to query would raise an internal error rather than the expected :class:`.NoResultFound` that occurred in 1.3. Fixes: #11562 Change-Id: I650305963a17592413520d8d1049c601761a0acc (cherry picked from commit 4208993938302e34a67e57af710be7d98ff37659) (cherry picked from commit 1ad8edb9e168bf2f7de88114f7bb6e25c8155b69) --- diff --git a/doc/build/changelog/unreleased_14/11562.rst b/doc/build/changelog/unreleased_14/11562.rst new file mode 100644 index 0000000000..15ccd0df6d --- /dev/null +++ b/doc/build/changelog/unreleased_14/11562.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, orm, regression + :tickets: 11562 + + Fixed regression going back to 1.4 where accessing a collection using the + "dynamic" strategy on a transient object and attempting to query would + raise an internal error rather than the expected :class:`.NoResultFound` + that occurred in 1.3. diff --git a/lib/sqlalchemy/orm/dynamic.py b/lib/sqlalchemy/orm/dynamic.py index 5d5ce3642c..0a0d17c08d 100644 --- a/lib/sqlalchemy/orm/dynamic.py +++ b/lib/sqlalchemy/orm/dynamic.py @@ -344,10 +344,12 @@ class AppenderMixin(object): return result.IteratorResult( result.SimpleResultMetaData([self.attr.class_.__name__]), - self.attr._get_collection_history( - attributes.instance_state(self.instance), - attributes.PASSIVE_NO_INITIALIZE, - ).added_items, + iter( + self.attr._get_collection_history( + attributes.instance_state(self.instance), + attributes.PASSIVE_NO_INITIALIZE, + ).added_items + ), _source_supports_scalars=True, ).scalars() else: diff --git a/setup.cfg b/setup.cfg index e4cee11058..3f8003a1ed 100644 --- a/setup.cfg +++ b/setup.cfg @@ -142,7 +142,7 @@ ignore = N801,N802,N806, RST304,RST303,RST299,RST399, W503,W504 - U100 + U100,U101 IS001 exclude = .venv,.git,.tox,dist,doc,*egg,build import-order-style = google diff --git a/test/orm/test_dynamic.py b/test/orm/test_dynamic.py index 0cb4d76d9c..3997aa9710 100644 --- a/test/orm/test_dynamic.py +++ b/test/orm/test_dynamic.py @@ -238,6 +238,31 @@ class DynamicTest(_DynamicFixture, _fixtures.FixtureTest, AssertsCompiledSQL): use_default_dialect=True, ) + @testing.combinations( + ("all", []), + ("one", exc.NoResultFound), + ("one_or_none", None), + argnames="method, expected", + ) + @testing.variation("add_to_session", [True, False]) + def test_transient_raise(self, method, expected, add_to_session): + """test 11562""" + User, Address = self._user_address_fixture() + + u1 = User(name="u1") + if add_to_session: + sess = fixture_session() + sess.add(u1) + + meth = getattr(u1.addresses, method) + if expected is exc.NoResultFound: + with expect_raises_message( + exc.NoResultFound, "No row was found when one was required" + ): + meth() + else: + eq_(meth(), expected) + def test_detached_raise(self): """so filtering on a detached dynamic list raises an error..."""