python-jsonrpc-lib 0.3.1__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.
jsonrpc/__init__.py ADDED
@@ -0,0 +1,83 @@
1
+ """Pure-Python JSON-RPC 1.0/2.0 protocol implementation.
2
+
3
+ This library provides a transport-agnostic implementation of the JSON-RPC protocol,
4
+ supporting both version 1.0 and 2.0 specifications.
5
+
6
+ Example:
7
+ >>> from jsonrpc import JSONRPC, MethodGroup, Method
8
+ >>> from dataclasses import dataclass
9
+ >>>
10
+ >>> @dataclass
11
+ ... class AddParams:
12
+ ... a: int
13
+ ... b: int
14
+ ...
15
+ >>> class Add(Method):
16
+ ... def execute(self, params: AddParams) -> int:
17
+ ... return params.a + params.b
18
+ ...
19
+ >>> math = MethodGroup()
20
+ >>> math.register("add", Add())
21
+ >>>
22
+ >>> rpc = JSONRPC()
23
+ >>> rpc.register("math", math)
24
+ >>>
25
+ >>> response = rpc.handle('{"jsonrpc":"2.0","method":"math.add","params":{"a":1,"b":2},"id":1}')
26
+ >>> print(response)
27
+ {"jsonrpc": "2.0", "result": 3, "id": 1}
28
+ """
29
+
30
+ from .errors import (
31
+ InternalError,
32
+ InvalidParamsError,
33
+ InvalidRequestError,
34
+ InvalidResultError,
35
+ JSONRPCError,
36
+ MethodNotFoundError,
37
+ ParseError,
38
+ RPCError,
39
+ ServerError,
40
+ )
41
+ from .jsonrpc import JSONRPC
42
+ from .method import Method, MethodGroup
43
+ from .openapi import OpenAPIGenerator
44
+ from .request import build_notification, build_request, parse_request
45
+ from .response import build_error_response, build_response, parse_response
46
+ from .types import ErrorResponse, Request, Response, Version
47
+ from .validation import validate_params, validate_result_type
48
+
49
+ __version__ = '0.3.1'
50
+
51
+ __all__ = [
52
+ # Main classes
53
+ 'JSONRPC',
54
+ 'Method',
55
+ 'MethodGroup',
56
+ # Types
57
+ 'Request',
58
+ 'Response',
59
+ 'ErrorResponse',
60
+ 'RPCError',
61
+ 'Version',
62
+ # Errors
63
+ 'JSONRPCError',
64
+ 'ParseError',
65
+ 'InvalidRequestError',
66
+ 'MethodNotFoundError',
67
+ 'InvalidParamsError',
68
+ 'InvalidResultError',
69
+ 'InternalError',
70
+ 'ServerError',
71
+ # Request/Response builders
72
+ 'build_request',
73
+ 'build_notification',
74
+ 'build_response',
75
+ 'build_error_response',
76
+ 'parse_request',
77
+ 'parse_response',
78
+ # Utilities
79
+ 'validate_params',
80
+ 'validate_result_type',
81
+ # OpenAPI
82
+ 'OpenAPIGenerator',
83
+ ]
jsonrpc/errors.py ADDED
@@ -0,0 +1,131 @@
1
+ """JSON-RPC error classes per specification.
2
+
3
+ Error codes:
4
+ -32700: Parse error - Invalid JSON
5
+ -32600: Invalid Request - Not a valid Request object
6
+ -32601: Method not found - Method does not exist
7
+ -32602: Invalid params - Invalid method parameters
8
+ -32603: Internal error - Internal JSON-RPC error
9
+ -32001: Invalid result - Return type mismatch (implementation-defined)
10
+ -32000 to -32099: Server error - Reserved for implementation
11
+ """
12
+
13
+ from dataclasses import dataclass
14
+ from typing import Any
15
+
16
+
17
+ @dataclass
18
+ class RPCError:
19
+ """JSON-RPC error object."""
20
+
21
+ code: int
22
+ message: str
23
+ data: Any = None
24
+
25
+ def to_dict(self) -> dict[str, Any]:
26
+ """Convert to JSON-RPC error object dict."""
27
+ result: dict[str, Any] = {
28
+ 'code': self.code,
29
+ 'message': self.message,
30
+ }
31
+ if self.data is not None:
32
+ result['data'] = self.data
33
+ return result
34
+
35
+
36
+ class JSONRPCError(Exception):
37
+ """Base exception for JSON-RPC errors."""
38
+
39
+ code: int = -32603
40
+ message: str = 'Internal error'
41
+
42
+ def __init__(
43
+ self,
44
+ message: str | None = None,
45
+ code: int | None = None,
46
+ data: Any = None,
47
+ ) -> None:
48
+ self._message = message if message is not None else self.message
49
+ self._code = code if code is not None else self.code
50
+ self.data = data
51
+ super().__init__(self._message)
52
+
53
+ @property
54
+ def error(self) -> RPCError:
55
+ """Get RPCError object for this exception."""
56
+ return RPCError(
57
+ code=self._code,
58
+ message=self._message,
59
+ data=self.data,
60
+ )
61
+
62
+ def to_dict(self) -> dict[str, Any]:
63
+ """Convert to JSON-RPC error object dict."""
64
+ return self.error.to_dict()
65
+
66
+
67
+ class ParseError(JSONRPCError):
68
+ """Invalid JSON was received by the server."""
69
+
70
+ code = -32700
71
+ message = 'Parse error'
72
+
73
+
74
+ class InvalidRequestError(JSONRPCError):
75
+ """The JSON sent is not a valid Request object."""
76
+
77
+ code = -32600
78
+ message = 'Invalid Request'
79
+
80
+
81
+ class MethodNotFoundError(JSONRPCError):
82
+ """The method does not exist / is not available."""
83
+
84
+ code = -32601
85
+ message = 'Method not found'
86
+
87
+
88
+ class InvalidParamsError(JSONRPCError):
89
+ """Invalid method parameter(s)."""
90
+
91
+ code = -32602
92
+ message = 'Invalid params'
93
+
94
+
95
+ class InvalidResultError(JSONRPCError):
96
+ """Method result doesn't match declared result_type.
97
+
98
+ This is an implementation-defined server error that indicates a contract
99
+ violation between the method implementation and its declared return type.
100
+ Uses code -32001 (in the -32000 to -32099 range reserved for implementation).
101
+ """
102
+
103
+ code = -32001
104
+ message = 'Invalid result'
105
+
106
+
107
+ class InternalError(JSONRPCError):
108
+ """Internal JSON-RPC error."""
109
+
110
+ code = -32603
111
+ message = 'Internal error'
112
+
113
+
114
+ class ServerError(JSONRPCError):
115
+ """Reserved for implementation-defined server-errors.
116
+
117
+ Code must be in range -32000 to -32099.
118
+ """
119
+
120
+ code = -32000
121
+ message = 'Server error'
122
+
123
+ def __init__(
124
+ self,
125
+ message: str | None = None,
126
+ code: int | None = None,
127
+ data: Any = None,
128
+ ) -> None:
129
+ if code is not None and not (-32099 <= code <= -32000):
130
+ raise ValueError(f'Server error code must be in range -32099 to -32000, got {code}')
131
+ super().__init__(message, code, data)