Passed
Push — master ( 0d356b...652bd4 )
by Michael
11:41 queued 05:19
created

JsonRpcRequest.is_notification()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
import typing
2
from dataclasses import dataclass, field
3
4
from .. import constants, errors, utils
5
6
7
__all__ = (
8
    'JsonRpcRequest',
9
    'JsonRpcBatchRequest',
10
)
11
12
13
@dataclass
14
class JsonRpcRequest:
15
    method_name: str
16
    id: typing.Any = constants.NOTHING
17
    jsonrpc: str = constants.VERSION_2_0
18
    extra_args: dict = field(default_factory=dict)
19
    context: dict = field(default_factory=dict)
20
    params: typing.Any = constants.NOTHING
21
    args: typing.Optional[typing.Union[list, tuple]] = None
22
    kwargs: typing.Optional[dict] = None
23
24
    def __post_init__(self) -> None:
25
        utils.validate_jsonrpc(self.jsonrpc)
26
27
        if self.params is constants.NOTHING:
28
            self.set_args_and_kwargs(self.args, self.kwargs)
29
        elif not self.args and not self.kwargs:
30
            self.set_params(self.params)
31
        else:
32
            raise errors.InvalidParams('Need use params or args with kwargs.')
33
34
    def set_params(self, params: typing.Any) -> None:
35
        self.params = params
36
        self.args, self.kwargs = utils.convert_params_to_args_and_kwargs(params)
37
38
    def set_args_and_kwargs(self, args: typing.Optional[list] = None, kwargs: typing.Optional[dict] = None) -> None:
39
        self.params, self.args, self.kwargs = utils.parse_args_and_kwargs(args, kwargs)
40
41
    @property
42
    def is_notification(self) -> bool:
43
        return self.id in constants.EMPTY_VALUES
44
45
    @classmethod
46
    def from_dict(cls, data: typing.Dict[str, typing.Any], **kwargs) -> 'JsonRpcRequest':
47
        cls._validate_json_request(data)
48
49
        return cls(
50
            id=data.get('id', constants.NOTHING),
51
            method_name=data['method'],
52
            params=data.get('params', constants.NOTHING),
53
            jsonrpc=data['jsonrpc'],
54
            **kwargs,
55
        )
56
57
    def to_dict(self) -> dict:
58
        data = {
59
            'method': self.method_name,
60
            'jsonrpc': self.jsonrpc,
61
        }
62
63
        if not self.is_notification:
64
            data['id'] = self.id
65
66
        if self.params is not constants.NOTHING:
67
            data['params'] = self.params
68
69
        return data
70
71
    @staticmethod
72
    def _validate_json_request(data: typing.Any) -> None:
73
        if not isinstance(data, dict):
74
            raise errors.InvalidRequest('A request must be of the dict type.')
75
76
        if not ({'method', 'jsonrpc'}) <= data.keys():
77
            raise errors.InvalidRequest('A request must contain "method" and "jsonrpc".')
78
79
        utils.validate_jsonrpc(data['jsonrpc'])
80
81
82
@dataclass
83
class JsonRpcBatchRequest:
84
    requests: typing.List[JsonRpcRequest] = field(default_factory=list)
85
86
    @property
87
    def is_notification(self) -> bool:
88
        return all(request.is_notification for request in self.requests)
89
90
    def to_list(self) -> typing.List[dict]:
91
        return [request.to_dict() for request in self.requests]
92
93
    @classmethod
94
    def from_list(cls, data: list, **kwargs) -> 'JsonRpcBatchRequest':
95
        requests = [
96
            JsonRpcRequest.from_dict(item,  **kwargs)
97
            for item in data
98
        ]
99
100
        return cls(requests=requests)
101
102