Adjust hooke.command.UncaughtException to properly handle pickle reconstruction.
authorW. Trevor King <wking@drexel.edu>
Wed, 12 May 2010 11:20:48 +0000 (07:20 -0400)
committerW. Trevor King <wking@drexel.edu>
Wed, 12 May 2010 11:20:48 +0000 (07:20 -0400)
multiprocessing.Queue pickles objects to send through its pipe, so our
objects must be capable of surving the pickling process unscathed.

hooke/command.py

index 73f01fe3d443a20b0fb9483ed462896e4a2f3884..21e09b8060b51e16c2bd992b91452df4b74a45b5 100644 (file)
@@ -23,11 +23,39 @@ class Failure (CommandExit):
     pass
 
 class UncaughtException (Failure):
-    def __init__(self, exception):
+    def __init__(self, exception, traceback_string=None):
+        super(UncaughtException, self).__init__()
+        if traceback_string == None:
+            traceback_string = traceback.format_exc()
+            sys.exc_clear()
         self.exception = exception
-        self.exc_string = traceback.format_exc()
-        sys.exc_clear()
-        super(UncaughtException, self).__init__(self.exc_string)
+        self.traceback = traceback_string
+        self.__setstate__(self.__getstate__())
+
+    def __getstate__(self):
+        """Return a picklable representation of the objects state.
+
+        :mod:`pickle`'s doesn't call a :meth:`__init__` when
+        rebuilding a class instance.  To preserve :attr:`args` through
+        a pickle cycle, we use :meth:`__getstate__` and
+        :meth:`__setstate__`.
+
+        See `pickling class instances`_ and `pickling examples`_.
+
+        .. _pickling class instances:
+          http://docs.python.org/library/pickle.html#pickling-and-unpickling-normal-class-instances
+        .. _pickling examples:
+          http://docs.python.org/library/pickle.html#example
+        """
+        return {'exception':self.exception, 'traceback':self.traceback}
+
+    def __setstate__(self, state):
+        """Apply the picklable state from :meth:`__getstate__` to
+        reconstruct the instance.
+        """
+        for key,value in state.items():
+            setattr(self, key, value)
+        self.args = (self.traceback + str(self.exception),)
 
 class Interaction (object):
     """Mid-command inter-process interaction.