diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_xmlrpc.py | 49 | ||||
-rw-r--r-- | Lib/xmlrpc/client.py | 32 |
2 files changed, 75 insertions, 6 deletions
diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index 29a9878..df9c79e 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -1,5 +1,6 @@ import base64 import datetime +import decimal import sys import time import unittest @@ -237,6 +238,54 @@ class XMLRPCTestCase(unittest.TestCase): '</struct></value></param></params>') self.assertRaises(ResponseError, xmlrpclib.loads, data) + def check_loads(self, s, value, **kwargs): + dump = '<params><param><value>%s</value></param></params>' % s + result, m = xmlrpclib.loads(dump, **kwargs) + (newvalue,) = result + self.assertEqual(newvalue, value) + self.assertIs(type(newvalue), type(value)) + self.assertIsNone(m) + + def test_load_standard_types(self): + check = self.check_loads + check('string', 'string') + check('<string>string</string>', 'string') + check('<string>𝔘𝔫𝔦𝔠𝔬𝔡𝔢 string</string>', '𝔘𝔫𝔦𝔠𝔬𝔡𝔢 string') + check('<int>2056183947</int>', 2056183947) + check('<int>-2056183947</int>', -2056183947) + check('<i4>2056183947</i4>', 2056183947) + check('<double>46093.78125</double>', 46093.78125) + check('<boolean>0</boolean>', False) + check('<base64>AGJ5dGUgc3RyaW5n/w==</base64>', + xmlrpclib.Binary(b'\x00byte string\xff')) + check('<base64>AGJ5dGUgc3RyaW5n/w==</base64>', + b'\x00byte string\xff', use_builtin_types=True) + check('<dateTime.iso8601>20050210T11:41:23</dateTime.iso8601>', + xmlrpclib.DateTime('20050210T11:41:23')) + check('<dateTime.iso8601>20050210T11:41:23</dateTime.iso8601>', + datetime.datetime(2005, 2, 10, 11, 41, 23), + use_builtin_types=True) + check('<array><data>' + '<value><int>1</int></value><value><int>2</int></value>' + '</data></array>', [1, 2]) + check('<struct>' + '<member><name>b</name><value><int>2</int></value></member>' + '<member><name>a</name><value><int>1</int></value></member>' + '</struct>', {'a': 1, 'b': 2}) + + def test_load_extension_types(self): + check = self.check_loads + check('<nil/>', None) + check('<ex:nil/>', None) + check('<i1>205</i1>', 205) + check('<i2>20561</i2>', 20561) + check('<i8>9876543210</i8>', 9876543210) + check('<biginteger>98765432100123456789</biginteger>', + 98765432100123456789) + check('<float>93.78125</float>', 93.78125) + check('<bigdecimal>9876543210.0123456789</bigdecimal>', + decimal.Decimal('9876543210.0123456789')) + def test_get_host_info(self): # see bug #3613, this raised a TypeError transp = xmlrpc.client.Transport() diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py index 581a3b9..bd3278e 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -132,6 +132,7 @@ import base64 import sys import time from datetime import datetime +from decimal import Decimal import http.client import urllib.parse from xml.parsers import expat @@ -667,6 +668,8 @@ class Unmarshaller: def start(self, tag, attrs): # prepare to handle this element + if ':' in tag: + tag = tag.split(':')[-1] if tag == "array" or tag == "struct": self._marks.append(len(self._stack)) self._data = [] @@ -682,9 +685,13 @@ class Unmarshaller: try: f = self.dispatch[tag] except KeyError: - pass # unknown tag ? - else: - return f(self, "".join(self._data)) + if ':' not in tag: + return # unknown tag ? + try: + f = self.dispatch[tag.split(':')[-1]] + except KeyError: + return # unknown tag ? + return f(self, "".join(self._data)) # # accelerator support @@ -694,9 +701,13 @@ class Unmarshaller: try: f = self.dispatch[tag] except KeyError: - pass # unknown tag ? - else: - return f(self, data) + if ':' not in tag: + return # unknown tag ? + try: + f = self.dispatch[tag.split(':')[-1]] + except KeyError: + return # unknown tag ? + return f(self, data) # # element decoders @@ -721,14 +732,23 @@ class Unmarshaller: def end_int(self, data): self.append(int(data)) self._value = 0 + dispatch["i1"] = end_int + dispatch["i2"] = end_int dispatch["i4"] = end_int dispatch["i8"] = end_int dispatch["int"] = end_int + dispatch["biginteger"] = end_int def end_double(self, data): self.append(float(data)) self._value = 0 dispatch["double"] = end_double + dispatch["float"] = end_double + + def end_bigdecimal(self, data): + self.append(Decimal(data)) + self._value = 0 + dispatch["bigdecimal"] = end_bigdecimal def end_string(self, data): if self._encoding: |