diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-01-11 20:58:10 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-01-11 20:58:10 -0500 |
| commit | 8e6c330673e28dfb6fa24022e66bb67d6f2f673a (patch) | |
| tree | b4e3ea46cc852bdd1680f57ede44e080ae384e4a | |
| parent | 26625d897f9becd7bccc6ece037e9ad39a6a77e9 (diff) | |
| download | sqlalchemy-8e6c330673e28dfb6fa24022e66bb67d6f2f673a.tar.gz | |
- [bug] ensure pickleability of all ORM exceptions
for multiprocessing compatibility. [ticket:2371]
| -rw-r--r-- | CHANGES | 8 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/exc.py | 17 | ||||
| -rw-r--r-- | test/orm/test_pickled.py | 15 |
3 files changed, 33 insertions, 7 deletions
@@ -29,10 +29,14 @@ CHANGES emitted on a pending object, it would fail to load. + - [bug] ensure pickleability of all ORM exceptions + for multiprocessing compatibility. [ticket:2371] + - engine - [bug] Added __reduce__ to StatementError, - DBAPIError so that exceptions are pickleable, - as when using multiprocessing. However, not + DBAPIError, column errors so that exceptions + are pickleable, as when using multiprocessing. + However, not all DBAPIs support this yet, such as psycopg2. [ticket:2371] diff --git a/lib/sqlalchemy/orm/exc.py b/lib/sqlalchemy/orm/exc.py index 1146284f9..2aaf1490b 100644 --- a/lib/sqlalchemy/orm/exc.py +++ b/lib/sqlalchemy/orm/exc.py @@ -72,6 +72,8 @@ class UnmappedInstanceError(UnmappedError): 'required?' % _safe_cls_name(obj)) UnmappedError.__init__(self, msg) + def __reduce__(self): + return self.__class__, (None, self.args[0]) class UnmappedClassError(UnmappedError): """An mapping operation was requested for an unknown class.""" @@ -81,6 +83,8 @@ class UnmappedClassError(UnmappedError): msg = _default_unmapped(cls) UnmappedError.__init__(self, msg) + def __reduce__(self): + return self.__class__, (None, self.args[0]) class ObjectDeletedError(sa.exc.InvalidRequestError): """A refresh operation failed to retrieve the database @@ -101,12 +105,15 @@ class ObjectDeletedError(sa.exc.InvalidRequestError): object. """ - def __init__(self, state): - sa.exc.InvalidRequestError.__init__( - self, - "Instance '%s' has been deleted, or its " + def __init__(self, state, msg=None): + if not msg: + msg = "Instance '%s' has been deleted, or its "\ "row is otherwise not present." % orm_util.state_str(state) - ) + + sa.exc.InvalidRequestError.__init__(self, msg) + + def __reduce__(self): + return self.__class__, (None, self.args[0]) class UnmappedColumnError(sa.exc.InvalidRequestError): """Mapping operation was requested on an unknown column.""" diff --git a/test/orm/test_pickled.py b/test/orm/test_pickled.py index f63c4cfa2..920159dc1 100644 --- a/test/orm/test_pickled.py +++ b/test/orm/test_pickled.py @@ -319,6 +319,21 @@ class PickleTest(fixtures.MappedTest): screen2 = Screen(Child2(), screen1) pickle.loads(pickle.dumps(screen2)) + def test_exceptions(self): + class Foo(object): + pass + users = self.tables.users + mapper(User, users) + + for sa_exc in ( + orm_exc.UnmappedInstanceError(Foo()), + orm_exc.UnmappedClassError(Foo), + orm_exc.ObjectDeletedError(attributes.instance_state(User())), + ): + for loads, dumps in picklers(): + repickled = loads(dumps(sa_exc)) + eq_(repickled.args[0], sa_exc.args[0]) + class PolymorphicDeferredTest(fixtures.MappedTest): @classmethod def define_tables(cls, metadata): |
