jsonrpcserver 5.0.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
jsonrpcserver/main.py ADDED
@@ -0,0 +1,308 @@
1
+ """The dispatch functions.
2
+
3
+ All three take a JSON-RPC request string, call the methods and give the response.
4
+ They differ only in the form of the response:
5
+
6
+ - dispatch_to_response gives Response objects, or None for a notification.
7
+ - dispatch_to_serializable gives a dict or a list of dicts, or None for a
8
+ notification.
9
+ - dispatch_to_json, also called dispatch, gives a JSON string, or an empty string
10
+ for a notification.
11
+ """
12
+
13
+ import json
14
+ import logging
15
+ import pkgutil
16
+ from typing import Any, Callable, Dict, List, Optional, Union, cast
17
+
18
+ from jsonschema.validators import validator_for
19
+
20
+ from .codes import ERROR_INTERNAL_ERROR
21
+ from .dispatcher import (
22
+ Deserialized,
23
+ check_max_batch_size,
24
+ dispatch_to_response_pure,
25
+ exception_data,
26
+ )
27
+
28
+ # Importable from here in 5.0.9. The "as" form marks a re-export.
29
+ from .methods import Methods as Methods
30
+ from .methods import MethodsArgument, global_methods
31
+ from .response import (
32
+ Response,
33
+ to_dict,
34
+ )
35
+ from .response import (
36
+ # Importable from here in 5.0.9. The "as" form marks it as a re-export.
37
+ to_serializable_one as to_serializable_one,
38
+ )
39
+ from .sentinels import NOCONTEXT, NODATA
40
+ from .utils import identity
41
+
42
+ logger = logging.getLogger(__name__)
43
+
44
+ default_deserializer = json.loads
45
+
46
+
47
+ def default_serializer(response: Any) -> str:
48
+ """json.dumps, but NaN and Infinity raise ValueError instead of producing output
49
+ that isn't valid JSON.
50
+ """
51
+ return json.dumps(response, allow_nan=False)
52
+
53
+
54
+ def serialize_one(
55
+ serializer: Callable[[Any], str], response: Dict[str, Any], debug: bool
56
+ ) -> str:
57
+ """Serialize one response. If that fails, serialize an Internal error for the same
58
+ request instead, so the client still gets a valid JSON-RPC response.
59
+ """
60
+ try:
61
+ return serializer(response)
62
+ except Exception as exc:
63
+ logger.exception(
64
+ "Could not serialize the response for request id %r", response.get("id")
65
+ )
66
+ data = exception_data(exc, debug)
67
+ error: Dict[str, Any] = {
68
+ "jsonrpc": "2.0",
69
+ "error": {
70
+ "code": ERROR_INTERNAL_ERROR,
71
+ "message": "Internal error",
72
+ **({} if data is NODATA else {"data": data}),
73
+ },
74
+ "id": response.get("id"),
75
+ }
76
+ try:
77
+ return serializer(error)
78
+ except Exception:
79
+ # The id itself can't be serialized (for example it was 1e400, which
80
+ # json.loads reads as infinity).
81
+ error["id"] = None
82
+ return json.dumps(error)
83
+
84
+
85
+ def serialize(
86
+ serializer: Callable[[Any], str],
87
+ response: Union[Dict[str, Any], List[Dict[str, Any]]],
88
+ debug: bool,
89
+ ) -> str:
90
+ """Serialize a response or batch of responses.
91
+
92
+ A response that can't be serialized becomes an Internal error response. In a batch,
93
+ the other responses are kept.
94
+ """
95
+ try:
96
+ return serializer(response)
97
+ except Exception:
98
+ if isinstance(response, list):
99
+ return (
100
+ "["
101
+ + ", ".join(serialize_one(serializer, r, debug) for r in response)
102
+ + "]"
103
+ )
104
+ return serialize_one(serializer, response, debug)
105
+
106
+
107
+ # Prepare the jsonschema validator. This is global so it loads only once, not every
108
+ # time dispatch is called.
109
+ # pkgutil.get_data works on every supported Python, and inside zip files and frozen
110
+ # apps. importlib.resources.read_text is deprecated on 3.11 and 3.12.
111
+ schema = json.loads(
112
+ pkgutil.get_data(__name__.rpartition(".")[0], "request-schema.json") or b""
113
+ )
114
+ klass = validator_for(schema)
115
+ klass.check_schema(schema)
116
+ default_validator = klass(schema).validate
117
+
118
+
119
+ def dispatch_to_response(
120
+ request: str,
121
+ methods: Optional[MethodsArgument] = None,
122
+ *,
123
+ context: Any = NOCONTEXT,
124
+ deserializer: Callable[[str], Deserialized] = json.loads,
125
+ validator: Callable[[Deserialized], object] = default_validator,
126
+ post_process: Callable[[Response], Any] = identity,
127
+ debug: bool = False,
128
+ max_batch_size: Optional[int] = None,
129
+ ) -> Union[Response, List[Response], None]:
130
+ """Dispatch a request and give the response as Response objects.
131
+
132
+ Most code wants `dispatch` (a JSON string) or `dispatch_to_serializable` (dicts)
133
+ instead. Use this one to inspect or change responses before they're serialized.
134
+
135
+ Each Response is an oslash `Right` holding a `SuccessResponse`, or a `Left`
136
+ holding an `ErrorResponse`. oslash has no public way to read them, so check
137
+ `isinstance(response, Left)` and read `response._error` or `response._value`.
138
+ These attributes are stable for all of 5.x. Printing a Response raises
139
+ `TypeError`, because of a bug in oslash; print `to_dict(response)` instead.
140
+
141
+ Args:
142
+ request: The JSON-RPC request string.
143
+ methods: The methods requests can call, as a dict (or any mapping) of names
144
+ to functions. The default is the dict that `@method` fills in,
145
+ `jsonrpcserver.methods.global_methods`.
146
+ context: If given, it's passed as the first argument to every method. The
147
+ client can't see or set it.
148
+ deserializer: The function that parses the request string. The default is
149
+ `json.loads`. If it raises, the client gets a -32700 Parse error whose
150
+ `data` is the exception message.
151
+ validator: The function that checks a parsed request against the JSON-RPC
152
+ spec. It should raise an exception, of any kind, if the request is
153
+ invalid. In a batch it's called once for each request (new in 5.0.10).
154
+ The default checks against a JSON schema. `lambda _: None` turns
155
+ validation off.
156
+ post_process: A function applied to each Response before it's returned.
157
+ debug: If True, the error response for an exception a method doesn't catch
158
+ includes the exception message in `data`. The default leaves `data`
159
+ out, because exception messages can contain passwords, file paths and
160
+ other details a client shouldn't see. The exception is logged either
161
+ way. New in 5.0.10.
162
+ max_batch_size: The most requests a batch may hold. A bigger batch gets a
163
+ single -32600 Invalid request response, and none of it is run. The
164
+ default, None, means no limit. A server open to the internet should set
165
+ one, such as 100. New in 5.0.10.
166
+
167
+ Returns:
168
+ A Response for a single request, a list of Responses for a batch, or None
169
+ if there's nothing to send back (a notification, or a batch of only
170
+ notifications). With `post_process`, whatever it returns for each.
171
+
172
+ Raises:
173
+ ValueError: If `max_batch_size` isn't None or a positive int. Requests never
174
+ raise: a bad request or a failing method gives an error response.
175
+ """
176
+ check_max_batch_size(max_batch_size)
177
+ response = dispatch_to_response_pure(
178
+ deserializer=deserializer,
179
+ validator=validator,
180
+ post_process=post_process,
181
+ context=context,
182
+ methods=global_methods if methods is None else methods,
183
+ request=request,
184
+ debug=debug,
185
+ max_batch_size=max_batch_size,
186
+ )
187
+ return cast(Union[Response, List[Response], None], response)
188
+
189
+
190
+ def dispatch_to_serializable(
191
+ request: str,
192
+ methods: Optional[MethodsArgument] = None,
193
+ *,
194
+ context: Any = NOCONTEXT,
195
+ deserializer: Callable[[str], Deserialized] = default_deserializer,
196
+ validator: Callable[[Deserialized], object] = default_validator,
197
+ debug: bool = False,
198
+ max_batch_size: Optional[int] = None,
199
+ ) -> Union[Dict[str, Any], List[Dict[str, Any]], None]:
200
+ """Dispatch a request and give the response as a dict.
201
+
202
+ Use it when your framework serializes the response itself, such as a Django
203
+ `JsonResponse`, or when you want to inspect it.
204
+
205
+ Args:
206
+ request: The JSON-RPC request string.
207
+ methods: The same as for `dispatch_to_response`.
208
+ context: The same as for `dispatch_to_response`.
209
+ deserializer: The same as for `dispatch_to_response`.
210
+ validator: The same as for `dispatch_to_response`.
211
+ debug: The same as for `dispatch_to_response`.
212
+ max_batch_size: The same as for `dispatch_to_response`.
213
+
214
+ Returns:
215
+ The response as a dict, a list of dicts for a batch, or None if there's
216
+ nothing to send back.
217
+
218
+ Raises:
219
+ ValueError: If `max_batch_size` isn't None or a positive int.
220
+
221
+ Example:
222
+ >>> from jsonrpcserver import Result, Success, dispatch_to_serializable
223
+ >>> def ping() -> Result:
224
+ ... return Success("pong")
225
+ >>> dispatch_to_serializable(
226
+ ... '{"jsonrpc": "2.0", "method": "ping", "id": 1}', methods={"ping": ping}
227
+ ... )
228
+ {'jsonrpc': '2.0', 'result': 'pong', 'id': 1}
229
+ """
230
+ return cast(
231
+ Union[Dict[str, Any], List[Dict[str, Any]], None],
232
+ dispatch_to_response(
233
+ request,
234
+ methods,
235
+ context=context,
236
+ deserializer=deserializer,
237
+ validator=validator,
238
+ debug=debug,
239
+ max_batch_size=max_batch_size,
240
+ post_process=to_dict,
241
+ ),
242
+ )
243
+
244
+
245
+ def dispatch_to_json(
246
+ request: str,
247
+ methods: Optional[MethodsArgument] = None,
248
+ *,
249
+ context: Any = NOCONTEXT,
250
+ deserializer: Callable[[str], Deserialized] = default_deserializer,
251
+ validator: Callable[[Deserialized], object] = default_validator,
252
+ debug: bool = False,
253
+ max_batch_size: Optional[int] = None,
254
+ serializer: Callable[
255
+ [Union[Dict[str, Any], List[Dict[str, Any]], str]], str
256
+ ] = default_serializer,
257
+ ) -> str:
258
+ """Dispatch a request and give the response as a JSON string.
259
+
260
+ This is `dispatch`, the function most code uses. Send the string back to the
261
+ client. An empty string means there's nothing to send back: the request was a
262
+ notification, or a batch of only notifications. Over HTTP, send status 204 with
263
+ no body for that.
264
+
265
+ Args:
266
+ request: The JSON-RPC request string.
267
+ methods: The same as for `dispatch_to_response`.
268
+ context: The same as for `dispatch_to_response`.
269
+ deserializer: The same as for `dispatch_to_response`.
270
+ validator: The same as for `dispatch_to_response`.
271
+ debug: The same as for `dispatch_to_response`.
272
+ max_batch_size: The same as for `dispatch_to_response`.
273
+ serializer: The function that turns the response into a string. The
274
+ default is `json.dumps` with `allow_nan=False`, so a result holding NaN
275
+ or Infinity gives an Internal error instead of invalid JSON (new in
276
+ 5.0.10). If the serializer raises for a response, say because the
277
+ method returned a `datetime`, that response becomes an Internal error
278
+ and the rest of a batch is sent as usual.
279
+
280
+ Returns:
281
+ The response as a JSON string, or "" if there's nothing to send back.
282
+
283
+ Raises:
284
+ ValueError: If `max_batch_size` isn't None or a positive int.
285
+
286
+ Example:
287
+ >>> from jsonrpcserver import Result, Success, dispatch
288
+ >>> def ping() -> Result:
289
+ ... return Success("pong")
290
+ >>> dispatch('{"jsonrpc": "2.0", "method": "ping", "id": 1}', {"ping": ping})
291
+ '{"jsonrpc": "2.0", "result": "pong", "id": 1}'
292
+ """
293
+ response = dispatch_to_serializable(
294
+ request,
295
+ methods,
296
+ context=context,
297
+ deserializer=deserializer,
298
+ validator=validator,
299
+ debug=debug,
300
+ max_batch_size=max_batch_size,
301
+ )
302
+ # Better to respond with the empty string instead of json "null", because "null" is
303
+ # an invalid JSON-RPC response.
304
+ return "" if response is None else serialize(serializer, response, debug)
305
+
306
+
307
+ dispatch = dispatch_to_json
308
+ """Another name for `dispatch_to_json`, and the one most code uses."""
@@ -0,0 +1,91 @@
1
+ """Methods: the functions a JSON-RPC request can call.
2
+
3
+ The dispatch functions look methods up in a dict of names to functions. The @method
4
+ decorator adds a function to global_methods, the dict they use by default. To use
5
+ your own dict instead, pass it as the methods argument:
6
+
7
+ dispatch(request) # the functions registered with @method
8
+ dispatch(request, methods={"ping": ping}) # only the functions in this dict
9
+
10
+ Either way, a method returns Success(...) or Error(...), not a plain value.
11
+
12
+ A request's params are either a list (positional arguments) or an object (named
13
+ arguments), not both. That's a JSON-RPC rule.
14
+ """
15
+
16
+ import warnings
17
+ from typing import Any, Callable, Dict, Mapping, Optional, TypeVar, overload
18
+
19
+ from .result import Result
20
+
21
+ Method = Callable[..., Result]
22
+ Methods = Dict[str, Method]
23
+ # Async methods return a coroutine rather than a Result, so the dispatch functions
24
+ # accept any callable. They check what comes back at run time.
25
+ AnyMethod = Callable[..., Any]
26
+ # What the dispatch functions accept for their methods argument. Any mapping will do.
27
+ MethodsArgument = Mapping[str, AnyMethod]
28
+
29
+ global_methods: Dict[str, AnyMethod] = {}
30
+ """The methods registered with `@method`, as a dict of names to functions.
31
+
32
+ The dispatch functions use it when they're called without `methods`. It's shared by
33
+ the whole process, so every module that uses `@method` adds to it.
34
+ """
35
+
36
+ F = TypeVar("F", bound=Callable[..., Any])
37
+
38
+
39
+ @overload
40
+ def method(f: F, name: Optional[str] = None) -> F: ...
41
+
42
+
43
+ @overload
44
+ def method(f: None = None, name: Optional[str] = None) -> Callable[[F], F]: ...
45
+
46
+
47
+ def method(f: Optional[F] = None, name: Optional[str] = None) -> Any:
48
+ """Register a function as a JSON-RPC method.
49
+
50
+ The function is added to `global_methods`, which the dispatch functions use when
51
+ they're called without `methods`. It's returned unchanged, so you can still call
52
+ it yourself, and type checkers see its real signature (from 5.0.10). A method
53
+ with the same name as an earlier one replaces it, without a warning.
54
+
55
+ Use it with or without arguments:
56
+
57
+ ```python
58
+ @method
59
+ def ping() -> Result:
60
+ return Success("pong")
61
+
62
+ @method(name="sum")
63
+ def add(a: int, b: int) -> Result:
64
+ return Success(a + b)
65
+ ```
66
+
67
+ Args:
68
+ f: The function. Leave it out to pass `name`.
69
+ name: The name requests use to call the method. The default is the
70
+ function's name.
71
+
72
+ Returns:
73
+ The function itself, or, when called with only `name`, a decorator.
74
+
75
+ Warns:
76
+ UserWarning: If the name starts with "rpc.". The JSON-RPC spec reserves those
77
+ names. New in 5.0.10.
78
+ """
79
+
80
+ def decorator(func: F) -> F:
81
+ method_name = func.__name__ if name is None else name
82
+ if method_name.startswith("rpc."):
83
+ warnings.warn(
84
+ f"Method names starting with 'rpc.' are reserved by the JSON-RPC spec "
85
+ f"({method_name!r})",
86
+ stacklevel=3 if callable(f) else 2,
87
+ )
88
+ global_methods[method_name] = func
89
+ return func
90
+
91
+ return decorator(f) if callable(f) else decorator
jsonrpcserver/py.typed ADDED
File without changes
@@ -0,0 +1,39 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "description": "A JSON RPC 2.0 request",
4
+ "oneOf": [
5
+ {
6
+ "description": "An individual request",
7
+ "$ref": "#/definitions/request"
8
+ },
9
+ {
10
+ "description": "An array of requests",
11
+ "type": "array",
12
+ "items": { "$ref": "#/definitions/request" },
13
+ "minItems": 1
14
+ }
15
+ ],
16
+ "definitions": {
17
+ "request": {
18
+ "type": "object",
19
+ "required": [ "jsonrpc", "method" ],
20
+ "properties": {
21
+ "jsonrpc": { "enum": [ "2.0" ] },
22
+ "method": {
23
+ "type": "string"
24
+ },
25
+ "id": {
26
+ "type": [ "string", "number", "null" ],
27
+ "note": [
28
+ "While allowed, null should be avoided: http://www.jsonrpc.org/specification#id1",
29
+ "While allowed, a number with a fractional part should be avoided: http://www.jsonrpc.org/specification#id2"
30
+ ]
31
+ },
32
+ "params": {
33
+ "type": [ "array", "object" ]
34
+ }
35
+ },
36
+ "additionalProperties": false
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,15 @@
1
+ """A simple namedtuple to hold a request.
2
+
3
+ After parsing a request string, we put the (dict) requests into these Request
4
+ namedtuples, simply because they're nicer to work with.
5
+ """
6
+
7
+ from typing import Any, Dict, List, NamedTuple, Union
8
+
9
+
10
+ class Request(NamedTuple):
11
+ """JSON-RPC Request"""
12
+
13
+ method: str
14
+ params: Union[List[Any], Dict[str, Any]]
15
+ id: Any # Use NOID for a Notification.
@@ -0,0 +1,170 @@
1
+ """Responses: what dispatch_to_response gives, and how to turn them into dicts.
2
+
3
+ A Response is a Result plus the request's id
4
+ (https://www.jsonrpc.org/specification#response_object).
5
+ """
6
+
7
+ import warnings
8
+ from typing import Any, Dict, List, NamedTuple, Type, Union, cast
9
+
10
+ from oslash.either import Either, Left, Right
11
+
12
+ from .codes import (
13
+ ERROR_INVALID_REQUEST,
14
+ ERROR_METHOD_NOT_FOUND,
15
+ ERROR_PARSE_ERROR,
16
+ ERROR_SERVER_ERROR,
17
+ )
18
+ from .sentinels import NODATA
19
+
20
+ Deserialized = Union[Dict[str, Any], List[Dict[str, Any]]]
21
+
22
+
23
+ class SuccessResponse(NamedTuple):
24
+ """A successful response: the method's result and the request's id."""
25
+
26
+ result: Any
27
+ id: Any
28
+
29
+
30
+ class ErrorResponse(NamedTuple):
31
+ """An error response: the error's code, message and data, and the request's id.
32
+
33
+ `data` is `NODATA` when there's no data, so it's left out of the response. `id`
34
+ is None when the request couldn't be read, as the spec requires.
35
+ """
36
+
37
+ code: int
38
+ message: str
39
+ data: Any
40
+ id: Any
41
+
42
+
43
+ # oslash's Either takes the success type first, then the error type.
44
+ Response = Either[SuccessResponse, ErrorResponse]
45
+ """What `dispatch_to_response` gives for each request.
46
+
47
+ An oslash `Either`: a `Right` holding a `SuccessResponse`, or a `Left` holding an
48
+ `ErrorResponse`. To read one, check `isinstance(response, Left)`, then read
49
+ `response._error` (an `ErrorResponse`) or `response._value` (a `SuccessResponse`).
50
+ oslash has no public accessor, but these attributes are stable for all of 5.x. Or turn
51
+ it into a dict with `to_dict`.
52
+ """
53
+ ResponseType = Type[Response]
54
+ """Deprecated: use `Response`. Kept so code written for 5.0.9 keeps working."""
55
+
56
+
57
+ def ParseErrorResponse(data: Any) -> ErrorResponse: # pylint: disable=invalid-name
58
+ """An ErrorResponse with most attributes already populated.
59
+
60
+ From the spec: "This (id) member is REQUIRED. It MUST be the same as the value of
61
+ the id member in the Request Object. If there was an error in detecting the id in
62
+ the Request object (e.g. Parse error/Invalid Request), it MUST be Null."
63
+ """
64
+ return ErrorResponse(ERROR_PARSE_ERROR, "Parse error", data, None)
65
+
66
+
67
+ def InvalidRequestResponse(data: Any) -> ErrorResponse: # pylint: disable=invalid-name
68
+ """An ErrorResponse with most attributes already populated.
69
+
70
+ From the spec: "This (id) member is REQUIRED. It MUST be the same as the value of
71
+ the id member in the Request Object. If there was an error in detecting the id in
72
+ the Request object (e.g. Parse error/Invalid Request), it MUST be Null."
73
+ """
74
+ return ErrorResponse(ERROR_INVALID_REQUEST, "Invalid request", data, None)
75
+
76
+
77
+ def MethodNotFoundResponse(data: Any, id: Any) -> ErrorResponse:
78
+ """An ErrorResponse with some attributes already populated."""
79
+ # pylint: disable=invalid-name,redefined-builtin
80
+ return ErrorResponse(ERROR_METHOD_NOT_FOUND, "Method not found", data, id)
81
+
82
+
83
+ def ServerErrorResponse(data: Any, id: Any) -> ErrorResponse:
84
+ """An ErrorResponse with some attributes already populated."""
85
+ # pylint: disable=invalid-name,redefined-builtin
86
+ return ErrorResponse(ERROR_SERVER_ERROR, "Server error", data, id)
87
+
88
+
89
+ def to_error_dict(response: ErrorResponse) -> Dict[str, Any]:
90
+ """Turn an ErrorResponse into a JSON-RPC response dict, leaving out missing data."""
91
+ return {
92
+ "jsonrpc": "2.0",
93
+ "error": {
94
+ "code": response.code,
95
+ "message": response.message,
96
+ # "data" may be omitted.
97
+ **({"data": response.data} if response.data is not NODATA else {}),
98
+ },
99
+ "id": response.id,
100
+ }
101
+
102
+
103
+ def to_success_dict(response: SuccessResponse) -> Dict[str, Any]:
104
+ """Turn a SuccessResponse into a JSON-RPC response dict."""
105
+ return {"jsonrpc": "2.0", "result": response.result, "id": response.id}
106
+
107
+
108
+ def to_dict(response: Response) -> Dict[str, Any]:
109
+ """Turn a Response into a JSON-RPC response dict.
110
+
111
+ Args:
112
+ response: A Response from `dispatch_to_response`.
113
+
114
+ Returns:
115
+ The response as a dict, ready for `json.dumps`.
116
+
117
+ Example:
118
+ >>> from jsonrpcserver import Result, Success, dispatch_to_response
119
+ >>> def ping() -> Result:
120
+ ... return Success("pong")
121
+ >>> request = '{"jsonrpc": "2.0", "method": "ping", "id": 1}'
122
+ >>> to_dict(dispatch_to_response(request, {"ping": ping}))
123
+ {'jsonrpc': '2.0', 'result': 'pong', 'id': 1}
124
+ """
125
+ if isinstance(response, Left):
126
+ return to_error_dict(response._error)
127
+ success = cast("Right[SuccessResponse, ErrorResponse]", response)
128
+ return to_success_dict(success._value)
129
+
130
+
131
+ def to_serializable(
132
+ response: Union[Response, List[Response], None],
133
+ ) -> Union[Deserialized, None]:
134
+ """Turn a Response, a list of them or None into a dict, a list of dicts or None."""
135
+ if response is None:
136
+ return None
137
+ if isinstance(response, List):
138
+ return [to_dict(r) for r in response]
139
+ return to_dict(response)
140
+
141
+
142
+ # The names used in 5.0.9. They were renamed before 5.0.10, and are kept so code that
143
+ # imports them keeps working. They will be removed in 6.0.
144
+
145
+
146
+ def _deprecated(old: str, new: str) -> None:
147
+ warnings.warn(
148
+ f"jsonrpcserver.response.{old} is deprecated and will be removed in 6.0. "
149
+ f"Use {new} instead.",
150
+ DeprecationWarning,
151
+ stacklevel=3,
152
+ )
153
+
154
+
155
+ def serialize_error(response: ErrorResponse) -> Dict[str, Any]:
156
+ """Deprecated: use `to_error_dict`. Warns with DeprecationWarning (5.0.10)."""
157
+ _deprecated("serialize_error", "to_error_dict")
158
+ return to_error_dict(response)
159
+
160
+
161
+ def serialize_success(response: SuccessResponse) -> Dict[str, Any]:
162
+ """Deprecated: use `to_success_dict`. Warns with DeprecationWarning (5.0.10)."""
163
+ _deprecated("serialize_success", "to_success_dict")
164
+ return to_success_dict(response)
165
+
166
+
167
+ def to_serializable_one(response: Response) -> Dict[str, Any]:
168
+ """Deprecated: use `to_dict`. Warns with DeprecationWarning (5.0.10)."""
169
+ _deprecated("to_serializable_one", "to_dict")
170
+ return to_dict(response)