Commit 9783b44b authored by Florent Xicluna's avatar Florent Xicluna

Merge heads

parents cd06a14d 93dfee1d
...@@ -66,15 +66,6 @@ class XMLRPCTestCase(unittest.TestCase): ...@@ -66,15 +66,6 @@ class XMLRPCTestCase(unittest.TestCase):
(newdt,), m = xmlrpclib.loads(s, use_datetime=0) (newdt,), m = xmlrpclib.loads(s, use_datetime=0)
self.assertEqual(newdt, xmlrpclib.DateTime('00010210T11:41:23')) self.assertEqual(newdt, xmlrpclib.DateTime('00010210T11:41:23'))
def test_cmp_datetime_DateTime(self):
now = datetime.datetime.now()
dt = xmlrpclib.DateTime(now.timetuple())
self.assertTrue(dt == now)
self.assertTrue(now == dt)
then = now + datetime.timedelta(seconds=4)
self.assertTrue(then >= dt)
self.assertTrue(dt < then)
def test_bug_1164912 (self): def test_bug_1164912 (self):
d = xmlrpclib.DateTime() d = xmlrpclib.DateTime()
((new_d,), dummy) = xmlrpclib.loads(xmlrpclib.dumps((d,), ((new_d,), dummy) = xmlrpclib.loads(xmlrpclib.dumps((d,),
...@@ -149,6 +140,9 @@ class XMLRPCTestCase(unittest.TestCase): ...@@ -149,6 +140,9 @@ class XMLRPCTestCase(unittest.TestCase):
('host.tld', ('host.tld',
[('Authorization', 'Basic dXNlcg==')], {})) [('Authorization', 'Basic dXNlcg==')], {}))
def test_dump_bytes(self):
self.assertRaises(TypeError, xmlrpclib.dumps, (b"my dog has fleas",))
def test_ssl_presence(self): def test_ssl_presence(self):
try: try:
import ssl import ssl
...@@ -186,7 +180,7 @@ class FaultTestCase(unittest.TestCase): ...@@ -186,7 +180,7 @@ class FaultTestCase(unittest.TestCase):
self.assertRaises(xmlrpclib.Fault, xmlrpclib.loads, s) self.assertRaises(xmlrpclib.Fault, xmlrpclib.loads, s)
def test_dotted_attribute(self): def test_dotted_attribute(self):
# this will raise AttirebuteError because code don't want us to use # this will raise AttributeError because code don't want us to use
# private methods # private methods
self.assertRaises(AttributeError, self.assertRaises(AttributeError,
xmlrpc.server.resolve_dotted_attribute, str, '__add') xmlrpc.server.resolve_dotted_attribute, str, '__add')
...@@ -233,6 +227,45 @@ class DateTimeTestCase(unittest.TestCase): ...@@ -233,6 +227,45 @@ class DateTimeTestCase(unittest.TestCase):
t2 = xmlrpclib._datetime(d) t2 = xmlrpclib._datetime(d)
self.assertEqual(t1, tref) self.assertEqual(t1, tref)
def test_comparison(self):
now = datetime.datetime.now()
dtime = xmlrpclib.DateTime(now.timetuple())
# datetime vs. DateTime
self.assertTrue(dtime == now)
self.assertTrue(now == dtime)
then = now + datetime.timedelta(seconds=4)
self.assertTrue(then >= dtime)
self.assertTrue(dtime < then)
# str vs. DateTime
dstr = now.strftime("%Y%m%dT%H:%M:%S")
self.assertTrue(dtime == dstr)
self.assertTrue(dstr == dtime)
dtime_then = xmlrpclib.DateTime(then.timetuple())
self.assertTrue(dtime_then >= dstr)
self.assertTrue(dstr < dtime_then)
# some other types
dbytes = dstr.encode('ascii')
dtuple = now.timetuple()
with self.assertRaises(TypeError):
dtime == 1970
with self.assertRaises(TypeError):
dtime != dbytes
with self.assertRaises(TypeError):
dtime == bytearray(dbytes)
with self.assertRaises(TypeError):
dtime != dtuple
with self.assertRaises(TypeError):
dtime < float(1970)
with self.assertRaises(TypeError):
dtime > dbytes
with self.assertRaises(TypeError):
dtime <= bytearray(dbytes)
with self.assertRaises(TypeError):
dtime >= dtuple
class BinaryTestCase(unittest.TestCase): class BinaryTestCase(unittest.TestCase):
# XXX What should str(Binary(b"\xff")) return? I'm chosing "\xff" # XXX What should str(Binary(b"\xff")) return? I'm chosing "\xff"
...@@ -346,6 +379,10 @@ def http_multi_server(evt, numrequests, requestHandler=None): ...@@ -346,6 +379,10 @@ def http_multi_server(evt, numrequests, requestHandler=None):
class MyRequestHandler(requestHandler): class MyRequestHandler(requestHandler):
rpc_paths = [] rpc_paths = []
class BrokenDispatcher:
def _marshaled_dispatch(self, data, dispatch_method=None, path=None):
raise RuntimeError("broken dispatcher")
serv = MyXMLRPCServer(("localhost", 0), MyRequestHandler, serv = MyXMLRPCServer(("localhost", 0), MyRequestHandler,
logRequests=False, bind_and_activate=False) logRequests=False, bind_and_activate=False)
serv.socket.settimeout(3) serv.socket.settimeout(3)
...@@ -366,6 +403,7 @@ def http_multi_server(evt, numrequests, requestHandler=None): ...@@ -366,6 +403,7 @@ def http_multi_server(evt, numrequests, requestHandler=None):
d.register_multicall_functions() d.register_multicall_functions()
serv.get_dispatcher(paths[0]).register_function(pow) serv.get_dispatcher(paths[0]).register_function(pow)
serv.get_dispatcher(paths[1]).register_function(lambda x,y: x+y, 'add') serv.get_dispatcher(paths[1]).register_function(lambda x,y: x+y, 'add')
serv.add_dispatcher("/is/broken", BrokenDispatcher())
evt.set() evt.set()
# handle up to 'numrequests' requests # handle up to 'numrequests' requests
...@@ -595,11 +633,16 @@ class MultiPathServerTestCase(BaseServerTestCase): ...@@ -595,11 +633,16 @@ class MultiPathServerTestCase(BaseServerTestCase):
p = xmlrpclib.ServerProxy(URL+"/foo") p = xmlrpclib.ServerProxy(URL+"/foo")
self.assertEqual(p.pow(6,8), 6**8) self.assertEqual(p.pow(6,8), 6**8)
self.assertRaises(xmlrpclib.Fault, p.add, 6, 8) self.assertRaises(xmlrpclib.Fault, p.add, 6, 8)
def test_path2(self): def test_path2(self):
p = xmlrpclib.ServerProxy(URL+"/foo/bar") p = xmlrpclib.ServerProxy(URL+"/foo/bar")
self.assertEqual(p.add(6,8), 6+8) self.assertEqual(p.add(6,8), 6+8)
self.assertRaises(xmlrpclib.Fault, p.pow, 6, 8) self.assertRaises(xmlrpclib.Fault, p.pow, 6, 8)
def test_path3(self):
p = xmlrpclib.ServerProxy(URL+"/is/broken")
self.assertRaises(xmlrpclib.Fault, p.add, 6, 8)
#A test case that verifies that a server using the HTTP/1.1 keep-alive mechanism #A test case that verifies that a server using the HTTP/1.1 keep-alive mechanism
#does indeed serve subsequent requests on the same connection #does indeed serve subsequent requests on the same connection
class BaseKeepaliveServerTestCase(BaseServerTestCase): class BaseKeepaliveServerTestCase(BaseServerTestCase):
......
...@@ -85,11 +85,6 @@ ...@@ -85,11 +85,6 @@
# OF THIS SOFTWARE. # 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. An XML-RPC client interface for Python.
...@@ -120,8 +115,7 @@ Exported classes: ...@@ -120,8 +115,7 @@ Exported classes:
Exported constants: Exported constants:
True (none)
False
Exported functions: Exported functions:
...@@ -133,7 +127,8 @@ Exported functions: ...@@ -133,7 +127,8 @@ Exported functions:
name (None if not present). name (None if not present).
""" """
import re, time, operator import base64
import time
import http.client import http.client
from xml.parsers import expat from xml.parsers import expat
import socket import socket
...@@ -230,7 +225,7 @@ class ResponseError(Error): ...@@ -230,7 +225,7 @@ class ResponseError(Error):
## ##
# Indicates an XML-RPC fault response package. This exception is # Indicates an XML-RPC fault response package. This exception is
# raised by the unmarshalling layer, if the XML-RPC response contains # raised by the unmarshalling layer, if the XML-RPC response contains
# a fault string. This exception can also used as a class, to # a fault string. This exception can also be used as a class, to
# generate a fault XML-RPC message. # generate a fault XML-RPC message.
# #
# @param faultCode The XML-RPC fault code. # @param faultCode The XML-RPC fault code.
...@@ -243,10 +238,7 @@ class Fault(Error): ...@@ -243,10 +238,7 @@ class Fault(Error):
self.faultCode = faultCode self.faultCode = faultCode
self.faultString = faultString self.faultString = faultString
def __repr__(self): def __repr__(self):
return ( return "<Fault %s: %r>" % (self.faultCode, self.faultString)
"<Fault %s: %s>" %
(self.faultCode, repr(self.faultString))
)
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Special values # Special values
...@@ -302,7 +294,7 @@ class DateTime: ...@@ -302,7 +294,7 @@ class DateTime:
elif datetime and isinstance(other, datetime.datetime): elif datetime and isinstance(other, datetime.datetime):
s = self.value s = self.value
o = other.strftime("%Y%m%dT%H:%M:%S") o = other.strftime("%Y%m%dT%H:%M:%S")
elif isinstance(other, (str, unicode)): elif isinstance(other, str):
s = self.value s = self.value
o = other o = other
elif hasattr(other, "timetuple"): elif hasattr(other, "timetuple"):
...@@ -352,7 +344,7 @@ class DateTime: ...@@ -352,7 +344,7 @@ class DateTime:
return self.value return self.value
def __repr__(self): def __repr__(self):
return "<DateTime %s at %x>" % (repr(self.value), id(self)) return "<DateTime %r at %x>" % (self.value, id(self))
def decode(self, data): def decode(self, data):
self.value = str(data).strip() self.value = str(data).strip()
...@@ -378,9 +370,6 @@ def _datetime_type(data): ...@@ -378,9 +370,6 @@ def _datetime_type(data):
# #
# @param data An 8-bit string containing arbitrary data. # @param data An 8-bit string containing arbitrary data.
import base64
import io
class Binary: class Binary:
"""Wrapper for binary data.""" """Wrapper for binary data."""
...@@ -514,9 +503,7 @@ class Marshaller: ...@@ -514,9 +503,7 @@ class Marshaller:
f = self.dispatch[type(value)] f = self.dispatch[type(value)]
except KeyError: except KeyError:
# check if this object can be marshalled as a structure # check if this object can be marshalled as a structure
try: if not hasattr(value, '__dict__'):
value.__dict__
except:
raise TypeError("cannot marshal %s objects" % type(value)) raise TypeError("cannot marshal %s objects" % type(value))
# check if this class is a sub-class of a basic type, # check if this class is a sub-class of a basic type,
# because we don't know how to marshal these types # because we don't know how to marshal these types
...@@ -564,12 +551,6 @@ class Marshaller: ...@@ -564,12 +551,6 @@ class Marshaller:
write("</double></value>\n") write("</double></value>\n")
dispatch[float] = dump_double dispatch[float] = dump_double
def dump_string(self, value, write, escape=escape):
write("<value><string>")
write(escape(value))
write("</string></value>\n")
dispatch[bytes] = dump_string
def dump_unicode(self, value, write, escape=escape): def dump_unicode(self, value, write, escape=escape):
write("<value><string>") write("<value><string>")
write(escape(value)) write(escape(value))
...@@ -1198,7 +1179,6 @@ class Transport: ...@@ -1198,7 +1179,6 @@ class Transport:
auth, host = urllib.parse.splituser(host) auth, host = urllib.parse.splituser(host)
if auth: if auth:
import base64
auth = urllib.parse.unquote_to_bytes(auth) auth = urllib.parse.unquote_to_bytes(auth)
auth = base64.encodebytes(auth).decode("utf-8") auth = base64.encodebytes(auth).decode("utf-8")
auth = "".join(auth.split()) # get rid of whitespace auth = "".join(auth.split()) # get rid of whitespace
......
...@@ -329,7 +329,6 @@ class SimpleXMLRPCDispatcher: ...@@ -329,7 +329,6 @@ class SimpleXMLRPCDispatcher:
if method is None: if method is None:
return "" return ""
else: else:
import pydoc
return pydoc.getdoc(method) return pydoc.getdoc(method)
def system_multicall(self, call_list): def system_multicall(self, call_list):
...@@ -560,7 +559,7 @@ class SimpleXMLRPCServer(socketserver.TCPServer, ...@@ -560,7 +559,7 @@ class SimpleXMLRPCServer(socketserver.TCPServer,
Simple XML-RPC server that allows functions and a single instance Simple XML-RPC server that allows functions and a single instance
to be installed to handle requests. The default implementation to be installed to handle requests. The default implementation
attempts to dispatch XML-RPC calls to the functions or instance attempts to dispatch XML-RPC calls to the functions or instance
installed in the server. Override the _dispatch method inhereted installed in the server. Override the _dispatch method inherited
from SimpleXMLRPCDispatcher to change this behavior. from SimpleXMLRPCDispatcher to change this behavior.
""" """
...@@ -602,7 +601,7 @@ class MultiPathXMLRPCServer(SimpleXMLRPCServer): ...@@ -602,7 +601,7 @@ class MultiPathXMLRPCServer(SimpleXMLRPCServer):
encoding, bind_and_activate) encoding, bind_and_activate)
self.dispatchers = {} self.dispatchers = {}
self.allow_none = allow_none self.allow_none = allow_none
self.encoding = encoding self.encoding = encoding or 'utf-8'
def add_dispatcher(self, path, dispatcher): def add_dispatcher(self, path, dispatcher):
self.dispatchers[path] = dispatcher self.dispatchers[path] = dispatcher
...@@ -620,9 +619,10 @@ class MultiPathXMLRPCServer(SimpleXMLRPCServer): ...@@ -620,9 +619,10 @@ class MultiPathXMLRPCServer(SimpleXMLRPCServer):
# (each dispatcher should have handled their own # (each dispatcher should have handled their own
# exceptions) # exceptions)
exc_type, exc_value = sys.exc_info()[:2] exc_type, exc_value = sys.exc_info()[:2]
response = xmlrpclib.dumps( response = dumps(
xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)), Fault(1, "%s:%s" % (exc_type, exc_value)),
encoding=self.encoding, allow_none=self.allow_none) encoding=self.encoding, allow_none=self.allow_none)
response = response.encode(self.encoding)
return response return response
class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher): class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher):
......
...@@ -66,6 +66,11 @@ Core and Builtins ...@@ -66,6 +66,11 @@ Core and Builtins
Library Library
------- -------
- Issue #13293: Better error message when trying to marshal bytes using
xmlrpc.client.
- Issue #13291: NameError in xmlrpc package.
- Issue #13258: Use callable() built-in in the standard library. - Issue #13258: Use callable() built-in in the standard library.
- Issue #13273: fix a bug that prevented HTMLParser to properly detect some - Issue #13273: fix a bug that prevented HTMLParser to properly detect some
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment