diff -r 62802d373e9f Doc/library/xmlrpc.server.rst --- a/Doc/library/xmlrpc.server.rst Thu Jul 07 18:00:22 2016 +0200 +++ b/Doc/library/xmlrpc.server.rst Fri Jul 08 01:18:46 2016 +0800 @@ -79,7 +79,7 @@ alone XML-RPC servers. -.. method:: SimpleXMLRPCServer.register_function(function, name=None) +.. method:: SimpleXMLRPCServer.register_function(function=None, name=None) Register a function that can respond to XML-RPC requests. If *name* is given, it will be the method name associated with *function*, otherwise @@ -87,6 +87,14 @@ string, and may contain characters not legal in Python identifiers, including the period character. + From version 3.6, this function can also be used as a decorator. When used as + a decorator, *name* can be given as a keyword-only argument to register + *function* under *name*. If no *name* is given, ``function.__name__`` will be + used. + + .. versionadded:: 3.6 + :meth:`register_function` can be used as a decorator. + .. method:: SimpleXMLRPCServer.register_instance(instance, allow_dotted_names=False) @@ -185,6 +193,37 @@ # Print list of available methods print(s.system.listMethods()) +Since version 3.6, :meth:`register_function` can also be used as a decorator. The +previous server example can register functions in a decorator way:: + + from xmlrpc.server import SimpleXMLRPCServer + from xmlrpc.server import SimpleXMLRPCRequestHandler + + class RequestHandler(SimpleXMLRPCRequestHandler): + rpc_paths = ('/RPC2',) + + with SimpleXMLRPCServer(("localhost", 8000), + requestHandler=RequestHandler) as server: + server.register_introspection_functions() + + # Register pow() function; this will use the value of + # pow.__name__ as the name, which is just 'pow'. + server.register_function(pow) + + # Register a function under a different name, using + # register_function as a decorator. *name* can only be given + # as a keyword argument. + @server.register_function(name='add') + def adder_function(x,y): + return x + y + + # Register a function under function.__name__. + @server.register_function + def mul(x, y): + return x * y + + server.serve_forever() + The following example included in the :file:`Lib/xmlrpc/server.py` module shows a server allowing dotted names and registering a multicall function. @@ -252,18 +291,26 @@ CGIXMLRPCRequestHandler ----------------------- -The :class:`CGIXMLRPCRequestHandler` class can be used to handle XML-RPC +The :class:`CGIXMLRPCRequestHandler` class can be used to handle XML-RPC requests sent to Python CGI scripts. -.. method:: CGIXMLRPCRequestHandler.register_function(function, name=None) +.. method:: CGIXMLRPCRequestHandler.register_function(function=None, name=None) - Register a function that can respond to XML-RPC requests. If *name* is given, - it will be the method name associated with function, otherwise - *function.__name__* will be used. *name* can be either a normal or Unicode - string, and may contain characters not legal in Python identifiers, including + Register a function that can respond to XML-RPC requests. If *name* is given, + it will be the method name associated with *function*, otherwise + ``function.__name__`` will be used. *name* can be either a normal or Unicode + string, and may contain characters not legal in Python identifiers, including the period character. + From version 3.6, this function can also be used as a decorator. When used as + a decorator, *name* can be given as a keyword-only argument to register + *function* under *name*. If no *name* is given, ``function.__name__`` will be + used. + + .. versionadded:: 3.6 + :meth:`register_function` can be used as a decorator. + .. method:: CGIXMLRPCRequestHandler.register_instance(instance) diff -r 62802d373e9f Lib/test/test_xmlrpc.py --- a/Lib/test/test_xmlrpc.py Thu Jul 07 18:00:22 2016 +0200 +++ b/Lib/test/test_xmlrpc.py Fri Jul 08 01:18:46 2016 +0800 @@ -456,10 +456,6 @@ def getData(): return '42' - def my_function(): - '''This is my function''' - return True - class MyXMLRPCServer(xmlrpc.server.SimpleXMLRPCServer): def get_request(self): # Ensure the socket is always non-blocking. On Linux, socket @@ -486,9 +482,14 @@ serv.register_introspection_functions() serv.register_multicall_functions() serv.register_function(pow) - serv.register_function(lambda x,y: x+y, 'add') serv.register_function(lambda x: x, 'têšt') - serv.register_function(my_function) + @serv.register_function + def my_function(): + '''This is my function''' + return True + @serv.register_function(name='add') + def _(x, y): + return x + y testInstance = TestInstanceClass() serv.register_instance(testInstance, allow_dotted_names=True) evt.set() diff -r 62802d373e9f Lib/xmlrpc/server.py --- a/Lib/xmlrpc/server.py Thu Jul 07 18:00:22 2016 +0200 +++ b/Lib/xmlrpc/server.py Fri Jul 08 01:18:46 2016 +0800 @@ -106,6 +106,7 @@ from xmlrpc.client import Fault, dumps, loads, gzip_encode, gzip_decode from http.server import BaseHTTPRequestHandler +from functools import partial import http.server import socketserver import sys @@ -204,17 +205,22 @@ self.instance = instance self.allow_dotted_names = allow_dotted_names - def register_function(self, function, name=None): + def register_function(self, function=None, name=None): """Registers a function to respond to XML-RPC requests. The optional name argument can be used to set a Unicode name for the function. """ + # decorator factory + if function is None: + return partial(self.register_function, name=name) if name is None: name = function.__name__ self.funcs[name] = function + return function + def register_introspection_functions(self): """Registers the XML-RPC introspection methods in the system namespace.