Author: tack
Date: Sat Feb 16 10:23:39 2008
New Revision: 3107
Log:
New AsyncException class, which is a more generic RemoteException
(RemoteException now subclasses it); when traceback is not available in
InProgress.get_result(), raise an AsyncException so that the traceback
is more useful.
Modified:
trunk/base/src/notifier/async.py
trunk/base/src/rpc.py
Modified: trunk/base/src/notifier/async.py
==============================================================================
--- trunk/base/src/notifier/async.py (original)
+++ trunk/base/src/notifier/async.py Sat Feb 16 10:23:39 2008
@@ -29,7 +29,8 @@
#
# -----------------------------------------------------------------------------
-__all__ = [ 'TimeoutException', 'InProgress', 'InProgressCallback' ]
+__all__ = [ 'TimeoutException', 'InProgress', 'InProgressCallback',
'AsyncException',
+ 'AsyncExceptionBase', 'make_exception_class' ]
# python imports
import sys
@@ -38,6 +39,7 @@
import time
import _weakref
import threading
+import types
# kaa.notifier imports
from callback import Callback
@@ -46,9 +48,59 @@
# get logging object
log = logging.getLogger('notifier.async')
+
+def make_exception_class(name, bases, dict):
+ """
+ Class generator for AsyncException. Creates AsyncException class
+ which derives the class of a particular Exception instance.
+ """
+ def create(exc, stack, *args):
+ from new import classobj
+ e = classobj(name, (exc.__class__,) + bases, dict)(*exc.args)
+ e._set_info(exc.__class__.__name__, stack, *args)
+ return e
+
+ return create
+
+
+class AsyncExceptionBase(Exception):
+ """
+ Base class for asynchronous exceptions. This class can be used to raise
+ exceptions where the traceback object is not available. The stack is
+ stored (which is safe to reference and can be pickled) instead, and when
+ AsyncExceptionBase instances are printed, the original traceback will
+ be printed.
+ """
+ def _set_info(self, exc_name, stack, *args):
+ self._kaa_exc_name = exc_name
+ self._kaa_exc_stack = stack
+ self._kaa_exc_args = args
+
+ def _get_header(self):
+ return 'Exception raised asynchronously; traceback follows:'
+
+ def __str__(self):
+ dump = ''.join(traceback.format_list(self._kaa_exc_stack))
+ # Python 2.5 always has self.message; for Python 2.4, fall back to
+ # first argument if it's a string.
+ msg = (hasattr(self, 'message') and self.message) or \
+ (self.args and isinstance(self.args[0], basestring) and
self.args[0])
+ if msg:
+ info = '%s: %s' % (self._kaa_exc_name, msg)
+ else:
+ info = self._kaa_exc_name
+
+ return self._get_header() + '\n' + dump + info
+
+
+class AsyncException(AsyncExceptionBase):
+ __metaclass__ = make_exception_class
+
+
class TimeoutException(Exception):
pass
+
class InProgress(Signal):
"""
An InProgress class used to return from function calls that need more time
@@ -190,6 +242,7 @@
self._finished = True
self._exception = type, value, tb
self._unhandled_exception = True
+ stack = traceback.extract_tb(tb)
# Attach a stringified traceback to the exception object. Right now,
# this is the best we can do for asynchronous handlers.
@@ -228,7 +281,7 @@
# Remove traceback from stored exception. If any waiting threads
# haven't gotten it by now, it's too late.
- self._exception = type, value, None
+ self._exception = type, value, stack
# cleanup
self.disconnect_all()
@@ -285,9 +338,15 @@
raise RuntimeError('operation not finished')
if self._exception:
self._unhandled_exception = None
- type, value, tb = self._exception
- # Special 3-argument form of raise; preserves traceback
- raise type, value, tb
+ exc_type, exc_value, exc_tb_or_stack = self._exception
+ if type(exc_tb_or_stack) == types.TracebackType:
+ # We have the traceback, so we can raise using it.
+ raise exc_type, exc_value, exc_tb_or_stack
+ else:
+ # No traceback, so construct an AsyncException based on the
+ # stack.
+ raise AsyncException(exc_value, exc_tb_or_stack)
+
return self._result
Modified: trunk/base/src/rpc.py
==============================================================================
--- trunk/base/src/rpc.py (original)
+++ trunk/base/src/rpc.py Sat Feb 16 10:23:39 2008
@@ -89,11 +89,11 @@
import sys
import sha
import time
-from new import classobj
import traceback
# kaa imports
import kaa
+from notifier.async import make_exception_class, AsyncExceptionBase
# get logging object
log = logging.getLogger('rpc')
@@ -101,21 +101,7 @@
class ConnectError(Exception):
pass
-
-def make_exception_class(name, bases, dict):
- """
- Class generator for RemoteException. Creates RemoteException class
- which derives the class of a particular Exception instance.
- """
- def create(exc, cmd, stack):
- e = classobj(name, (exc.__class__,) + bases, dict)(*exc.args)
- e._set_info(exc.__class__.__name__, cmd, stack)
- return e
-
- return create
-
-
-class RemoteException(Exception):
+class RemoteException(AsyncExceptionBase):
"""
Raised when remote RPC calls raise exceptions. Instances of this class
inherit the actual remote exception class, so this works:
@@ -129,25 +115,8 @@
traceback of the remote stack.
"""
__metaclass__ = make_exception_class
-
- def _set_info(self, exc_name, cmd, stack):
- self._rpc_exc_name = exc_name
- self._rpc_cmd = cmd
- self._rpc_stack = stack
-
- def __str__(self):
- dump = ''.join(traceback.format_list(self._rpc_stack))
- # Python 2.5 always has self.message; for Python 2.4, fall back to
- # first argument if it's a string.
- msg = (hasattr(self, 'message') and self.message) or \
- (self.args and isinstance(self.args[0], basestring) and
self.args[0])
- if msg:
- info = '%s: %s' % (self._rpc_exc_name, msg)
- else:
- info = self._rpc_exc_name
-
- return "Exception during RPC call '%s'; remote traceback follows:\n" %
self._rpc_cmd + \
- dump + info
+ def _get_header(self):
+ return "Exception during RPC call '%s'; remote traceback follows:" %
self._kaa_exc_args[0]
class Server(object):
@@ -553,7 +522,7 @@
if callback is None:
return True
del self._rpc_in_progress[seq]
- remote_exc = RemoteException(exc_value, cmd, stack)
+ remote_exc = RemoteException(exc_value, stack, cmd)
callback.throw(remote_exc.__class__, remote_exc, None)
return True
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog