| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 1 | :mod:`xmlrpc.client` --- XML-RPC client access | 
 | 2 | ============================================== | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 3 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 4 | .. module:: xmlrpc.client | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 5 |    :synopsis: XML-RPC client access. | 
 | 6 | .. moduleauthor:: Fredrik Lundh <fredrik@pythonware.com> | 
 | 7 | .. sectionauthor:: Eric S. Raymond <esr@snark.thyrsus.com> | 
 | 8 |  | 
 | 9 |  | 
| Christian Heimes | 5b5e81c | 2007-12-31 16:14:33 +0000 | [diff] [blame] | 10 | .. XXX Not everything is documented yet.  It might be good to describe | 
 | 11 |    Marshaller, Unmarshaller, getparser, dumps, loads, and Transport. | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 12 |  | 
| Raymond Hettinger | 3029aff | 2011-02-10 08:09:36 +0000 | [diff] [blame] | 13 | **Source code:** :source:`Lib/xmlrpc/client.py` | 
 | 14 |  | 
 | 15 | -------------- | 
 | 16 |  | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 17 | XML-RPC is a Remote Procedure Call method that uses XML passed via HTTP as a | 
 | 18 | transport.  With it, a client can call methods with parameters on a remote | 
 | 19 | server (the server is named by a URI) and get back structured data.  This module | 
 | 20 | supports writing XML-RPC client code; it handles all the details of translating | 
 | 21 | between conformable Python objects and XML on the wire. | 
 | 22 |  | 
 | 23 |  | 
| Georg Brandl | 7f01a13 | 2009-09-16 15:58:14 +0000 | [diff] [blame] | 24 | .. class:: ServerProxy(uri, transport=None, encoding=None, verbose=False, allow_none=False, use_datetime=False) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 25 |  | 
 | 26 |    A :class:`ServerProxy` instance is an object that manages communication with a | 
 | 27 |    remote XML-RPC server.  The required first argument is a URI (Uniform Resource | 
 | 28 |    Indicator), and will normally be the URL of the server.  The optional second | 
 | 29 |    argument is a transport factory instance; by default it is an internal | 
 | 30 |    :class:`SafeTransport` instance for https: URLs and an internal HTTP | 
 | 31 |    :class:`Transport` instance otherwise.  The optional third argument is an | 
 | 32 |    encoding, by default UTF-8. The optional fourth argument is a debugging flag. | 
 | 33 |    If *allow_none* is true,  the Python constant ``None`` will be translated into | 
 | 34 |    XML; the default behaviour is for ``None`` to raise a :exc:`TypeError`. This is | 
 | 35 |    a commonly-used extension to the XML-RPC specification, but isn't supported by | 
 | 36 |    all clients and servers; see http://ontosys.com/xml-rpc/extensions.php for a | 
 | 37 |    description.  The *use_datetime* flag can be used to cause date/time values to | 
 | 38 |    be presented as :class:`datetime.datetime` objects; this is false by default. | 
| Christian Heimes | 05e8be1 | 2008-02-23 18:30:17 +0000 | [diff] [blame] | 39 |    :class:`datetime.datetime` objects may be passed to calls. | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 40 |  | 
 | 41 |    Both the HTTP and HTTPS transports support the URL syntax extension for HTTP | 
 | 42 |    Basic Authentication: ``http://user:pass@host:port/path``.  The  ``user:pass`` | 
 | 43 |    portion will be base64-encoded as an HTTP 'Authorization' header, and sent to | 
 | 44 |    the remote server as part of the connection process when invoking an XML-RPC | 
 | 45 |    method.  You only need to use this if the remote server requires a Basic | 
 | 46 |    Authentication user and password. | 
 | 47 |  | 
 | 48 |    The returned instance is a proxy object with methods that can be used to invoke | 
 | 49 |    corresponding RPC calls on the remote server.  If the remote server supports the | 
 | 50 |    introspection API, the proxy can also be used to query the remote server for the | 
 | 51 |    methods it supports (service discovery) and fetch other server-associated | 
 | 52 |    metadata. | 
 | 53 |  | 
 | 54 |    :class:`ServerProxy` instance methods take Python basic types and objects as | 
 | 55 |    arguments and return Python basic types and classes.  Types that are conformable | 
 | 56 |    (e.g. that can be marshalled through XML), include the following (and except | 
 | 57 |    where noted, they are unmarshalled as the same Python type): | 
 | 58 |  | 
 | 59 |    +---------------------------------+---------------------------------------------+ | 
 | 60 |    | Name                            | Meaning                                     | | 
 | 61 |    +=================================+=============================================+ | 
 | 62 |    | :const:`boolean`                | The :const:`True` and :const:`False`        | | 
 | 63 |    |                                 | constants                                   | | 
 | 64 |    +---------------------------------+---------------------------------------------+ | 
 | 65 |    | :const:`integers`               | Pass in directly                            | | 
 | 66 |    +---------------------------------+---------------------------------------------+ | 
 | 67 |    | :const:`floating-point numbers` | Pass in directly                            | | 
 | 68 |    +---------------------------------+---------------------------------------------+ | 
 | 69 |    | :const:`strings`                | Pass in directly                            | | 
 | 70 |    +---------------------------------+---------------------------------------------+ | 
 | 71 |    | :const:`arrays`                 | Any Python sequence type containing         | | 
 | 72 |    |                                 | conformable elements. Arrays are returned   | | 
 | 73 |    |                                 | as lists                                    | | 
 | 74 |    +---------------------------------+---------------------------------------------+ | 
 | 75 |    | :const:`structures`             | A Python dictionary. Keys must be strings,  | | 
 | 76 |    |                                 | values may be any conformable type. Objects | | 
 | 77 |    |                                 | of user-defined classes can be passed in;   | | 
 | 78 |    |                                 | only their *__dict__* attribute is          | | 
 | 79 |    |                                 | transmitted.                                | | 
 | 80 |    +---------------------------------+---------------------------------------------+ | 
 | 81 |    | :const:`dates`                  | in seconds since the epoch (pass in an      | | 
 | 82 |    |                                 | instance of the :class:`DateTime` class) or | | 
| Christian Heimes | 05e8be1 | 2008-02-23 18:30:17 +0000 | [diff] [blame] | 83 |    |                                 | a :class:`datetime.datetime` instance.      | | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 84 |    +---------------------------------+---------------------------------------------+ | 
 | 85 |    | :const:`binary data`            | pass in an instance of the :class:`Binary`  | | 
 | 86 |    |                                 | wrapper class                               | | 
 | 87 |    +---------------------------------+---------------------------------------------+ | 
 | 88 |  | 
 | 89 |    This is the full set of data types supported by XML-RPC.  Method calls may also | 
 | 90 |    raise a special :exc:`Fault` instance, used to signal XML-RPC server errors, or | 
 | 91 |    :exc:`ProtocolError` used to signal an error in the HTTP/HTTPS transport layer. | 
 | 92 |    Both :exc:`Fault` and :exc:`ProtocolError` derive from a base class called | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 93 |    :exc:`Error`.  Note that the xmlrpc client module currently does not marshal | 
| Georg Brandl | 22b3431 | 2009-07-26 14:54:51 +0000 | [diff] [blame] | 94 |    instances of subclasses of built-in types. | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 95 |  | 
 | 96 |    When passing strings, characters special to XML such as ``<``, ``>``, and ``&`` | 
 | 97 |    will be automatically escaped.  However, it's the caller's responsibility to | 
 | 98 |    ensure that the string is free of characters that aren't allowed in XML, such as | 
 | 99 |    the control characters with ASCII values between 0 and 31 (except, of course, | 
 | 100 |    tab, newline and carriage return); failing to do this will result in an XML-RPC | 
 | 101 |    request that isn't well-formed XML.  If you have to pass arbitrary strings via | 
 | 102 |    XML-RPC, use the :class:`Binary` wrapper class described below. | 
 | 103 |  | 
 | 104 |    :class:`Server` is retained as an alias for :class:`ServerProxy` for backwards | 
 | 105 |    compatibility.  New code should use :class:`ServerProxy`. | 
 | 106 |  | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 107 |  | 
 | 108 | .. seealso:: | 
 | 109 |  | 
 | 110 |    `XML-RPC HOWTO <http://www.tldp.org/HOWTO/XML-RPC-HOWTO/index.html>`_ | 
| Christian Heimes | a62da1d | 2008-01-12 19:39:10 +0000 | [diff] [blame] | 111 |       A good description of XML-RPC operation and client software in several languages. | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 112 |       Contains pretty much everything an XML-RPC client developer needs to know. | 
 | 113 |  | 
| Christian Heimes | a62da1d | 2008-01-12 19:39:10 +0000 | [diff] [blame] | 114 |    `XML-RPC Introspection <http://xmlrpc-c.sourceforge.net/introspection.html>`_ | 
 | 115 |       Describes the XML-RPC protocol extension for introspection. | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 116 |  | 
| Christian Heimes | 81ee3ef | 2008-05-04 22:42:01 +0000 | [diff] [blame] | 117 |    `XML-RPC Specification <http://www.xmlrpc.com/spec>`_ | 
 | 118 |       The official specification. | 
 | 119 |  | 
 | 120 |    `Unofficial XML-RPC Errata <http://effbot.org/zone/xmlrpc-errata.htm>`_ | 
 | 121 |       Fredrik Lundh's "unofficial errata, intended to clarify certain | 
 | 122 |       details in the XML-RPC specification, as well as hint at | 
 | 123 |       'best practices' to use when designing your own XML-RPC | 
 | 124 |       implementations." | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 125 |  | 
 | 126 | .. _serverproxy-objects: | 
 | 127 |  | 
 | 128 | ServerProxy Objects | 
 | 129 | ------------------- | 
 | 130 |  | 
 | 131 | A :class:`ServerProxy` instance has a method corresponding to each remote | 
 | 132 | procedure call accepted by the XML-RPC server.  Calling the method performs an | 
 | 133 | RPC, dispatched by both name and argument signature (e.g. the same method name | 
 | 134 | can be overloaded with multiple argument signatures).  The RPC finishes by | 
 | 135 | returning a value, which may be either returned data in a conformant type or a | 
 | 136 | :class:`Fault` or :class:`ProtocolError` object indicating an error. | 
 | 137 |  | 
 | 138 | Servers that support the XML introspection API support some common methods | 
| Senthil Kumaran | a6bac95 | 2011-07-04 11:28:30 -0700 | [diff] [blame] | 139 | grouped under the reserved :attr:`system` attribute: | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 140 |  | 
 | 141 |  | 
 | 142 | .. method:: ServerProxy.system.listMethods() | 
 | 143 |  | 
 | 144 |    This method returns a list of strings, one for each (non-system) method | 
 | 145 |    supported by the XML-RPC server. | 
 | 146 |  | 
 | 147 |  | 
 | 148 | .. method:: ServerProxy.system.methodSignature(name) | 
 | 149 |  | 
 | 150 |    This method takes one parameter, the name of a method implemented by the XML-RPC | 
| Georg Brandl | 9460648 | 2009-05-04 20:46:44 +0000 | [diff] [blame] | 151 |    server. It returns an array of possible signatures for this method. A signature | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 152 |    is an array of types. The first of these types is the return type of the method, | 
 | 153 |    the rest are parameters. | 
 | 154 |  | 
 | 155 |    Because multiple signatures (ie. overloading) is permitted, this method returns | 
 | 156 |    a list of signatures rather than a singleton. | 
 | 157 |  | 
 | 158 |    Signatures themselves are restricted to the top level parameters expected by a | 
 | 159 |    method. For instance if a method expects one array of structs as a parameter, | 
 | 160 |    and it returns a string, its signature is simply "string, array". If it expects | 
 | 161 |    three integers and returns a string, its signature is "string, int, int, int". | 
 | 162 |  | 
 | 163 |    If no signature is defined for the method, a non-array value is returned. In | 
 | 164 |    Python this means that the type of the returned  value will be something other | 
| Georg Brandl | 9460648 | 2009-05-04 20:46:44 +0000 | [diff] [blame] | 165 |    than list. | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 166 |  | 
 | 167 |  | 
 | 168 | .. method:: ServerProxy.system.methodHelp(name) | 
 | 169 |  | 
 | 170 |    This method takes one parameter, the name of a method implemented by the XML-RPC | 
 | 171 |    server.  It returns a documentation string describing the use of that method. If | 
 | 172 |    no such string is available, an empty string is returned. The documentation | 
 | 173 |    string may contain HTML markup. | 
 | 174 |  | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 175 |  | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 176 | A working example follows. The server code:: | 
 | 177 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 178 |    from xmlrpc.server import SimpleXMLRPCServer | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 179 |  | 
 | 180 |    def is_even(n): | 
 | 181 |        return n%2 == 0 | 
 | 182 |  | 
 | 183 |    server = SimpleXMLRPCServer(("localhost", 8000)) | 
| Georg Brandl | f694518 | 2008-02-01 11:56:49 +0000 | [diff] [blame] | 184 |    print("Listening on port 8000...") | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 185 |    server.register_function(is_even, "is_even") | 
 | 186 |    server.serve_forever() | 
 | 187 |  | 
 | 188 | The client code for the preceding server:: | 
 | 189 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 190 |    import xmlrpc.client | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 191 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 192 |    proxy = xmlrpc.client.ServerProxy("http://localhost:8000/") | 
| Georg Brandl | f694518 | 2008-02-01 11:56:49 +0000 | [diff] [blame] | 193 |    print("3 is even: %s" % str(proxy.is_even(3))) | 
 | 194 |    print("100 is even: %s" % str(proxy.is_even(100))) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 195 |  | 
 | 196 | .. _datetime-objects: | 
 | 197 |  | 
 | 198 | DateTime Objects | 
 | 199 | ---------------- | 
 | 200 |  | 
| Christian Heimes | 05e8be1 | 2008-02-23 18:30:17 +0000 | [diff] [blame] | 201 | This class may be initialized with seconds since the epoch, a time | 
 | 202 | tuple, an ISO 8601 time/date string, or a :class:`datetime.datetime` | 
 | 203 | instance.  It has the following methods, supported mainly for internal | 
 | 204 | use by the marshalling/unmarshalling code: | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 205 |  | 
 | 206 |  | 
 | 207 | .. method:: DateTime.decode(string) | 
 | 208 |  | 
 | 209 |    Accept a string as the instance's new time value. | 
 | 210 |  | 
 | 211 |  | 
 | 212 | .. method:: DateTime.encode(out) | 
 | 213 |  | 
 | 214 |    Write the XML-RPC encoding of this :class:`DateTime` item to the *out* stream | 
 | 215 |    object. | 
 | 216 |  | 
| Georg Brandl | 05f5ab7 | 2008-09-24 09:11:47 +0000 | [diff] [blame] | 217 | It also supports certain of Python's built-in operators through rich comparison | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 218 | and :meth:`__repr__` methods. | 
 | 219 |  | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 220 | A working example follows. The server code:: | 
 | 221 |  | 
 | 222 |    import datetime | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 223 |    from xmlrpc.server import SimpleXMLRPCServer | 
 | 224 |    import xmlrpc.client | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 225 |  | 
 | 226 |    def today(): | 
 | 227 |        today = datetime.datetime.today() | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 228 |        return xmlrpc.client.DateTime(today) | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 229 |  | 
 | 230 |    server = SimpleXMLRPCServer(("localhost", 8000)) | 
| Georg Brandl | f694518 | 2008-02-01 11:56:49 +0000 | [diff] [blame] | 231 |    print("Listening on port 8000...") | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 232 |    server.register_function(today, "today") | 
 | 233 |    server.serve_forever() | 
 | 234 |  | 
 | 235 | The client code for the preceding server:: | 
 | 236 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 237 |    import xmlrpc.client | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 238 |    import datetime | 
 | 239 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 240 |    proxy = xmlrpc.client.ServerProxy("http://localhost:8000/") | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 241 |  | 
 | 242 |    today = proxy.today() | 
 | 243 |    # convert the ISO8601 string to a datetime object | 
 | 244 |    converted = datetime.datetime.strptime(today.value, "%Y%m%dT%H:%M:%S") | 
| Georg Brandl | f694518 | 2008-02-01 11:56:49 +0000 | [diff] [blame] | 245 |    print("Today: %s" % converted.strftime("%d.%m.%Y, %H:%M")) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 246 |  | 
 | 247 | .. _binary-objects: | 
 | 248 |  | 
 | 249 | Binary Objects | 
 | 250 | -------------- | 
 | 251 |  | 
 | 252 | This class may be initialized from string data (which may include NULs). The | 
 | 253 | primary access to the content of a :class:`Binary` object is provided by an | 
 | 254 | attribute: | 
 | 255 |  | 
 | 256 |  | 
 | 257 | .. attribute:: Binary.data | 
 | 258 |  | 
 | 259 |    The binary data encapsulated by the :class:`Binary` instance.  The data is | 
 | 260 |    provided as an 8-bit string. | 
 | 261 |  | 
 | 262 | :class:`Binary` objects have the following methods, supported mainly for | 
 | 263 | internal use by the marshalling/unmarshalling code: | 
 | 264 |  | 
 | 265 |  | 
 | 266 | .. method:: Binary.decode(string) | 
 | 267 |  | 
 | 268 |    Accept a base64 string and decode it as the instance's new data. | 
 | 269 |  | 
 | 270 |  | 
 | 271 | .. method:: Binary.encode(out) | 
 | 272 |  | 
 | 273 |    Write the XML-RPC base 64 encoding of this binary item to the out stream object. | 
 | 274 |  | 
| Christian Heimes | 81ee3ef | 2008-05-04 22:42:01 +0000 | [diff] [blame] | 275 |    The encoded data will have newlines every 76 characters as per | 
 | 276 |    `RFC 2045 section 6.8 <http://tools.ietf.org/html/rfc2045#section-6.8>`_, | 
 | 277 |    which was the de facto standard base64 specification when the | 
 | 278 |    XML-RPC spec was written. | 
 | 279 |  | 
| Georg Brandl | 05f5ab7 | 2008-09-24 09:11:47 +0000 | [diff] [blame] | 280 | It also supports certain of Python's built-in operators through :meth:`__eq__` | 
 | 281 | and :meth:`__ne__` methods. | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 282 |  | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 283 | Example usage of the binary objects.  We're going to transfer an image over | 
 | 284 | XMLRPC:: | 
 | 285 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 286 |    from xmlrpc.server import SimpleXMLRPCServer | 
 | 287 |    import xmlrpc.client | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 288 |  | 
 | 289 |    def python_logo(): | 
| Victor Stinner | 757db83 | 2010-01-30 02:16:55 +0000 | [diff] [blame] | 290 |        with open("python_logo.jpg", "rb") as handle: | 
 | 291 |            return xmlrpc.client.Binary(handle.read()) | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 292 |  | 
 | 293 |    server = SimpleXMLRPCServer(("localhost", 8000)) | 
| Georg Brandl | f694518 | 2008-02-01 11:56:49 +0000 | [diff] [blame] | 294 |    print("Listening on port 8000...") | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 295 |    server.register_function(python_logo, 'python_logo') | 
 | 296 |  | 
 | 297 |    server.serve_forever() | 
 | 298 |  | 
 | 299 | The client gets the image and saves it to a file:: | 
 | 300 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 301 |    import xmlrpc.client | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 302 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 303 |    proxy = xmlrpc.client.ServerProxy("http://localhost:8000/") | 
| Victor Stinner | 757db83 | 2010-01-30 02:16:55 +0000 | [diff] [blame] | 304 |    with open("fetched_python_logo.jpg", "wb") as handle: | 
 | 305 |        handle.write(proxy.python_logo().data) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 306 |  | 
 | 307 | .. _fault-objects: | 
 | 308 |  | 
 | 309 | Fault Objects | 
 | 310 | ------------- | 
 | 311 |  | 
 | 312 | A :class:`Fault` object encapsulates the content of an XML-RPC fault tag. Fault | 
| Senthil Kumaran | a6bac95 | 2011-07-04 11:28:30 -0700 | [diff] [blame] | 313 | objects have the following attributes: | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 314 |  | 
 | 315 |  | 
 | 316 | .. attribute:: Fault.faultCode | 
 | 317 |  | 
 | 318 |    A string indicating the fault type. | 
 | 319 |  | 
 | 320 |  | 
 | 321 | .. attribute:: Fault.faultString | 
 | 322 |  | 
 | 323 |    A string containing a diagnostic message associated with the fault. | 
 | 324 |  | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 325 | In the following example we're going to intentionally cause a :exc:`Fault` by | 
 | 326 | returning a complex type object.  The server code:: | 
 | 327 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 328 |    from xmlrpc.server import SimpleXMLRPCServer | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 329 |  | 
 | 330 |    # A marshalling error is going to occur because we're returning a | 
 | 331 |    # complex number | 
 | 332 |    def add(x,y): | 
 | 333 |        return x+y+0j | 
 | 334 |  | 
 | 335 |    server = SimpleXMLRPCServer(("localhost", 8000)) | 
| Georg Brandl | f694518 | 2008-02-01 11:56:49 +0000 | [diff] [blame] | 336 |    print("Listening on port 8000...") | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 337 |    server.register_function(add, 'add') | 
 | 338 |  | 
 | 339 |    server.serve_forever() | 
 | 340 |  | 
 | 341 | The client code for the preceding server:: | 
 | 342 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 343 |    import xmlrpc.client | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 344 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 345 |    proxy = xmlrpc.client.ServerProxy("http://localhost:8000/") | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 346 |    try: | 
 | 347 |        proxy.add(2, 5) | 
| Georg Brandl | 0dedf45 | 2009-05-22 16:44:06 +0000 | [diff] [blame] | 348 |    except xmlrpc.client.Fault as err: | 
| Georg Brandl | 2ee470f | 2008-07-16 12:55:28 +0000 | [diff] [blame] | 349 |        print("A fault occurred") | 
| Georg Brandl | f694518 | 2008-02-01 11:56:49 +0000 | [diff] [blame] | 350 |        print("Fault code: %d" % err.faultCode) | 
 | 351 |        print("Fault string: %s" % err.faultString) | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 352 |  | 
 | 353 |  | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 354 |  | 
 | 355 | .. _protocol-error-objects: | 
 | 356 |  | 
 | 357 | ProtocolError Objects | 
 | 358 | --------------------- | 
 | 359 |  | 
 | 360 | A :class:`ProtocolError` object describes a protocol error in the underlying | 
 | 361 | transport layer (such as a 404 'not found' error if the server named by the URI | 
| Senthil Kumaran | a6bac95 | 2011-07-04 11:28:30 -0700 | [diff] [blame] | 362 | does not exist).  It has the following attributes: | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 363 |  | 
 | 364 |  | 
 | 365 | .. attribute:: ProtocolError.url | 
 | 366 |  | 
 | 367 |    The URI or URL that triggered the error. | 
 | 368 |  | 
 | 369 |  | 
 | 370 | .. attribute:: ProtocolError.errcode | 
 | 371 |  | 
 | 372 |    The error code. | 
 | 373 |  | 
 | 374 |  | 
 | 375 | .. attribute:: ProtocolError.errmsg | 
 | 376 |  | 
 | 377 |    The error message or diagnostic string. | 
 | 378 |  | 
 | 379 |  | 
 | 380 | .. attribute:: ProtocolError.headers | 
 | 381 |  | 
| Guido van Rossum | 460add4 | 2007-08-23 02:13:35 +0000 | [diff] [blame] | 382 |    A dict containing the headers of the HTTP/HTTPS request that triggered the | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 383 |    error. | 
 | 384 |  | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 385 | In the following example we're going to intentionally cause a :exc:`ProtocolError` | 
 | 386 | by providing an invalid URI:: | 
 | 387 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 388 |    import xmlrpc.client | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 389 |  | 
| Benjamin Peterson | 5e55b3e | 2010-02-03 02:35:45 +0000 | [diff] [blame] | 390 |    # create a ServerProxy with an URI that doesn't respond to XMLRPC requests | 
 | 391 |    proxy = xmlrpc.client.ServerProxy("http://google.com/") | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 392 |  | 
 | 393 |    try: | 
 | 394 |        proxy.some_method() | 
| Georg Brandl | 0dedf45 | 2009-05-22 16:44:06 +0000 | [diff] [blame] | 395 |    except xmlrpc.client.ProtocolError as err: | 
| Georg Brandl | 2ee470f | 2008-07-16 12:55:28 +0000 | [diff] [blame] | 396 |        print("A protocol error occurred") | 
| Georg Brandl | f694518 | 2008-02-01 11:56:49 +0000 | [diff] [blame] | 397 |        print("URL: %s" % err.url) | 
 | 398 |        print("HTTP/HTTPS headers: %s" % err.headers) | 
 | 399 |        print("Error code: %d" % err.errcode) | 
 | 400 |        print("Error message: %s" % err.errmsg) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 401 |  | 
 | 402 | MultiCall Objects | 
 | 403 | ----------------- | 
 | 404 |  | 
| Sandro Tosi | 9daf98d | 2011-08-20 17:05:56 +0200 | [diff] [blame] | 405 | The :class:`MultiCall` object provides a way to encapsulate multiple calls to a | 
 | 406 | remote server into a single request [#]_. | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 407 |  | 
 | 408 |  | 
 | 409 | .. class:: MultiCall(server) | 
 | 410 |  | 
 | 411 |    Create an object used to boxcar method calls. *server* is the eventual target of | 
 | 412 |    the call. Calls can be made to the result object, but they will immediately | 
 | 413 |    return ``None``, and only store the call name and parameters in the | 
 | 414 |    :class:`MultiCall` object. Calling the object itself causes all stored calls to | 
 | 415 |    be transmitted as a single ``system.multicall`` request. The result of this call | 
| Georg Brandl | 9afde1c | 2007-11-01 20:32:30 +0000 | [diff] [blame] | 416 |    is a :term:`generator`; iterating over this generator yields the individual | 
 | 417 |    results. | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 418 |  | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 419 | A usage example of this class follows.  The server code :: | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 420 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 421 |    from xmlrpc.server import SimpleXMLRPCServer | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 422 |  | 
 | 423 |    def add(x,y): | 
 | 424 |        return x+y | 
 | 425 |  | 
 | 426 |    def subtract(x, y): | 
 | 427 |        return x-y | 
 | 428 |  | 
 | 429 |    def multiply(x, y): | 
 | 430 |        return x*y | 
 | 431 |  | 
 | 432 |    def divide(x, y): | 
 | 433 |        return x/y | 
 | 434 |  | 
 | 435 |    # A simple server with simple arithmetic functions | 
 | 436 |    server = SimpleXMLRPCServer(("localhost", 8000)) | 
| Georg Brandl | f694518 | 2008-02-01 11:56:49 +0000 | [diff] [blame] | 437 |    print("Listening on port 8000...") | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 438 |    server.register_multicall_functions() | 
 | 439 |    server.register_function(add, 'add') | 
 | 440 |    server.register_function(subtract, 'subtract') | 
 | 441 |    server.register_function(multiply, 'multiply') | 
 | 442 |    server.register_function(divide, 'divide') | 
 | 443 |    server.serve_forever() | 
 | 444 |  | 
 | 445 | The client code for the preceding server:: | 
 | 446 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 447 |    import xmlrpc.client | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 448 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 449 |    proxy = xmlrpc.client.ServerProxy("http://localhost:8000/") | 
 | 450 |    multicall = xmlrpc.client.MultiCall(proxy) | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 451 |    multicall.add(7,3) | 
 | 452 |    multicall.subtract(7,3) | 
 | 453 |    multicall.multiply(7,3) | 
 | 454 |    multicall.divide(7,3) | 
 | 455 |    result = multicall() | 
 | 456 |  | 
| Georg Brandl | f694518 | 2008-02-01 11:56:49 +0000 | [diff] [blame] | 457 |    print("7+3=%d, 7-3=%d, 7*3=%d, 7/3=%d" % tuple(result)) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 458 |  | 
 | 459 |  | 
 | 460 | Convenience Functions | 
 | 461 | --------------------- | 
 | 462 |  | 
| Georg Brandl | 7f01a13 | 2009-09-16 15:58:14 +0000 | [diff] [blame] | 463 | .. function:: dumps(params, methodname=None, methodresponse=None, encoding=None, allow_none=False) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 464 |  | 
 | 465 |    Convert *params* into an XML-RPC request. or into a response if *methodresponse* | 
 | 466 |    is true. *params* can be either a tuple of arguments or an instance of the | 
 | 467 |    :exc:`Fault` exception class.  If *methodresponse* is true, only a single value | 
 | 468 |    can be returned, meaning that *params* must be of length 1. *encoding*, if | 
 | 469 |    supplied, is the encoding to use in the generated XML; the default is UTF-8. | 
 | 470 |    Python's :const:`None` value cannot be used in standard XML-RPC; to allow using | 
 | 471 |    it via an extension,  provide a true value for *allow_none*. | 
 | 472 |  | 
 | 473 |  | 
| Georg Brandl | 7f01a13 | 2009-09-16 15:58:14 +0000 | [diff] [blame] | 474 | .. function:: loads(data, use_datetime=False) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 475 |  | 
 | 476 |    Convert an XML-RPC request or response into Python objects, a ``(params, | 
 | 477 |    methodname)``.  *params* is a tuple of argument; *methodname* is a string, or | 
 | 478 |    ``None`` if no method name is present in the packet. If the XML-RPC packet | 
 | 479 |    represents a fault condition, this function will raise a :exc:`Fault` exception. | 
 | 480 |    The *use_datetime* flag can be used to cause date/time values to be presented as | 
| Christian Heimes | 05e8be1 | 2008-02-23 18:30:17 +0000 | [diff] [blame] | 481 |    :class:`datetime.datetime` objects; this is false by default. | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 482 |  | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 483 |  | 
 | 484 | .. _xmlrpc-client-example: | 
 | 485 |  | 
 | 486 | Example of Client Usage | 
 | 487 | ----------------------- | 
 | 488 |  | 
 | 489 | :: | 
 | 490 |  | 
 | 491 |    # simple test program (from the XML-RPC specification) | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 492 |    from xmlrpc.client import ServerProxy, Error | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 493 |  | 
 | 494 |    # server = ServerProxy("http://localhost:8000") # local server | 
 | 495 |    server = ServerProxy("http://betty.userland.com") | 
 | 496 |  | 
| Collin Winter | c79461b | 2007-09-01 23:34:30 +0000 | [diff] [blame] | 497 |    print(server) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 498 |  | 
 | 499 |    try: | 
| Collin Winter | c79461b | 2007-09-01 23:34:30 +0000 | [diff] [blame] | 500 |        print(server.examples.getStateName(41)) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 501 |    except Error as v: | 
| Collin Winter | c79461b | 2007-09-01 23:34:30 +0000 | [diff] [blame] | 502 |        print("ERROR", v) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 503 |  | 
 | 504 | To access an XML-RPC server through a proxy, you need to define  a custom | 
| Christian Heimes | 5b5e81c | 2007-12-31 16:14:33 +0000 | [diff] [blame] | 505 | transport.  The following example shows how: | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 506 |  | 
| Christian Heimes | 5b5e81c | 2007-12-31 16:14:33 +0000 | [diff] [blame] | 507 | .. Example taken from http://lowlife.jp/nobonobo/wiki/xmlrpcwithproxy.html | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 508 |  | 
 | 509 | :: | 
 | 510 |  | 
| Georg Brandl | 2442015 | 2008-05-26 16:32:26 +0000 | [diff] [blame] | 511 |    import xmlrpc.client, http.client | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 512 |  | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 513 |    class ProxiedTransport(xmlrpc.client.Transport): | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 514 |        def set_proxy(self, proxy): | 
 | 515 |            self.proxy = proxy | 
 | 516 |        def make_connection(self, host): | 
 | 517 |            self.realhost = host | 
| Georg Brandl | 06788c9 | 2009-01-03 21:31:47 +0000 | [diff] [blame] | 518 |            h = http.client.HTTP(self.proxy) | 
 | 519 |            return h | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 520 |        def send_request(self, connection, handler, request_body): | 
 | 521 |            connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler)) | 
 | 522 |        def send_host(self, connection, host): | 
 | 523 |            connection.putheader('Host', self.realhost) | 
 | 524 |  | 
 | 525 |    p = ProxiedTransport() | 
 | 526 |    p.set_proxy('proxy-server:8080') | 
| Georg Brandl | 38eceaa | 2008-05-26 11:14:17 +0000 | [diff] [blame] | 527 |    server = xmlrpc.client.Server('http://time.xmlrpc.com/RPC2', transport=p) | 
| Collin Winter | c79461b | 2007-09-01 23:34:30 +0000 | [diff] [blame] | 528 |    print(server.currentTime.getCurrentTime()) | 
| Georg Brandl | 116aa62 | 2007-08-15 14:28:22 +0000 | [diff] [blame] | 529 |  | 
| Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 530 |  | 
 | 531 | Example of Client and Server Usage | 
 | 532 | ---------------------------------- | 
 | 533 |  | 
 | 534 | See :ref:`simplexmlrpcserver-example`. | 
 | 535 |  | 
 | 536 |  | 
| Sandro Tosi | 9daf98d | 2011-08-20 17:05:56 +0200 | [diff] [blame] | 537 | .. rubric:: Footnotes | 
 | 538 |  | 
 | 539 | .. [#] This approach has been first presented in `a discussion on xmlrpc.com | 
 | 540 |    <http://web.archive.org/web/20060624230303/http://www.xmlrpc.com/discuss/msgReader$1208?mode=topic>`_. | 
 | 541 | .. the link now points to webarchive since the one at | 
 | 542 | .. http://www.xmlrpc.com/discuss/msgReader%241208 is broken (and webadmin | 
 | 543 | .. doesn't reply) |