diff --git a/src/descanso/jsonrpc.py b/src/descanso/jsonrpc.py index 2dcbd0b..df16775 100644 --- a/src/descanso/jsonrpc.py +++ b/src/descanso/jsonrpc.py @@ -291,6 +291,7 @@ def _add_body_transformer(self, spec: MethodSpec): self._add_request_transformer(spec, Body(field.name)) def _add_default_request_body_transformers(self, spec: MethodSpec): + self._add_default_jsonrpc_method(spec) self._add_body_transformer(spec) if self._get_body_field(spec): @@ -357,6 +358,19 @@ def _add_default_response_transformers(self, spec: MethodSpec) -> None: BodyModelLoad(spec.result_type, loader=loader), ) + def _add_default_jsonrpc_method(self, spec: MethodSpec) -> None: + jsonrpc_method_field = next( + ( + field + for field in spec.fields_out + if field.name == EXTRA_JSON_RPC_METHOD + and field.dest is FieldDestination.EXTRA + ), + None, + ) + if jsonrpc_method_field is None: + self._add_request_transformer(spec, JsonRPCMethod(spec.name)) + @overload def decorate( self, @@ -403,14 +417,15 @@ def __call__( @overload def __call__( self, - method: str, + parameter: Transformer | str | None = None, *transformers: Transformer, + method: str | None = None, **params: Unpack[BuilderParams], ) -> "JsonRPCBuilder": ... def __call__( self, - func_or_method: str | Callable, + func_or_parameter: Callable | Transformer | str | None = None, *transformers: Transformer, **params: Unpack[BuilderParams], ) -> Any: @@ -418,7 +433,16 @@ def __call__( instance = self.with_params(*transformers, **params) else: instance = self - if isinstance(func_or_method, str): - return instance.with_params(JsonRPCMethod(func_or_method)) + + if func_or_parameter is None: + return instance + elif isinstance(func_or_parameter, str): + return instance.with_params( + JsonRPCMethod(func_or_parameter), + ) + elif isinstance(func_or_parameter, Transformer): + return instance.with_params( + func_or_parameter, + ) else: - return instance.decorate(func_or_method) + return instance.decorate(func_or_parameter) diff --git a/tests/builders/test_jsonrpc.py b/tests/builders/test_jsonrpc.py index a419110..cf5e900 100644 --- a/tests/builders/test_jsonrpc.py +++ b/tests/builders/test_jsonrpc.py @@ -1,3 +1,5 @@ +from dirty_equals import IsList + from descanso import JsonRPCBuilder from descanso.jsonrpc import ( JsonRPCErrorRaiser, @@ -130,3 +132,47 @@ def do(self, data: int) -> Model: dirty[JsonRPCErrorRaiser](), dirty[UnpackJsonRPC](), ] + + +def test_default_jsonrpc_method() -> None: + jsonrpc = JsonRPCBuilder(url="/foo") + + class Api: + @jsonrpc + def do(self, data: int) -> Model:... + + @jsonrpc() + def work(self, data: int) -> Model:... + + + assert Api.do.spec.request_transformers == IsList( + dirty[JsonRPCMethod](method="do"), + length=..., + ) + assert Api.work.spec.request_transformers == IsList( + dirty[JsonRPCMethod](method="work"), + length=..., + ) + + +def test_default_jsonrpc_method_with_transformers_and_params() -> None: + jsonrpc = JsonRPCBuilder(url="/foo") + req_transformer = Skip("0") + res_transformer = ErrorRaiser(codes=[200]) + + class Api: + @jsonrpc(req_transformer, res_transformer, url="/bar") + def do(self, data: int) -> Model:... + + assert Api.do.spec.request_transformers == IsList( + dirty[JsonRPCMethod](method="do"), + req_transformer, + dirty[Url](original_template="/bar"), + check_order=False, + length=..., + ) + assert Api.do.spec.response_transformers == IsList( + res_transformer, + check_order=False, + length=..., + )