summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjonathan vanasco <jonathan@2xlp.com>2021-09-27 12:51:32 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2021-11-08 13:25:51 -0500
commit2432d2ed0b28480c0e1004a47aa74238865105b5 (patch)
tree14c0478ec6a8e54a82e0fa8b52652184a93a2220
parentd80f5277e1c6a6043408244288effb08713c8d70 (diff)
downloadsqlalchemy-2432d2ed0b28480c0e1004a47aa74238865105b5.tar.gz
Fixes: #4390
Deprecated an undocumented loader option syntax ``".*"``, which appears to be no different than passing a single asterisk, and will emit a deprecation warning if used. This syntax may have been intended for something but there is currently no need for it. The original ticket was to document the `.{WILDCARD}` (e.g. `.*`) format, however this format does not appear to be used or needed by SQLAlchemy and is likely not used by any projects or developers. This PR invokes `util.warn_deprecated` to notify users this functionality is deprecated, and directs them to the #4390 issue if they actually use it. Assuming there are no complaints over this warning in the coming months, this code can be removed in a future major release. Change-Id: I665e3ac26be0a7819246a2ee56fb5a5f32980c91
-rw-r--r--doc/build/changelog/unreleased_14/4390.rst9
-rw-r--r--lib/sqlalchemy/orm/strategy_options.py9
-rw-r--r--test/orm/test_default_strategies.py4
-rw-r--r--test/orm/test_deferred.py5
-rw-r--r--test/orm/test_deprecations.py93
5 files changed, 114 insertions, 6 deletions
diff --git a/doc/build/changelog/unreleased_14/4390.rst b/doc/build/changelog/unreleased_14/4390.rst
new file mode 100644
index 000000000..abbc664ee
--- /dev/null
+++ b/doc/build/changelog/unreleased_14/4390.rst
@@ -0,0 +1,9 @@
+.. change::
+ :tags: deprecated, orm
+ :tickets: 4390
+
+ Deprecated an undocumented loader option syntax ``".*"``, which appears to
+ be no different than passing a single asterisk, and will emit a deprecation
+ warning if used. This syntax may have been intended for something but there
+ is currently no need for it.
+
diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py
index 675c7218b..30286c1d8 100644
--- a/lib/sqlalchemy/orm/strategy_options.py
+++ b/lib/sqlalchemy/orm/strategy_options.py
@@ -919,6 +919,15 @@ class _UnboundLoad(Load):
return (_DEFAULT_TOKEN,)
# coerce fooload(".*") into "wildcard on default entity"
elif key.startswith("." + _WILDCARD_TOKEN):
+ util.warn_deprecated(
+ "The undocumented `.{WILDCARD}` format is deprecated "
+ "and will be removed in a future version as it is "
+ "believed to be unused. "
+ "If you have been using this functionality, please "
+ "comment on Issue #4390 on the SQLAlchemy project "
+ "tracker.",
+ version="1.4",
+ )
key = key[1:]
return key.split(".")
else:
diff --git a/test/orm/test_default_strategies.py b/test/orm/test_default_strategies.py
index 9b228bbaa..9162d63ec 100644
--- a/test/orm/test_default_strategies.py
+++ b/test/orm/test_default_strategies.py
@@ -437,7 +437,7 @@ class DefaultStrategyOptionsTest(_fixtures.FixtureTest):
def go():
users[:] = (
sess.query(User)
- .options(joinedload(".*"))
+ .options(joinedload("*"))
.options(defaultload(User.addresses).joinedload("*"))
.options(defaultload(User.orders).joinedload("*"))
.options(
@@ -548,7 +548,7 @@ class DefaultStrategyOptionsTest(_fixtures.FixtureTest):
def go():
users[:] = (
sess.query(User)
- .options(subqueryload(".*"))
+ .options(subqueryload("*"))
.options(defaultload(User.addresses).subqueryload("*"))
.options(defaultload(User.orders).subqueryload("*"))
.options(
diff --git a/test/orm/test_deferred.py b/test/orm/test_deferred.py
index bfdfb00b7..41e9fa4dd 100644
--- a/test/orm/test_deferred.py
+++ b/test/orm/test_deferred.py
@@ -1563,14 +1563,11 @@ class InheritanceTest(_Polymorphic):
def test_defer_on_wildcard_subclass(self):
# pretty much the same as load_only except doesn't
# exclude the primary key
-
- # TODO: what is ".*"? this is not documented anywhere, how did this
- # get implemented without docs ? see #4390
s = fixture_session()
q = (
s.query(Manager)
.order_by(Person.person_id)
- .options(defer(".*"), undefer(Manager.status))
+ .options(defer("*"), undefer(Manager.status))
)
self.assert_compile(
q,
diff --git a/test/orm/test_deprecations.py b/test/orm/test_deprecations.py
index 061cad7e3..3928b9051 100644
--- a/test/orm/test_deprecations.py
+++ b/test/orm/test_deprecations.py
@@ -88,8 +88,14 @@ from .inheritance import _poly_fixtures
from .inheritance._poly_fixtures import _Polymorphic
from .inheritance._poly_fixtures import Company
from .inheritance._poly_fixtures import Engineer
+from .inheritance._poly_fixtures import Manager
+from .inheritance._poly_fixtures import Person
from .test_ac_relationships import PartitionByFixture
from .test_bind import GetBindTest as _GetBindTest
+from .test_default_strategies import (
+ DefaultStrategyOptionsTest as _DefaultStrategyOptionsTest,
+)
+from .test_deferred import InheritanceTest as _deferred_InheritanceTest
from .test_dynamic import _DynamicFixture
from .test_events import _RemoveListeners
from .test_options import PathTest as OptionsPathTest
@@ -155,6 +161,13 @@ merge_result_dep = (
r"The merge_result\(\) function is considered legacy as of the 1.x series"
)
+dep_exc_wildcard = (
+ r"The undocumented `.{WILDCARD}` format is deprecated and will be removed "
+ r"in a future version as it is believed to be unused. If you have been "
+ r"using this functionality, please comment on Issue #4390 on the "
+ r"SQLAlchemy project tracker."
+)
+
def _aliased_join_warning(arg=None):
return testing.expect_warnings(
@@ -8696,3 +8709,83 @@ class MergeResultTest(_fixtures.FixtureTest):
[(x and x.id or None, y and y.id or None) for x, y in it],
[(u1.id, u2.id), (u1.id, None), (u2.id, u3.id)],
)
+
+
+class DefaultStrategyOptionsTest(_DefaultStrategyOptionsTest):
+ def test_joined_path_wildcards(self):
+ sess = self._upgrade_fixture()
+ users = []
+
+ User, Order, Item = self.classes("User", "Order", "Item")
+
+ # test upgrade all to joined: 1 sql
+ def go():
+ users[:] = (
+ sess.query(User)
+ .options(joinedload(".*"))
+ .options(defaultload(User.addresses).joinedload("*"))
+ .options(defaultload(User.orders).joinedload("*"))
+ .options(
+ defaultload(User.orders)
+ .defaultload(Order.items)
+ .joinedload("*")
+ )
+ .order_by(self.classes.User.id)
+ .all()
+ )
+
+ with assertions.expect_deprecated(dep_exc_wildcard):
+ self.assert_sql_count(testing.db, go, 1)
+ self._assert_fully_loaded(users)
+
+ def test_subquery_path_wildcards(self):
+ sess = self._upgrade_fixture()
+ users = []
+
+ User, Order = self.classes("User", "Order")
+
+ # test upgrade all to subquery: 1 sql + 4 relationships = 5
+ def go():
+ users[:] = (
+ sess.query(User)
+ .options(subqueryload(".*"))
+ .options(defaultload(User.addresses).subqueryload("*"))
+ .options(defaultload(User.orders).subqueryload("*"))
+ .options(
+ defaultload(User.orders)
+ .defaultload(Order.items)
+ .subqueryload("*")
+ )
+ .order_by(User.id)
+ .all()
+ )
+
+ with assertions.expect_deprecated(dep_exc_wildcard):
+ self.assert_sql_count(testing.db, go, 5)
+
+ # verify everything loaded, with no additional sql needed
+ self._assert_fully_loaded(users)
+
+
+class Deferred_InheritanceTest(_deferred_InheritanceTest):
+ def test_defer_on_wildcard_subclass(self):
+ # pretty much the same as load_only except doesn't
+ # exclude the primary key
+
+ # what is ".*"? this is not documented anywhere, how did this
+ # get implemented without docs ? see #4390
+ s = fixture_session()
+ with assertions.expect_deprecated(dep_exc_wildcard):
+ q = (
+ s.query(Manager)
+ .order_by(Person.person_id)
+ .options(defer(".*"), undefer(Manager.status))
+ )
+ self.assert_compile(
+ q,
+ "SELECT managers.status AS managers_status "
+ "FROM people JOIN managers ON "
+ "people.person_id = managers.person_id ORDER BY people.person_id",
+ )
+ # note this doesn't apply to "bound" loaders since they don't seem
+ # to have this ".*" featue.