Issue #26147: xmlrpc now works with strings not encodable with used

non-UTF-8 encoding.
This commit is contained in:
Serhiy Storchaka 2016-01-20 10:41:33 +02:00
commit 5ccbf79eae
4 changed files with 30 additions and 11 deletions

View File

@ -184,19 +184,26 @@ class XMLRPCTestCase(unittest.TestCase):
self.assertRaises(TypeError, xmlrpclib.dumps, (arg1,)) self.assertRaises(TypeError, xmlrpclib.dumps, (arg1,))
def test_dump_encoding(self): def test_dump_encoding(self):
value = '\u20ac' value = {'key\u20ac\xa4':
'value\u20ac\xa4'}
strg = xmlrpclib.dumps((value,), encoding='iso-8859-15') strg = xmlrpclib.dumps((value,), encoding='iso-8859-15')
strg = "<?xml version='1.0' encoding='iso-8859-15'?>" + strg strg = "<?xml version='1.0' encoding='iso-8859-15'?>" + strg
self.assertEqual(xmlrpclib.loads(strg)[0][0], value) 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) self.assertEqual(xmlrpclib.loads(strg)[0][0], value)
strg = xmlrpclib.dumps((value,), encoding='iso-8859-15', strg = xmlrpclib.dumps((value,), encoding='iso-8859-15',
methodresponse=True) methodresponse=True)
self.assertEqual(xmlrpclib.loads(strg)[0][0], value) 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) 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): def test_dump_bytes(self):
sample = b"my dog has fleas" sample = b"my dog has fleas"
self.assertEqual(sample, xmlrpclib.Binary(sample)) 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_multicall_functions()
serv.register_function(pow) serv.register_function(pow)
serv.register_function(lambda x,y: x+y, 'add') serv.register_function(lambda x,y: x+y, 'add')
serv.register_function(lambda x: x, 'têšt')
serv.register_function(my_function) serv.register_function(my_function)
testInstance = TestInstanceClass() testInstance = TestInstanceClass()
serv.register_instance(testInstance, allow_dotted_names=True) serv.register_instance(testInstance, allow_dotted_names=True)
@ -599,7 +607,7 @@ class SimpleServerTestCase(BaseServerTestCase):
def test_client_encoding(self): def test_client_encoding(self):
start_string = '\u20ac' start_string = '\u20ac'
end_string = '\xa3' end_string = '\xa4'
try: try:
p = xmlrpclib.ServerProxy(URL, encoding='iso-8859-15') p = xmlrpclib.ServerProxy(URL, encoding='iso-8859-15')
@ -611,6 +619,16 @@ class SimpleServerTestCase(BaseServerTestCase):
# protocol error; provide additional information in test output # protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, getattr(e, "headers", ""))) 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. # [ch] The test 404 is causing lots of false alarms.
def XXXtest_404(self): def XXXtest_404(self):
# send POST with http.client, it should return 404 header and # send POST with http.client, it should return 404 header and
@ -624,7 +642,7 @@ class SimpleServerTestCase(BaseServerTestCase):
self.assertEqual(response.reason, 'Not Found') self.assertEqual(response.reason, 'Not Found')
def test_introspection1(self): 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.listMethods', 'system.methodHelp',
'system.methodSignature', 'system.multicall', 'system.methodSignature', 'system.multicall',
'Fixture']) 'Fixture'])
@ -767,7 +785,7 @@ class SimpleServerEncodingTestCase(BaseServerTestCase):
def test_server_encoding(self): def test_server_encoding(self):
start_string = '\u20ac' start_string = '\u20ac'
end_string = '\xa3' end_string = '\xa4'
try: try:
p = xmlrpclib.ServerProxy(URL) p = xmlrpclib.ServerProxy(URL)

View File

@ -955,8 +955,6 @@ def dumps(params, methodname=None, methodresponse=None, encoding=None,
# standard XML-RPC wrappings # standard XML-RPC wrappings
if methodname: if methodname:
# a method call # a method call
if not isinstance(methodname, str):
methodname = methodname.encode(encoding)
data = ( data = (
xmlheader, xmlheader,
"<methodCall>\n" "<methodCall>\n"
@ -1422,7 +1420,7 @@ class ServerProxy:
# call a method on the remote server # call a method on the remote server
request = dumps(params, methodname, encoding=self.__encoding, 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( response = self.__transport.request(
self.__host, self.__host,

View File

@ -269,7 +269,7 @@ class SimpleXMLRPCDispatcher:
encoding=self.encoding, allow_none=self.allow_none, encoding=self.encoding, allow_none=self.allow_none,
) )
return response.encode(self.encoding) return response.encode(self.encoding, 'xmlcharrefreplace')
def system_listMethods(self): def system_listMethods(self):
"""system.listMethods() => ['add', 'subtract', 'multiple'] """system.listMethods() => ['add', 'subtract', 'multiple']
@ -622,7 +622,7 @@ class MultiPathXMLRPCServer(SimpleXMLRPCServer):
response = dumps( response = dumps(
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) response = response.encode(self.encoding, 'xmlcharrefreplace')
return response return response
class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher): class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher):

View File

@ -133,6 +133,9 @@ Core and Builtins
Library 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 #25935: Garbage collector now breaks reference loops with OrderedDict.
- Issue #16620: Fixed AttributeError in msilib.Directory.glob(). - Issue #16620: Fixed AttributeError in msilib.Directory.glob().