ยปCore Development>Code coverage>Lib/xmlrpclib.py

Python code coverage for Lib/xmlrpclib.py

#countcontent
1n/a#
2n/a# XML-RPC CLIENT LIBRARY
3n/a# $Id: xmlrpclib.py 74543 2009-08-24 11:39:31Z kristjan.jonsson $
4n/a#
5n/a# an XML-RPC client interface for Python.
6n/a#
7n/a# the marshalling and response parser code can also be used to
8n/a# implement XML-RPC servers.
9n/a#
10n/a# Notes:
11n/a# this version is designed to work with Python 2.1 or newer.
12n/a#
13n/a# History:
14n/a# 1999-01-14 fl Created
15n/a# 1999-01-15 fl Changed dateTime to use localtime
16n/a# 1999-01-16 fl Added Binary/base64 element, default to RPC2 service
17n/a# 1999-01-19 fl Fixed array data element (from Skip Montanaro)
18n/a# 1999-01-21 fl Fixed dateTime constructor, etc.
19n/a# 1999-02-02 fl Added fault handling, handle empty sequences, etc.
20n/a# 1999-02-10 fl Fixed problem with empty responses (from Skip Montanaro)
21n/a# 1999-06-20 fl Speed improvements, pluggable parsers/transports (0.9.8)
22n/a# 2000-11-28 fl Changed boolean to check the truth value of its argument
23n/a# 2001-02-24 fl Added encoding/Unicode/SafeTransport patches
24n/a# 2001-02-26 fl Added compare support to wrappers (0.9.9/1.0b1)
25n/a# 2001-03-28 fl Make sure response tuple is a singleton
26n/a# 2001-03-29 fl Don't require empty params element (from Nicholas Riley)
27n/a# 2001-06-10 fl Folded in _xmlrpclib accelerator support (1.0b2)
28n/a# 2001-08-20 fl Base xmlrpclib.Error on built-in Exception (from Paul Prescod)
29n/a# 2001-09-03 fl Allow Transport subclass to override getparser
30n/a# 2001-09-10 fl Lazy import of urllib, cgi, xmllib (20x import speedup)
31n/a# 2001-10-01 fl Remove containers from memo cache when done with them
32n/a# 2001-10-01 fl Use faster escape method (80% dumps speedup)
33n/a# 2001-10-02 fl More dumps microtuning
34n/a# 2001-10-04 fl Make sure import expat gets a parser (from Guido van Rossum)
35n/a# 2001-10-10 sm Allow long ints to be passed as ints if they don't overflow
36n/a# 2001-10-17 sm Test for int and long overflow (allows use on 64-bit systems)
37n/a# 2001-11-12 fl Use repr() to marshal doubles (from Paul Felix)
38n/a# 2002-03-17 fl Avoid buffered read when possible (from James Rucker)
39n/a# 2002-04-07 fl Added pythondoc comments
40n/a# 2002-04-16 fl Added __str__ methods to datetime/binary wrappers
41n/a# 2002-05-15 fl Added error constants (from Andrew Kuchling)
42n/a# 2002-06-27 fl Merged with Python CVS version
43n/a# 2002-10-22 fl Added basic authentication (based on code from Phillip Eby)
44n/a# 2003-01-22 sm Add support for the bool type
45n/a# 2003-02-27 gvr Remove apply calls
46n/a# 2003-04-24 sm Use cStringIO if available
47n/a# 2003-04-25 ak Add support for nil
48n/a# 2003-06-15 gn Add support for time.struct_time
49n/a# 2003-07-12 gp Correct marshalling of Faults
50n/a# 2003-10-31 mvl Add multicall support
51n/a# 2004-08-20 mvl Bump minimum supported Python version to 2.1
52n/a#
53n/a# Copyright (c) 1999-2002 by Secret Labs AB.
54n/a# Copyright (c) 1999-2002 by Fredrik Lundh.
55n/a#
56n/a# info@pythonware.com
57n/a# http://www.pythonware.com
58n/a#
59n/a# --------------------------------------------------------------------
60n/a# The XML-RPC client interface is
61n/a#
62n/a# Copyright (c) 1999-2002 by Secret Labs AB
63n/a# Copyright (c) 1999-2002 by Fredrik Lundh
64n/a#
65n/a# By obtaining, using, and/or copying this software and/or its
66n/a# associated documentation, you agree that you have read, understood,
67n/a# and will comply with the following terms and conditions:
68n/a#
69n/a# Permission to use, copy, modify, and distribute this software and
70n/a# its associated documentation for any purpose and without fee is
71n/a# hereby granted, provided that the above copyright notice appears in
72n/a# all copies, and that both that copyright notice and this permission
73n/a# notice appear in supporting documentation, and that the name of
74n/a# Secret Labs AB or the author not be used in advertising or publicity
75n/a# pertaining to distribution of the software without specific, written
76n/a# prior permission.
77n/a#
78n/a# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
79n/a# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
80n/a# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
81n/a# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
82n/a# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
83n/a# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
84n/a# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
85n/a# OF THIS SOFTWARE.
86n/a# --------------------------------------------------------------------
87n/a
88n/a#
89n/a# things to look into some day:
90n/a
91n/a# TODO: sort out True/False/boolean issues for Python 2.3
92n/a
93n/a"""
94n/aAn XML-RPC client interface for Python.
95n/a
96n/aThe marshalling and response parser code can also be used to
97n/aimplement XML-RPC servers.
98n/a
99n/aExported exceptions:
100n/a
101n/a Error Base class for client errors
102n/a ProtocolError Indicates an HTTP protocol error
103n/a ResponseError Indicates a broken response package
104n/a Fault Indicates an XML-RPC fault package
105n/a
106n/aExported classes:
107n/a
108n/a ServerProxy Represents a logical connection to an XML-RPC server
109n/a
110n/a MultiCall Executor of boxcared xmlrpc requests
111n/a Boolean boolean wrapper to generate a "boolean" XML-RPC value
112n/a DateTime dateTime wrapper for an ISO 8601 string or time tuple or
113n/a localtime integer value to generate a "dateTime.iso8601"
114n/a XML-RPC value
115n/a Binary binary data wrapper
116n/a
117n/a SlowParser Slow but safe standard parser (based on xmllib)
118n/a Marshaller Generate an XML-RPC params chunk from a Python data structure
119n/a Unmarshaller Unmarshal an XML-RPC response from incoming XML event message
120n/a Transport Handles an HTTP transaction to an XML-RPC server
121n/a SafeTransport Handles an HTTPS transaction to an XML-RPC server
122n/a
123n/aExported constants:
124n/a
125n/a True
126n/a False
127n/a
128n/aExported functions:
129n/a
130n/a boolean Convert any Python value to an XML-RPC boolean
131n/a getparser Create instance of the fastest available parser & attach
132n/a to an unmarshalling object
133n/a dumps Convert an argument tuple or a Fault instance to an XML-RPC
134n/a request (or response, if the methodresponse option is used).
135n/a loads Convert an XML-RPC packet to unmarshalled data plus a method
136n/a name (None if not present).
1371"""
138n/a
1391import re, string, time, operator
140n/a
1411from types import *
1421import socket
1431import errno
1441import httplib
1451try:
1461 import gzip
1470except ImportError:
1480 gzip = None #python can be built without zlib/gzip support
149n/a
150n/a# --------------------------------------------------------------------
151n/a# Internal stuff
152n/a
1531try:
1541 unicode
1550except NameError:
1560 unicode = None # unicode support not available
157n/a
1581try:
1591 import datetime
1600except ImportError:
1610 datetime = None
162n/a
1631try:
1641 _bool_is_builtin = False.__class__.__name__ == "bool"
1650except NameError:
1660 _bool_is_builtin = 0
167n/a
1681def _decode(data, encoding, is8bit=re.compile("[\x80-\xff]").search):
169n/a # decode non-ascii string (if possible)
1700 if unicode and encoding and is8bit(data):
1710 data = unicode(data, encoding)
1720 return data
173n/a
1741def escape(s, replace=string.replace):
175170 s = replace(s, "&", "&")
176170 s = replace(s, "<", "&lt;")
177170 return replace(s, ">", "&gt;",)
178n/a
1791if unicode:
1801 def _stringify(string):
181n/a # convert to 7-bit ascii if possible
182223 try:
183223 return string.encode("ascii")
18410 except UnicodeError:
18510 return string
186n/aelse:
1870 def _stringify(string):
1880 return string
189n/a
1901__version__ = "1.0.1"
191n/a
192n/a# xmlrpc integer limits
1931MAXINT = 2L**31-1
1941MININT = -2L**31
195n/a
196n/a# --------------------------------------------------------------------
197n/a# Error constants (from Dan Libby's specification at
198n/a# http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php)
199n/a
200n/a# Ranges of errors
2011PARSE_ERROR = -32700
2021SERVER_ERROR = -32600
2031APPLICATION_ERROR = -32500
2041SYSTEM_ERROR = -32400
2051TRANSPORT_ERROR = -32300
206n/a
207n/a# Specific errors
2081NOT_WELLFORMED_ERROR = -32700
2091UNSUPPORTED_ENCODING = -32701
2101INVALID_ENCODING_CHAR = -32702
2111INVALID_XMLRPC = -32600
2121METHOD_NOT_FOUND = -32601
2131INVALID_METHOD_PARAMS = -32602
2141INTERNAL_ERROR = -32603
215n/a
216n/a# --------------------------------------------------------------------
217n/a# Exceptions
218n/a
219n/a##
220n/a# Base class for all kinds of client-side errors.
221n/a
2222class Error(Exception):
2231 """Base class for client errors."""
2241 def __str__(self):
2252 return repr(self)
226n/a
227n/a##
228n/a# Indicates an HTTP-level protocol error. This is raised by the HTTP
229n/a# transport layer, if the server returns an error code other than 200
230n/a# (OK).
231n/a#
232n/a# @param url The target URL.
233n/a# @param errcode The HTTP error code.
234n/a# @param errmsg The HTTP error message.
235n/a# @param headers The HTTP header dictionary.
236n/a
2372class ProtocolError(Error):
2381 """Indicates an HTTP protocol error."""
2391 def __init__(self, url, errcode, errmsg, headers):
2403 Error.__init__(self)
2413 self.url = url
2423 self.errcode = errcode
2433 self.errmsg = errmsg
2443 self.headers = headers
2451 def __repr__(self):
246n/a return (
2471 "<ProtocolError for %s: %s %s>" %
2481 (self.url, self.errcode, self.errmsg)
249n/a )
250n/a
251n/a##
252n/a# Indicates a broken XML-RPC response package. This exception is
253n/a# raised by the unmarshalling layer, if the XML-RPC response is
254n/a# malformed.
255n/a
2562class ResponseError(Error):
2571 """Indicates a broken response package."""
2581 pass
259n/a
260n/a##
261n/a# Indicates an XML-RPC fault response package. This exception is
262n/a# raised by the unmarshalling layer, if the XML-RPC response contains
263n/a# a fault string. This exception can also used as a class, to
264n/a# generate a fault XML-RPC message.
265n/a#
266n/a# @param faultCode The XML-RPC fault code.
267n/a# @param faultString The XML-RPC fault string.
268n/a
2692class Fault(Error):
2701 """Indicates an XML-RPC fault package."""
2711 def __init__(self, faultCode, faultString, **extra):
2729 Error.__init__(self)
2739 self.faultCode = faultCode
2749 self.faultString = faultString
2751 def __repr__(self):
276n/a return (
2773 "<Fault %s: %s>" %
2783 (self.faultCode, repr(self.faultString))
279n/a )
280n/a
281n/a# --------------------------------------------------------------------
282n/a# Special values
283n/a
284n/a##
285n/a# Wrapper for XML-RPC boolean values. Use the xmlrpclib.True and
286n/a# xmlrpclib.False constants, or the xmlrpclib.boolean() function, to
287n/a# generate boolean XML-RPC values.
288n/a#
289n/a# @param value A boolean value. Any true value is interpreted as True,
290n/a# all other values are interpreted as False.
291n/a
2921from sys import modules
2931mod_dict = modules[__name__].__dict__
2941if _bool_is_builtin:
2951 boolean = Boolean = bool
296n/a # to avoid breaking code which references xmlrpclib.{True,False}
2971 mod_dict['True'] = True
2981 mod_dict['False'] = False
299n/aelse:
3000 class Boolean:
301n/a """Boolean-value wrapper.
302n/a
303n/a Use True or False to generate a "boolean" XML-RPC value.
304n/a """
305n/a
3060 def __init__(self, value = 0):
3070 self.value = operator.truth(value)
308n/a
3090 def encode(self, out):
3100 out.write("<value><boolean>%d</boolean></value>\n" % self.value)
311n/a
3120 def __cmp__(self, other):
3130 if isinstance(other, Boolean):
3140 other = other.value
3150 return cmp(self.value, other)
316n/a
3170 def __repr__(self):
3180 if self.value:
3190 return "<Boolean True at %x>" % id(self)
320n/a else:
3210 return "<Boolean False at %x>" % id(self)
322n/a
3230 def __int__(self):
3240 return self.value
325n/a
3260 def __nonzero__(self):
3270 return self.value
328n/a
3290 mod_dict['True'] = Boolean(1)
3300 mod_dict['False'] = Boolean(0)
331n/a
332n/a ##
333n/a # Map true or false value to XML-RPC boolean values.
334n/a #
335n/a # @def boolean(value)
336n/a # @param value A boolean value. Any true value is mapped to True,
337n/a # all other values are mapped to False.
338n/a # @return xmlrpclib.True or xmlrpclib.False.
339n/a # @see Boolean
340n/a # @see True
341n/a # @see False
342n/a
3430 def boolean(value, _truefalse=(False, True)):
344n/a """Convert any Python value to XML-RPC 'boolean'."""
3450 return _truefalse[operator.truth(value)]
346n/a
3471del modules, mod_dict
348n/a
349n/a##
350n/a# Wrapper for XML-RPC DateTime values. This converts a time value to
351n/a# the format used by XML-RPC.
352n/a# <p>
353n/a# The value can be given as a string in the format
354n/a# "yyyymmddThh:mm:ss", as a 9-item time tuple (as returned by
355n/a# time.localtime()), or an integer value (as returned by time.time()).
356n/a# The wrapper uses time.localtime() to convert an integer to a time
357n/a# tuple.
358n/a#
359n/a# @param value The time, given as an ISO 8601 string, a time
360n/a# tuple, or a integer time value.
361n/a
3621def _strftime(value):
36326 if datetime:
36426 if isinstance(value, datetime.datetime):
3656 return "%04d%02d%02dT%02d:%02d:%02d" % (
3666 value.year, value.month, value.day,
3676 value.hour, value.minute, value.second)
368n/a
36920 if not isinstance(value, (TupleType, time.struct_time)):
37016 if value == 0:
37115 value = time.time()
37216 value = time.localtime(value)
373n/a
37420 return "%04d%02d%02dT%02d:%02d:%02d" % value[:6]
375n/a
3762class DateTime:
377n/a """DateTime wrapper for an ISO 8601 string or time tuple or
378n/a localtime integer value to generate 'dateTime.iso8601' XML-RPC
379n/a value.
3801 """
381n/a
3821 def __init__(self, value=0):
38327 if isinstance(value, StringType):
3843 self.value = value
385n/a else:
38624 self.value = _strftime(value)
387n/a
3881 def make_comparable(self, other):
38914 if isinstance(other, DateTime):
39010 s = self.value
39110 o = other.value
3924 elif datetime and isinstance(other, datetime.datetime):
3934 s = self.value
3944 o = other.strftime("%Y%m%dT%H:%M:%S")
3950 elif isinstance(other, (str, unicode)):
3960 s = self.value
3970 o = other
3980 elif hasattr(other, "timetuple"):
3990 s = self.timetuple()
4000 o = other.timetuple()
401n/a else:
4020 otype = (hasattr(other, "__class__")
4030 and other.__class__.__name__
4040 or type(other))
4050 raise TypeError("Can't compare %s and %s" %
4060 (self.__class__.__name__, otype))
40714 return s, o
408n/a
4091 def __lt__(self, other):
4101 s, o = self.make_comparable(other)
4111 return s < o
412n/a
4131 def __le__(self, other):
4141 s, o = self.make_comparable(other)
4151 return s <= o
416n/a
4171 def __gt__(self, other):
4180 s, o = self.make_comparable(other)
4190 return s > o
420n/a
4211 def __ge__(self, other):
4220 s, o = self.make_comparable(other)
4230 return s >= o
424n/a
4251 def __eq__(self, other):
42612 s, o = self.make_comparable(other)
42712 return s == o
428n/a
4291 def __ne__(self, other):
4300 s, o = self.make_comparable(other)
4310 return s != o
432n/a
4331 def timetuple(self):
4340 return time.strptime(self.value, "%Y%m%dT%H:%M:%S")
435n/a
4361 def __cmp__(self, other):
4370 s, o = self.make_comparable(other)
4380 return cmp(s, o)
439n/a
440n/a ##
441n/a # Get date/time value.
442n/a #
443n/a # @return Date/time value, as an ISO 8601 string.
444n/a
4451 def __str__(self):
4464 return self.value
447n/a
4481 def __repr__(self):
4491 return "<DateTime %s at %x>" % (repr(self.value), id(self))
450n/a
4511 def decode(self, data):
45213 data = str(data)
45313 self.value = string.strip(data)
454n/a
4551 def encode(self, out):
45611 out.write("<value><dateTime.iso8601>")
45711 out.write(self.value)
45811 out.write("</dateTime.iso8601></value>\n")
459n/a
4601def _datetime(data):
461n/a # decode xml element contents into a DateTime structure.
4621 value = DateTime()
4631 value.decode(data)
4641 return value
465n/a
4661def _datetime_type(data):
4672 t = time.strptime(data, "%Y%m%dT%H:%M:%S")
4682 return datetime.datetime(*tuple(t)[:6])
469n/a
470n/a##
471n/a# Wrapper for binary data. This can be used to transport any kind
472n/a# of binary data over XML-RPC, using BASE64 encoding.
473n/a#
474n/a# @param data An 8-bit string containing arbitrary data.
475n/a
4761import base64
4771try:
4781 import cStringIO as StringIO
4790except ImportError:
4800 import StringIO
481n/a
4822class Binary:
4831 """Wrapper for binary data."""
484n/a
4851 def __init__(self, data=None):
4867 self.data = data
487n/a
488n/a ##
489n/a # Get buffer contents.
490n/a #
491n/a # @return Buffer contents, as an 8-bit string.
492n/a
4931 def __str__(self):
4944 return self.data or ""
495n/a
4961 def __cmp__(self, other):
4972 if isinstance(other, Binary):
4982 other = other.data
4992 return cmp(self.data, other)
500n/a
5011 def decode(self, data):
5024 self.data = base64.decodestring(data)
503n/a
5041 def encode(self, out):
5053 out.write("<value><base64>\n")
5063 base64.encode(StringIO.StringIO(self.data), out)
5073 out.write("</base64></value>\n")
508n/a
5091def _binary(data):
510n/a # decode xml element contents into a Binary structure
5111 value = Binary()
5121 value.decode(data)
5131 return value
514n/a
5151WRAPPERS = (DateTime, Binary)
5161if not _bool_is_builtin:
5170 WRAPPERS = WRAPPERS + (Boolean,)
518n/a
519n/a# --------------------------------------------------------------------
520n/a# XML parsers
521n/a
5221try:
523n/a # optional xmlrpclib accelerator
5241 import _xmlrpclib
5250 FastParser = _xmlrpclib.Parser
5260 FastUnmarshaller = _xmlrpclib.Unmarshaller
5271except (AttributeError, ImportError):
5281 FastParser = FastUnmarshaller = None
529n/a
5301try:
5311 import _xmlrpclib
5320 FastMarshaller = _xmlrpclib.Marshaller
5331except (AttributeError, ImportError):
5341 FastMarshaller = None
535n/a
5361try:
5371 from xml.parsers import expat
5381 if not hasattr(expat, "ParserCreate"):
5390 raise ImportError
5400except ImportError:
5410 ExpatParser = None # expat not available
542n/aelse:
5432 class ExpatParser:
544n/a # fast expat parser for Python 2.0 and later.
5451 def __init__(self, target):
546106 self._parser = parser = expat.ParserCreate(None, None)
547106 self._target = target
548106 parser.StartElementHandler = target.start
549106 parser.EndElementHandler = target.end
550106 parser.CharacterDataHandler = target.data
551106 encoding = None
552106 if not parser.returns_unicode:
5530 encoding = "utf-8"
554106 target.xml(encoding, None)
555n/a
5561 def feed(self, data):
557106 self._parser.Parse(data, 0)
558n/a
5591 def close(self):
560106 self._parser.Parse("", 1) # end of data
561106 del self._target, self._parser # get rid of circular references
562n/a
5632class SlowParser:
5641 """Default XML parser (based on xmllib.XMLParser)."""
565n/a # this is the slowest parser.
5661 def __init__(self, target):
5670 import xmllib # lazy subclassing (!)
5680 if xmllib.XMLParser not in SlowParser.__bases__:
5690 SlowParser.__bases__ = (xmllib.XMLParser,)
5700 self.handle_xml = target.xml
5710 self.unknown_starttag = target.start
5720 self.handle_data = target.data
5730 self.handle_cdata = target.data
5740 self.unknown_endtag = target.end
5750 try:
5760 xmllib.XMLParser.__init__(self, accept_utf8=1)
5770 except TypeError:
5780 xmllib.XMLParser.__init__(self) # pre-2.0
579n/a
580n/a# --------------------------------------------------------------------
581n/a# XML-RPC marshalling and unmarshalling code
582n/a
583n/a##
584n/a# XML-RPC marshaller.
585n/a#
586n/a# @param encoding Default encoding for 8-bit strings. The default
587n/a# value is None (interpreted as UTF-8).
588n/a# @see dumps
589n/a
5902class Marshaller:
591n/a """Generate an XML-RPC params chunk from a Python data structure.
592n/a
593n/a Create a Marshaller instance for each set of parameters, and use
594n/a the "dumps" method to convert your data (represented as a tuple)
595n/a to an XML-RPC params chunk. To write a fault response, pass a
596n/a Fault instance instead. You may prefer to use the "dumps" module
597n/a function for this purpose.
5981 """
599n/a
600n/a # by the way, if you don't understand what's going on in here,
601n/a # that's perfectly ok.
602n/a
6031 def __init__(self, encoding=None, allow_none=0):
604121 self.memo = {}
605121 self.data = None
606121 self.encoding = encoding
607121 self.allow_none = allow_none
608n/a
6091 dispatch = {}
610n/a
6111 def dumps(self, values):
612120 out = []
613120 write = out.append
614120 dump = self.__dump
615120 if isinstance(values, Fault):
616n/a # fault instance
6174 write("<fault>\n")
6184 dump({'faultCode': values.faultCode,
6194 'faultString': values.faultString},
6204 write)
6214 write("</fault>\n")
622n/a else:
623n/a # parameter block
624n/a # FIXME: the xml-rpc specification allows us to leave out
625n/a # the entire <params> block if there are no parameters.
626n/a # however, changing this may break older code (including
627n/a # old versions of xmlrpclib.py), so this is better left as
628n/a # is for now. See @XMLRPC3 for more information. /F
629116 write("<params>\n")
630253 for v in values:
631146 write("<param>\n")
632146 dump(v, write)
633137 write("</param>\n")
634107 write("</params>\n")
635111 result = string.join(out, "")
636111 return result
637n/a
6381 def __dump(self, value, write):
639421 try:
640421 f = self.dispatch[type(value)]
6413 except KeyError:
642n/a # check if this object can be marshalled as a structure
6433 try:
6443 value.__dict__
6451 except:
6461 raise TypeError, "cannot marshal %s objects" % type(value)
647n/a # check if this class is a sub-class of a basic type,
648n/a # because we don't know how to marshal these types
649n/a # (e.g. a string sub-class)
6509 for type_ in type(value).__mro__:
6517 if type_ in self.dispatch.keys():
6520 raise TypeError, "cannot marshal %s objects" % type(value)
6532 f = self.dispatch[InstanceType]
654420 f(self, value, write)
655n/a
6561 def dump_nil (self, value, write):
65732 if not self.allow_none:
6581 raise TypeError, "cannot marshal None unless allow_none is enabled"
65931 write("<value><nil/></value>")
6601 dispatch[NoneType] = dump_nil
661n/a
6621 def dump_int(self, value, write):
663n/a # in case ints are > 32 bits
664111 if value > MAXINT or value < MININT:
6653 raise OverflowError, "int exceeds XML-RPC limits"
666108 write("<value><int>")
667108 write(str(value))
668108 write("</int></value>\n")
6691 dispatch[IntType] = dump_int
670n/a
6711 if _bool_is_builtin:
6721 def dump_bool(self, value, write):
6733 write("<value><boolean>")
6743 write(value and "1" or "0")
6753 write("</boolean></value>\n")
6761 dispatch[bool] = dump_bool
677n/a
6781 def dump_long(self, value, write):
6798 if value > MAXINT or value < MININT:
6803 raise OverflowError, "long int exceeds XML-RPC limits"
6815 write("<value><int>")
6825 write(str(int(value)))
6835 write("</int></value>\n")
6841 dispatch[LongType] = dump_long
685n/a
6861 def dump_double(self, value, write):
6873 write("<value><double>")
6883 write(repr(value))
6893 write("</double></value>\n")
6901 dispatch[FloatType] = dump_double
691n/a
6921 def dump_string(self, value, write, escape=escape):
693101 write("<value><string>")
694101 write(escape(value))
695101 write("</string></value>\n")
6961 dispatch[StringType] = dump_string
697n/a
6981 if unicode:
6991 def dump_unicode(self, value, write, escape=escape):
7003 value = value.encode(self.encoding)
7013 write("<value><string>")
7023 write(escape(value))
7033 write("</string></value>\n")
7041 dispatch[UnicodeType] = dump_unicode
705n/a
7061 def dump_array(self, value, write):
70794 i = id(value)
70894 if i in self.memo:
7091 raise TypeError, "cannot marshal recursive sequences"
71093 self.memo[i] = None
71193 dump = self.__dump
71293 write("<value><array><data>\n")
713295 for v in value:
714208 dump(v, write)
71587 write("</data></array></value>\n")
71687 del self.memo[i]
7171 dispatch[TupleType] = dump_array
7181 dispatch[ListType] = dump_array
719n/a
7201 def dump_struct(self, value, write, escape=escape):
72153 i = id(value)
72253 if i in self.memo:
7231 raise TypeError, "cannot marshal recursive dictionaries"
72452 self.memo[i] = None
72552 dump = self.__dump
72652 write("<value><struct>\n")
727113 for k, v in value.items():
72864 write("<member>\n")
72964 if type(k) is not StringType:
7304 if unicode and type(k) is UnicodeType:
7313 k = k.encode(self.encoding)
732n/a else:
7331 raise TypeError, "dictionary key must be string"
73463 write("<name>%s</name>\n" % escape(k))
73563 dump(v, write)
73661 write("</member>\n")
73749 write("</struct></value>\n")
73849 del self.memo[i]
7391 dispatch[DictType] = dump_struct
740n/a
7411 if datetime:
7421 def dump_datetime(self, value, write):
7432 write("<value><dateTime.iso8601>")
7442 write(_strftime(value))
7452 write("</dateTime.iso8601></value>\n")
7461 dispatch[datetime.datetime] = dump_datetime
747n/a
7481 def dump_instance(self, value, write):
749n/a # check for special wrappers
75016 if value.__class__ in WRAPPERS:
75114 self.write = write
75214 value.encode(self)
75314 del self.write
754n/a else:
755n/a # store instance attributes as a struct (really?)
7562 self.dump_struct(value.__dict__, write)
7571 dispatch[InstanceType] = dump_instance
758n/a
759n/a##
760n/a# XML-RPC unmarshaller.
761n/a#
762n/a# @see loads
763n/a
7642class Unmarshaller:
765n/a """Unmarshal an XML-RPC response, based on incoming XML event
766n/a messages (start, data, end). Call close() to get the resulting
767n/a data structure.
768n/a
769n/a Note that this reader is fairly tolerant, and gladly accepts bogus
770n/a XML-RPC data without complaining (but not bogus XML).
7711 """
772n/a
773n/a # and again, if you don't understand what's going on in here,
774n/a # that's perfectly ok.
775n/a
7761 def __init__(self, use_datetime=0):
777106 self._type = None
778106 self._stack = []
779106 self._marks = []
780106 self._data = []
781106 self._methodname = None
782106 self._encoding = "utf-8"
783106 self.append = self._stack.append
784106 self._use_datetime = use_datetime
785106 if use_datetime and not datetime:
7860 raise ValueError, "the datetime module is not available"
787n/a
7881 def close(self):
789n/a # return response tuple and target method
790106 if self._type is None or self._marks:
7910 raise ResponseError()
792106 if self._type == "fault":
7934 raise Fault(**self._stack[0])
794102 return tuple(self._stack)
795n/a
7961 def getmethodname(self):
79775 return self._methodname
798n/a
799n/a #
800n/a # event handlers
801n/a
8021 def xml(self, encoding, standalone):
803106 self._encoding = encoding
804n/a # FIXME: assert standalone == 1 ???
805n/a
8061 def start(self, tag, attrs):
807n/a # prepare to handle this element
8081151 if tag == "array" or tag == "struct":
80976 self._marks.append(len(self._stack))
8101151 self._data = []
8111151 self._value = (tag == "value")
812n/a
8131 def data(self, text):
8141382 self._data.append(text)
815n/a
8161 def end(self, tag, join=string.join):
817n/a # call the appropriate end tag handler
8181151 try:
8191151 f = self.dispatch[tag]
820296 except KeyError:
821296 pass # unknown tag ?
822n/a else:
823855 return f(self, join(self._data, ""))
824n/a
825n/a #
826n/a # accelerator support
827n/a
8281 def end_dispatch(self, tag, data):
829n/a # dispatch data
8300 try:
8310 f = self.dispatch[tag]
8320 except KeyError:
8330 pass # unknown tag ?
834n/a else:
8350 return f(self, data)
836n/a
837n/a #
838n/a # element decoders
839n/a
8401 dispatch = {}
841n/a
8421 def end_nil (self, data):
84328 self.append(None)
84428 self._value = 0
8451 dispatch["nil"] = end_nil
846n/a
8471 def end_boolean(self, data):
8483 if data == "0":
8492 self.append(False)
8501 elif data == "1":
8511 self.append(True)
852n/a else:
8530 raise TypeError, "bad boolean value"
8543 self._value = 0
8551 dispatch["boolean"] = end_boolean
856n/a
8571 def end_int(self, data):
85884 self.append(int(data))
85984 self._value = 0
8601 dispatch["i4"] = end_int
8611 dispatch["i8"] = end_int
8621 dispatch["int"] = end_int
863n/a
8641 def end_double(self, data):
8653 self.append(float(data))
8663 self._value = 0
8671 dispatch["double"] = end_double
868n/a
8691 def end_string(self, data):
870176 if self._encoding:
8710 data = _decode(data, self._encoding)
872176 self.append(_stringify(data))
873176 self._value = 0
8741 dispatch["string"] = end_string
8751 dispatch["name"] = end_string # struct keys are always strings
876n/a
8771 def end_array(self, data):
87862 mark = self._marks.pop()
879n/a # map arrays to Python lists
88062 self._stack[mark:] = [self._stack[mark:]]
88162 self._value = 0
8821 dispatch["array"] = end_array
883n/a
8841 def end_struct(self, data):
88514 mark = self._marks.pop()
886n/a # map structs to Python dictionaries
88714 dict = {}
88814 items = self._stack[mark:]
88961 for i in range(0, len(items), 2):
89047 dict[_stringify(items[i])] = items[i+1]
89114 self._stack[mark:] = [dict]
89214 self._value = 0
8931 dispatch["struct"] = end_struct
894n/a
8951 def end_base64(self, data):
8962 value = Binary()
8972 value.decode(data)
8982 self.append(value)
8992 self._value = 0
9001 dispatch["base64"] = end_base64
901n/a
9021 def end_dateTime(self, data):
90311 value = DateTime()
90411 value.decode(data)
90511 if self._use_datetime:
9062 value = _datetime_type(data)
90711 self.append(value)
9081 dispatch["dateTime.iso8601"] = end_dateTime
909n/a
9101 def end_value(self, data):
911n/a # if we stumble upon a value element with no internal
912n/a # elements, treat it as a string element
913336 if self._value:
9140 self.end_string(data)
9151 dispatch["value"] = end_value
916n/a
9171 def end_params(self, data):
918102 self._type = "params"
9191 dispatch["params"] = end_params
920n/a
9211 def end_fault(self, data):
9224 self._type = "fault"
9231 dispatch["fault"] = end_fault
924n/a
9251 def end_methodName(self, data):
92630 if self._encoding:
9270 data = _decode(data, self._encoding)
92830 self._methodname = data
92930 self._type = "methodName" # no params
9301 dispatch["methodName"] = end_methodName
931n/a
932n/a## Multicall support
933n/a#
934n/a
9352class _MultiCallMethod:
936n/a # some lesser magic to store calls made to a MultiCall object
937n/a # for batch execution
9381 def __init__(self, call_list, name):
9394 self.__call_list = call_list
9404 self.__name = name
9411 def __getattr__(self, name):
9420 return _MultiCallMethod(self.__call_list, "%s.%s" % (self.__name, name))
9431 def __call__(self, *args):
9444 self.__call_list.append((self.__name, args))
945n/a
9462class MultiCallIterator:
947n/a """Iterates over the results of a multicall. Exceptions are
9481 thrown in response to xmlrpc faults."""
949n/a
9501 def __init__(self, results):
9512 self.results = results
952n/a
9531 def __getitem__(self, i):
9544 item = self.results[i]
9553 if type(item) == type({}):
9560 raise Fault(item['faultCode'], item['faultString'])
9573 elif type(item) == type([]):
9583 return item[0]
959n/a else:
9600 raise ValueError,\
9610 "unexpected type in multicall result"
962n/a
9632class MultiCall:
964n/a """server -> a object used to boxcar method calls
965n/a
966n/a server should be a ServerProxy object.
967n/a
968n/a Methods can be added to the MultiCall using normal
969n/a method call syntax e.g.:
970n/a
971n/a multicall = MultiCall(server_proxy)
972n/a multicall.add(2,3)
973n/a multicall.get_address("Guido")
974n/a
975n/a To execute the multicall, call the MultiCall object e.g.:
976n/a
977n/a add_result, address = multicall()
9781 """
979n/a
9801 def __init__(self, server):
9812 self.__server = server
9822 self.__call_list = []
983n/a
9841 def __repr__(self):
9850 return "<MultiCall at %x>" % id(self)
986n/a
9871 __str__ = __repr__
988n/a
9891 def __getattr__(self, name):
9904 return _MultiCallMethod(self.__call_list, name)
991n/a
9921 def __call__(self):
9932 marshalled_list = []
9946 for name, args in self.__call_list:
9954 marshalled_list.append({'methodName' : name, 'params' : args})
996n/a
9972 return MultiCallIterator(self.__server.system.multicall(marshalled_list))
998n/a
999n/a# --------------------------------------------------------------------
1000n/a# convenience functions
1001n/a
1002n/a##
1003n/a# Create a parser object, and connect it to an unmarshalling instance.
1004n/a# This function picks the fastest available XML parser.
1005n/a#
1006n/a# return A (parser, unmarshaller) tuple.
1007n/a
10081def getparser(use_datetime=0):
1009n/a """getparser() -> parser, unmarshaller
1010n/a
1011n/a Create an instance of the fastest available parser, and attach it
1012n/a to an unmarshalling object. Return both objects.
1013n/a """
1014106 if use_datetime and not datetime:
10150 raise ValueError, "the datetime module is not available"
1016106 if FastParser and FastUnmarshaller:
10170 if use_datetime:
10180 mkdatetime = _datetime_type
1019n/a else:
10200 mkdatetime = _datetime
10210 target = FastUnmarshaller(True, False, _binary, mkdatetime, Fault)
10220 parser = FastParser(target)
1023n/a else:
1024106 target = Unmarshaller(use_datetime=use_datetime)
1025106 if FastParser:
10260 parser = FastParser(target)
1027106 elif ExpatParser:
1028106 parser = ExpatParser(target)
1029n/a else:
10300 parser = SlowParser(target)
1031106 return parser, target
1032n/a
1033n/a##
1034n/a# Convert a Python tuple or a Fault instance to an XML-RPC packet.
1035n/a#
1036n/a# @def dumps(params, **options)
1037n/a# @param params A tuple or Fault instance.
1038n/a# @keyparam methodname If given, create a methodCall request for
1039n/a# this method name.
1040n/a# @keyparam methodresponse If given, create a methodResponse packet.
1041n/a# If used with a tuple, the tuple must be a singleton (that is,
1042n/a# it must contain exactly one element).
1043n/a# @keyparam encoding The packet encoding.
1044n/a# @return A string containing marshalled data.
1045n/a
10461def dumps(params, methodname=None, methodresponse=None, encoding=None,
10471 allow_none=0):
1048n/a """data [,options] -> marshalled data
1049n/a
1050n/a Convert an argument tuple or a Fault instance to an XML-RPC
1051n/a request (or response, if the methodresponse option is used).
1052n/a
1053n/a In addition to the data object, the following options can be given
1054n/a as keyword arguments:
1055n/a
1056n/a methodname: the method name for a methodCall packet
1057n/a
1058n/a methodresponse: true to create a methodResponse packet.
1059n/a If this option is used with a tuple, the tuple must be
1060n/a a singleton (i.e. it can contain only one element).
1061n/a
1062n/a encoding: the packet encoding (default is UTF-8)
1063n/a
1064n/a All 8-bit strings in the data structure are assumed to use the
1065n/a packet encoding. Unicode strings are automatically converted,
1066n/a where necessary.
1067n/a """
1068n/a
1069119 assert isinstance(params, TupleType) or isinstance(params, Fault),\
10700 "argument must be tuple or Fault instance"
1071n/a
1072119 if isinstance(params, Fault):
10733 methodresponse = 1
1074116 elif methodresponse and isinstance(params, TupleType):
107529 assert len(params) == 1, "response tuple must be a singleton"
1076n/a
1077119 if not encoding:
1078119 encoding = "utf-8"
1079n/a
1080119 if FastMarshaller:
10810 m = FastMarshaller(encoding)
1082n/a else:
1083119 m = Marshaller(encoding, allow_none)
1084n/a
1085119 data = m.dumps(params)
1086n/a
1087110 if encoding != "utf-8":
10880 xmlheader = "<?xml version='1.0' encoding='%s'?>\n" % str(encoding)
1089n/a else:
1090110 xmlheader = "<?xml version='1.0'?>\n" # utf-8 is default
1091n/a
1092n/a # standard XML-RPC wrappings
1093110 if methodname:
1094n/a # a method call
109536 if not isinstance(methodname, StringType):
10960 methodname = methodname.encode(encoding)
1097n/a data = (
109836 xmlheader,
109936 "<methodCall>\n"
110036 "<methodName>", methodname, "</methodName>\n",
110136 data,
110236 "</methodCall>\n"
1103n/a )
110474 elif methodresponse:
1105n/a # a method response, or a fault structure
1106n/a data = (
110732 xmlheader,
110832 "<methodResponse>\n",
110932 data,
111032 "</methodResponse>\n"
1111n/a )
1112n/a else:
111342 return data # return as is
111468 return string.join(data, "")
1115n/a
1116n/a##
1117n/a# Convert an XML-RPC packet to a Python object. If the XML-RPC packet
1118n/a# represents a fault condition, this function raises a Fault exception.
1119n/a#
1120n/a# @param data An XML-RPC packet, given as an 8-bit string.
1121n/a# @return A tuple containing the unpacked data, and the method name
1122n/a# (None if not present).
1123n/a# @see Fault
1124n/a
11251def loads(data, use_datetime=0):
1126n/a """data -> unmarshalled data, method name
1127n/a
1128n/a Convert an XML-RPC packet to unmarshalled data plus a method
1129n/a name (None if not present).
1130n/a
1131n/a If the XML-RPC packet represents a fault condition, this function
1132n/a raises a Fault exception.
1133n/a """
113477 p, u = getparser(use_datetime=use_datetime)
113577 p.feed(data)
113677 p.close()
113777 return u.close(), u.getmethodname()
1138n/a
1139n/a##
1140n/a# Encode a string using the gzip content encoding such as specified by the
1141n/a# Content-Encoding: gzip
1142n/a# in the HTTP header, as described in RFC 1952
1143n/a#
1144n/a# @param data the unencoded data
1145n/a# @return the encoded data
1146n/a
11471def gzip_encode(data):
1148n/a """data -> gzip encoded data
1149n/a
1150n/a Encode data using the gzip content encoding as described in RFC 1952
1151n/a """
11522 if not gzip:
11530 raise NotImplementedError
11542 f = StringIO.StringIO()
11552 gzf = gzip.GzipFile(mode="wb", fileobj=f, compresslevel=1)
11562 gzf.write(data)
11572 gzf.close()
11582 encoded = f.getvalue()
11592 f.close()
11602 return encoded
1161n/a
1162n/a##
1163n/a# Decode a string using the gzip content encoding such as specified by the
1164n/a# Content-Encoding: gzip
1165n/a# in the HTTP header, as described in RFC 1952
1166n/a#
1167n/a# @param data The encoded data
1168n/a# @return the unencoded data
1169n/a# @raises ValueError if data is not correctly coded.
1170n/a
11711def gzip_decode(data):
1172n/a """gzip encoded data -> unencoded data
1173n/a
1174n/a Decode data using the gzip content encoding as described in RFC 1952
1175n/a """
11762 if not gzip:
11770 raise NotImplementedError
11782 f = StringIO.StringIO(data)
11792 gzf = gzip.GzipFile(mode="rb", fileobj=f)
11802 try:
11812 decoded = gzf.read()
11821 except IOError:
11831 raise ValueError("invalid data")
11841 f.close()
11851 gzf.close()
11861 return decoded
1187n/a
1188n/a##
1189n/a# Return a decoded file-like object for the gzip encoding
1190n/a# as described in RFC 1952.
1191n/a#
1192n/a# @param response A stream supporting a read() method
1193n/a# @return a file-like object that the decoded data can be read() from
1194n/a
11952class GzipDecodedResponse(gzip.GzipFile if gzip else object):
1196n/a """a file-like object to decode a response encoded with the gzip
1197n/a method, as described in RFC 1952.
11981 """
11991 def __init__(self, response):
1200n/a #response doesn't support tell() and read(), required by
1201n/a #GzipFile
12021 if not gzip:
12030 raise NotImplementedError
12041 self.stringio = StringIO.StringIO(response.read())
12051 gzip.GzipFile.__init__(self, mode="rb", fileobj=self.stringio)
1206n/a
12071 def close(self):
12081 gzip.GzipFile.close(self)
12091 self.stringio.close()
1210n/a
1211n/a
1212n/a# --------------------------------------------------------------------
1213n/a# request dispatcher
1214n/a
12152class _Method:
1216n/a # some magic to bind an XML-RPC method to an RPC server.
1217n/a # supports "nested" methods (e.g. examples.getStateName)
12181 def __init__(self, send, name):
121942 self.__send = send
122042 self.__name = name
12211 def __getattr__(self, name):
12226 return _Method(self.__send, "%s.%s" % (self.__name, name))
12231 def __call__(self, *args):
122436 return self.__send(self.__name, args)
1225n/a
1226n/a##
1227n/a# Standard transport class for XML-RPC over HTTP.
1228n/a# <p>
1229n/a# You can create custom transports by subclassing this method, and
1230n/a# overriding selected methods.
1231n/a
12322class Transport:
12331 """Handles an HTTP transaction to an XML-RPC server."""
1234n/a
1235n/a # client identifier (may be overridden)
12361 user_agent = "xmlrpclib.py/%s (by www.pythonware.com)" % __version__
1237n/a
1238n/a #if true, we'll request gzip encoding
12391 accept_gzip_encoding = True
1240n/a
1241n/a # if positive, encode request using gzip if it exceeds this threshold
1242n/a # note that many server will get confused, so only use it if you know
1243n/a # that they can decode such a request
12441 encode_threshold = None #None = don't encode
1245n/a
12461 def __init__(self, use_datetime=0):
124726 self._use_datetime = use_datetime
124826 self._connection = (None, None)
124926 self._extra_headers = []
1250n/a ##
1251n/a # Send a complete request, and parse the response.
1252n/a # Retry request if a cached connection has disconnected.
1253n/a #
1254n/a # @param host Target host.
1255n/a # @param handler Target PRC handler.
1256n/a # @param request_body XML-RPC request body.
1257n/a # @param verbose Debugging flag.
1258n/a # @return Parsed response.
1259n/a
12601 def request(self, host, handler, request_body, verbose=0):
1261n/a #retry request once if cached connection has gone cold
126236 for i in (0, 1):
126336 try:
126436 return self.single_request(host, handler, request_body, verbose)
12659 except socket.error, e:
12660 if i or e.errno not in (errno.ECONNRESET, errno.ECONNABORTED):
12670 raise
12689 except httplib.BadStatusLine: #close after we sent request
12690 if i:
12700 raise
1271n/a
1272n/a ##
1273n/a # Send a complete request, and parse the response.
1274n/a #
1275n/a # @param host Target host.
1276n/a # @param handler Target PRC handler.
1277n/a # @param request_body XML-RPC request body.
1278n/a # @param verbose Debugging flag.
1279n/a # @return Parsed response.
1280n/a
12811 def single_request(self, host, handler, request_body, verbose=0):
1282n/a # issue XML-RPC request
1283n/a
128436 h = self.make_connection(host)
128536 if verbose:
12860 h.set_debuglevel(1)
1287n/a
128836 try:
128936 self.send_request(h, handler, request_body)
129036 self.send_host(h, host)
129136 self.send_user_agent(h)
129236 self.send_content(h, request_body)
1293n/a
129436 response = h.getresponse(buffering=True)
129532 if response.status == 200:
129629 self.verbose = verbose
129729 return self.parse_response(response)
12986 except Fault:
12992 raise
13004 except Exception:
1301n/a # All unexpected errors leave connection in
1302n/a # a strange state, so we clear it.
13034 self.close()
13044 raise
1305n/a
1306n/a #discard any response data and raise exception
13073 if (response.getheader("content-length", 0)):
13082 response.read()
13093 raise ProtocolError(
13103 host + handler,
13113 response.status, response.reason,
13123 response.msg,
1313n/a )
1314n/a
1315n/a ##
1316n/a # Create parser.
1317n/a #
1318n/a # @return A 2-tuple containing a parser and a unmarshaller.
1319n/a
13201 def getparser(self):
1321n/a # get parser and unmarshaller
132229 return getparser(use_datetime=self._use_datetime)
1323n/a
1324n/a ##
1325n/a # Get authorization info from host parameter
1326n/a # Host may be a string, or a (host, x509-dict) tuple; if a string,
1327n/a # it is checked for a "user:pw@host" format, and a "Basic
1328n/a # Authentication" header is added if appropriate.
1329n/a #
1330n/a # @param host Host descriptor (URL or (URL, x509 info) tuple).
1331n/a # @return A 3-tuple containing (actual host, extra headers,
1332n/a # x509 info). The header and x509 fields may be None.
1333n/a
13341 def get_host_info(self, host):
1335n/a
133626 x509 = {}
133726 if isinstance(host, TupleType):
13380 host, x509 = host
1339n/a
134026 import urllib
134126 auth, host = urllib.splituser(host)
1342n/a
134326 if auth:
13440 import base64
13450 auth = base64.encodestring(urllib.unquote(auth))
13460 auth = string.join(string.split(auth), "") # get rid of whitespace
1347n/a extra_headers = [
13480 ("Authorization", "Basic " + auth)
1349n/a ]
1350n/a else:
135126 extra_headers = None
1352n/a
135326 return host, extra_headers, x509
1354n/a
1355n/a ##
1356n/a # Connect to server.
1357n/a #
1358n/a # @param host Target host.
1359n/a # @return A connection handle.
1360n/a
13611 def make_connection(self, host):
1362n/a #return an existing connection if possible. This allows
1363n/a #HTTP/1.1 keep-alive.
136436 if self._connection and host == self._connection[0]:
136510 return self._connection[1]
1366n/a
1367n/a # create a HTTP connection object from a host descriptor
136826 chost, self._extra_headers, x509 = self.get_host_info(host)
1369n/a #store the host argument along with the connection object
137026 self._connection = host, httplib.HTTPConnection(chost)
137126 return self._connection[1]
1372n/a
1373n/a ##
1374n/a # Clear any cached connection object.
1375n/a # Used in the event of socket errors.
1376n/a #
13771 def close(self):
13787 if self._connection[1]:
13796 self._connection[1].close()
13806 self._connection = (None, None)
1381n/a
1382n/a ##
1383n/a # Send request header.
1384n/a #
1385n/a # @param connection Connection handle.
1386n/a # @param handler Target RPC handler.
1387n/a # @param request_body XML-RPC body.
1388n/a
13891 def send_request(self, connection, handler, request_body):
139036 if (self.accept_gzip_encoding and gzip):
139136 connection.putrequest("POST", handler, skip_accept_encoding=True)
139236 connection.putheader("Accept-Encoding", "gzip")
1393n/a else:
13940 connection.putrequest("POST", handler)
1395n/a
1396n/a ##
1397n/a # Send host name.
1398n/a #
1399n/a # @param connection Connection handle.
1400n/a # @param host Host name.
1401n/a #
1402n/a # Note: This function doesn't actually add the "Host"
1403n/a # header anymore, it is done as part of the connection.putrequest() in
1404n/a # send_request() above.
1405n/a
14061 def send_host(self, connection, host):
140736 extra_headers = self._extra_headers
140836 if extra_headers:
14090 if isinstance(extra_headers, DictType):
14100 extra_headers = extra_headers.items()
14110 for key, value in extra_headers:
14120 connection.putheader(key, value)
1413n/a
1414n/a ##
1415n/a # Send user-agent identifier.
1416n/a #
1417n/a # @param connection Connection handle.
1418n/a
14191 def send_user_agent(self, connection):
142036 connection.putheader("User-Agent", self.user_agent)
1421n/a
1422n/a ##
1423n/a # Send request body.
1424n/a #
1425n/a # @param connection Connection handle.
1426n/a # @param request_body XML-RPC request body.
1427n/a
14281 def send_content(self, connection, request_body):
142936 connection.putheader("Content-Type", "text/xml")
1430n/a
1431n/a #optionally encode the request
143236 if (self.encode_threshold is not None and
14331 self.encode_threshold < len(request_body) and
14341 gzip):
14351 connection.putheader("Content-Encoding", "gzip")
14361 request_body = gzip_encode(request_body)
1437n/a
143836 connection.putheader("Content-Length", str(len(request_body)))
143936 connection.endheaders(request_body)
1440n/a
1441n/a ##
1442n/a # Parse response.
1443n/a #
1444n/a # @param file Stream.
1445n/a # @return Response tuple and target method.
1446n/a
14471 def parse_response(self, response):
1448n/a # read response data from httpresponse, and parse it
144929 if response.getheader("Content-Encoding", "") == "gzip":
14501 stream = GzipDecodedResponse(response)
1451n/a else:
145228 stream = response
1453n/a
145429 p, u = self.getparser()
1455n/a
145629 while 1:
145758 data = stream.read(1024)
145858 if not data:
145929 break
146029 if self.verbose:
14610 print "body:", repr(data)
146229 p.feed(data)
1463n/a
146429 if stream is not response:
14651 stream.close()
146629 p.close()
1467n/a
146829 return u.close()
1469n/a
1470n/a##
1471n/a# Standard transport class for XML-RPC over HTTPS.
1472n/a
14732class SafeTransport(Transport):
14741 """Handles an HTTPS transaction to an XML-RPC server."""
1475n/a
1476n/a # FIXME: mostly untested
1477n/a
14781 def make_connection(self, host):
14790 if self._connection and host == self._connection[0]:
14800 return self._connection[1]
1481n/a # create a HTTPS connection object from a host descriptor
1482n/a # host may be a string, or a (host, x509-dict) tuple
14830 try:
14840 HTTPS = httplib.HTTPSConnection
14850 except AttributeError:
14860 raise NotImplementedError(
14870 "your version of httplib doesn't support HTTPS"
1488n/a )
1489n/a else:
14900 chost, self._extra_headers, x509 = self.get_host_info(host)
14910 self._connection = host, HTTPS(chost, None, **(x509 or {}))
14920 return self._connection[1]
1493n/a
1494n/a##
1495n/a# Standard server proxy. This class establishes a virtual connection
1496n/a# to an XML-RPC server.
1497n/a# <p>
1498n/a# This class is available as ServerProxy and Server. New code should
1499n/a# use ServerProxy, to avoid confusion.
1500n/a#
1501n/a# @def ServerProxy(uri, **options)
1502n/a# @param uri The connection point on the server.
1503n/a# @keyparam transport A transport factory, compatible with the
1504n/a# standard transport class.
1505n/a# @keyparam encoding The default encoding used for 8-bit strings
1506n/a# (default is UTF-8).
1507n/a# @keyparam verbose Use a true value to enable debugging output.
1508n/a# (printed to standard output).
1509n/a# @see Transport
1510n/a
15112class ServerProxy:
1512n/a """uri [,options] -> a logical connection to an XML-RPC server
1513n/a
1514n/a uri is the connection point on the server, given as
1515n/a scheme://host/target.
1516n/a
1517n/a The standard implementation always supports the "http" scheme. If
1518n/a SSL socket support is available (Python 2.0), it also supports
1519n/a "https".
1520n/a
1521n/a If the target part and the slash preceding it are both omitted,
1522n/a "/RPC2" is assumed.
1523n/a
1524n/a The following options can be given as keyword arguments:
1525n/a
1526n/a transport: a transport factory
1527n/a encoding: the request encoding (default is UTF-8)
1528n/a
1529n/a All 8-bit strings passed to the server proxy are assumed to use
1530n/a the given encoding.
15311 """
1532n/a
15331 def __init__(self, uri, transport=None, encoding=None, verbose=0,
15341 allow_none=0, use_datetime=0):
1535n/a # establish a "logical" server connection
1536n/a
1537n/a # get the url
153826 import urllib
153926 type, uri = urllib.splittype(uri)
154026 if type not in ("http", "https"):
15410 raise IOError, "unsupported XML-RPC protocol"
154226 self.__host, self.__handler = urllib.splithost(uri)
154326 if not self.__handler:
154420 self.__handler = "/RPC2"
1545n/a
154626 if transport is None:
154718 if type == "https":
15480 transport = SafeTransport(use_datetime=use_datetime)
1549n/a else:
155018 transport = Transport(use_datetime=use_datetime)
155126 self.__transport = transport
1552n/a
155326 self.__encoding = encoding
155426 self.__verbose = verbose
155526 self.__allow_none = allow_none
1556n/a
15571 def __close(self):
15582 self.__transport.close()
1559n/a
15601 def __request(self, methodname, params):
1561n/a # call a method on the remote server
1562n/a
156336 request = dumps(params, methodname, encoding=self.__encoding,
156436 allow_none=self.__allow_none)
1565n/a
156636 response = self.__transport.request(
156736 self.__host,
156836 self.__handler,
156936 request,
157036 verbose=self.__verbose
1571n/a )
1572n/a
157327 if len(response) == 1:
157427 response = response[0]
1575n/a
157627 return response
1577n/a
15781 def __repr__(self):
1579n/a return (
15800 "<ServerProxy for %s%s>" %
15810 (self.__host, self.__handler)
1582n/a )
1583n/a
15841 __str__ = __repr__
1585n/a
15861 def __getattr__(self, name):
1587n/a # magic method dispatcher
158836 return _Method(self.__request, name)
1589n/a
1590n/a # note: to call a remote object with an non-standard name, use
1591n/a # result getattr(server, "strange-python-name")(args)
1592n/a
15931 def __call__(self, attr):
1594n/a """A workaround to get special attributes on the ServerProxy
1595n/a without interfering with the magic __getattr__
1596n/a """
15974 if attr == "close":
15982 return self.__close
15992 elif attr == "transport":
16002 return self.__transport
16010 raise AttributeError("Attribute %r not found" % (attr,))
1602n/a
1603n/a# compatibility
1604n/a
16051Server = ServerProxy
1606n/a
1607n/a# --------------------------------------------------------------------
1608n/a# test code
1609n/a
16101if __name__ == "__main__":
1611n/a
1612n/a # simple test program (from the XML-RPC specification)
1613n/a
1614n/a # server = ServerProxy("http://localhost:8000") # local server
16150 server = ServerProxy("http://time.xmlrpc.com/RPC2")
1616n/a
16170 print server
1618n/a
16190 try:
16200 print server.currentTime.getCurrentTime()
16210 except Error, v:
16220 print "ERROR", v
1623n/a
16240 multi = MultiCall(server)
16250 multi.currentTime.getCurrentTime()
16260 multi.currentTime.getCurrentTime()
16270 try:
16280 for response in multi():
16290 print response
16300 except Error, v:
16310 print "ERROR", v