diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py
index 2c199411a7a..ca8d5d8cc03 100644
--- a/Lib/test/test_xmlrpc.py
+++ b/Lib/test/test_xmlrpc.py
@@ -149,7 +149,8 @@ class XMLRPCTestCase(unittest.TestCase):
@test_support.requires_unicode
def test_dump_encoding(self):
- value = unichr(0x20ac)
+ value = {test_support.u(r'key\u20ac\xa4'):
+ test_support.u(r'value\u20ac\xa4')}
strg = xmlrpclib.dumps((value,), encoding='iso-8859-15')
strg = "" + strg
self.assertEqual(xmlrpclib.loads(strg)[0][0], value)
@@ -158,6 +159,12 @@ class XMLRPCTestCase(unittest.TestCase):
methodresponse=True)
self.assertEqual(xmlrpclib.loads(strg)[0][0], value)
+ methodname = test_support.u(r'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)
+
@test_support.requires_unicode
def test_default_encoding_issues(self):
# SF bug #1115989: wrong decoding in '_stringify'
@@ -332,6 +339,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, test_support.u(r't\xea\u0161t'))
serv.register_function(my_function)
serv.register_instance(TestInstanceClass())
evt.set()
@@ -496,7 +504,7 @@ class SimpleServerTestCase(BaseServerTestCase):
@test_support.requires_unicode
def test_client_encoding(self):
start_string = unichr(0x20ac)
- end_string = unichr(0xa3)
+ end_string = unichr(0xa4)
try:
p = xmlrpclib.ServerProxy(URL, encoding='iso-8859-15')
@@ -508,6 +516,18 @@ class SimpleServerTestCase(BaseServerTestCase):
# protocol error; provide additional information in test output
self.fail("%s\n%s" % (e, getattr(e, "headers", "")))
+ @test_support.requires_unicode
+ def test_nonascii_methodname(self):
+ try:
+ p = xmlrpclib.ServerProxy(URL, encoding='iso-8859-15')
+ m = getattr(p, 't\xea\xa8t')
+ self.assertEqual(m(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 httplib, it should return 404 header and
@@ -525,6 +545,7 @@ class SimpleServerTestCase(BaseServerTestCase):
p = xmlrpclib.ServerProxy(URL)
meth = p.system.listMethods()
expected_methods = set(['pow', 'div', 'my_function', 'add',
+ test_support.u(r't\xea\u0161t'),
'system.listMethods', 'system.methodHelp',
'system.methodSignature', 'system.multicall'])
self.assertEqual(set(meth), expected_methods)
@@ -635,7 +656,7 @@ class SimpleServerEncodingTestCase(BaseServerTestCase):
@test_support.requires_unicode
def test_server_encoding(self):
start_string = unichr(0x20ac)
- end_string = unichr(0xa3)
+ end_string = unichr(0xa4)
try:
p = xmlrpclib.ServerProxy(URL)
diff --git a/Lib/xmlrpclib.py b/Lib/xmlrpclib.py
index a1800a18a56..e0e399c449a 100644
--- a/Lib/xmlrpclib.py
+++ b/Lib/xmlrpclib.py
@@ -703,9 +703,8 @@ class Marshaller:
if unicode:
def dump_unicode(self, value, write, escape=escape):
- value = value.encode(self.encoding)
write("")
- write(escape(value))
+ write(escape(value).encode(self.encoding, 'xmlcharrefreplace'))
write("\n")
dispatch[UnicodeType] = dump_unicode
@@ -732,12 +731,13 @@ class Marshaller:
write("\n")
for k, v in value.items():
write("\n")
- if type(k) is not StringType:
- if unicode and type(k) is UnicodeType:
- k = k.encode(self.encoding)
- else:
- raise TypeError, "dictionary key must be string"
- write("%s\n" % escape(k))
+ if type(k) is StringType:
+ k = escape(k)
+ elif unicode and type(k) is UnicodeType:
+ k = escape(k).encode(self.encoding, 'xmlcharrefreplace')
+ else:
+ raise TypeError, "dictionary key must be string"
+ write("%s\n" % k)
dump(v, write)
write("\n")
write("\n")
@@ -1099,7 +1099,7 @@ def dumps(params, methodname=None, methodresponse=None, encoding=None,
if methodname:
# a method call
if not isinstance(methodname, StringType):
- methodname = methodname.encode(encoding)
+ methodname = methodname.encode(encoding, 'xmlcharrefreplace')
data = (
xmlheader,
"\n"
diff --git a/Misc/NEWS b/Misc/NEWS
index b658f729ad6..0d176456e6d 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -39,6 +39,9 @@ Core and Builtins
Library
-------
+- Issue #26147: xmlrpclib now works with unicode not encodable with used
+ non-UTF-8 encoding.
+
- Issue #16620: Fixed AttributeError in msilib.Directory.glob().
- Issue #21847: Fixed xmlrpclib on Unicode-disabled builds.