From: Mike Bayer Date: Tue, 25 Oct 2022 14:22:14 +0000 (-0400) Subject: raise for non-Load opt passed to options() X-Git-Tag: rel_2_0_0b3~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eae9d1420bbfde4dbd835b654e80653cd5ac2155;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git raise for non-Load opt passed to options() Fixed the exception that's raised when the :func:`_orm.with_loader_criteria` option is attempted to be used within a specific loader path, like in loader.options(). :func:`_orm.with_loader_criteria` is only intended to be used at the top level. Fixes: #8711 Change-Id: Iaa7b13956b808761e618a6be6406e5c82df1c65c --- diff --git a/doc/build/changelog/unreleased_14/8711.rst b/doc/build/changelog/unreleased_14/8711.rst new file mode 100644 index 0000000000..82e68bbc43 --- /dev/null +++ b/doc/build/changelog/unreleased_14/8711.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: bug, orm + :tickets: 8711 + + Fixed the exception that's raised when the + :func:`_orm.with_loader_criteria` option is attempted to be used within a + specific loader path, like in loader.options(). + :func:`_orm.with_loader_criteria` is only intended to be used at the top + level. diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py index 1140303465..23b3466f59 100644 --- a/lib/sqlalchemy/orm/strategy_options.py +++ b/lib/sqlalchemy/orm/strategy_options.py @@ -1218,7 +1218,16 @@ class Load(_AbstractLoad): """ for opt in opts: - opt._apply_to_parent(self) + try: + opt._apply_to_parent(self) + except AttributeError as ae: + if not isinstance(opt, _AbstractLoad): + raise sa_exc.ArgumentError( + f"Loader option {opt} is not compatible with the " + "Load.options() method." + ) from ae + else: + raise return self def _clone_for_bind_strategy( diff --git a/test/orm/test_relationship_criteria.py b/test/orm/test_relationship_criteria.py index 16d2088ebf..baa19e31ee 100644 --- a/test/orm/test_relationship_criteria.py +++ b/test/orm/test_relationship_criteria.py @@ -26,6 +26,7 @@ from sqlalchemy.orm import subqueryload from sqlalchemy.orm import with_loader_criteria from sqlalchemy.orm.decl_api import declared_attr from sqlalchemy.testing import eq_ +from sqlalchemy.testing import expect_raises_message from sqlalchemy.testing.assertions import expect_raises from sqlalchemy.testing.assertsql import CompiledSQL from sqlalchemy.testing.fixtures import fixture_session @@ -231,6 +232,22 @@ class LoaderCriteriaTest(_Fixtures, testing.AssertsCompiledSQL): "FROM users WHERE users.name != :name_1", ) + def test_err_given_in_pathed(self, user_address_fixture): + User, Address = user_address_fixture + + with expect_raises_message( + sa_exc.ArgumentError, + r"Loader option <.*LoaderCriteriaOption.*> is not compatible " + r"with the Load.options\(\) method.", + ): + select(User).options( + selectinload(User.addresses).options( + with_loader_criteria( + Address, Address.email_address != "foo" + ) + ) + ) + def test_criteria_post_replace(self, user_address_fixture): User, Address = user_address_fixture