Issue #26885: xmlrpc now supports unmarshalling additional data types used
by Apache XML-RPC implementation for numerics and None.
This commit is contained in:
parent
9fab79bcb5
commit
352601ca00
|
@ -88,9 +88,13 @@ between conformable Python objects and XML on the wire.
|
|||
+======================+=======================================================+
|
||||
| ``boolean`` | :class:`bool` |
|
||||
+----------------------+-------------------------------------------------------+
|
||||
| ``int`` or ``i4`` | :class:`int` in range from -2147483648 to 2147483647. |
|
||||
| ``int``, ``i1``, | :class:`int` in range from -2147483648 to 2147483647. |
|
||||
| ``i2``, ``i4``, | Values get the ``<int>`` tag. |
|
||||
| ``i8`` or | |
|
||||
| ``biginteger`` | |
|
||||
+----------------------+-------------------------------------------------------+
|
||||
| ``double`` | :class:`float` |
|
||||
| ``double`` or | :class:`float`. Values get the ``<double>`` tag. |
|
||||
| ``float`` | |
|
||||
+----------------------+-------------------------------------------------------+
|
||||
| ``string`` | :class:`str` |
|
||||
+----------------------+-------------------------------------------------------+
|
||||
|
@ -114,6 +118,8 @@ between conformable Python objects and XML on the wire.
|
|||
| ``nil`` | The ``None`` constant. Passing is allowed only if |
|
||||
| | *allow_none* is true. |
|
||||
+----------------------+-------------------------------------------------------+
|
||||
| ``bigdecimal`` | :class:`decimal.Decimal`. Returned type only. |
|
||||
+----------------------+-------------------------------------------------------+
|
||||
|
||||
This is the full set of data types supported by XML-RPC. Method calls may also
|
||||
raise a special :exc:`Fault` instance, used to signal XML-RPC server errors, or
|
||||
|
@ -137,6 +143,13 @@ between conformable Python objects and XML on the wire.
|
|||
.. versionchanged:: 3.5
|
||||
Added the *context* argument.
|
||||
|
||||
.. versionchanged:: 3.6
|
||||
Added support of type tags with prefixes (e.g.``ex:nil``).
|
||||
Added support of unmarsalling additional types used by Apache XML-RPC
|
||||
implementation for numerics: ``i1``, ``i2``, ``i8``, ``biginteger``,
|
||||
``float`` and ``bigdecimal``.
|
||||
See http://ws.apache.org/xmlrpc/types.html for a description.
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
||||
|
|
|
@ -934,6 +934,14 @@ Allowed keyword arguments to be passed to :func:`Beep <winsound.Beep>`,
|
|||
<winsound.PlaySound>` (:issue:`27982`).
|
||||
|
||||
|
||||
xmlrpc.client
|
||||
-------------
|
||||
|
||||
The module now supports unmarshalling additional data types used by
|
||||
Apache XML-RPC implementation for numerics and ``None``.
|
||||
(Contributed by Serhiy Storchaka in :issue:`26885`.)
|
||||
|
||||
|
||||
zipfile
|
||||
-------
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -143,6 +143,9 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #26885: xmlrpc now supports unmarshalling additional data types used
|
||||
by Apache XML-RPC implementation for numerics and None.
|
||||
|
||||
- Issue #28070: Fixed parsing inline verbose flag in regular expressions.
|
||||
|
||||
- Issue #19500: Add client-side SSL session resumption to the ssl module.
|
||||
|
|
Loading…
Reference in New Issue