diff --git a/Lib/xmlrpclib.py b/Lib/xmlrpclib.py
index 37c9429da41..3524a45bdaa 100644
--- a/Lib/xmlrpclib.py
+++ b/Lib/xmlrpclib.py
@@ -31,6 +31,8 @@
# 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)
#
# Copyright (c) 1999-2001 by Secret Labs AB.
# Copyright (c) 1999-2001 by Fredrik Lundh.
@@ -70,24 +72,11 @@
#
# things to look into before 1.0 final:
-# TODO: unicode marshalling -DONE
-# TODO: ascii-compatible encoding support -DONE
-# TODO: safe transport -DONE (but mostly untested)
-# TODO: sgmlop memory leak -DONE
-# TODO: sgmlop xml parsing -DONE
-# TODO: support unicode method names -DONE
-# TODO: update selftest -DONE
-# TODO: add docstrings -DONE
-# TODO: clean up parser encoding (trust the parser) -DONE
-# TODO: expat support -DONE
-# TODO: _xmlrpclib accelerator support -DONE
-# TODO: use smarter/faster escape from effdom
# TODO: support basic authentication (see robin's patch)
# TODO: fix host tuple handling in the server constructor
# TODO: let transport verify schemes
# TODO: update documentation
# TODO: authentication plugins
-# TODO: memo problem (see HP's mail)
"""
An XML-RPC client interface for Python.
@@ -134,9 +123,9 @@
name (None if not present).
"""
-import re, string, time, operator
+import re, string, sys, time, operator
+
from types import *
-from cgi import escape as _escape
try:
unicode
@@ -149,6 +138,11 @@ def _decode(data, encoding, is8bit=re.compile("[\x80-\xff]").search):
data = unicode(data, encoding)
return data
+def escape(s, replace=string.replace):
+ s = replace(s, "&", "&")
+ s = replace(s, "<", "<")
+ return replace(s, ">", ">",)
+
if unicode:
def _stringify(string):
# convert to 7-bit ascii if possible
@@ -160,7 +154,7 @@ def _stringify(string):
def _stringify(string):
return string
-__version__ = "1.0b3"
+__version__ = "1.0b4"
# --------------------------------------------------------------------
# Exceptions
@@ -472,51 +466,53 @@ def dump_double(self, value):
self.write("%s\n" % value)
dispatch[FloatType] = dump_double
- def dump_string(self, value):
- self.write("%s\n" % _escape(value))
+ def dump_string(self, value, escape=escape):
+ self.write("%s\n" % escape(value))
dispatch[StringType] = dump_string
if unicode:
- def dump_unicode(self, value):
+ def dump_unicode(self, value, escape=escape):
value = value.encode(self.encoding)
- self.write("%s\n" % _escape(value))
+ self.write("%s\n" % escape(value))
dispatch[UnicodeType] = dump_unicode
- def container(self, value):
+ def opencontainer(self, value):
if value:
i = id(value)
if self.memo.has_key(i):
raise TypeError, "cannot marshal recursive data structures"
self.memo[i] = None
- def endcontainer(self, value):
+ def closecontainer(self, value):
if value:
del self.memo[id(value)]
def dump_array(self, value):
- self.container(value)
+ self.opencontainer(value)
write = self.write
+ dump = self.__dump
write("\n")
for v in value:
- self.__dump(v)
+ dump(v)
write("\n")
- self.endcontainer(value)
+ self.closecontainer(value)
dispatch[TupleType] = dump_array
dispatch[ListType] = dump_array
- def dump_struct(self, value):
- self.container(value)
+ def dump_struct(self, value, escape=escape):
+ self.opencontainer(value)
write = self.write
+ dump = self.__dump
write("\n")
for k, v in value.items():
write("\n")
if type(k) is not StringType:
raise TypeError, "dictionary key must be string"
- write("%s\n" % _escape(k))
- self.__dump(v)
+ write("%s\n" % escape(k))
+ dump(v)
write("\n")
write("\n")
- self.endcontainer(value)
+ self.closecontainer(value)
dispatch[DictType] = dump_struct
def dump_instance(self, value):
@@ -577,14 +573,14 @@ def start(self, tag, attrs):
def data(self, text):
self._data.append(text)
- def end(self, tag):
+ def end(self, tag, join=string.join):
# call the appropriate end tag handler
try:
f = self.dispatch[tag]
except KeyError:
pass # unknown tag ?
else:
- return f(self, self._data)
+ return f(self, join(self._data, ""))
#
# accelerator support
@@ -603,8 +599,7 @@ def end_dispatch(self, tag, data):
dispatch = {}
- def end_boolean(self, data, join=string.join):
- data = join(data, "")
+ def end_boolean(self, data):
if data == "0":
self.append(False)
elif data == "1":
@@ -614,19 +609,18 @@ def end_boolean(self, data, join=string.join):
self._value = 0
dispatch["boolean"] = end_boolean
- def end_int(self, data, join=string.join):
- self.append(int(join(data, "")))
+ def end_int(self, data):
+ self.append(int(data))
self._value = 0
dispatch["i4"] = end_int
dispatch["int"] = end_int
- def end_double(self, data, join=string.join):
- self.append(float(join(data, "")))
+ def end_double(self, data):
+ self.append(float(data))
self._value = 0
dispatch["double"] = end_double
- def end_string(self, data, join=string.join):
- data = join(data, "")
+ def end_string(self, data):
if self._encoding:
data = _decode(data, self._encoding)
self.append(_stringify(data))
@@ -654,16 +648,16 @@ def end_struct(self, data):
self._value = 0
dispatch["struct"] = end_struct
- def end_base64(self, data, join=string.join):
+ def end_base64(self, data):
value = Binary()
- value.decode(join(data, ""))
+ value.decode(data)
self.append(value)
self._value = 0
dispatch["base64"] = end_base64
- def end_dateTime(self, data, join=string.join):
+ def end_dateTime(self, data):
value = DateTime()
- value.decode(join(data, ""))
+ value.decode(data)
self.append(value)
dispatch["dateTime.iso8601"] = end_dateTime
@@ -682,8 +676,7 @@ def end_fault(self, data):
self._type = "fault"
dispatch["fault"] = end_fault
- def end_methodName(self, data, join=string.join):
- data = join(data, "")
+ def end_methodName(self, data):
if self._encoding:
data = _decode(data, self._encoding)
self._methodname = data