From 3fa29f7cd77970df2d85db3e7565cf0ad2548883 Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Sun, 30 Oct 2011 20:18:50 +0100 Subject: Closes #13291: NameError in xmlrpc package. --- Lib/test/test_xmlrpc.py | 58 +++++++++++++++++++++++++++++++++++++++++-------- Lib/xmlrpc/client.py | 2 +- Lib/xmlrpc/server.py | 7 +++--- Misc/NEWS | 2 ++ 4 files changed, 56 insertions(+), 13 deletions(-) diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index 4ccc6ff..e7b048b 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -66,15 +66,6 @@ class XMLRPCTestCase(unittest.TestCase): (newdt,), m = xmlrpclib.loads(s, use_datetime=0) 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): d = xmlrpclib.DateTime() ((new_d,), dummy) = xmlrpclib.loads(xmlrpclib.dumps((d,), @@ -233,6 +224,45 @@ class DateTimeTestCase(unittest.TestCase): t2 = xmlrpclib._datetime(d) 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): # XXX What should str(Binary(b"\xff")) return? I'm chosing "\xff" @@ -346,6 +376,10 @@ def http_multi_server(evt, numrequests, requestHandler=None): class MyRequestHandler(requestHandler): rpc_paths = [] + class BrokenDispatcher: + def _marshaled_dispatch(self, data, dispatch_method=None, path=None): + raise RuntimeError("broken dispatcher") + serv = MyXMLRPCServer(("localhost", 0), MyRequestHandler, logRequests=False, bind_and_activate=False) serv.socket.settimeout(3) @@ -366,6 +400,7 @@ def http_multi_server(evt, numrequests, requestHandler=None): d.register_multicall_functions() serv.get_dispatcher(paths[0]).register_function(pow) serv.get_dispatcher(paths[1]).register_function(lambda x,y: x+y, 'add') + serv.add_dispatcher("/is/broken", BrokenDispatcher()) evt.set() # handle up to 'numrequests' requests @@ -595,11 +630,16 @@ class MultiPathServerTestCase(BaseServerTestCase): p = xmlrpclib.ServerProxy(URL+"/foo") self.assertEqual(p.pow(6,8), 6**8) self.assertRaises(xmlrpclib.Fault, p.add, 6, 8) + def test_path2(self): p = xmlrpclib.ServerProxy(URL+"/foo/bar") self.assertEqual(p.add(6,8), 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 #does indeed serve subsequent requests on the same connection class BaseKeepaliveServerTestCase(BaseServerTestCase): diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py index 19d4d69..9312344 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -302,7 +302,7 @@ class DateTime: elif datetime and isinstance(other, datetime.datetime): s = self.value o = other.strftime("%Y%m%dT%H:%M:%S") - elif isinstance(other, (str, unicode)): + elif isinstance(other, str): s = self.value o = other elif hasattr(other, "timetuple"): diff --git a/Lib/xmlrpc/server.py b/Lib/xmlrpc/server.py index ac252f1..9d93b1c7 100644 --- a/Lib/xmlrpc/server.py +++ b/Lib/xmlrpc/server.py @@ -602,7 +602,7 @@ class MultiPathXMLRPCServer(SimpleXMLRPCServer): encoding, bind_and_activate) self.dispatchers = {} self.allow_none = allow_none - self.encoding = encoding + self.encoding = encoding or 'utf-8' def add_dispatcher(self, path, dispatcher): self.dispatchers[path] = dispatcher @@ -620,9 +620,10 @@ class MultiPathXMLRPCServer(SimpleXMLRPCServer): # (each dispatcher should have handled their own # exceptions) exc_type, exc_value = sys.exc_info()[:2] - response = xmlrpclib.dumps( - xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)), + response = dumps( + Fault(1, "%s:%s" % (exc_type, exc_value)), encoding=self.encoding, allow_none=self.allow_none) + response = response.encode(self.encoding) return response class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher): diff --git a/Misc/NEWS b/Misc/NEWS index 16c808c..80c435a 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -63,6 +63,8 @@ Core and Builtins Library ------- +- Issue #13291: NameError in xmlrpc package. + - Issue #13258: Use callable() built-in in the standard library. - Issue #13273: fix a bug that prevented HTMLParser to properly detect some -- cgit v0.12 From c4fec937dcb70175fb0a0e772563a35ebba2d1c6 Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Sun, 30 Oct 2011 20:19:32 +0100 Subject: Cleanup xmlrpc: remove obsolete comments, unused imports. Add test for bytes marshalling. --- Lib/test/test_xmlrpc.py | 5 ++++- Lib/xmlrpc/client.py | 24 ++++++------------------ Lib/xmlrpc/server.py | 3 +-- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index e7b048b..e97420b 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -140,6 +140,9 @@ class XMLRPCTestCase(unittest.TestCase): ('host.tld', [('Authorization', 'Basic dXNlcg==')], {})) + def test_dump_bytes(self): + self.assertRaises(TypeError, xmlrpclib.dumps, (b"my dog has fleas",)) + def test_ssl_presence(self): try: import ssl @@ -177,7 +180,7 @@ class FaultTestCase(unittest.TestCase): self.assertRaises(xmlrpclib.Fault, xmlrpclib.loads, s) 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 self.assertRaises(AttributeError, xmlrpc.server.resolve_dotted_attribute, str, '__add') diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py index 9312344..bd59f32 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -85,11 +85,6 @@ # 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. @@ -120,8 +115,7 @@ Exported classes: Exported constants: - True - False + (none) Exported functions: @@ -133,7 +127,8 @@ Exported functions: name (None if not present). """ -import re, time, operator +import base64 +import time import http.client from xml.parsers import expat import socket @@ -230,7 +225,7 @@ class ResponseError(Error): ## # 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 +# a fault string. This exception can also be used as a class, to # generate a fault XML-RPC message. # # @param faultCode The XML-RPC fault code. @@ -243,10 +238,7 @@ class Fault(Error): self.faultCode = faultCode self.faultString = faultString def __repr__(self): - return ( - "" % - (self.faultCode, repr(self.faultString)) - ) + return "" % (self.faultCode, self.faultString) # -------------------------------------------------------------------- # Special values @@ -352,7 +344,7 @@ class DateTime: return self.value def __repr__(self): - return "" % (repr(self.value), id(self)) + return "" % (self.value, id(self)) def decode(self, data): self.value = str(data).strip() @@ -378,9 +370,6 @@ def _datetime_type(data): # # @param data An 8-bit string containing arbitrary data. -import base64 -import io - class Binary: """Wrapper for binary data.""" @@ -1198,7 +1187,6 @@ class Transport: auth, host = urllib.parse.splituser(host) if auth: - import base64 auth = urllib.parse.unquote_to_bytes(auth) auth = base64.encodebytes(auth).decode("utf-8") auth = "".join(auth.split()) # get rid of whitespace diff --git a/Lib/xmlrpc/server.py b/Lib/xmlrpc/server.py index 9d93b1c7..72f3bfc 100644 --- a/Lib/xmlrpc/server.py +++ b/Lib/xmlrpc/server.py @@ -329,7 +329,6 @@ class SimpleXMLRPCDispatcher: if method is None: return "" else: - import pydoc return pydoc.getdoc(method) def system_multicall(self, call_list): @@ -560,7 +559,7 @@ class SimpleXMLRPCServer(socketserver.TCPServer, Simple XML-RPC server that allows functions and a single instance to be installed to handle requests. The default implementation 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. """ -- cgit v0.12 From 93dfee1dfc0bf572d4d9579fd455a72c0c81f148 Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Sun, 30 Oct 2011 20:22:25 +0100 Subject: Issue #13293: Better error message when trying to marshal bytes using xmlrpc.client. --- Lib/xmlrpc/client.py | 10 +--------- Misc/NEWS | 3 +++ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py index bd59f32..97d5aac 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -503,9 +503,7 @@ class Marshaller: f = self.dispatch[type(value)] except KeyError: # check if this object can be marshalled as a structure - try: - value.__dict__ - except: + if not hasattr(value, '__dict__'): raise TypeError("cannot marshal %s objects" % type(value)) # check if this class is a sub-class of a basic type, # because we don't know how to marshal these types @@ -553,12 +551,6 @@ class Marshaller: write("\n") dispatch[float] = dump_double - def dump_string(self, value, write, escape=escape): - write("") - write(escape(value)) - write("\n") - dispatch[bytes] = dump_string - def dump_unicode(self, value, write, escape=escape): write("") write(escape(value)) diff --git a/Misc/NEWS b/Misc/NEWS index 80c435a..70572b4 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -63,6 +63,9 @@ Core and Builtins 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. -- cgit v0.12