Skip to content

Commit 1fe3547

Browse files
Issue #26147: xmlrpc now works with strings not encodable with used
non-UTF-8 encoding.
1 parent 388083b commit 1fe3547

File tree

4 files changed

+30
-11
lines changed

4 files changed

+30
-11
lines changed

Lib/test/test_xmlrpc.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,19 +184,26 @@ def test_dump_none(self):
184184
self.assertRaises(TypeError, xmlrpclib.dumps, (arg1,))
185185

186186
def test_dump_encoding(self):
187-
value = '\u20ac'
187+
value = {'key\u20ac\xa4':
188+
'value\u20ac\xa4'}
188189
strg = xmlrpclib.dumps((value,), encoding='iso-8859-15')
189190
strg = "<?xml version='1.0' encoding='iso-8859-15'?>" + strg
190191
self.assertEqual(xmlrpclib.loads(strg)[0][0], value)
191-
strg = strg.encode('iso-8859-15')
192+
strg = strg.encode('iso-8859-15', 'xmlcharrefreplace')
192193
self.assertEqual(xmlrpclib.loads(strg)[0][0], value)
193194

194195
strg = xmlrpclib.dumps((value,), encoding='iso-8859-15',
195196
methodresponse=True)
196197
self.assertEqual(xmlrpclib.loads(strg)[0][0], value)
197-
strg = strg.encode('iso-8859-15')
198+
strg = strg.encode('iso-8859-15', 'xmlcharrefreplace')
198199
self.assertEqual(xmlrpclib.loads(strg)[0][0], value)
199200

201+
methodname = 'method\u20ac\xa4'
202+
strg = xmlrpclib.dumps((value,), encoding='iso-8859-15',
203+
methodname=methodname)
204+
self.assertEqual(xmlrpclib.loads(strg)[0][0], value)
205+
self.assertEqual(xmlrpclib.loads(strg)[1], methodname)
206+
200207
def test_dump_bytes(self):
201208
sample = b"my dog has fleas"
202209
self.assertEqual(sample, xmlrpclib.Binary(sample))
@@ -430,6 +437,7 @@ def get_request(self):
430437
serv.register_multicall_functions()
431438
serv.register_function(pow)
432439
serv.register_function(lambda x,y: x+y, 'add')
440+
serv.register_function(lambda x: x, 'têšt')
433441
serv.register_function(my_function)
434442
testInstance = TestInstanceClass()
435443
serv.register_instance(testInstance, allow_dotted_names=True)
@@ -599,7 +607,7 @@ def test_nonascii(self):
599607

600608
def test_client_encoding(self):
601609
start_string = '\u20ac'
602-
end_string = '\xa3'
610+
end_string = '\xa4'
603611

604612
try:
605613
p = xmlrpclib.ServerProxy(URL, encoding='iso-8859-15')
@@ -611,6 +619,16 @@ def test_client_encoding(self):
611619
# protocol error; provide additional information in test output
612620
self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
613621

622+
def test_nonascii_methodname(self):
623+
try:
624+
p = xmlrpclib.ServerProxy(URL, encoding='ascii')
625+
self.assertEqual(p.têšt(42), 42)
626+
except (xmlrpclib.ProtocolError, socket.error) as e:
627+
# ignore failures due to non-blocking socket unavailable errors.
628+
if not is_unavailable_exception(e):
629+
# protocol error; provide additional information in test output
630+
self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
631+
614632
# [ch] The test 404 is causing lots of false alarms.
615633
def XXXtest_404(self):
616634
# send POST with http.client, it should return 404 header and
@@ -624,7 +642,7 @@ def XXXtest_404(self):
624642
self.assertEqual(response.reason, 'Not Found')
625643

626644
def test_introspection1(self):
627-
expected_methods = set(['pow', 'div', 'my_function', 'add',
645+
expected_methods = set(['pow', 'div', 'my_function', 'add', 'têšt',
628646
'system.listMethods', 'system.methodHelp',
629647
'system.methodSignature', 'system.multicall',
630648
'Fixture'])
@@ -767,7 +785,7 @@ def threadFunc(evt, numrequests, requestHandler=None, encoding=None):
767785

768786
def test_server_encoding(self):
769787
start_string = '\u20ac'
770-
end_string = '\xa3'
788+
end_string = '\xa4'
771789

772790
try:
773791
p = xmlrpclib.ServerProxy(URL)

Lib/xmlrpc/client.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -955,8 +955,6 @@ def dumps(params, methodname=None, methodresponse=None, encoding=None,
955955
# standard XML-RPC wrappings
956956
if methodname:
957957
# a method call
958-
if not isinstance(methodname, str):
959-
methodname = methodname.encode(encoding)
960958
data = (
961959
xmlheader,
962960
"<methodCall>\n"
@@ -1422,7 +1420,7 @@ def __request(self, methodname, params):
14221420
# call a method on the remote server
14231421

14241422
request = dumps(params, methodname, encoding=self.__encoding,
1425-
allow_none=self.__allow_none).encode(self.__encoding)
1423+
allow_none=self.__allow_none).encode(self.__encoding, 'xmlcharrefreplace')
14261424

14271425
response = self.__transport.request(
14281426
self.__host,

Lib/xmlrpc/server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ def _marshaled_dispatch(self, data, dispatch_method = None, path = None):
269269
encoding=self.encoding, allow_none=self.allow_none,
270270
)
271271

272-
return response.encode(self.encoding)
272+
return response.encode(self.encoding, 'xmlcharrefreplace')
273273

274274
def system_listMethods(self):
275275
"""system.listMethods() => ['add', 'subtract', 'multiple']
@@ -622,7 +622,7 @@ def _marshaled_dispatch(self, data, dispatch_method = None, path = None):
622622
response = dumps(
623623
Fault(1, "%s:%s" % (exc_type, exc_value)),
624624
encoding=self.encoding, allow_none=self.allow_none)
625-
response = response.encode(self.encoding)
625+
response = response.encode(self.encoding, 'xmlcharrefreplace')
626626
return response
627627

628628
class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher):

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ Core and Builtins
4646
Library
4747
-------
4848

49+
- Issue #26147: xmlrpc now works with strings not encodable with used
50+
non-UTF-8 encoding.
51+
4952
- Issue #25935: Garbage collector now breaks reference loops with OrderedDict.
5053

5154
- Issue #16620: Fixed AttributeError in msilib.Directory.glob().

0 commit comments

Comments
 (0)