rrefutil: generically wrap any errback from callRemote() in a ServerFailure instance

This facilitates client code to easily catch ServerFailures without also catching exceptions arising from client-side code.
See also:
http://foolscap.lothar.com/trac/ticket/105 # make it easy to distinguish server-side failures/exceptions from client-side
This commit is contained in:
Zooko O'Whielacronx 2008-12-31 14:28:30 -07:00
parent 3a47031a51
commit c00d20361f

View File

@ -1,15 +1,33 @@
import exceptions
from foolscap.tokens import Violation
class VersionedRemoteReference:
"""I wrap a RemoteReference, and add a .version attribute."""
from twisted.python import failure
def __init__(self, original, version):
class ServerFailure(exceptions.Exception):
# If the server returns a Failure instead of the normal response to a protocol, then this
# exception will be raised, with the Failure that the server returned as its .remote_failure
# attribute.
def __init__(self, remote_failure):
self.remote_failure = remote_failure
def __repr__(self):
return repr(self.remote_failure)
def __str__(self):
return str(self.remote_failure)
def _wrap_server_failure(f):
raise ServerFailure(f)
class WrappedRemoteReference(object):
"""I intercept any errback from the server and wrap it in a ServerFailure."""
def __init__(self, original):
self.rref = original
self.version = version
def callRemote(self, *args, **kwargs):
return self.rref.callRemote(*args, **kwargs)
d = self.rref.callRemote(*args, **kwargs)
d.addErrback(_wrap_server_failure)
return d
def callRemoteOnly(self, *args, **kwargs):
return self.rref.callRemoteOnly(*args, **kwargs)
@ -17,6 +35,13 @@ class VersionedRemoteReference:
def notifyOnDisconnect(self, *args, **kwargs):
return self.rref.notifyOnDisconnect(*args, **kwargs)
class VersionedRemoteReference(WrappedRemoteReference):
"""I wrap a RemoteReference, and add a .version attribute. I also intercept any errback from
the server and wrap it in a ServerFailure."""
def __init__(self, original, version):
WrappedRemoteReference.__init__(self, original)
self.version = version
def get_versioned_remote_reference(rref, default):
"""I return a Deferred that fires with a VersionedRemoteReference"""