]> granicus.if.org Git - python/commitdiff
bpo-7769: enable xmlrpc.server.SimpleXMLRPCDispatcher.register_function used as decor...
authorXiang Zhang <angwerzx@126.com>
Tue, 28 Feb 2017 09:12:52 +0000 (17:12 +0800)
committerGitHub <noreply@github.com>
Tue, 28 Feb 2017 09:12:52 +0000 (17:12 +0800)
Doc/library/xmlrpc.server.rst
Doc/whatsnew/3.7.rst
Lib/test/test_xmlrpc.py
Lib/xmlrpc/server.py
Misc/NEWS

index 0511ddf47e9948211d26752e63d841a2fdac05e6..7d561e2303f89848112981c7fc851b27320316d5 100644 (file)
@@ -79,13 +79,19 @@ The :class:`SimpleXMLRPCServer` class is based on
 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
-   ``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.
+   ``function.__name__`` will be used.  *name* is a string, and may contain
+   characters not legal in Python identifiers, including the period character.
+
+   This method can also be used as a decorator.  When used as a decorator,
+   *name* can only be given as a keyword argument to register *function* under
+   *name*.  If no *name* is given, ``function.__name__`` will be used.
+
+   .. versionchanged:: 3.7
+      :meth:`register_function` can be used as a decorator.
 
 
 .. method:: SimpleXMLRPCServer.register_instance(instance, allow_dotted_names=False)
@@ -148,7 +154,7 @@ Server code::
        rpc_paths = ('/RPC2',)
 
    # Create server
-   with SimpleXMLRPCServer(("localhost", 8000),
+   with SimpleXMLRPCServer(('localhost', 8000),
                            requestHandler=RequestHandler) as server:
        server.register_introspection_functions()
 
@@ -157,7 +163,7 @@ Server code::
        server.register_function(pow)
 
        # Register a function under a different name
-       def adder_function(x,y):
+       def adder_function(x, y):
            return x + y
        server.register_function(adder_function, 'add')
 
@@ -185,6 +191,37 @@ server::
    # Print list of available methods
    print(s.system.listMethods())
 
+: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,17 +289,23 @@ This client which interacts with the demo XMLRPC server can be invoked as::
 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* is a string, and may contain
+   characters not legal in Python identifiers, including the period character.
+
+   This method can also be used as a decorator.  When used as a decorator,
+   *name* can only be given as a keyword argument to register *function* under
+   *name*.  If no *name* is given, ``function.__name__`` will be used.
 
-   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.
+   .. versionchanged:: 3.7
+      :meth:`register_function` can be used as a decorator.
 
 
 .. method:: CGIXMLRPCRequestHandler.register_instance(instance)
index 6c071adb96fe4840432926bcd3366d77d52db982..1f5aa79c87a1e580c27acae16859ad8440268445 100644 (file)
@@ -104,6 +104,13 @@ The :const:`~unittest.mock.sentinel` attributes now preserve their identity
 when they are :mod:`copied <copy>` or :mod:`pickled <pickle>`.
 (Contributed by Serhiy Storchaka in :issue:`20804`.)
 
+xmlrpc.server
+-------------
+
+:meth:`register_function` of :class:`xmlrpc.server.SimpleXMLRPCDispatcher` and
+its subclasses can be used as a decorator.
+(Contributed by Xiang Zhang in :issue:`7769`.)
+
 urllib.parse
 ------------
 
index df9c79e3df0689182129888b4f91a77ebb1401a2..ef8ad217eae61fade3d6a4630a8f3fc14f0951ca 100644 (file)
@@ -505,10 +505,6 @@ def http_server(evt, numrequests, requestHandler=None, encoding=None):
             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
@@ -535,9 +531,14 @@ def http_server(evt, numrequests, requestHandler=None, encoding=None):
         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()
index 849bfddd84816f25c3488d5a6c8f68b44d3050e8..a6275a1b746844fab3d59f03ee1f52fc170cf67f 100644 (file)
@@ -106,6 +106,7 @@ server.handle_request()
 
 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 @@ class SimpleXMLRPCDispatcher:
         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.
index a55112750a2aa6eb562c933f5d9fd426ddebdb23..4f19e75aeaa8fc560fd5b86329fe4fe0e0cfbf51 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -249,6 +249,9 @@ Extension Modules
 Library
 -------
 
+- bpo-7769: Method register_function() of xmlrpc.server.SimpleXMLRPCDispatcher
+  and its subclasses can now be used as a decorator.
+
 - bpo-29376: Fix assertion error in threading._DummyThread.is_alive().
 
 - bpo-28624: Add a test that checks that cwd parameter of Popen() accepts