diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index f9af09c72fb..d142a15b6f9 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -184,19 +184,26 @@ class XMLRPCTestCase(unittest.TestCase): self.assertRaises(TypeError, xmlrpclib.dumps, (arg1,)) def test_dump_encoding(self): - value = '\u20ac' + value = {'key\u20ac\xa4': + 'value\u20ac\xa4'} strg = xmlrpclib.dumps((value,), encoding='iso-8859-15') strg = "" + strg self.assertEqual(xmlrpclib.loads(strg)[0][0], value) - strg = strg.encode('iso-8859-15') + strg = strg.encode('iso-8859-15', 'xmlcharrefreplace') self.assertEqual(xmlrpclib.loads(strg)[0][0], value) strg = xmlrpclib.dumps((value,), encoding='iso-8859-15', methodresponse=True) self.assertEqual(xmlrpclib.loads(strg)[0][0], value) - strg = strg.encode('iso-8859-15') + strg = strg.encode('iso-8859-15', 'xmlcharrefreplace') self.assertEqual(xmlrpclib.loads(strg)[0][0], value) + methodname = 'method\u20ac\xa4' + strg = xmlrpclib.dumps((value,), encoding='iso-8859-15', + methodname=methodname) + self.assertEqual(xmlrpclib.loads(strg)[0][0], value) + self.assertEqual(xmlrpclib.loads(strg)[1], methodname) + def test_dump_bytes(self): sample = b"my dog has fleas" self.assertEqual(sample, xmlrpclib.Binary(sample)) @@ -430,6 +437,7 @@ def http_server(evt, numrequests, requestHandler=None, encoding=None): serv.register_multicall_functions() serv.register_function(pow) serv.register_function(lambda x,y: x+y, 'add') + serv.register_function(lambda x: x, 'têšt') serv.register_function(my_function) testInstance = TestInstanceClass() serv.register_instance(testInstance, allow_dotted_names=True) @@ -599,7 +607,7 @@ class SimpleServerTestCase(BaseServerTestCase): def test_client_encoding(self): start_string = '\u20ac' - end_string = '\xa3' + end_string = '\xa4' try: p = xmlrpclib.ServerProxy(URL, encoding='iso-8859-15') @@ -611,6 +619,16 @@ class SimpleServerTestCase(BaseServerTestCase): # protocol error; provide additional information in test output self.fail("%s\n%s" % (e, getattr(e, "headers", ""))) + def test_nonascii_methodname(self): + try: + p = xmlrpclib.ServerProxy(URL, encoding='ascii') + self.assertEqual(p.têšt(42), 42) + except (xmlrpclib.ProtocolError, socket.error) as e: + # ignore failures due to non-blocking socket unavailable errors. + if not is_unavailable_exception(e): + # protocol error; provide additional information in test output + self.fail("%s\n%s" % (e, getattr(e, "headers", ""))) + # [ch] The test 404 is causing lots of false alarms. def XXXtest_404(self): # send POST with http.client, it should return 404 header and @@ -624,7 +642,7 @@ class SimpleServerTestCase(BaseServerTestCase): self.assertEqual(response.reason, 'Not Found') def test_introspection1(self): - expected_methods = set(['pow', 'div', 'my_function', 'add', + expected_methods = set(['pow', 'div', 'my_function', 'add', 'têšt', 'system.listMethods', 'system.methodHelp', 'system.methodSignature', 'system.multicall', 'Fixture']) @@ -767,7 +785,7 @@ class SimpleServerEncodingTestCase(BaseServerTestCase): def test_server_encoding(self): start_string = '\u20ac' - end_string = '\xa3' + end_string = '\xa4' try: p = xmlrpclib.ServerProxy(URL) diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py index 25e684f05ba..bf428358439 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -955,8 +955,6 @@ def dumps(params, methodname=None, methodresponse=None, encoding=None, # standard XML-RPC wrappings if methodname: # a method call - if not isinstance(methodname, str): - methodname = methodname.encode(encoding) data = ( xmlheader, "\n" @@ -1422,7 +1420,7 @@ class ServerProxy: # call a method on the remote server request = dumps(params, methodname, encoding=self.__encoding, - allow_none=self.__allow_none).encode(self.__encoding) + allow_none=self.__allow_none).encode(self.__encoding, 'xmlcharrefreplace') response = self.__transport.request( self.__host, diff --git a/Lib/xmlrpc/server.py b/Lib/xmlrpc/server.py index 304e218c008..5b5bf7c405e 100644 --- a/Lib/xmlrpc/server.py +++ b/Lib/xmlrpc/server.py @@ -269,7 +269,7 @@ class SimpleXMLRPCDispatcher: encoding=self.encoding, allow_none=self.allow_none, ) - return response.encode(self.encoding) + return response.encode(self.encoding, 'xmlcharrefreplace') def system_listMethods(self): """system.listMethods() => ['add', 'subtract', 'multiple'] @@ -622,7 +622,7 @@ class MultiPathXMLRPCServer(SimpleXMLRPCServer): response = dumps( Fault(1, "%s:%s" % (exc_type, exc_value)), encoding=self.encoding, allow_none=self.allow_none) - response = response.encode(self.encoding) + response = response.encode(self.encoding, 'xmlcharrefreplace') return response class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher): diff --git a/Misc/NEWS b/Misc/NEWS index f44b3dde4d7..3fe9bd0d26c 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -46,6 +46,9 @@ Core and Builtins Library ------- +- Issue #26147: xmlrpc now works with strings not encodable with used + non-UTF-8 encoding. + - Issue #25935: Garbage collector now breaks reference loops with OrderedDict. - Issue #16620: Fixed AttributeError in msilib.Directory.glob().