Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1b7458b

Browse files
committed
Closes #2979: add parameter 'use_builtin_types' to the SimpleXMLRPCServer.
1 parent e3b4715 commit 1b7458b

3 files changed

Lines changed: 73 additions & 14 deletions

File tree

Doc/library/xmlrpc.server.rst

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ servers written in Python. Servers can either be free standing, using
1616
:class:`CGIXMLRPCRequestHandler`.
1717

1818

19-
.. class:: SimpleXMLRPCServer(addr, requestHandler=SimpleXMLRPCRequestHandler, logRequests=True, allow_none=False, encoding=None, bind_and_activate=True)
19+
.. class:: SimpleXMLRPCServer(addr, requestHandler=SimpleXMLRPCRequestHandler,\
20+
logRequests=True, allow_none=False, encoding=None,\
21+
bind_and_activate=True, use_builtin_types=False)
2022

2123
Create a new server instance. This class provides methods for registration of
2224
functions that can be called by the XML-RPC protocol. The *requestHandler*
@@ -25,18 +27,31 @@ servers written in Python. Servers can either be free standing, using
2527
are passed to the :class:`socketserver.TCPServer` constructor. If *logRequests*
2628
is true (the default), requests will be logged; setting this parameter to false
2729
will turn off logging. The *allow_none* and *encoding* parameters are passed
28-
on to :mod:`xmlrpc.client` and control the XML-RPC responses that will be returned
30+
on to :mod:`xmlrpc.client` and control the XML-RPC responses that will be returned
2931
from the server. The *bind_and_activate* parameter controls whether
3032
:meth:`server_bind` and :meth:`server_activate` are called immediately by the
3133
constructor; it defaults to true. Setting it to false allows code to manipulate
3234
the *allow_reuse_address* class variable before the address is bound.
35+
The *use_builtin_types* parameter is passed to the
36+
:func:`~xmlrpc.client.loads` function and controls which types are processed
37+
when date/times values or binary data are received; it defaults to false.
3338

39+
.. versionchanged:: 3.3
40+
The *use_builtin_types* flag was added.
3441

35-
.. class:: CGIXMLRPCRequestHandler(allow_none=False, encoding=None)
42+
43+
.. class:: CGIXMLRPCRequestHandler(allow_none=False, encoding=None,\
44+
use_builtin_types=False)
3645

3746
Create a new instance to handle XML-RPC requests in a CGI environment. The
3847
*allow_none* and *encoding* parameters are passed on to :mod:`xmlrpc.client`
3948
and control the XML-RPC responses that will be returned from the server.
49+
The *use_builtin_types* parameter is passed to the
50+
:func:`~xmlrpc.client.loads` function and controls which types are processed
51+
when date/times values or binary data are received; it defaults to false.
52+
53+
.. versionchanged:: 3.3
54+
The *use_builtin_types* flag was added.
4055

4156

4257
.. class:: SimpleXMLRPCRequestHandler()
@@ -233,12 +248,17 @@ to HTTP GET requests. Servers can either be free standing, using
233248
:class:`DocCGIXMLRPCRequestHandler`.
234249

235250

236-
.. class:: DocXMLRPCServer(addr, requestHandler=DocXMLRPCRequestHandler, logRequests=True, allow_none=False, encoding=None, bind_and_activate=True)
251+
.. class:: DocXMLRPCServer(addr, requestHandler=DocXMLRPCRequestHandler,\
252+
logRequests=True, allow_none=False, encoding=None,\
253+
bind_and_activate=True, use_builtin_types=True)
237254

238255
Create a new server instance. All parameters have the same meaning as for
239256
:class:`SimpleXMLRPCServer`; *requestHandler* defaults to
240257
:class:`DocXMLRPCRequestHandler`.
241258

259+
.. versionchanged:: 3.3
260+
The *use_builtin_types* flag was added.
261+
242262

243263
.. class:: DocCGIXMLRPCRequestHandler()
244264

Lib/test/test_xmlrpc.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,10 +1023,44 @@ def test_cgi_xmlrpc_response(self):
10231023
len(content))
10241024

10251025

1026+
class UseBuiltinTypesTestCase(unittest.TestCase):
1027+
1028+
def test_use_builtin_types(self):
1029+
# SimpleXMLRPCDispatcher.__init__ accepts use_builtin_types, which
1030+
# makes all dispatch of binary data as bytes instances, and all
1031+
# dispatch of datetime argument as datetime.datetime instances.
1032+
self.log = []
1033+
expected_bytes = b"my dog has fleas"
1034+
expected_date = datetime.datetime(2008, 5, 26, 18, 25, 12)
1035+
marshaled = xmlrpclib.dumps((expected_bytes, expected_date), 'foobar')
1036+
def foobar(*args):
1037+
self.log.extend(args)
1038+
handler = xmlrpc.server.SimpleXMLRPCDispatcher(
1039+
allow_none=True, encoding=None, use_builtin_types=True)
1040+
handler.register_function(foobar)
1041+
handler._marshaled_dispatch(marshaled)
1042+
self.assertEqual(len(self.log), 2)
1043+
mybytes, mydate = self.log
1044+
self.assertEqual(self.log, [expected_bytes, expected_date])
1045+
self.assertIs(type(mydate), datetime.datetime)
1046+
self.assertIs(type(mybytes), bytes)
1047+
1048+
def test_cgihandler_has_use_builtin_types_flag(self):
1049+
handler = xmlrpc.server.CGIXMLRPCRequestHandler(use_builtin_types=True)
1050+
self.assertTrue(handler.use_builtin_types)
1051+
1052+
def test_xmlrpcserver_has_use_builtin_types_flag(self):
1053+
server = xmlrpc.server.SimpleXMLRPCServer(("localhost", 0),
1054+
use_builtin_types=True)
1055+
server.server_close()
1056+
self.assertTrue(server.use_builtin_types)
1057+
1058+
10261059
@support.reap_threads
10271060
def test_main():
10281061
xmlrpc_tests = [XMLRPCTestCase, HelperTestCase, DateTimeTestCase,
10291062
BinaryTestCase, FaultTestCase]
1063+
xmlrpc_tests.append(UseBuiltinTypesTestCase)
10301064
xmlrpc_tests.append(SimpleServerTestCase)
10311065
xmlrpc_tests.append(KeepaliveServerTestCase1)
10321066
xmlrpc_tests.append(KeepaliveServerTestCase2)

Lib/xmlrpc/server.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,13 @@ class SimpleXMLRPCDispatcher:
160160
can be instanced when used by the MultiPathXMLRPCServer
161161
"""
162162

163-
def __init__(self, allow_none=False, encoding=None):
163+
def __init__(self, allow_none=False, encoding=None,
164+
use_builtin_types=False):
164165
self.funcs = {}
165166
self.instance = None
166167
self.allow_none = allow_none
167168
self.encoding = encoding or 'utf-8'
169+
self.use_builtin_types = use_builtin_types
168170

169171
def register_instance(self, instance, allow_dotted_names=False):
170172
"""Registers an instance to respond to XML-RPC requests.
@@ -245,7 +247,7 @@ def _marshaled_dispatch(self, data, dispatch_method = None, path = None):
245247
"""
246248

247249
try:
248-
params, method = loads(data)
250+
params, method = loads(data, use_builtin_types=self.use_builtin_types)
249251

250252
# generate response
251253
if dispatch_method is not None:
@@ -572,10 +574,11 @@ class SimpleXMLRPCServer(socketserver.TCPServer,
572574
_send_traceback_header = False
573575

574576
def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler,
575-
logRequests=True, allow_none=False, encoding=None, bind_and_activate=True):
577+
logRequests=True, allow_none=False, encoding=None,
578+
bind_and_activate=True, use_builtin_types=False):
576579
self.logRequests = logRequests
577580

578-
SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
581+
SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding, use_builtin_types)
579582
socketserver.TCPServer.__init__(self, addr, requestHandler, bind_and_activate)
580583

581584
# [Bug #1222790] If possible, set close-on-exec flag; if a
@@ -595,10 +598,11 @@ class MultiPathXMLRPCServer(SimpleXMLRPCServer):
595598
Make sure that the requestHandler accepts the paths in question.
596599
"""
597600
def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler,
598-
logRequests=True, allow_none=False, encoding=None, bind_and_activate=True):
601+
logRequests=True, allow_none=False, encoding=None,
602+
bind_and_activate=True, use_builtin_types=False):
599603

600604
SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests, allow_none,
601-
encoding, bind_and_activate)
605+
encoding, bind_and_activate, use_builtin_types)
602606
self.dispatchers = {}
603607
self.allow_none = allow_none
604608
self.encoding = encoding or 'utf-8'
@@ -628,8 +632,8 @@ def _marshaled_dispatch(self, data, dispatch_method = None, path = None):
628632
class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher):
629633
"""Simple handler for XML-RPC data passed through CGI."""
630634

631-
def __init__(self, allow_none=False, encoding=None):
632-
SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
635+
def __init__(self, allow_none=False, encoding=None, use_builtin_types=False):
636+
SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding, use_builtin_types)
633637

634638
def handle_xmlrpc(self, request_text):
635639
"""Handle a single XML-RPC request"""
@@ -924,9 +928,10 @@ class DocXMLRPCServer( SimpleXMLRPCServer,
924928

925929
def __init__(self, addr, requestHandler=DocXMLRPCRequestHandler,
926930
logRequests=True, allow_none=False, encoding=None,
927-
bind_and_activate=True):
931+
bind_and_activate=True, use_builtin_types=False):
928932
SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests,
929-
allow_none, encoding, bind_and_activate)
933+
allow_none, encoding, bind_and_activate,
934+
use_builtin_types)
930935
XMLRPCDocGenerator.__init__(self)
931936

932937
class DocCGIXMLRPCRequestHandler( CGIXMLRPCRequestHandler,

0 commit comments

Comments
 (0)