22# XML-RPC CLIENT LIBRARY
33# $Id$
44#
5+ # an XML-RPC client interface for Python.
6+ #
7+ # the marshalling and response parser code can also be used to
8+ # implement XML-RPC servers.
9+ #
10+ # Notes:
11+ # this version is designed to work with Python 1.5.2 or newer.
12+ # unicode encoding support requires at least Python 1.6.
13+ # experimental HTTPS requires Python 2.0 built with SSL sockets.
14+ # expat parser support requires Python 2.0 with pyexpat support.
15+ #
516# History:
617# 1999-01-14 fl Created
718# 1999-01-15 fl Changed dateTime to use localtime
1829# 2001-03-29 fl Don't require empty params element (from Nicholas Riley)
1930# 2001-06-10 fl Folded in _xmlrpclib accelerator support (1.0b2)
2031# 2001-08-20 fl Base xmlrpclib.Error on built-in Exception (from Paul Prescod)
32+ # 2001-09-03 fl Allow Transport subclass to override getparser
33+ # 2001-09-10 fl Lazy import of urllib, cgi, xmllib (20x import speedup)
2134#
2235# Copyright (c) 1999-2001 by Secret Labs AB.
2336# Copyright (c) 1999-2001 by Fredrik Lundh.
8295The marshalling and response parser code can also be used to
8396implement XML-RPC servers.
8497
85- Notes:
86- This version is designed to work with Python 1.5.2 or newer.
87- Unicode encoding support requires at least Python 1.6.
88- Experimental HTTPS requires Python 2.0 built with SSL sockets.
89- Expat parser support requires Python 2.0 with pyexpat support.
90-
9198Exported exceptions:
9299
93- Error Base class for client errors
94- ProtocolError Indicates an HTTP protocol error
95- ResponseError Indicates a broken response package
96- Fault Indicates a XML-RPC fault package
100+ Error Base class for client errors
101+ ProtocolError Indicates an HTTP protocol error
102+ ResponseError Indicates a broken response package
103+ Fault Indicates an XML-RPC fault package
97104
98105Exported classes:
99106
100- Boolean boolean wrapper to generate a "boolean" XML-RPC value
101- DateTime dateTime wrapper for an ISO 8601 string or time tuple or
102- localtime integer value to generate a "dateTime.iso8601"
103- XML-RPC value
104- Binary binary data wrapper
107+ ServerProxy Represents a logical connection to an XML-RPC server
105108
106- SlowParser Slow but safe standard parser
107- Marshaller Generate an XML-RPC params chunk from a Python data structure
108- Unmarshaller Unmarshal an XML-RPC response from incoming XML event message
109+ Boolean boolean wrapper to generate a "boolean" XML-RPC value
110+ DateTime dateTime wrapper for an ISO 8601 string or time tuple or
111+ localtime integer value to generate a "dateTime.iso8601"
112+ XML-RPC value
113+ Binary binary data wrapper
109114
110- Transport Handles an HTTP transaction to an XML-RPC server
111- SafeTransport Handles an HTTPS transaction to an XML-RPC server
112- ServerProxy Connect to a server through a proxy
113- Server Same as ServerProxy
115+ SlowParser Slow but safe standard parser (based on xmllib)
116+ Marshaller Generate an XML-RPC params chunk from a Python data structure
117+ Unmarshaller Unmarshal an XML-RPC response from incoming XML event message
118+ Transport Handles an HTTP transaction to an XML-RPC server
119+ SafeTransport Handles an HTTPS transaction to an XML-RPC server
114120
115121Exported constants:
116122
117- True
118- False
123+ True
124+ False
119125
120126Exported functions:
121127
122- boolean Convert any Python value to an XML-RPC boolean
123- datetime Convert value to an XML-RPC datetime
124- binary Convert value to an XML-RPC binary value
125- getparser Create instance of the fastest available parser & attach
126- to an unmarshalling object
127- dumps Convert an argument tuple or a Fault instance to an XML-RPC
128- request (or response, if the methodresponse option is used).
129- loads Convert an XML-RPC packet to unmarshalled data plus a method
130- name (None if not present).
131-
128+ boolean Convert any Python value to an XML-RPC boolean
129+ getparser Create instance of the fastest available parser & attach
130+ to an unmarshalling object
131+ dumps Convert an argument tuple or a Fault instance to an XML-RPC
132+ request (or response, if the methodresponse option is used).
133+ loads Convert an XML-RPC packet to unmarshalled data plus a method
134+ name (None if not present).
132135"""
133136
134137import re , string , time , operator
135- import urllib , xmllib
136138from types import *
137- from cgi import escape
138139
139140try :
140141 unicode
@@ -181,24 +182,23 @@ def __repr__(self):
181182 )
182183
183184class ResponseError (Error ):
184- """Indicates a broken response package"""
185+ """Indicates a broken response package. """
185186 pass
186187
187188class Fault (Error ):
188- """indicates a XML-RPC fault package"""
189+ """Indicates an XML-RPC fault package. """
189190 def __init__ (self , faultCode , faultString , ** extra ):
190191 self .faultCode = faultCode
191192 self .faultString = faultString
192193 def __repr__ (self ):
193194 return (
194195 "<Fault %s: %s>" %
195- (self .faultCode , repr (self .faultString ))
196+ (repr ( self .faultCode ) , repr (self .faultString ))
196197 )
197198
198199# --------------------------------------------------------------------
199200# Special values
200201
201-
202202class Boolean :
203203 """Boolean-value wrapper.
204204
@@ -231,18 +231,14 @@ def __nonzero__(self):
231231True , False = Boolean (1 ), Boolean (0 )
232232
233233def boolean (value , truefalse = (False , True )):
234- """Convert any Python value to XML-RPC boolean."""
234+ """Convert any Python value to XML-RPC ' boolean' ."""
235235 return truefalse [operator .truth (value )]
236236
237- #
238- # dateTime wrapper
239- # wrap your iso8601 string or time tuple or localtime integer value
240- # in this class to generate a "dateTime.iso8601" XML-RPC value
241-
242237class DateTime :
243- """DataTime wrapper for an ISO 8601 string or time tuple or
244- localtime integer value to generate a 'dateTime.iso8601' XML-RPC
245- value."""
238+ """DateTime wrapper for an ISO 8601 string or time tuple or
239+ localtime integer value to generate 'dateTime.iso8601' XML-RPC
240+ value.
241+ """
246242
247243 def __init__ (self , value = 0 ):
248244 if not isinstance (value , StringType ):
@@ -274,7 +270,6 @@ def datetime(data):
274270 value .decode (data )
275271 return value
276272
277-
278273class Binary :
279274 """Wrapper for binary data."""
280275
@@ -354,6 +349,7 @@ def close(self):
354349 self .parser = self .feed = None # nuke circular reference
355350
356351 def handle_proc (self , tag , attr ):
352+ import re
357353 m = re .search ("encoding\s*=\s*['\" ]([^\" ']+)[\" ']" , attr )
358354 if m :
359355 self .handle_xml (m .group (1 ), 1 )
@@ -391,13 +387,14 @@ def close(self):
391387 self ._parser .Parse ("" , 1 ) # end of data
392388 del self ._target , self ._parser # get rid of circular references
393389
394- class SlowParser (xmllib .XMLParser ):
395- """XML parser using xmllib.XMLParser.
396-
397- This is about 10 times slower than sgmlop on roundtrip testing.
398- """
399-
390+ class SlowParser :
391+ """Default XML parser (based on xmllib.XMLParser)."""
392+ # this is about 10 times slower than sgmlop, on roundtrip
393+ # testing.
400394 def __init__ (self , target ):
395+ import xmllib # lazy subclassing (!)
396+ if xmllib .XMLParser not in SlowParser .__bases__ :
397+ SlowParser .__bases__ = (xmllib .XMLParser ,)
401398 self .handle_xml = target .xml
402399 self .unknown_starttag = target .start
403400 self .handle_data = target .data
@@ -411,11 +408,11 @@ def __init__(self, target):
411408class Marshaller :
412409 """Generate an XML-RPC params chunk from a Python data structure.
413410
414- Create a marshaller instance for each set of parameters, and use
415- "dumps" method to convert your data (represented as a tuple) to a
416- XML-RPC params chunk. to write a fault response, pass a Fault
417- instance instead. You may prefer to use the "dumps" convenience
418- function for this purpose (see below) .
411+ Create a Marshaller instance for each set of parameters, and use
412+ the "dumps" method to convert your data (represented as a tuple)
413+ to an XML-RPC params chunk. To write a fault response, pass a
414+ Fault instance instead. You may prefer to use the "dumps" module
415+ function for this purpose.
419416 """
420417
421418 # by the way, if you don't understand what's going on in here,
@@ -470,12 +467,14 @@ def dump_double(self, value):
470467 dispatch [FloatType ] = dump_double
471468
472469 def dump_string (self , value ):
470+ from cgi import escape
473471 self .write ("<value><string>%s</string></value>\n " % escape (value ))
474472 dispatch [StringType ] = dump_string
475473
476474 if unicode :
477475 def dump_unicode (self , value ):
478476 value = value .encode (self .encoding )
477+ from cgi import escape
479478 self .write ("<value><string>%s</string></value>\n " % escape (value ))
480479 dispatch [UnicodeType ] = dump_unicode
481480
@@ -504,6 +503,7 @@ def dump_struct(self, value):
504503 write ("<member>\n " )
505504 if type (k ) is not StringType :
506505 raise TypeError , "dictionary key must be string"
506+ from cgi import escape
507507 write ("<name>%s</name>\n " % escape (k ))
508508 self .__dump (v )
509509 write ("</member>\n " )
@@ -521,7 +521,7 @@ def dump_instance(self, value):
521521
522522class Unmarshaller :
523523 """Unmarshal an XML-RPC response, based on incoming XML event
524- messages (start, data, end). Call close() to get the resulting
524+ messages (start, data, end). Call close to get the resulting
525525 data structure.
526526
527527 Note that this reader is fairly tolerant, and gladly accepts
@@ -802,7 +802,7 @@ def __call__(self, *args):
802802
803803
804804class Transport :
805- """Handles an HTTP transaction to an XML-RPC server"""
805+ """Handles an HTTP transaction to an XML-RPC server. """
806806
807807 # client identifier (may be overridden)
808808 user_agent = "xmlrpclib.py/%s (by www.pythonware.com)" % __version__
@@ -832,6 +832,10 @@ def request(self, host, handler, request_body, verbose=0):
832832
833833 return self .parse_response (h .getfile ())
834834
835+ def getparser (self ):
836+ # get parser and unmarshaller
837+ return getparser ()
838+
835839 def make_connection (self , host ):
836840 # create a HTTP connection object from a host descriptor
837841 import httplib
@@ -856,7 +860,7 @@ def send_content(self, connection, request_body):
856860 def parse_response (self , f ):
857861 # read response from input file, and parse it
858862
859- p , u = getparser ()
863+ p , u = self . getparser ()
860864
861865 while 1 :
862866 response = f .read (1024 )
@@ -872,7 +876,7 @@ def parse_response(self, f):
872876 return u .close ()
873877
874878class SafeTransport (Transport ):
875- """Handles an HTTPS transaction to an XML-RPC server"""
879+ """Handles an HTTPS transaction to an XML-RPC server. """
876880
877881 def make_connection (self , host ):
878882 # create a HTTPS connection object from a host descriptor
@@ -921,6 +925,7 @@ def __init__(self, uri, transport=None, encoding=None, verbose=0):
921925 # establish a "logical" server connection
922926
923927 # get the url
928+ import urllib
924929 type , uri = urllib .splittype (uri )
925930 if type not in ("http" , "https" ):
926931 raise IOError , "unsupported XML-RPC protocol"
0 commit comments