mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
bpo-7769: enable xmlrpc.server.SimpleXMLRPCDispatcher.register_function used as decorator (GH-231)
This commit is contained in:
parent
7c8b3fa31c
commit
267b9d2fa8
5 changed files with 80 additions and 20 deletions
|
@ -79,13 +79,19 @@ The :class:`SimpleXMLRPCServer` class is based on
|
||||||
alone XML-RPC servers.
|
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,
|
Register a function that can respond to XML-RPC requests. If *name* is given,
|
||||||
it will be the method name associated with *function*, otherwise
|
it will be the method name associated with *function*, otherwise
|
||||||
``function.__name__`` will be used. *name* can be either a normal or Unicode
|
``function.__name__`` will be used. *name* is a string, and may contain
|
||||||
string, and may contain characters not legal in Python identifiers, including
|
characters not legal in Python identifiers, including the period character.
|
||||||
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)
|
.. method:: SimpleXMLRPCServer.register_instance(instance, allow_dotted_names=False)
|
||||||
|
@ -148,7 +154,7 @@ Server code::
|
||||||
rpc_paths = ('/RPC2',)
|
rpc_paths = ('/RPC2',)
|
||||||
|
|
||||||
# Create server
|
# Create server
|
||||||
with SimpleXMLRPCServer(("localhost", 8000),
|
with SimpleXMLRPCServer(('localhost', 8000),
|
||||||
requestHandler=RequestHandler) as server:
|
requestHandler=RequestHandler) as server:
|
||||||
server.register_introspection_functions()
|
server.register_introspection_functions()
|
||||||
|
|
||||||
|
@ -157,7 +163,7 @@ Server code::
|
||||||
server.register_function(pow)
|
server.register_function(pow)
|
||||||
|
|
||||||
# Register a function under a different name
|
# Register a function under a different name
|
||||||
def adder_function(x,y):
|
def adder_function(x, y):
|
||||||
return x + y
|
return x + y
|
||||||
server.register_function(adder_function, 'add')
|
server.register_function(adder_function, 'add')
|
||||||
|
|
||||||
|
@ -185,6 +191,37 @@ server::
|
||||||
# Print list of available methods
|
# Print list of available methods
|
||||||
print(s.system.listMethods())
|
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
|
The following example included in the :file:`Lib/xmlrpc/server.py` module shows
|
||||||
a server allowing dotted names and registering a multicall function.
|
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
|
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.
|
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,
|
Register a function that can respond to XML-RPC requests. If *name* is given,
|
||||||
it will be the method name associated with function, otherwise
|
it will be the method name associated with *function*, otherwise
|
||||||
*function.__name__* will be used. *name* can be either a normal or Unicode
|
``function.__name__`` will be used. *name* is a string, and may contain
|
||||||
string, and may contain characters not legal in Python identifiers, including
|
characters not legal in Python identifiers, including the period character.
|
||||||
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:: CGIXMLRPCRequestHandler.register_instance(instance)
|
.. method:: CGIXMLRPCRequestHandler.register_instance(instance)
|
||||||
|
|
|
@ -104,6 +104,13 @@ The :const:`~unittest.mock.sentinel` attributes now preserve their identity
|
||||||
when they are :mod:`copied <copy>` or :mod:`pickled <pickle>`.
|
when they are :mod:`copied <copy>` or :mod:`pickled <pickle>`.
|
||||||
(Contributed by Serhiy Storchaka in :issue:`20804`.)
|
(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
|
urllib.parse
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
|
|
@ -505,10 +505,6 @@ def http_server(evt, numrequests, requestHandler=None, encoding=None):
|
||||||
def getData():
|
def getData():
|
||||||
return '42'
|
return '42'
|
||||||
|
|
||||||
def my_function():
|
|
||||||
'''This is my function'''
|
|
||||||
return True
|
|
||||||
|
|
||||||
class MyXMLRPCServer(xmlrpc.server.SimpleXMLRPCServer):
|
class MyXMLRPCServer(xmlrpc.server.SimpleXMLRPCServer):
|
||||||
def get_request(self):
|
def get_request(self):
|
||||||
# Ensure the socket is always non-blocking. On Linux, socket
|
# 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_introspection_functions()
|
||||||
serv.register_multicall_functions()
|
serv.register_multicall_functions()
|
||||||
serv.register_function(pow)
|
serv.register_function(pow)
|
||||||
serv.register_function(lambda x,y: x+y, 'add')
|
|
||||||
serv.register_function(lambda x: x, 'têšt')
|
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()
|
testInstance = TestInstanceClass()
|
||||||
serv.register_instance(testInstance, allow_dotted_names=True)
|
serv.register_instance(testInstance, allow_dotted_names=True)
|
||||||
evt.set()
|
evt.set()
|
||||||
|
|
|
@ -106,6 +106,7 @@ server.handle_request()
|
||||||
|
|
||||||
from xmlrpc.client import Fault, dumps, loads, gzip_encode, gzip_decode
|
from xmlrpc.client import Fault, dumps, loads, gzip_encode, gzip_decode
|
||||||
from http.server import BaseHTTPRequestHandler
|
from http.server import BaseHTTPRequestHandler
|
||||||
|
from functools import partial
|
||||||
import http.server
|
import http.server
|
||||||
import socketserver
|
import socketserver
|
||||||
import sys
|
import sys
|
||||||
|
@ -204,17 +205,22 @@ class SimpleXMLRPCDispatcher:
|
||||||
self.instance = instance
|
self.instance = instance
|
||||||
self.allow_dotted_names = allow_dotted_names
|
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.
|
"""Registers a function to respond to XML-RPC requests.
|
||||||
|
|
||||||
The optional name argument can be used to set a Unicode name
|
The optional name argument can be used to set a Unicode name
|
||||||
for the function.
|
for the function.
|
||||||
"""
|
"""
|
||||||
|
# decorator factory
|
||||||
|
if function is None:
|
||||||
|
return partial(self.register_function, name=name)
|
||||||
|
|
||||||
if name is None:
|
if name is None:
|
||||||
name = function.__name__
|
name = function.__name__
|
||||||
self.funcs[name] = function
|
self.funcs[name] = function
|
||||||
|
|
||||||
|
return function
|
||||||
|
|
||||||
def register_introspection_functions(self):
|
def register_introspection_functions(self):
|
||||||
"""Registers the XML-RPC introspection methods in the system
|
"""Registers the XML-RPC introspection methods in the system
|
||||||
namespace.
|
namespace.
|
||||||
|
|
|
@ -249,6 +249,9 @@ Extension Modules
|
||||||
Library
|
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-29376: Fix assertion error in threading._DummyThread.is_alive().
|
||||||
|
|
||||||
- bpo-28624: Add a test that checks that cwd parameter of Popen() accepts
|
- bpo-28624: Add a test that checks that cwd parameter of Popen() accepts
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue