Skip to content

Commit 267b9d2

Browse files
authored
bpo-7769: enable xmlrpc.server.SimpleXMLRPCDispatcher.register_function used as decorator (GH-231)
1 parent 7c8b3fa commit 267b9d2

File tree

5 files changed

+80
-20
lines changed

5 files changed

+80
-20
lines changed

Doc/library/xmlrpc.server.rst

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,19 @@ The :class:`SimpleXMLRPCServer` class is based on
7979
alone XML-RPC servers.
8080

8181

82-
.. method:: SimpleXMLRPCServer.register_function(function, name=None)
82+
.. method:: SimpleXMLRPCServer.register_function(function=None, name=None)
8383

8484
Register a function that can respond to XML-RPC requests. If *name* is given,
8585
it will be the method name associated with *function*, otherwise
86-
``function.__name__`` will be used. *name* can be either a normal or Unicode
87-
string, and may contain characters not legal in Python identifiers, including
88-
the period character.
86+
``function.__name__`` will be used. *name* is a string, and may contain
87+
characters not legal in Python identifiers, including the period character.
88+
89+
This method can also be used as a decorator. When used as a decorator,
90+
*name* can only be given as a keyword argument to register *function* under
91+
*name*. If no *name* is given, ``function.__name__`` will be used.
92+
93+
.. versionchanged:: 3.7
94+
:meth:`register_function` can be used as a decorator.
8995

9096

9197
.. method:: SimpleXMLRPCServer.register_instance(instance, allow_dotted_names=False)
@@ -148,7 +154,7 @@ Server code::
148154
rpc_paths = ('/RPC2',)
149155

150156
# Create server
151-
with SimpleXMLRPCServer(("localhost", 8000),
157+
with SimpleXMLRPCServer(('localhost', 8000),
152158
requestHandler=RequestHandler) as server:
153159
server.register_introspection_functions()
154160

@@ -157,7 +163,7 @@ Server code::
157163
server.register_function(pow)
158164

159165
# Register a function under a different name
160-
def adder_function(x,y):
166+
def adder_function(x, y):
161167
return x + y
162168
server.register_function(adder_function, 'add')
163169

@@ -185,6 +191,37 @@ server::
185191
# Print list of available methods
186192
print(s.system.listMethods())
187193

194+
:meth:`register_function` can also be used as a decorator. The previous server
195+
example can register functions in a decorator way::
196+
197+
from xmlrpc.server import SimpleXMLRPCServer
198+
from xmlrpc.server import SimpleXMLRPCRequestHandler
199+
200+
class RequestHandler(SimpleXMLRPCRequestHandler):
201+
rpc_paths = ('/RPC2',)
202+
203+
with SimpleXMLRPCServer(('localhost', 8000),
204+
requestHandler=RequestHandler) as server:
205+
server.register_introspection_functions()
206+
207+
# Register pow() function; this will use the value of
208+
# pow.__name__ as the name, which is just 'pow'.
209+
server.register_function(pow)
210+
211+
# Register a function under a different name, using
212+
# register_function as a decorator. *name* can only be given
213+
# as a keyword argument.
214+
@server.register_function(name='add')
215+
def adder_function(x, y):
216+
return x + y
217+
218+
# Register a function under function.__name__.
219+
@server.register_function
220+
def mul(x, y):
221+
return x * y
222+
223+
server.serve_forever()
224+
188225
The following example included in the :file:`Lib/xmlrpc/server.py` module shows
189226
a server allowing dotted names and registering a multicall function.
190227

@@ -252,17 +289,23 @@ This client which interacts with the demo XMLRPC server can be invoked as::
252289
CGIXMLRPCRequestHandler
253290
-----------------------
254291

255-
The :class:`CGIXMLRPCRequestHandler` class can be used to handle XML-RPC
292+
The :class:`CGIXMLRPCRequestHandler` class can be used to handle XML-RPC
256293
requests sent to Python CGI scripts.
257294

258295

259-
.. method:: CGIXMLRPCRequestHandler.register_function(function, name=None)
296+
.. method:: CGIXMLRPCRequestHandler.register_function(function=None, name=None)
297+
298+
Register a function that can respond to XML-RPC requests. If *name* is given,
299+
it will be the method name associated with *function*, otherwise
300+
``function.__name__`` will be used. *name* is a string, and may contain
301+
characters not legal in Python identifiers, including the period character.
302+
303+
This method can also be used as a decorator. When used as a decorator,
304+
*name* can only be given as a keyword argument to register *function* under
305+
*name*. If no *name* is given, ``function.__name__`` will be used.
260306

261-
Register a function that can respond to XML-RPC requests. If *name* is given,
262-
it will be the method name associated with function, otherwise
263-
*function.__name__* will be used. *name* can be either a normal or Unicode
264-
string, and may contain characters not legal in Python identifiers, including
265-
the period character.
307+
.. versionchanged:: 3.7
308+
:meth:`register_function` can be used as a decorator.
266309

267310

268311
.. method:: CGIXMLRPCRequestHandler.register_instance(instance)

Doc/whatsnew/3.7.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ The :const:`~unittest.mock.sentinel` attributes now preserve their identity
104104
when they are :mod:`copied <copy>` or :mod:`pickled <pickle>`.
105105
(Contributed by Serhiy Storchaka in :issue:`20804`.)
106106

107+
xmlrpc.server
108+
-------------
109+
110+
:meth:`register_function` of :class:`xmlrpc.server.SimpleXMLRPCDispatcher` and
111+
its subclasses can be used as a decorator.
112+
(Contributed by Xiang Zhang in :issue:`7769`.)
113+
107114
urllib.parse
108115
------------
109116

Lib/test/test_xmlrpc.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -505,10 +505,6 @@ class Fixture:
505505
def getData():
506506
return '42'
507507

508-
def my_function():
509-
'''This is my function'''
510-
return True
511-
512508
class MyXMLRPCServer(xmlrpc.server.SimpleXMLRPCServer):
513509
def get_request(self):
514510
# Ensure the socket is always non-blocking. On Linux, socket
@@ -535,9 +531,14 @@ def get_request(self):
535531
serv.register_introspection_functions()
536532
serv.register_multicall_functions()
537533
serv.register_function(pow)
538-
serv.register_function(lambda x,y: x+y, 'add')
539534
serv.register_function(lambda x: x, 'têšt')
540-
serv.register_function(my_function)
535+
@serv.register_function
536+
def my_function():
537+
'''This is my function'''
538+
return True
539+
@serv.register_function(name='add')
540+
def _(x, y):
541+
return x + y
541542
testInstance = TestInstanceClass()
542543
serv.register_instance(testInstance, allow_dotted_names=True)
543544
evt.set()

Lib/xmlrpc/server.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ def export_add(self, x, y):
106106

107107
from xmlrpc.client import Fault, dumps, loads, gzip_encode, gzip_decode
108108
from http.server import BaseHTTPRequestHandler
109+
from functools import partial
109110
import http.server
110111
import socketserver
111112
import sys
@@ -204,17 +205,22 @@ def register_instance(self, instance, allow_dotted_names=False):
204205
self.instance = instance
205206
self.allow_dotted_names = allow_dotted_names
206207

207-
def register_function(self, function, name=None):
208+
def register_function(self, function=None, name=None):
208209
"""Registers a function to respond to XML-RPC requests.
209210
210211
The optional name argument can be used to set a Unicode name
211212
for the function.
212213
"""
214+
# decorator factory
215+
if function is None:
216+
return partial(self.register_function, name=name)
213217

214218
if name is None:
215219
name = function.__name__
216220
self.funcs[name] = function
217221

222+
return function
223+
218224
def register_introspection_functions(self):
219225
"""Registers the XML-RPC introspection methods in the system
220226
namespace.

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,9 @@ Extension Modules
249249
Library
250250
-------
251251

252+
- bpo-7769: Method register_function() of xmlrpc.server.SimpleXMLRPCDispatcher
253+
and its subclasses can now be used as a decorator.
254+
252255
- bpo-29376: Fix assertion error in threading._DummyThread.is_alive().
253256

254257
- bpo-28624: Add a test that checks that cwd parameter of Popen() accepts

0 commit comments

Comments
 (0)