cinap_lenrekadd hg and python4bb9e2215 years agoHistory
1488 lines · 45.4 KB · Python
RawDownload
## XML-RPC CLIENT LIBRARY# $Id: xmlrpclib.py 41594 2005-12-04 19:11:17Z andrew.kuchling $## an XML-RPC client interface for Python.## the marshalling and response parser code can also be used to# implement XML-RPC servers.## Notes:# this version is designed to work with Python 2.1 or newer.## History:# 1999-01-14 fl  Created# 1999-01-15 fl  Changed dateTime to use localtime# 1999-01-16 fl  Added Binary/base64 element, default to RPC2 service# 1999-01-19 fl  Fixed array data element (from Skip Montanaro)# 1999-01-21 fl  Fixed dateTime constructor, etc.# 1999-02-02 fl  Added fault handling, handle empty sequences, etc.# 1999-02-10 fl  Fixed problem with empty responses (from Skip Montanaro)# 1999-06-20 fl  Speed improvements, pluggable parsers/transports (0.9.8)# 2000-11-28 fl  Changed boolean to check the truth value of its argument# 2001-02-24 fl  Added encoding/Unicode/SafeTransport patches# 2001-02-26 fl  Added compare support to wrappers (0.9.9/1.0b1)# 2001-03-28 fl  Make sure response tuple is a singleton# 2001-03-29 fl  Don't require empty params element (from Nicholas Riley)# 2001-06-10 fl  Folded in _xmlrpclib accelerator support (1.0b2)# 2001-08-20 fl  Base xmlrpclib.Error on built-in Exception (from Paul Prescod)# 2001-09-03 fl  Allow Transport subclass to override getparser# 2001-09-10 fl  Lazy import of urllib, cgi, xmllib (20x import speedup)# 2001-10-01 fl  Remove containers from memo cache when done with them# 2001-10-01 fl  Use faster escape method (80% dumps speedup)# 2001-10-02 fl  More dumps microtuning# 2001-10-04 fl  Make sure import expat gets a parser (from Guido van Rossum)# 2001-10-10 sm  Allow long ints to be passed as ints if they don't overflow# 2001-10-17 sm  Test for int and long overflow (allows use on 64-bit systems)# 2001-11-12 fl  Use repr() to marshal doubles (from Paul Felix)# 2002-03-17 fl  Avoid buffered read when possible (from James Rucker)# 2002-04-07 fl  Added pythondoc comments# 2002-04-16 fl  Added __str__ methods to datetime/binary wrappers# 2002-05-15 fl  Added error constants (from Andrew Kuchling)# 2002-06-27 fl  Merged with Python CVS version# 2002-10-22 fl  Added basic authentication (based on code from Phillip Eby)# 2003-01-22 sm  Add support for the bool type# 2003-02-27 gvr Remove apply calls# 2003-04-24 sm  Use cStringIO if available# 2003-04-25 ak  Add support for nil# 2003-06-15 gn  Add support for time.struct_time# 2003-07-12 gp  Correct marshalling of Faults# 2003-10-31 mvl Add multicall support# 2004-08-20 mvl Bump minimum supported Python version to 2.1## Copyright (c) 1999-2002 by Secret Labs AB.# Copyright (c) 1999-2002 by Fredrik Lundh.## info@pythonware.com# http://www.pythonware.com## --------------------------------------------------------------------# The XML-RPC client interface is## Copyright (c) 1999-2002 by Secret Labs AB# Copyright (c) 1999-2002 by Fredrik Lundh## By obtaining, using, and/or copying this software and/or its# associated documentation, you agree that you have read, understood,# and will comply with the following terms and conditions:## Permission to use, copy, modify, and distribute this software and# its associated documentation for any purpose and without fee is# hereby granted, provided that the above copyright notice appears in# all copies, and that both that copyright notice and this permission# notice appear in supporting documentation, and that the name of# Secret Labs AB or the author not be used in advertising or publicity# pertaining to distribution of the software without specific, written# prior permission.## SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE# OF THIS SOFTWARE.# -------------------------------------------------------------------- ## things to look into some day: # TODO: sort out True/False/boolean issues for Python 2.3 """An XML-RPC client interface for Python. The marshalling and response parser code can also be used toimplement XML-RPC servers. Exported exceptions:   Error          Base class for client errors  ProtocolError  Indicates an HTTP protocol error  ResponseError  Indicates a broken response package  Fault          Indicates an XML-RPC fault package Exported classes:   ServerProxy    Represents a logical connection to an XML-RPC server   MultiCall      Executor of boxcared xmlrpc requests  Boolean        boolean wrapper to generate a "boolean" XML-RPC value  DateTime       dateTime wrapper for an ISO 8601 string or time tuple or                 localtime integer value to generate a "dateTime.iso8601"                 XML-RPC value  Binary         binary data wrapper   SlowParser     Slow but safe standard parser (based on xmllib)  Marshaller     Generate an XML-RPC params chunk from a Python data structure  Unmarshaller   Unmarshal an XML-RPC response from incoming XML event message  Transport      Handles an HTTP transaction to an XML-RPC server  SafeTransport  Handles an HTTPS transaction to an XML-RPC server Exported constants:   True  False Exported functions:   boolean        Convert any Python value to an XML-RPC boolean  getparser      Create instance of the fastest available parser & attach                 to an unmarshalling object  dumps          Convert an argument tuple or a Fault instance to an XML-RPC                 request (or response, if the methodresponse option is used).  loads          Convert an XML-RPC packet to unmarshalled data plus a method                 name (None if not present).""" import re, string, time, operator from types import * # --------------------------------------------------------------------# Internal stuff try:    unicodeexcept NameError:    unicode = None # unicode support not available try:    import datetimeexcept ImportError:    datetime = None try:    _bool_is_builtin = False.__class__.__name__ == "bool"except NameError:    _bool_is_builtin = 0 def _decode(data, encoding, is8bit=re.compile("[\x80-\xff]").search):    # decode non-ascii string (if possible)    if unicode and encoding and is8bit(data):        data = unicode(data, encoding)    return data def escape(s, replace=string.replace):    s = replace(s, "&", "&amp;")    s = replace(s, "<", "&lt;")    return replace(s, ">", "&gt;",) if unicode:    def _stringify(string):        # convert to 7-bit ascii if possible        try:            return string.encode("ascii")        except UnicodeError:            return stringelse:    def _stringify(string):        return string __version__ = "1.0.1" # xmlrpc integer limitsMAXINT =  2L**31-1MININT = -2L**31 # --------------------------------------------------------------------# Error constants (from Dan Libby's specification at# http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php) # Ranges of errorsPARSE_ERROR       = -32700SERVER_ERROR      = -32600APPLICATION_ERROR = -32500SYSTEM_ERROR      = -32400TRANSPORT_ERROR   = -32300 # Specific errorsNOT_WELLFORMED_ERROR  = -32700UNSUPPORTED_ENCODING  = -32701INVALID_ENCODING_CHAR = -32702INVALID_XMLRPC        = -32600METHOD_NOT_FOUND      = -32601INVALID_METHOD_PARAMS = -32602INTERNAL_ERROR        = -32603 # --------------------------------------------------------------------# Exceptions ### Base class for all kinds of client-side errors. class Error(Exception):    """Base class for client errors."""    def __str__(self):        return repr(self) ### Indicates an HTTP-level protocol error.  This is raised by the HTTP# transport layer, if the server returns an error code other than 200# (OK).## @param url The target URL.# @param errcode The HTTP error code.# @param errmsg The HTTP error message.# @param headers The HTTP header dictionary. class ProtocolError(Error):    """Indicates an HTTP protocol error."""    def __init__(self, url, errcode, errmsg, headers):        Error.__init__(self)        self.url = url        self.errcode = errcode        self.errmsg = errmsg        self.headers = headers    def __repr__(self):        return (            "<ProtocolError for %s: %s %s>" %            (self.url, self.errcode, self.errmsg)            ) ### Indicates a broken XML-RPC response package.  This exception is# raised by the unmarshalling layer, if the XML-RPC response is# malformed. class ResponseError(Error):    """Indicates a broken response package."""    pass ### Indicates an XML-RPC fault response package.  This exception is# raised by the unmarshalling layer, if the XML-RPC response contains# a fault string.  This exception can also used as a class, to# generate a fault XML-RPC message.## @param faultCode The XML-RPC fault code.# @param faultString The XML-RPC fault string. class Fault(Error):    """Indicates an XML-RPC fault package."""    def __init__(self, faultCode, faultString, **extra):        Error.__init__(self)        self.faultCode = faultCode        self.faultString = faultString    def __repr__(self):        return (            "<Fault %s: %s>" %            (self.faultCode, repr(self.faultString))            ) # --------------------------------------------------------------------# Special values ### Wrapper for XML-RPC boolean values.  Use the xmlrpclib.True and# xmlrpclib.False constants, or the xmlrpclib.boolean() function, to# generate boolean XML-RPC values.## @param value A boolean value.  Any true value is interpreted as True,#              all other values are interpreted as False. if _bool_is_builtin:    boolean = Boolean = bool    # to avoid breaking code which references xmlrpclib.{True,False}    True, False = True, Falseelse:    class Boolean:        """Boolean-value wrapper.         Use True or False to generate a "boolean" XML-RPC value.        """         def __init__(self, value = 0):            self.value = operator.truth(value)         def encode(self, out):            out.write("<value><boolean>%d</boolean></value>\n" % self.value)         def __cmp__(self, other):            if isinstance(other, Boolean):                other = other.value            return cmp(self.value, other)         def __repr__(self):            if self.value:                return "<Boolean True at %x>" % id(self)            else:                return "<Boolean False at %x>" % id(self)         def __int__(self):            return self.value         def __nonzero__(self):            return self.value     True, False = Boolean(1), Boolean(0)     ##    # Map true or false value to XML-RPC boolean values.    #    # @def boolean(value)    # @param value A boolean value.  Any true value is mapped to True,    #              all other values are mapped to False.    # @return xmlrpclib.True or xmlrpclib.False.    # @see Boolean    # @see True    # @see False     def boolean(value, _truefalse=(False, True)):        """Convert any Python value to XML-RPC 'boolean'."""        return _truefalse[operator.truth(value)] ### Wrapper for XML-RPC DateTime values.  This converts a time value to# the format used by XML-RPC.# <p># The value can be given as a string in the format# "yyyymmddThh:mm:ss", as a 9-item time tuple (as returned by# time.localtime()), or an integer value (as returned by time.time()).# The wrapper uses time.localtime() to convert an integer to a time# tuple.## @param value The time, given as an ISO 8601 string, a time#              tuple, or a integer time value. class DateTime:    """DateTime wrapper for an ISO 8601 string or time tuple or    localtime integer value to generate 'dateTime.iso8601' XML-RPC    value.    """     def __init__(self, value=0):        if not isinstance(value, StringType):            if datetime and isinstance(value, datetime.datetime):                self.value = value.strftime("%Y%m%dT%H:%M:%S")                return            if datetime and isinstance(value, datetime.date):                self.value = value.strftime("%Y%m%dT%H:%M:%S")                return            if datetime and isinstance(value, datetime.time):                today = datetime.datetime.now().strftime("%Y%m%d")                self.value = value.strftime(today+"T%H:%M:%S")                return            if not isinstance(value, (TupleType, time.struct_time)):                if value == 0:                    value = time.time()                value = time.localtime(value)            value = time.strftime("%Y%m%dT%H:%M:%S", value)        self.value = value     def __cmp__(self, other):        if isinstance(other, DateTime):            other = other.value        return cmp(self.value, other)     ##    # Get date/time value.    #    # @return Date/time value, as an ISO 8601 string.     def __str__(self):        return self.value     def __repr__(self):        return "<DateTime %s at %x>" % (repr(self.value), id(self))     def decode(self, data):        data = str(data)        self.value = string.strip(data)     def encode(self, out):        out.write("<value><dateTime.iso8601>")        out.write(self.value)        out.write("</dateTime.iso8601></value>\n") def _datetime(data):    # decode xml element contents into a DateTime structure.    value = DateTime()    value.decode(data)    return value def _datetime_type(data):    t = time.strptime(data, "%Y%m%dT%H:%M:%S")    return datetime.datetime(*tuple(t)[:6]) ### Wrapper for binary data.  This can be used to transport any kind# of binary data over XML-RPC, using BASE64 encoding.## @param data An 8-bit string containing arbitrary data. import base64try:    import cStringIO as StringIOexcept ImportError:    import StringIO class Binary:    """Wrapper for binary data."""     def __init__(self, data=None):        self.data = data     ##    # Get buffer contents.    #    # @return Buffer contents, as an 8-bit string.     def __str__(self):        return self.data or ""     def __cmp__(self, other):        if isinstance(other, Binary):            other = other.data        return cmp(self.data, other)     def decode(self, data):        self.data = base64.decodestring(data)     def encode(self, out):        out.write("<value><base64>\n")        base64.encode(StringIO.StringIO(self.data), out)        out.write("</base64></value>\n") def _binary(data):    # decode xml element contents into a Binary structure    value = Binary()    value.decode(data)    return value WRAPPERS = (DateTime, Binary)if not _bool_is_builtin:    WRAPPERS = WRAPPERS + (Boolean,) # --------------------------------------------------------------------# XML parsers try:    # optional xmlrpclib accelerator    import _xmlrpclib    FastParser = _xmlrpclib.Parser    FastUnmarshaller = _xmlrpclib.Unmarshallerexcept (AttributeError, ImportError):    FastParser = FastUnmarshaller = None try:    import _xmlrpclib    FastMarshaller = _xmlrpclib.Marshallerexcept (AttributeError, ImportError):    FastMarshaller = None ## the SGMLOP parser is about 15x faster than Python's builtin# XML parser.  SGMLOP sources can be downloaded from:##     http://www.pythonware.com/products/xml/sgmlop.htm# try:    import sgmlop    if not hasattr(sgmlop, "XMLParser"):        raise ImportErrorexcept ImportError:    SgmlopParser = None # sgmlop accelerator not availableelse:    class SgmlopParser:        def __init__(self, target):             # setup callbacks            self.finish_starttag = target.start            self.finish_endtag = target.end            self.handle_data = target.data            self.handle_xml = target.xml             # activate parser            self.parser = sgmlop.XMLParser()            self.parser.register(self)

Lines 1–500 of 1488.