cast("_InternalEntityType[Any]", parent.path[-1]),
cast("_InternalEntityType[Any]", cloned.path[0]),
):
- raise sa_exc.ArgumentError(
- f'Attribute "{cloned.path[1]}" does not link '
- f'from element "{parent.path[-1]}".'
- )
+ if len(cloned.path) > 1:
+ attrname = cloned.path[1]
+ parent_entity = cloned.path[0]
+ else:
+ attrname = cloned.path[0]
+ parent_entity = cloned.path[0]
+ _raise_for_does_not_link(parent.path, attrname, parent_entity)
cloned.path = PathRegistry.coerce(parent.path[0:-1] + cloned.path[:])
"loader option to multiple entities in the "
"same option. Use separate options per entity."
)
- elif len(path) > 1:
- path_is_of_type = (
- path[-1].entity is not path[-2].mapper.class_
- )
- raise sa_exc.ArgumentError(
- f'ORM mapped attribute "{attr}" does not '
- f'link from relationship "{path[-2]}%s".%s'
- % (
- f".of_type({path[-1]})" if path_is_of_type else "",
- (
- " Did you mean to use "
- f'"{path[-2]}'
- f'.of_type({attr.class_.__name__})"?'
- if not path_is_of_type
- and not path[-1].is_aliased_class
- and orm_util._entity_corresponds_to(
- path.entity, attr.parent.mapper
- )
- else ""
- ),
- )
- )
else:
- raise sa_exc.ArgumentError(
- f'ORM mapped attribute "{attr}" does not '
- f'link mapped class "{path[-1]}"'
- )
+ _raise_for_does_not_link(path, str(attr), attr.parent)
else:
return None
) -> _AbstractLoad:
ul = Load(base_cls)
return ul.selectin_polymorphic(classes)
+
+
+def _raise_for_does_not_link(path, attrname, parent_entity):
+ if len(path) > 1:
+ path_is_of_type = path[-1].entity is not path[-2].mapper.class_
+ if insp_is_aliased_class(parent_entity):
+ parent_entity_str = str(parent_entity)
+ else:
+ parent_entity_str = parent_entity.class_.__name__
+
+ raise sa_exc.ArgumentError(
+ f'ORM mapped entity or attribute "{attrname}" does not '
+ f'link from relationship "{path[-2]}%s".%s'
+ % (
+ f".of_type({path[-1]})" if path_is_of_type else "",
+ (
+ " Did you mean to use "
+ f'"{path[-2]}'
+ f'.of_type({parent_entity_str})"?'
+ if not path_is_of_type
+ and not path[-1].is_aliased_class
+ and orm_util._entity_corresponds_to(
+ path.entity, inspect(parent_entity).mapper
+ )
+ else ""
+ ),
+ )
+ )
+ else:
+ raise sa_exc.ArgumentError(
+ f'ORM mapped attribute "{attrname}" does not '
+ f'link mapped class "{path[-1]}"'
+ )
self._assert_eager_with_entity_exception(
[User],
lambda: (joinedload(User.addresses).joinedload(User.orders),),
- r'ORM mapped attribute "User.orders" does not link '
+ r'ORM mapped entity or attribute "User.orders" does not link '
r'from relationship "User.addresses"',
)
User.orders.of_type(Order)
),
),
- r'ORM mapped attribute "User.orders" does not link '
+ r'ORM mapped entity or attribute "User.orders" does not link '
r'from relationship "User.addresses"',
)
e1 = with_polymorphic(Person, [Engineer])
assert_raises_message(
sa.exc.ArgumentError,
- r'ORM mapped attribute "Manager.manager_name" does not link from '
+ r'ORM mapped entity or attribute "Manager.manager_name" does '
+ r"not link from "
r'relationship "Company.employees.'
r'of_type\(with_polymorphic\(Person, \[Engineer\]\)\)".$',
lambda: s.query(Company)
assert_raises_message(
sa.exc.ArgumentError,
- r'ORM mapped attribute "Manager.manager_name" does not link from '
+ r'ORM mapped entity or attribute "Manager.manager_name" does '
+ r"not link from "
r'relationship "Company.employees.'
r'of_type\(Mapper\[Engineer\(engineers\)\]\)".$',
lambda: s.query(Company)
# that doesn't get mixed up here
assert_raises_message(
sa.exc.ArgumentError,
- r'ORM mapped attribute "Manager.status" does not link from '
+ r'ORM mapped entity or attribute "Manager.status" does '
+ r"not link from "
r'relationship "Company.employees.'
r'of_type\(Mapper\[Engineer\(engineers\)\]\)".$',
lambda: s.query(Company)
assert_raises_message(
sa.exc.ArgumentError,
- r'ORM mapped attribute "Manager.manager_name" does not link from '
+ r'ORM mapped entity or attribute "Manager.manager_name" does '
+ r"not link from "
r'relationship "Company.employees.'
r'of_type\(with_polymorphic\(Person, \[Manager\]\)\)".$',
lambda: s.query(Company)
._compile_state(),
)
- def test_missing_attr_is_missing_of_type_for_alias(self):
+ @testing.variation("use_options", [True, False])
+ def test_missing_attr_is_missing_of_type_for_subtype(self, use_options):
s = fixture_session()
- pa = aliased(Person)
-
- assert_raises_message(
+ with expect_raises_message(
sa.exc.ArgumentError,
- r'ORM mapped attribute "aliased\(Person\).name" does not link '
- r'from relationship "Company.employees". Did you mean to use '
- r'"Company.employees.of_type\(aliased\(Person\)\)\"?',
- lambda: s.query(Company)
- .options(joinedload(Company.employees).load_only(pa.name))
- ._compile_state(),
- )
+ r"ORM mapped entity or attribute "
+ r'(?:"Mapper\[Engineer\(engineers\)\]"|"Engineer.engineer_name") '
+ r'does not link from relationship "Company.employees". Did you '
+ r'mean to use "Company.employees.of_type\(Engineer\)"\?',
+ ):
- q = s.query(Company).options(
- joinedload(Company.employees.of_type(pa)).load_only(pa.name)
- )
- orig_path = inspect(Company)._path_registry[
- Company.employees.property
- ][inspect(pa)][pa.name.property]
- key = ("loader", orig_path.natural_path)
- loader = q._compile_state().attributes[key]
- eq_(loader.path, orig_path)
+ if use_options:
+ s.query(Company).options(
+ joinedload(Company.employees).options(
+ defer(Engineer.engineer_name)
+ )
+ )._compile_state()
+ else:
+ s.query(Company).options(
+ joinedload(Company.employees).defer(Engineer.engineer_name)
+ )._compile_state()
class PickleTest(fixtures.MappedTest):
with expect_raises_message(
sa.exc.ArgumentError,
- r'ORM mapped attribute "Item.keywords" does not link from '
+ r'ORM mapped entity or attribute "Item.keywords" does '
+ r"not link from "
r'relationship "User.orders"',
):
[
]
with expect_raises_message(
sa.exc.ArgumentError,
- r'Attribute "Item.keywords" does not link from '
- r'element "Mapper\[Order\(orders\)\]"',
+ r'ORM mapped entity or attribute "Item.keywords" does '
+ r"not link from "
+ r'relationship "User.orders"',
):
joinedload(User.orders).options(
joinedload(Item.keywords), joinedload(Order.items)