diff --git a/jsonrpcserver/async_dispatcher.py b/jsonrpcserver/async_dispatcher.py index 18dc2a0..ffa0fa8 100644 --- a/jsonrpcserver/async_dispatcher.py +++ b/jsonrpcserver/async_dispatcher.py @@ -9,6 +9,7 @@ from jsonschema import ValidationError # type: ignore from .dispatcher import ( + Context, add_handlers, config, create_requests, @@ -35,12 +36,20 @@ async def call(method: Method, *args: Any, **kwargs: Any) -> Any: async def safe_call( - request: Request, methods: Methods, *, debug: bool, serialize: Callable + request: Request, methods: Methods, *, debug: bool, extra: Any, serialize: Callable ) -> Response: with handle_exceptions(request, debug) as handler: - result = await call( - lookup(methods, request.method), *request.args, **request.kwargs - ) + if isinstance(request.params, list): + result = await call( + lookup(methods, request.method), + *([Context(request=request, extra=extra)] + request.params), + ) + else: + result = await call( + lookup(methods, request.method), + Context(request=request, extra=extra), + **request.params, + ) # Ensure value returned from the method is JSON-serializable. If not, # handle_exception will set handler.response to an ExceptionResponse serialize(result) @@ -54,22 +63,26 @@ async def call_requests( requests: Union[Request, Iterable[Request]], methods: Methods, debug: bool, + extra: Any, serialize: Callable, ) -> Response: if isinstance(requests, collections.abc.Iterable): responses = ( - safe_call(r, methods, debug=debug, serialize=serialize) for r in requests + safe_call(r, methods, debug=debug, extra=extra, serialize=serialize) + for r in requests ) return BatchResponse(await asyncio.gather(*responses), serialize_func=serialize) - return await safe_call(requests, methods, debug=debug, serialize=serialize) + return await safe_call( + requests, methods, debug=debug, extra=extra, serialize=serialize + ) async def dispatch_pure( request: str, methods: Methods, *, - context: Any, debug: bool, + extra: Any, serialize: Callable, deserialize: Callable, ) -> Response: @@ -80,9 +93,10 @@ async def dispatch_pure( except ValidationError as exc: return InvalidJSONRPCResponse(data=None, debug=debug) return await call_requests( - create_requests(deserialized, context=context), + create_requests(deserialized), methods, debug=debug, + extra=extra, serialize=serialize, ) @@ -93,8 +107,8 @@ async def dispatch( methods: Optional[Methods] = None, *, basic_logging: bool = False, - context: Optional[dict] = None, debug: bool = False, + extra: Optional[Any] = None, trim_log_values: bool = False, serialize: Callable = default_serialize, deserialize: Callable = default_deserialize, @@ -110,7 +124,7 @@ async def dispatch( request, methods, debug=debug, - context=context, + extra=extra, serialize=serialize, deserialize=deserialize, ) diff --git a/jsonrpcserver/dispatcher.py b/jsonrpcserver/dispatcher.py index c6a9723..97e4b81 100644 --- a/jsonrpcserver/dispatcher.py +++ b/jsonrpcserver/dispatcher.py @@ -22,9 +22,9 @@ List, NamedTuple, Optional, - Set, Tuple, Union, + cast, ) from apply_defaults import apply_config # type: ignore @@ -234,14 +234,18 @@ def call_requests( ) if isinstance(requests, list) else safe_call( - requests, methods=methods, debug=debug, extra=extra, serialize=serialize + cast(Request, requests), + methods, + debug=debug, + extra=extra, + serialize=serialize, ) ) def create_requests( requests: Union[Dict, List[Dict]], -) -> Union[Request, Set[Request]]: +) -> Union[Request, List[Request]]: """ Converts a raw deserialized request dictionary to a Request (namedtuple). @@ -316,7 +320,7 @@ def dispatch( methods: Optional[Methods] = None, *, basic_logging: bool = False, - extra: Optional[dict] = None, + extra: Optional[Any] = None, debug: bool = False, trim_log_values: bool = False, serialize: Callable = default_serialize, diff --git a/jsonrpcserver/methods.py b/jsonrpcserver/methods.py index e830368..c88bdad 100644 --- a/jsonrpcserver/methods.py +++ b/jsonrpcserver/methods.py @@ -85,18 +85,19 @@ def decorator(method): return decorator def _batch_add(self, *args: Any, **kwargs: Any) -> Optional[Callable]: - # Multiple loops here, but due to changes in dictionary comprehension evaluation - # order in Python 3.8 (PEP 572), we need to validate separately from the - # dictionary comprehension. Otherwise different exceptions will be raised in 3.8 - # vs earlier Pythons, depending on evaluation order. + # Multiple loops here, but due to changes in dictionary comprehension + # evaluation order in Python 3.8 (PEP 572), we need to validate + # separately from the dictionary comprehension. Otherwise different + # exceptions will be raised in 3.8 vs earlier Pythons, depending on + # evaluation order. for m in args: assert callable(m) for _, m in kwargs.items(): assert callable(m) self.items = { **self.items, - # Methods passed as positional args need a __name__ attribute, raises - # AttributeError otherwise. + # Methods passed as positional args need a __name__ attribute, + # raises AttributeError otherwise. **{m.__name__: m for m in args}, **{k: v for k, v in kwargs.items()}, }