diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2018-07-08 19:10:36 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2018-07-08 19:10:36 -0400 |
| commit | aec57258b3b33fe070ebb54f31f1627db07f072b (patch) | |
| tree | 93dfb251684d782b310416dcb6a823e97791beb8 | |
| parent | 284009683d9e48e19cc09e740e7b928c2c02997c (diff) | |
| download | sqlalchemy-aec57258b3b33fe070ebb54f31f1627db07f072b.tar.gz | |
Check tokens in chop path for inspectionattr before calling is_mapper
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
| -rw-r--r-- | doc/build/changelog/unreleased_12/4298.rst | 7 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategy_options.py | 6 | ||||
| -rw-r--r-- | test/orm/test_options.py | 52 |
3 files changed, 62 insertions, 3 deletions
diff --git a/doc/build/changelog/unreleased_12/4298.rst b/doc/build/changelog/unreleased_12/4298.rst new file mode 100644 index 000000000..8066ccdd0 --- /dev/null +++ b/doc/build/changelog/unreleased_12/4298.rst @@ -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. diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py index 90d14075c..af9bd71b6 100644 --- a/lib/sqlalchemy/orm/strategy_options.py +++ b/lib/sqlalchemy/orm/strategy_options.py @@ -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: diff --git a/test/orm/test_options.py b/test/orm/test_options.py index 3c1f6527d..e94b9e6b6 100644 --- a/test/orm/test_options.py +++ b/test/orm/test_options.py @@ -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") |
