Index: twisted/spread/jelly.py =================================================================== --- twisted/spread/jelly.py (revision 12808) +++ twisted/spread/jelly.py (working copy) @@ -164,6 +164,16 @@ unjellyableRegistry[classname] = unjellyable globalSecurity.allowTypes(classname) +def getUnjellyableForClass(classname): + """Lookup and return the registered unjellyable for the classname. + + If no class is registered as an unjellyable, raise an exception. + """ + global unjellyableRegistry + classname = _maybeClass(classname) + return unjellyableRegistry[classname] + + def setUnjellyableFactoryForClass(classname, copyFactory): """ Set the factory to construct a remote instance of a type:: Index: twisted/spread/pb.py =================================================================== --- twisted/spread/pb.py (revision 12808) +++ twisted/spread/pb.py (working copy) @@ -81,7 +81,7 @@ # Sibling Imports from twisted.spread.interfaces import IJellyable, IUnjellyable -from jelly import jelly, unjelly, globalSecurity +from jelly import jelly, unjelly, globalSecurity, getUnjellyableForClass import banana # Tightly coupled sibling import @@ -459,8 +459,17 @@ if isinstance(self.value, failure.Failure): state['value'] = failure2Copyable(self.value, self.unsafeTracebacks) else: - state['value'] = str(self.value) # Exception instance - state['type'] = str(self.type) # Exception class + try: + getUnjellyableForClass(self.type) + except: + # If the class has no registered unjellyable, save a string + # representation of it instead + state['value'] = str(self.value) + else: + # Otherwise save the actual exception instance + state['value'] = self.value + # Always save a string representation of the type, since it is difficult to jelly types + state['type'] = str(self.type) if self.unsafeTracebacks: io = StringIO.StringIO() self.printTraceback(io)