diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-02-07 23:58:17 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2010-02-07 23:58:17 +0000 |
| commit | 03167fb4bbb2d4a1d68ef04dff02ed2033b4f138 (patch) | |
| tree | 858b2e36b83467b8f4c2a3b72b9e4fc4bd7cadaa /lib/sqlalchemy | |
| parent | 52ab4041affc8618892d82d82281eedc5b3d0b6f (diff) | |
| download | sqlalchemy-03167fb4bbb2d4a1d68ef04dff02ed2033b4f138.tar.gz | |
- Now uses sqlalchemy.orm.exc.DetachedInstanceError when an
attribute load or refresh action fails due to object
being detached from any Session. UnboundExecutionError
is specific to engines bound to sessions and statements.
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/dynamic.py | 5 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/exc.py | 4 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/mapper.py | 18 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 8 |
4 files changed, 19 insertions, 16 deletions
diff --git a/lib/sqlalchemy/orm/dynamic.py b/lib/sqlalchemy/orm/dynamic.py index 456bcd34e..308d69fe8 100644 --- a/lib/sqlalchemy/orm/dynamic.py +++ b/lib/sqlalchemy/orm/dynamic.py @@ -12,7 +12,8 @@ basic add/delete mutation. """ from sqlalchemy import log, util -import sqlalchemy.exceptions as sa_exc +from sqlalchemy import exc as sa_exc +from sqlalchemy.orm import exc as sa_exc from sqlalchemy.sql import operators from sqlalchemy.orm import ( attributes, object_session, util as mapperutil, strategies, object_mapper @@ -234,7 +235,7 @@ class AppenderMixin(object): if sess is None: sess = object_session(instance) if sess is None: - raise sa_exc.UnboundExecutionError( + raise orm_exc.DetachedInstanceError( "Parent instance %s is not bound to a Session, and no " "contextual session is established; lazy load operation " "of attribute '%s' cannot proceed" % ( diff --git a/lib/sqlalchemy/orm/exc.py b/lib/sqlalchemy/orm/exc.py index 8b52eec8a..431acc15c 100644 --- a/lib/sqlalchemy/orm/exc.py +++ b/lib/sqlalchemy/orm/exc.py @@ -23,7 +23,9 @@ class FlushError(sa.exc.SQLAlchemyError): class UnmappedError(sa.exc.InvalidRequestError): """TODO""" - +class DetachedInstanceError(sa.exc.SQLAlchemyError): + """An attempt to access unloaded attributes on a mapped instance that is detached.""" + class UnmappedInstanceError(UnmappedError): """An mapping operation was requested for an unknown instance.""" diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 2bdf2b847..63ad20bca 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -22,7 +22,7 @@ deque = __import__('collections').deque from sqlalchemy import sql, util, log, exc as sa_exc from sqlalchemy.sql import expression, visitors, operators, util as sqlutil -from sqlalchemy.orm import attributes, exc, sync +from sqlalchemy.orm import attributes, sync, exc as orm_exc from sqlalchemy.orm.interfaces import ( MapperProperty, EXT_CONTINUE, PropComparator ) @@ -1123,9 +1123,9 @@ class Mapper(object): except KeyError: prop = self._props.get(column.key, None) if prop: - raise exc.UnmappedColumnError("Column '%s.%s' is not available, due to conflicting property '%s':%s" % (column.table.name, column.name, column.key, repr(prop))) + raise orm_exc.UnmappedColumnError("Column '%s.%s' is not available, due to conflicting property '%s':%s" % (column.table.name, column.name, column.key, repr(prop))) else: - raise exc.UnmappedColumnError("No column %s is configured on mapper %s..." % (column, self)) + raise orm_exc.UnmappedColumnError("No column %s is configured on mapper %s..." % (column, self)) # TODO: improve names? def _get_state_attr_by_column(self, state, column): @@ -1319,7 +1319,7 @@ class Mapper(object): instance = uowtransaction.session.identity_map[instance_key] existing = attributes.instance_state(instance) if not uowtransaction.is_deleted(existing): - raise exc.FlushError( + raise orm_exc.FlushError( "New instance %s with identity key %s conflicts with persistent instance %s" % (state_str(state), instance_key, state_str(existing))) if self._should_log_debug: @@ -1460,7 +1460,7 @@ class Mapper(object): if connection.dialect.supports_sane_rowcount: if rows != len(update): - raise exc.ConcurrentModificationError( + raise orm_exc.ConcurrentModificationError( "Updated rowcount %d does not match number of objects updated %d" % (rows, len(update))) @@ -1600,7 +1600,7 @@ class Mapper(object): statement = table.delete(clause) c = connection.execute(statement, del_objects) if c.supports_sane_multi_rowcount() and c.rowcount != len(del_objects): - raise exc.ConcurrentModificationError("Deleted rowcount %d does not match " + raise orm_exc.ConcurrentModificationError("Deleted rowcount %d does not match " "number of objects deleted %d" % (c.rowcount, len(del_objects))) for state, mapper, connection in tups: @@ -1725,7 +1725,7 @@ class Mapper(object): if not currentload and version_id_col is not None and context.version_check and \ self._get_state_attr_by_column(state, self.version_id_col) != row[version_id_col]: - raise exc.ConcurrentModificationError( + raise orm_exc.ConcurrentModificationError( "Instance '%s' version of %s does not match %s" % (state_str(state), self._get_state_attr_by_column(state, self.version_id_col), row[version_id_col])) elif refresh_state: @@ -1928,7 +1928,7 @@ def _load_scalar_attributes(state, attribute_names): mapper = _state_mapper(state) session = _state_session(state) if not session: - raise sa_exc.UnboundExecutionError("Instance %s is not bound to a Session; " + raise orm_exc.DetachedInstanceError("Instance %s is not bound to a Session; " "attribute refresh operation cannot proceed" % (state_str(state))) has_key = _state_has_identity(state) @@ -1948,4 +1948,4 @@ def _load_scalar_attributes(state, attribute_names): # if instance is pending, a refresh operation may not complete (even if PK attributes are assigned) if has_key and result is None: - raise exc.ObjectDeletedError("Instance '%s' has been deleted." % state_str(state)) + raise orm_exc.ObjectDeletedError("Instance '%s' has been deleted." % state_str(state)) diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 0970f3836..33e60491a 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -6,11 +6,11 @@ """sqlalchemy.orm.interfaces.LoaderStrategy implementations, and related MapperOptions.""" -import sqlalchemy.exceptions as sa_exc +from sqlalchemy import exc as sa_exc from sqlalchemy import sql, util, log from sqlalchemy.sql import util as sql_util from sqlalchemy.sql import visitors, expression, operators -from sqlalchemy.orm import mapper, attributes, interfaces +from sqlalchemy.orm import mapper, attributes, interfaces, exc as orm_exc from sqlalchemy.orm.interfaces import ( LoaderStrategy, StrategizedOption, MapperOption, PropertyOption, serialize_path, deserialize_path, StrategizedProperty @@ -291,7 +291,7 @@ class LoadDeferredColumns(object): session = sessionlib._state_session(state) if session is None: - raise sa_exc.UnboundExecutionError( + raise orm_exc.DetachedInstanceError( "Parent instance %s is not bound to a Session; " "deferred load operation of attribute '%s' cannot proceed" % (mapperutil.state_str(state), self.key) @@ -556,7 +556,7 @@ class LoadLazyAttribute(object): session = sessionlib._state_session(state) if session is None: - raise sa_exc.UnboundExecutionError( + raise orm_exc.DetachedInstanceError( "Parent instance %s is not bound to a Session; " "lazy load operation of attribute '%s' cannot proceed" % (mapperutil.state_str(state), self.key) |
