def test_methods_partials(self): multiply = lambda x, y: x * y double = partial(multiply, 2) methods = Methods() methods.add(double, 'double') req = Request({'jsonrpc': '2.0', 'method': 'double', 'params': [3], 'id': 1}) self.assertEqual(6, req.call(methods)['result'])
def test_invalid_string(self): with self.assertRaises(InvalidParams): Request._get_arguments({ 'jsonrpc': '2.0', 'method': 'foo', 'params': 'str' })
def test_methods_functions_with_decorator(self): methods = Methods() @methods.add def foo(): # pylint: disable=redefined-outer-name,unused-variable return 'bar' req = Request({'jsonrpc': '2.0', 'method': 'foo', 'id': 1}) self.assertEqual('bar', req.call(methods)['result'])
def test_positionals_with_context(self): methods = {"square": lambda x, context=None: context} req = Request( {"jsonrpc": "2.0", "method": "square", "params": [FOO], "id": 1}, context=BAR, ) self.assertEqual(BAR, req.call(methods)["result"])
def test_methods_functions_with_decorator(self): methods = Methods() @methods.add def foo(): return 'bar' req = Request({'jsonrpc': '2.0', 'method': 'foo', 'id': 1}) self.assertEqual('bar', req.call(methods)['result'])
def test_methods_object(self): def cat(): pass # pylint: disable=multiple-statements def dog(): pass # pylint: disable=multiple-statements methods = Methods() methods.add(cat) methods.add(dog) self.assertIs(cat, Request._get_method(methods, 'cat')) self.assertIs(dog, Request._get_method(methods, 'dog'))
def test_methods_object(self): def cat(): pass def dog(): pass methods = Methods() methods.add(cat) methods.add(dog) self.assertIs(cat, Request._get_method(methods, 'cat')) self.assertIs(dog, Request._get_method(methods, 'dog'))
def test_keywords(): req = Request({ 'jsonrpc': '2.0', 'method': 'foo', 'params': { 'foo': 'bar' } }) req._validate_arguments_against_signature(lambda **kwargs: None)
def test_list(self): def cat(): pass # pylint: disable=multiple-statements def dog(): pass # pylint: disable=multiple-statements self.assertIs(cat, Request._get_method([cat, dog], 'cat')) self.assertIs(dog, Request._get_method([cat, dog], 'dog'))
def test_dict_partials(self): multiply = lambda x, y: x * y req = Request({ 'jsonrpc': '2.0', 'method': 'baz', 'params': [3], 'id': 1 }) self.assertEqual(6, req.call({'baz': partial(multiply, 2)})['result'])
def test_positionals(self): methods = {'square': lambda x: x * x} req = Request({ 'jsonrpc': '2.0', 'method': 'square', 'params': [3], 'id': 1 }) self.assertEqual(9, req.call(methods)['result'])
def test_noargs_with_context(self): methods = {'foo': lambda context=None: context} req = Request({ 'jsonrpc': '2.0', 'method': 'foo', 'id': 1 }, context=FOO) self.assertEqual(FOO, req.call(methods)['result'])
def test_methods_functions_with_decorator(self): methods = Methods() @methods.add def foo(): return "bar" req = Request({"jsonrpc": "2.0", "method": "foo", "id": 1}) self.assertEqual("bar", req.call(methods)["result"])
def test_positionals_not_passed(self): req = Request({ 'jsonrpc': '2.0', 'method': 'foo', 'params': { 'foo': 'bar' } }) with self.assertRaises(InvalidParams): req._validate_arguments_against_signature(lambda x: None)
def test_keywords_with_context(self): methods = { "square": lambda foo=None, context=None: {"foo": foo, "context": context} } req = Request( {"jsonrpc": "2.0", "method": "square", "params": {"foo": FOO}, "id": 1}, context=BAR, ) self.assertEqual(FOO, req.call(methods)["result"]["foo"]) self.assertEqual(BAR, req.call(methods)["result"]["context"])
def test_dict(self): def cat(): pass # pylint: disable=multiple-statements def dog(): pass # pylint: disable=multiple-statements dictionary = {'cat_says': cat, 'dog_says': dog} self.assertIs(cat, Request._get_method(dictionary, 'cat_says')) self.assertIs(dog, Request._get_method(dictionary, 'dog_says'))
def test_list_partials(self): multiply = lambda x, y: x * y double = partial(multiply, 2) double.__name__ = 'double' req = Request({ 'jsonrpc': '2.0', 'method': 'double', 'params': [3], 'id': 1 }) self.assertEqual(6, req.call([double])['result'])
def test_keywords(self): methods = {'get_name': lambda **kwargs: kwargs['name']} req = Request({ 'jsonrpc': '2.0', 'method': 'get_name', 'params': { 'name': 'foo' }, 'id': 1 }) self.assertEqual('foo', req.call(methods)['result'])
def test_object_method(self): methods = {'foo': Foo().foo} req = Request({ 'jsonrpc': '2.0', 'method': 'foo', 'params': [1, 2], 'id': 1 }) response = req.call(methods) self.assertIsInstance(response, RequestResponse) self.assertEqual('bar', response['result'])
def test_positionals_with_context(self): methods = {'square': lambda x, context=None: context} req = Request( { 'jsonrpc': '2.0', 'method': 'square', 'params': [FOO], 'id': 1 }, context=BAR) self.assertEqual(BAR, req.call(methods)['result'])
def test_call_requests_batch_all_notifications(): """Should return a BatchResponse response, an empty list""" response = call_requests( { Request(**{"jsonrpc": "2.0", "method": "notify_sum", "params": [1, 2, 4]}), Request(**{"jsonrpc": "2.0", "method": "notify_hello", "params": [7]}), }, Methods(ping), debug=True, ) assert str(response) == ""
def test_keywords(self): def get_name(**kwargs): return kwargs['name'] req = Request({ 'jsonrpc': '2.0', 'method': 'get_name', 'params': { 'name': 'foo' }, 'id': 1 }) self.assertEqual('foo', req.call([get_name])['result'])
def test_validate_result_object_method(): class FooClass: def foo(self, one, two): return "bar" f = FooClass().foo assert validate_args(Request("f", ["one", "two"], NOID), NOCONTEXT, f) == Right(f)
def test_call_raising_exception(): def method(): raise ValueError("foo") assert call(Request("ping", [], 1), NOCONTEXT, method) == Left( ErrorResult(ERROR_INTERNAL_ERROR, "Internal error", "foo") )
def test_positional(self): self.assertEqual(([2, 3], None), Request._get_arguments({ 'jsonrpc': '2.0', 'method': 'foo', 'params': [2, 3] }))
def test_call_raising_jsonrpcerror(): def method(): raise JsonRpcError(code=1, message="foo", data=NODATA) assert call(Request("ping", [], 1), NOCONTEXT, method) == Left( ErrorResult(1, "foo") )
def test_safe_call_invalid_args(): response = safe_call( Request(method="ping", params=[1], id=1), Methods(ping), debug=True, serialize=default_serialize, ) assert isinstance(response, InvalidParamsResponse)
def test_safe_call_notification(): response = safe_call( Request(method="ping", params=[], id=NOID), Methods(ping), extra=None, serialize=default_serialize, ) assert isinstance(response, NotificationResponse)
def test_convert_camel_case_positional_args(self): config.convert_camel_case = True req = Request({ 'jsonrpc': '2.0', 'method': 'foo', 'params': ['Camel', 'Case'] }) self.assertEqual(['Camel', 'Case'], req.args)
def test_safe_call_method_not_found(): response = safe_call( Request(method="nonexistant", id=1), Methods(ping), debug=True, serialize=default_serialize, ) assert isinstance(response, MethodNotFoundResponse)
def test_keywords(self): def get_name(**kwargs): return kwargs['name'] req = Request({'jsonrpc': '2.0', 'method': 'get_name', 'params': {'name': 'foo'}, 'id': 1}) self.assertEqual('foo', req.call([get_name])['result'])
def test_none(self): self.assertEqual((None, None), Request._get_arguments( {'jsonrpc': '2.0', 'method': 'foo'}))
def test_positional(self): self.assertEqual(([2, 3], None), Request._get_arguments( {'jsonrpc': '2.0', 'method': 'foo', 'params': [2, 3]}))
def test_keyword(self): self.assertEqual((None, {'foo': 'bar'}), Request._get_arguments( {'jsonrpc': '2.0', 'method': 'foo', 'params': {'foo': 'bar'}}))
def test_dict_non_existant(self): def cat(): pass # pylint: disable=multiple-statements with self.assertRaises(MethodNotFound): Request._get_method({'cat_says': cat}, 'cat')
def test_dict_lambdas(self): req = Request({'jsonrpc': '2.0', 'method': 'baz', 'id': 1}) self.assertEqual('bar', req.call({'baz': lambda: 'bar'})['result'])
def test_dict_functions(self): req = Request({'jsonrpc': '2.0', 'method': 'baz', 'id': 1}) self.assertEqual('bar', req.call({'baz': foo})['result'])
def test_positionals(): req = Request({'jsonrpc': '2.0', 'method': 'foo', 'params': [1]}) req._validate_arguments_against_signature(lambda x: None)
def test_positionals_not_passed(self): req = Request({'jsonrpc': '2.0', 'method': 'foo', 'params': {'foo': 'bar'}}) with self.assertRaises(InvalidParams): req._validate_arguments_against_signature(lambda x: None)
def test_keywords(): req = Request({'jsonrpc': '2.0', 'method': 'foo', 'params': {'foo': 'bar'}}) req._validate_arguments_against_signature(lambda **kwargs: None)
def test_list_lambdas(self): foo = lambda: 'bar' # pylint: disable=redefined-outer-name foo.__name__ = 'foo' req = Request({'jsonrpc': '2.0', 'method': 'foo', 'id': 1}) self.assertEqual('bar', req.call([foo])['result'])
def test_methods_lambdas(self): methods = Methods() methods.add(lambda: 'bar', 'foo') req = Request({'jsonrpc': '2.0', 'method': 'foo', 'id': 1}) self.assertEqual('bar', req.call(methods)['result'])
def test_positionals(self): methods = Methods() methods.add(lambda x: x * x, 'square') req = Request({'jsonrpc': '2.0', 'method': 'square', 'params': [3], 'id': 1}) self.assertEqual(9, req.call(methods)['result'])
def test_list_partials(self): multiply = lambda x, y: x * y double = partial(multiply, 2) double.__name__ = 'double' req = Request({'jsonrpc': '2.0', 'method': 'double', 'params': [3], 'id': 1}) self.assertEqual(6, req.call([double])['result'])
def test_no_arguments_too_many_positionals(self): req = Request({'jsonrpc': '2.0', 'method': 'foo', 'params': ['foo']}) with self.assertRaises(InvalidParams): req._validate_arguments_against_signature(lambda: None)
def dispatch(methods, request): """Dispatch JSON-RPC requests to a collection of methods:: r = dispatch([cat, dog], {'jsonrpc': '2.0', 'method': 'cat', 'id': 1}) The first parameter can be either: - A *list* of methods, or - A *dictionary* of name:method pairs. When using a **list**, the methods must be identifiable by a ``__name__`` attribute. Functions already have a ``__name__`` attribute:: >>> def cat(): ... return 'meow' ... >>> cat.__name__ 'cat' >>> dispatch([cat], ...) Lambdas require setting it:: >>> cat = lambda: 'meow' >>> cat.__name__ = 'cat' >>> dispatch([cat], ...) As do partials:: >>> max_ten = partial(min, 10) >>> max_ten.__name__ = 'max_ten' >>> dispatch([max_ten], ...) Alternatively, use a **dictionary**:: >>> dispatch({'cat': cat, 'max_ten': max_ten}, ...) The :mod:`methods` module also gives nice and easy ways to build the collection of methods. :param methods: Collection of methods to dispatch to. :param request: JSON-RPC request - can be a JSON-serializable object, or a string. Strings must be valid json (use double quotes!). :returns: A :mod:`response` object. """ # Process the request response = None try: # Log the request request_log.info(request) # If the request is a string, convert it to a dict first if isinstance(request, string_types): request = _string_to_dict(request) # Batch requests if isinstance(request, list): # An empty list is invalid if len(request) == 0: raise InvalidRequest() # Process each request response = BatchResponse() for r in request: try: req = Request(r) except InvalidRequest as e: resp = ExceptionResponse(e, None) else: resp = req.process(methods) response.append(resp) # Remove Notification responses response = BatchResponse( [r for r in response if not isinstance( r, NotificationResponse)]) # "Nothing is returned for all notification batches" if not response: response = NotificationResponse() # pylint: disable=redefined-variable-type # Single request else: response = Request(request).process(methods) except JsonRpcServerError as e: response = ExceptionResponse(e, None) # Batch requests can have mixed results, just return 200 http_status = 200 if isinstance(request, list) else response.http_status # Log the response response_log.info(str(response), extra={ 'http_code': http_status, 'http_reason': HTTP_STATUS_CODES[http_status]}) return response
def test_list_functions(self): req = Request({'jsonrpc': '2.0', 'method': 'foo', 'id': 1}) self.assertEqual('bar', req.call([foo])['result'])
def test_no_arguments(): req = Request({'jsonrpc': '2.0', 'method': 'foo'}) req._validate_arguments_against_signature(lambda: None)
def test_config_notification_errors_on(self): # Should return "method not found" error request = Request({'jsonrpc': '2.0', 'method': 'baz'}) config.notification_errors = True req = request.call([foo]) self.assertIsInstance(req, ErrorResponse)
def test_invalid_string(self): with self.assertRaises(InvalidParams): Request._get_arguments({'jsonrpc': '2.0', 'method': 'foo', 'params': 'str'})
def test_dict_partials(self): multiply = lambda x, y: x * y req = Request({'jsonrpc': '2.0', 'method': 'baz', 'params': [3], 'id': 1}) self.assertEqual(6, req.call({'baz': partial(multiply, 2)})['result'])