--- Lib/xmlrpclib.py 2007-11-20 08:34:46.000000000 -0500
+++ Lib/xmlrpclib.py.orig 2008-03-21 15:36:01.000000000 -0400
@@ -236,6 +236,29 @@
(self.url, self.errcode, self.errmsg)
)
+
+class MarshallError(Error):
+ """Indicates an error occurred while marshalling to/from XML"""
+ def __init__(self, message, value, key=None, slot=None):
+ self.message = message
+ self.value = value
+ self.slot = slot
+ self.key = key
+
+ def __str__(self):
+ message = str(self.message)
+
+ if self.slot is not None:
+ message += "; slot %s" % self.slot
+
+ if self.key is not None:
+ message += "; key %s" % self.key
+
+ message += "; value='%s'" % self.value
+
+ return ' %s ' % message
+
+
##
# Indicates a broken XML-RPC response package. This exception is
# raised by the unmarshalling layer, if the XML-RPC response is
@@ -579,17 +602,26 @@
dispatch = {}
+ def dump_fault(self, fault, write, dump):
+ '''dumps the fault provided to the writer'''
+ self._dump_fault(fault.faultCode, fault.faultString, write, dump)
+
+
+ def _dump_fault(self, faultCode, faultString, write, dump):
+ '''dumps the fault code and string to the writer provided'''
+ write("\n")
+ dump({'faultCode': faultCode,
+ 'faultString': faultString},
+ write)
+ write("\n")
+
+
def dumps(self, values):
out = []
write = out.append
dump = self.__dump
if isinstance(values, Fault):
- # fault instance
- write("\n")
- dump({'faultCode': values.faultCode,
- 'faultString': values.faultString},
- write)
- write("\n")
+ self.dump_fault(values, write, dump)
else:
# parameter block
# FIXME: the xml-rpc specification allows us to leave out
@@ -597,15 +629,32 @@
# however, changing this may break older code (including
# old versions of xmlrpclib.py), so this is better left as
# is for now. See @XMLRPC3 for more information. /F
- write("\n")
- for v in values:
- write("\n")
- dump(v, write)
- write("\n")
- write("\n")
+ pos = 0
+ try:
+ params = []
+ write = params.append
+
+ write("\n")
+ for pos, v in enumerate(values):
+ write("\n")
+ dump(v, write)
+ write("\n")
+ write("\n")
+
+ out.extend(params)
+
+ except MarshallError, e:
+ fault = []
+ write = fault.append
+ message = "could not serialize value #%d: %s" % (pos, str(e))
+ self._dump_fault(8002, message, write, dump)
+
+ out.extend(fault)
+
result = string.join(out, "")
return result
+
def __dump(self, value, write):
try:
f = self.dispatch[type(value)]
@@ -671,8 +720,12 @@
self.memo[i] = None
dump = self.__dump
write("\n")
- for v in value:
- dump(v, write)
+ for pos, v in enumerate(value):
+ try:
+ dump(v, write)
+ except Exception, e:
+ raise MarshallError(e, v, slot=pos)
+
write("\n")
del self.memo[i]
dispatch[TupleType] = dump_array
@@ -693,7 +746,11 @@
else:
raise TypeError, "dictionary key must be string"
write("%s\n" % escape(k))
- dump(v, write)
+ try:
+ dump(v, write)
+ except Exception, e:
+ raise MarshallError(e, v, key=k)
+
write("\n")
write("\n")
del self.memo[i]