85 An XML-RPC client interface for Python.
87 The marshalling and response parser code can also be used to
88 implement XML-RPC servers.
92 Error Base class for client errors
93 ProtocolError Indicates an HTTP protocol error
94 ResponseError Indicates a broken response package
95 Fault Indicates an XML-RPC fault package
99 ServerProxy Represents a logical connection to an XML-RPC server
101 Boolean boolean wrapper to generate a "boolean" XML-RPC value
102 DateTime dateTime wrapper for an ISO 8601 string or time tuple or
103 localtime integer value to generate a "dateTime.iso8601"
105 Binary binary data wrapper
107 SlowParser Slow but safe standard parser (based on xmllib)
108 Marshaller Generate an XML-RPC params chunk from a Python data structure
109 Unmarshaller Unmarshal an XML-RPC response from incoming XML event message
110 Transport Handles an HTTP transaction to an XML-RPC server
111 SafeTransport Handles an HTTPS transaction to an XML-RPC server
120 boolean Convert any Python value to an XML-RPC boolean
121 getparser Create instance of the fastest available parser & attach
122 to an unmarshalling object
123 dumps Convert an argument tuple or a Fault instance to an XML-RPC
124 request (or response, if the methodresponse option is used).
125 loads Convert an XML-RPC packet to unmarshalled data plus a method
126 name (None if not present).
129 import re, string, time, operator
138 def _decode(data, encoding, is8bit=re.compile(
"[\x80-\xff]").search):
140 if unicode
and encoding
and is8bit(data):
147 return replace(s,
">",
">",)
153 def _stringify(string):
160 def _stringify(string):
163 __version__ =
"1.0.0"
169 """Base class for client errors."""
174 """Indicates an HTTP protocol error."""
183 "<ProtocolError for %s: %s %s>" %
188 """Indicates a broken response package."""
192 """Indicates an XML-RPC fault package."""
193 def __init__(self, faultCode, faultString, **extra):
207 """Boolean-value wrapper.
209 Use True or False to generate a "boolean" XML-RPC value.
216 out.write(
"<value><boolean>%d</boolean></value>\n" % self.
value)
219 if isinstance(other, Boolean):
225 return "<Boolean True at %x>" % id(self)
227 return "<Boolean False at %x>" % id(self)
238 """Convert any Python value to XML-RPC 'boolean'."""
239 return truefalse[operator.truth(value)]
242 """DateTime wrapper for an ISO 8601 string or time tuple or
243 localtime integer value to generate 'dateTime.iso8601' XML-RPC
248 if not isinstance(value, StringType):
249 if not isinstance(value, TupleType):
252 value = time.localtime(value)
253 value = time.strftime(
"%Y%m%dT%H:%M:%S", value)
257 if isinstance(other, DateTime):
262 return "<DateTime %s at %x>" % (self.
value, id(self))
268 out.write(
"<value><dateTime.iso8601>")
269 out.write(self.
value)
270 out.write(
"</dateTime.iso8601></value>\n")
278 """Wrapper for binary data."""
284 if isinstance(other, Binary):
293 import base64, StringIO
294 out.write(
"<value><base64>\n")
296 out.write(
"</base64></value>\n")
303 WRAPPERS = DateTime, Binary, Boolean
312 FastParser = _xmlrpclib.Parser
313 FastUnmarshaller = _xmlrpclib.Unmarshaller
314 except (AttributeError, ImportError):
315 FastParser = FastUnmarshaller =
None
326 if not hasattr(sgmlop,
"XMLParser"):
342 self.parser.register(self)
345 "amp":
"&",
"gt":
">",
"lt":
"<",
346 "apos":
"'",
"quot":
'"'
357 m = re.search(
"encoding\s*=\s*['\"]([^\"']+)[\"']", attr)
369 from xml.parsers
import expat
370 if not hasattr(expat,
"ParserCreate"):
371 raise ImportError,
"ParserCreate"
379 self.
_parser = parser = expat.ParserCreate(
None,
None)
381 parser.StartElementHandler = target.start
382 parser.EndElementHandler = target.end
383 parser.CharacterDataHandler = target.data
385 if not parser.returns_unicode:
387 target.xml(encoding,
None)
390 self._parser.Parse(data, 0)
393 self._parser.Parse(
"", 1)
397 """Default XML parser (based on xmllib.XMLParser)."""
402 if xmllib.XMLParser
not in SlowParser.__bases__:
403 SlowParser.__bases__ = (xmllib.XMLParser,)
409 xmllib.XMLParser.__init__(self, accept_utf8=1)
411 xmllib.XMLParser.__init__(self)
417 """Generate an XML-RPC params chunk from a Python data structure.
419 Create a Marshaller instance for each set of parameters, and use
420 the "dumps" method to convert your data (represented as a tuple)
421 to an XML-RPC params chunk. To write a fault response, pass a
422 Fault instance instead. You may prefer to use the "dumps" module
423 function for this purpose.
438 self.
write = write = self.__out.append
439 if isinstance(values, Fault):
461 def __dump(self, value):
465 raise TypeError,
"cannot marshal %s objects" % type(value)
471 if value > MAXINT
or value < MININT:
472 raise OverflowError,
"int exceeds XML-RPC limits"
473 self.
write(
"<value><int>%s</int></value>\n" % value)
474 dispatch[IntType] = dump_int
478 if value > MAXINT
or value < MININT:
479 raise OverflowError,
"long int exceeds XML-RPC limits"
480 self.
write(
"<value><int>%s</int></value>\n" % int(value))
481 dispatch[LongType] = dump_long
484 self.
write(
"<value><double>%s</double></value>\n" %
repr(value))
485 dispatch[FloatType] = dump_double
488 self.
write(
"<value><string>%s</string></value>\n" %
escape(value))
489 dispatch[StringType] = dump_string
494 self.
write(
"<value><string>%s</string></value>\n" %
escape(value))
495 dispatch[UnicodeType] = dump_unicode
500 if self.memo.has_key(i):
501 raise TypeError,
"cannot marshal recursive data structures"
506 del self.
memo[id(value)]
512 write(
"<value><array><data>\n")
515 write(
"</data></array></value>\n")
517 dispatch[TupleType] = dump_array
518 dispatch[ListType] = dump_array
524 write(
"<value><struct>\n")
525 for k, v
in value.items():
527 if type(k)
is not StringType:
528 raise TypeError,
"dictionary key must be string"
532 write(
"</struct></value>\n")
534 dispatch[DictType] = dump_struct
538 if value.__class__
in WRAPPERS:
543 dispatch[InstanceType] = dump_instance
546 """Unmarshal an XML-RPC response, based on incoming XML event
547 messages (start, data, end). Call close() to get the resulting
550 Note that this reader is fairly tolerant, and gladly accepts bogus
551 XML-RPC data without complaining (but not bogus XML).
570 if self.
_type ==
"fault":
571 raise apply(Fault, (), self.
_stack[0])
580 def xml(self, encoding, standalone):
586 if tag ==
"array" or tag ==
"struct":
587 self._marks.append(len(self.
_stack))
589 self.
_value = (tag ==
"value")
592 self._data.append(text)
594 def end(self, tag, join=string.join):
626 raise TypeError,
"bad boolean value"
628 dispatch[
"boolean"] = end_boolean
633 dispatch[
"i4"] = end_int
634 dispatch[
"int"] = end_int
639 dispatch[
"double"] = end_double
644 self.
append(_stringify(data))
646 dispatch[
"string"] = end_string
647 dispatch[
"name"] = end_string
655 dispatch[
"array"] = end_array
662 items = self.
_stack[mark:]
663 for i
in range(0, len(items), 2):
664 dict[_stringify(items[i])] = items[i+1]
665 self.
_stack[mark:] = [dict]
667 dispatch[
"struct"] = end_struct
674 dispatch[
"base64"] = end_base64
680 dispatch[
"dateTime.iso8601"] = end_dateTime
687 dispatch[
"value"] = end_value
690 self.
_type =
"params"
691 dispatch[
"params"] = end_params
695 dispatch[
"fault"] = end_fault
701 self.
_type =
"methodName"
702 dispatch[
"methodName"] = end_methodName
709 """getparser() -> parser, unmarshaller
711 Create an instance of the fastest available parser, and attach it
712 to an unmarshalling object. Return both objects.
714 if FastParser
and FastUnmarshaller:
727 return parser, target
729 def dumps(params, methodname=None, methodresponse=None, encoding=None):
730 """data [,options] -> marshalled data
732 Convert an argument tuple or a Fault instance to an XML-RPC
733 request (or response, if the methodresponse option is used).
735 In addition to the data object, the following options can be given
736 as keyword arguments:
738 methodname: the method name for a methodCall packet
740 methodresponse: true to create a methodResponse packet.
741 If this option is used with a tuple, the tuple must be
742 a singleton (i.e. it can contain only one element).
744 encoding: the packet encoding (default is UTF-8)
746 All 8-bit strings in the data structure are assumed to use the
747 packet encoding. Unicode strings are automatically converted,
751 assert isinstance(params, TupleType)
or isinstance(params, Fault),\
752 "argument must be tuple or Fault instance"
754 if isinstance(params, Fault):
756 elif methodresponse
and isinstance(params, TupleType):
757 assert len(params) == 1,
"response tuple must be a singleton"
763 data = m.dumps(params)
765 if encoding !=
"utf-8":
766 xmlheader =
"<?xml version='1.0' encoding=%s?>\n" %
repr(encoding)
768 xmlheader =
"<?xml version='1.0'?>\n"
773 if not isinstance(methodname, StringType):
774 methodname = methodname.encode(encoding)
778 "<methodName>", methodname,
"</methodName>\n",
786 "<methodResponse>\n",
788 "</methodResponse>\n"
795 """data -> unmarshalled data, method name
797 Convert an XML-RPC packet to unmarshalled data plus a method
798 name (None if not present).
800 If the XML-RPC packet represents a fault condition, this function
801 raises a Fault exception.
806 return u.close(), u.getmethodname()
825 """Handles an HTTP transaction to an XML-RPC server."""
828 user_agent =
"xmlrpclib.py/%s (by www.pythonware.com)" % __version__
830 def request(self, host, handler, request_body, verbose=0):
842 errcode, errmsg, headers = h.getreply()
865 connection.putrequest(
"POST", handler)
868 connection.putheader(
"Host", host)
871 connection.putheader(
"User-Agent", self.
user_agent)
874 connection.putheader(
"Content-Type",
"text/xml")
875 connection.putheader(
"Content-Length",
str(len(request_body)))
876 connection.endheaders()
878 connection.send(request_body)
886 response = f.read(1024)
890 print "body:",
repr(response)
899 """Handles an HTTPS transaction to an XML-RPC server."""
905 if isinstance(host, TupleType):
911 except AttributeError:
912 raise NotImplementedError,\
913 "your version of httplib doesn't support HTTPS"
915 return apply(HTTPS, (host,
None), x509)
918 if isinstance(host, TupleType):
920 connection.putheader(
"Host", host)
923 """uri [,options] -> a logical connection to an XML-RPC server
925 uri is the connection point on the server, given as
926 scheme://host/target.
928 The standard implementation always supports the "http" scheme. If
929 SSL socket support is available (Python 2.0), it also supports
932 If the target part and the slash preceding it are both omitted,
935 The following options can be given as keyword arguments:
937 transport: a transport factory
938 encoding: the request encoding (default is UTF-8)
940 All 8-bit strings passed to the server proxy are assumed to use
944 def __init__(self, uri, transport=None, encoding=None, verbose=0):
950 if type
not in (
"http",
"https"):
951 raise IOError,
"unsupported XML-RPC protocol"
956 if transport
is None:
966 def __request(self, methodname, params):
971 response = self.__transport.request(
978 if len(response) == 1:
979 response = response[0]
985 "<ServerProxy for %s%s>" %
1004 if __name__ ==
"__main__":
1014 print server.examples.getStateName(41)