diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-04-17 21:03:02 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-04-17 21:03:02 -0400 |
commit | b02193bd7e84a8fe1ac74d16cf78a90bd3d59f7c (patch) | |
tree | 54044fe649546626f40a269aff16fe2a0244327f /lib/sqlalchemy/orm/interfaces.py | |
parent | 4dd69ff878b2b7fe60a48ba7d12c29183a5f8012 (diff) | |
download | sqlalchemy-b02193bd7e84a8fe1ac74d16cf78a90bd3d59f7c.tar.gz |
- Fixed regression introduced in 0.7b4 (!) whereby
query.options(someoption("nonexistent name")) would
fail to raise an error. Also added additional
error catching for cases where the option would
try to build off a column-based element, further
fixed up some of the error messages tailored
in [ticket:2069]
- added another huge crapload of tests to the existing
crapload of tests we already had for options..._get_paths()
and dependencies are covered 100% now
- one case still doesn't do the "right" thing, using an option
specific to relationships will silently pass if the endpoint
is a column-based attribute, and vice versa.
Diffstat (limited to 'lib/sqlalchemy/orm/interfaces.py')
-rw-r--r-- | lib/sqlalchemy/orm/interfaces.py | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py index fec9d45fc..7a8748556 100644 --- a/lib/sqlalchemy/orm/interfaces.py +++ b/lib/sqlalchemy/orm/interfaces.py @@ -19,7 +19,7 @@ classes within should be considered mostly private. from itertools import chain from sqlalchemy import exc as sa_exc -from sqlalchemy import log, util, event +from sqlalchemy import util from sqlalchemy.sql import expression deque = util.importlater('collections').deque @@ -435,12 +435,20 @@ class PropertyOption(MapperOption): return ent else: if raiseerr: - raise sa_exc.ArgumentError( - "Can't find property '%s' on any entity " - "specified in this Query. Note the full path " - "from root (%s) to target entity must be specified." - % (token, ",".join(str(x) for x in query._mapper_entities)) - ) + if not list(query._mapper_entities): + raise sa_exc.ArgumentError( + "Query has only expression-based entities - " + "can't find property named '%s'." + % (token, ) + ) + else: + raise sa_exc.ArgumentError( + "Can't find property '%s' on any entity " + "specified in this Query. Note the full path " + "from root (%s) to target entity must be specified." + % (token, ",".join(str(x) for + x in query._mapper_entities)) + ) else: return None @@ -453,10 +461,9 @@ class PropertyOption(MapperOption): else: if raiseerr: raise sa_exc.ArgumentError( - "Can't find property named '%s' on the first mapped " - "entity in this Query. " - "Consider using an attribute object instead of a " - "string name to target a specific entity." % (token, ) + "Query has only expression-based entities - " + "can't find property named '%s'." + % (token, ) ) else: return None @@ -493,13 +500,22 @@ class PropertyOption(MapperOption): query, token, raiseerr) + if entity is None: + return [], [] path_element = entity.path_entity mapper = entity.mapper mappers.append(mapper) if mapper.has_property(token): prop = mapper.get_property(token) else: - prop = None + if raiseerr: + raise sa_exc.ArgumentError( + "Can't find property named '%s' on the " + "mapped entity %s in this Query. " % ( + token, mapper) + ) + else: + return [], [] elif isinstance(token, PropComparator): prop = token.property @@ -528,14 +544,19 @@ class PropertyOption(MapperOption): raise sa_exc.ArgumentError( "mapper option expects " "string key or list of attributes") - if prop is None: - return [], [] + assert prop is not None path = build_path(path_element, prop.key, path) l.append(path) if getattr(token, '_of_type', None): path_element = mapper = token._of_type else: path_element = mapper = getattr(prop, 'mapper', None) + if mapper is None and tokens: + raise sa_exc.ArgumentError( + "Attribute '%s' of entity '%s' does not " + "refer to a mapped entity" % + (token, entity) + ) if path_element: path_element = path_element @@ -547,8 +568,6 @@ class PropertyOption(MapperOption): return l, mappers - - class StrategizedOption(PropertyOption): """A MapperOption that affects which LoaderStrategy will be used for an operation by a StrategizedProperty. @@ -726,7 +745,7 @@ class InstrumentationManager(object): setattr(instance, '_default_state', state) def remove_state(self, class_, instance): - delattr(instance, '_default_state', state) + delattr(instance, '_default_state') def state_getter(self, class_): return lambda instance: getattr(instance, '_default_state') |