]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Check tokens in chop path for inspectionattr before calling is_mapper
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 8 Jul 2018 23:10:36 +0000 (19:10 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 8 Jul 2018 23:10:36 +0000 (19:10 -0400)
Fixed regression in 1.2.9 due to :ticket:`4287` where using a
:class::`.Load` option in conjunction with a string wildcard would result
in a TypeError.

Change-Id: I2997ead0b8b9fa0edd009aa6f3161f4618fab97b
Fixes: #4298
doc/build/changelog/unreleased_12/4298.rst [new file with mode: 0644]
lib/sqlalchemy/orm/strategy_options.py
test/orm/test_options.py

diff --git a/doc/build/changelog/unreleased_12/4298.rst b/doc/build/changelog/unreleased_12/4298.rst
new file mode 100644 (file)
index 0000000..8066ccd
--- /dev/null
@@ -0,0 +1,7 @@
+.. change::
+    :tags: bug, orm
+    :tickets: 4298
+
+    Fixed regression in 1.2.9 due to :ticket:`4287` where using a
+    :class::`.Load` option in conjunction with a string wildcard would result
+    in a TypeError.
index 90d14075cb0e9641ea479aa802f39b54291195d5..af9bd71b6aa08e9a7739adc3f86e6c430082c797 100644 (file)
@@ -13,7 +13,8 @@ from .attributes import QueryableAttribute
 from .. import util
 from ..sql.base import _generative, Generative
 from .. import exc as sa_exc, inspect
-from .base import _is_aliased_class, _class_to_mapper, _is_mapped_class
+from .base import _is_aliased_class, _class_to_mapper, _is_mapped_class, \
+    InspectionAttr
 from . import util as orm_util
 from .path_registry import PathRegistry, TokenRegistry, \
     _WILDCARD_TOKEN, _DEFAULT_TOKEN
@@ -385,7 +386,8 @@ class Load(Generative, MapperOption):
 
             if c_token is p_token:
                 continue
-            elif c_token.is_mapper and p_token.is_mapper and \
+            elif isinstance(c_token, InspectionAttr) and \
+                c_token.is_mapper and p_token.is_mapper and \
                     c_token.isa(p_token):
                 continue
             else:
index 3c1f6527dbe05c0c4a8aa5fcc0f2cdc9e32f64d5..e94b9e6b63b470b4d2e020a7093f882a67c3fda5 100644 (file)
@@ -2,7 +2,7 @@ from sqlalchemy import inspect
 from sqlalchemy.orm import attributes, mapper, relationship, backref, \
     configure_mappers, create_session, synonym, Session, class_mapper, \
     aliased, column_property, joinedload_all, joinedload, Query,\
-    util as orm_util, Load, defer, defaultload
+    util as orm_util, Load, defer, defaultload, lazyload
 from sqlalchemy.orm.query import QueryContext
 from sqlalchemy.orm import strategy_options
 import sqlalchemy as sa
@@ -1228,6 +1228,56 @@ class CacheKeyTest(PathTest, QueryTest):
             None
         )
 
+    def test_bound_cache_key_wildcard_one(self):
+        # do not change this test, it is testing
+        # a specific condition in Load._chop_path().
+        User, Address = self.classes('User', 'Address')
+
+        query_path = self._make_path_registry([User, "addresses"])
+
+        opt = Load(User).lazyload("*")
+        eq_(
+            opt._generate_cache_key(query_path),
+            None
+        )
+
+    def test_unbound_cache_key_wildcard_one(self):
+        User, Address = self.classes('User', 'Address')
+
+        query_path = self._make_path_registry([User, "addresses"])
+
+        opt = lazyload("*")
+        eq_(
+            opt._generate_cache_key(query_path),
+            (('relationship:_sa_default', ('lazy', 'select')),)
+        )
+
+    def test_bound_cache_key_wildcard_two(self):
+        User, Address, Order, Item, SubItem, Keyword = self.classes(
+            'User', 'Address', 'Order', 'Item', 'SubItem', "Keyword")
+
+        query_path = self._make_path_registry([User])
+
+        opt = Load(User).lazyload("orders").lazyload("*")
+        eq_(
+            opt._generate_cache_key(query_path),
+            (('orders', Order, ('lazy', 'select')),
+             ('orders', Order, 'relationship:*', ('lazy', 'select')))
+        )
+
+    def test_unbound_cache_key_wildcard_two(self):
+        User, Address, Order, Item, SubItem, Keyword = self.classes(
+            'User', 'Address', 'Order', 'Item', 'SubItem', "Keyword")
+
+        query_path = self._make_path_registry([User])
+
+        opt = lazyload("orders").lazyload("*")
+        eq_(
+            opt._generate_cache_key(query_path),
+            (('orders', Order, ('lazy', 'select')),
+             ('orders', Order, 'relationship:*', ('lazy', 'select')))
+        )
+
     def test_unbound_cache_key_of_type_subclass_relationship(self):
         User, Address, Order, Item, SubItem, Keyword = self.classes(
             'User', 'Address', 'Order', 'Item', 'SubItem', "Keyword")