bpo-29615: SimpleXMLRPCDispatcher no longer chains KeyError (#260)
(or any other exception) to exception(s) raised in the dispatched methods. Patch by Petr Motejlek.
This commit is contained in:
parent
da62373b0d
commit
3c6314c08d
|
@ -343,6 +343,94 @@ class XMLRPCTestCase(unittest.TestCase):
|
|||
self.assertEqual(p.method(), 5)
|
||||
self.assertEqual(p.method(), 5)
|
||||
|
||||
|
||||
class SimpleXMLRPCDispatcherTestCase(unittest.TestCase):
|
||||
class DispatchExc(Exception):
|
||||
"""Raised inside the dispatched functions when checking for
|
||||
chained exceptions"""
|
||||
|
||||
def test_call_registered_func(self):
|
||||
"""Calls explicitly registered function"""
|
||||
# Makes sure any exception raised inside the function has no other
|
||||
# exception chained to it
|
||||
|
||||
exp_params = 1, 2, 3
|
||||
|
||||
def dispatched_func(*params):
|
||||
raise self.DispatchExc(params)
|
||||
|
||||
dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
|
||||
dispatcher.register_function(dispatched_func)
|
||||
with self.assertRaises(self.DispatchExc) as exc_ctx:
|
||||
dispatcher._dispatch('dispatched_func', exp_params)
|
||||
self.assertEqual(exc_ctx.exception.args, (exp_params,))
|
||||
self.assertIsNone(exc_ctx.exception.__cause__)
|
||||
self.assertIsNone(exc_ctx.exception.__context__)
|
||||
|
||||
def test_call_instance_func(self):
|
||||
"""Calls a registered instance attribute as a function"""
|
||||
# Makes sure any exception raised inside the function has no other
|
||||
# exception chained to it
|
||||
|
||||
exp_params = 1, 2, 3
|
||||
|
||||
class DispatchedClass:
|
||||
def dispatched_func(self, *params):
|
||||
raise SimpleXMLRPCDispatcherTestCase.DispatchExc(params)
|
||||
|
||||
dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
|
||||
dispatcher.register_instance(DispatchedClass())
|
||||
with self.assertRaises(self.DispatchExc) as exc_ctx:
|
||||
dispatcher._dispatch('dispatched_func', exp_params)
|
||||
self.assertEqual(exc_ctx.exception.args, (exp_params,))
|
||||
self.assertIsNone(exc_ctx.exception.__cause__)
|
||||
self.assertIsNone(exc_ctx.exception.__context__)
|
||||
|
||||
def test_call_dispatch_func(self):
|
||||
"""Calls the registered instance's `_dispatch` function"""
|
||||
# Makes sure any exception raised inside the function has no other
|
||||
# exception chained to it
|
||||
|
||||
exp_method = 'method'
|
||||
exp_params = 1, 2, 3
|
||||
|
||||
class TestInstance:
|
||||
def _dispatch(self, method, params):
|
||||
raise SimpleXMLRPCDispatcherTestCase.DispatchExc(
|
||||
method, params)
|
||||
|
||||
dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
|
||||
dispatcher.register_instance(TestInstance())
|
||||
with self.assertRaises(self.DispatchExc) as exc_ctx:
|
||||
dispatcher._dispatch(exp_method, exp_params)
|
||||
self.assertEqual(exc_ctx.exception.args, (exp_method, exp_params))
|
||||
self.assertIsNone(exc_ctx.exception.__cause__)
|
||||
self.assertIsNone(exc_ctx.exception.__context__)
|
||||
|
||||
def test_registered_func_is_none(self):
|
||||
"""Calls explicitly registered function which is None"""
|
||||
|
||||
dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
|
||||
dispatcher.register_function(None, name='method')
|
||||
with self.assertRaises(Exception, expected_regex='method'):
|
||||
dispatcher._dispatch('method', ('param',))
|
||||
|
||||
def test_instance_has_no_func(self):
|
||||
"""Attempts to call nonexistent function on a registered instance"""
|
||||
|
||||
dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
|
||||
dispatcher.register_instance(object())
|
||||
with self.assertRaises(Exception, expected_regex='method'):
|
||||
dispatcher._dispatch('method', ('param',))
|
||||
|
||||
def test_cannot_locate_func(self):
|
||||
"""Calls a function that the dispatcher cannot locate"""
|
||||
|
||||
dispatcher = xmlrpc.server.SimpleXMLRPCDispatcher()
|
||||
with self.assertRaises(Exception, expected_regex='method'):
|
||||
dispatcher._dispatch('method', ('param',))
|
||||
|
||||
|
||||
class HelperTestCase(unittest.TestCase):
|
||||
def test_escape(self):
|
||||
self.assertEqual(xmlrpclib.escape("a&b"), "a&b")
|
||||
|
@ -1313,7 +1401,7 @@ def test_main():
|
|||
KeepaliveServerTestCase1, KeepaliveServerTestCase2,
|
||||
GzipServerTestCase, GzipUtilTestCase,
|
||||
MultiPathServerTestCase, ServerProxyTestCase, FailingServerTestCase,
|
||||
CGIHandlerTestCase)
|
||||
CGIHandlerTestCase, SimpleXMLRPCDispatcherTestCase)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -392,17 +392,22 @@ class SimpleXMLRPCDispatcher:
|
|||
not be called.
|
||||
"""
|
||||
|
||||
func = None
|
||||
try:
|
||||
# check to see if a matching function has been registered
|
||||
# call the matching registered function
|
||||
func = self.funcs[method]
|
||||
except KeyError:
|
||||
if self.instance is not None:
|
||||
# check for a _dispatch method
|
||||
if hasattr(self.instance, '_dispatch'):
|
||||
return self.instance._dispatch(method, params)
|
||||
pass
|
||||
else:
|
||||
# call instance method directly
|
||||
if func is not None:
|
||||
return func(*params)
|
||||
raise Exception('method "%s" is not supported' % method)
|
||||
|
||||
if self.instance is not None:
|
||||
if hasattr(self.instance, '_dispatch'):
|
||||
# call the `_dispatch` method on the instance
|
||||
return self.instance._dispatch(method, params)
|
||||
|
||||
# call the instance's method directly
|
||||
try:
|
||||
func = resolve_dotted_attribute(
|
||||
self.instance,
|
||||
|
@ -411,10 +416,10 @@ class SimpleXMLRPCDispatcher:
|
|||
)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
else:
|
||||
if func is not None:
|
||||
return func(*params)
|
||||
else:
|
||||
|
||||
raise Exception('method "%s" is not supported' % method)
|
||||
|
||||
class SimpleXMLRPCRequestHandler(BaseHTTPRequestHandler):
|
||||
|
|
|
@ -253,6 +253,10 @@ Extension Modules
|
|||
Library
|
||||
-------
|
||||
|
||||
- bpo-29615: SimpleXMLRPCDispatcher no longer chains KeyError (or any other
|
||||
exception) to exception(s) raised in the dispatched methods.
|
||||
Patch by Petr Motejlek.
|
||||
|
||||
- bpo-7769: Method register_function() of xmlrpc.server.SimpleXMLRPCDispatcher
|
||||
and its subclasses can now be used as a decorator.
|
||||
|
||||
|
|
Loading…
Reference in New Issue