diff -r 88b5a93b1725 Lib/SimpleXMLRPCServer.py --- a/Lib/SimpleXMLRPCServer.py Tue Mar 08 17:08:25 2011 +0200 +++ b/Lib/SimpleXMLRPCServer.py Tue Mar 08 12:14:00 2011 -0800 @@ -15,6 +15,12 @@ server = SimpleXMLRPCServer(("localhost", 8000)) server.register_function(pow) server.register_function(lambda x,y: x+y, 'add') +@server.register_function +def my_function(): + return True +@server.register_function('my_function_2') +def another_function(): + return True server.serve_forever() 2. Install an instance: @@ -208,16 +214,52 @@ self.instance = instance self.allow_dotted_names = allow_dotted_names - def register_function(self, function, name = None): + def register_function(self, *args, **kwargs): """Registers a function to respond to XML-RPC requests. - The optional name argument can be used to set a Unicode name - for the function. + Used as a decorator, the optional name argument can be used + to set a Unicode name for the registered function. + + Used as a traditional method call, the first argument needs + to be a function or a function keyword argument must be present. + Otherwise, a function wrapper will be returned and no registration + takes place until that wrapper itself is called with a function + argument. """ - if name is None: - name = function.__name__ - self.funcs[name] = function + def wrapper(function, name = None): + if not name: + name = function.__name__ + self.funcs[name] = function + return function + + def name_wrapper(name): + def _wrapper(function): + return wrapper(function, name) + return _wrapper + + name = function = None + + if args: + if isinstance(args[0], str): + name = args[0] + function = kwargs.get('function') + elif callable(args[0]): + function = args[0] + try: + name = args[1] if isinstance(args[1], str) else None + except IndexError: + name = kwargs.get('name') + else: # pure kwargs + function = kwargs.get('function') + name = kwargs.get('name') + if function is None and name is None: + raise TypeError("register_function() got unexpected " + "keyword argument(s), 'name' and/or " + "'function' expected") + + # now we have function and name; at least one is defined + return wrapper(function, name) if function else name_wrapper(name) def register_introspection_functions(self): """Registers the XML-RPC introspection methods in the system diff -r 88b5a93b1725 Lib/test/test_xmlrpc.py --- a/Lib/test/test_xmlrpc.py Tue Mar 08 17:08:25 2011 +0200 +++ b/Lib/test/test_xmlrpc.py Tue Mar 08 12:14:00 2011 -0800 @@ -286,7 +286,7 @@ if name == 'div': return 'This is the div function' - def my_function(): + def _my_function(): '''This is my function''' return True @@ -302,6 +302,12 @@ requestHandler = SimpleXMLRPCServer.SimpleXMLRPCRequestHandler serv = MyXMLRPCServer(("localhost", 0), requestHandler, logRequests=False, bind_and_activate=False) + + @serv.register_function('my_function2') + def _my_function_bare(): + '''This is another of my function''' + return True + try: serv.socket.settimeout(3) serv.server_bind() @@ -317,7 +323,7 @@ serv.register_multicall_functions() serv.register_function(pow) serv.register_function(lambda x,y: x+y, 'add') - serv.register_function(my_function) + serv.register_function(_my_function, name='my_function') serv.register_instance(TestInstanceClass()) evt.set() @@ -489,8 +495,8 @@ try: p = xmlrpclib.ServerProxy(URL) meth = p.system.listMethods() - expected_methods = set(['pow', 'div', 'my_function', 'add', - 'system.listMethods', 'system.methodHelp', + expected_methods = set(['pow', 'div', 'my_function', 'my_function2', + 'add', 'system.listMethods', 'system.methodHelp', 'system.methodSignature', 'system.multicall']) self.assertEqual(set(meth), expected_methods) except (xmlrpclib.ProtocolError, socket.error), e: @@ -545,10 +551,15 @@ multicall.add(2,3) multicall.pow(6,8) multicall.div(127,42) - add_result, pow_result, div_result = multicall() + multicall.my_function() + multicall.my_function2() + add_result, pow_result, div_result, \ + myfunc_result, myfunc2_result = multicall() self.assertEqual(add_result, 2+3) self.assertEqual(pow_result, 6**8) self.assertEqual(div_result, 127//42) + self.assertTrue(myfunc_result) + self.assertTrue(myfunc2_result) except (xmlrpclib.ProtocolError, socket.error), e: # ignore failures due to non-blocking socket 'unavailable' errors if not is_unavailable_exception(e):