omlish 0.0.0.dev33__py3-none-any.whl → 0.0.0.dev34__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.
- omlish/__about__.py +2 -2
- omlish/bootstrap/marshal.py +1 -4
- omlish/dataclasses/impl/api.py +1 -1
- omlish/dataclasses/impl/fields.py +8 -1
- omlish/dataclasses/impl/params.py +1 -1
- omlish/lang/__init__.py +1 -0
- omlish/lang/cached.py +7 -0
- omlish/lang/classes/simple.py +3 -0
- omlish/marshal/__init__.py +8 -0
- omlish/marshal/base.py +2 -1
- omlish/marshal/dataclasses.py +11 -0
- omlish/marshal/maybes.py +4 -0
- omlish/marshal/objects.py +37 -0
- omlish/marshal/unions.py +6 -2
- omlish/secrets/marshal.py +1 -4
- omlish/specs/jsonrpc/__init__.py +28 -0
- omlish/specs/jsonrpc/errors.py +20 -0
- omlish/specs/jsonrpc/marshal.py +59 -0
- omlish/specs/jsonrpc/types.py +93 -0
- {omlish-0.0.0.dev33.dist-info → omlish-0.0.0.dev34.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev33.dist-info → omlish-0.0.0.dev34.dist-info}/RECORD +25 -21
- {omlish-0.0.0.dev33.dist-info → omlish-0.0.0.dev34.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev33.dist-info → omlish-0.0.0.dev34.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev33.dist-info → omlish-0.0.0.dev34.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev33.dist-info → omlish-0.0.0.dev34.dist-info}/top_level.txt +0 -0
omlish/__about__.py
CHANGED
omlish/bootstrap/marshal.py
CHANGED
@@ -4,7 +4,7 @@ from .base import Bootstrap
|
|
4
4
|
from .harness import BOOTSTRAP_TYPES_BY_NAME
|
5
5
|
|
6
6
|
|
7
|
-
@lang.
|
7
|
+
@lang.static_init
|
8
8
|
def _install_standard_marshalling() -> None:
|
9
9
|
cfgs_poly = msh.Polymorphism(
|
10
10
|
Bootstrap.Config,
|
@@ -13,6 +13,3 @@ def _install_standard_marshalling() -> None:
|
|
13
13
|
|
14
14
|
msh.STANDARD_MARSHALER_FACTORIES[0:0] = [msh.PolymorphismMarshalerFactory(cfgs_poly)]
|
15
15
|
msh.STANDARD_UNMARSHALER_FACTORIES[0:0] = [msh.PolymorphismUnmarshalerFactory(cfgs_poly)]
|
16
|
-
|
17
|
-
|
18
|
-
_install_standard_marshalling()
|
omlish/dataclasses/impl/api.py
CHANGED
@@ -33,7 +33,7 @@ def field( # noqa
|
|
33
33
|
derive: ta.Callable[..., ta.Any] | None = None,
|
34
34
|
coerce: bool | ta.Callable[[ta.Any], ta.Any] | None = None,
|
35
35
|
validate: ta.Callable[[ta.Any], bool] | None = None,
|
36
|
-
check_type: bool | None = None,
|
36
|
+
check_type: bool | type | None = None,
|
37
37
|
override: bool = False,
|
38
38
|
repr_fn: ta.Callable[[ta.Any], str | None] | None = None,
|
39
39
|
frozen: bool | None = None,
|
@@ -193,7 +193,14 @@ def field_init(
|
|
193
193
|
|
194
194
|
if fx.check_type:
|
195
195
|
cn = f'__dataclass_check_type__{f.name}__'
|
196
|
-
|
196
|
+
if isinstance(fx.check_type, type):
|
197
|
+
ct = fx.check_type
|
198
|
+
# FIXME:
|
199
|
+
# elif info.params_extras.generic_init:
|
200
|
+
# ct = info.generic_replaced_field_annotations[f.name]
|
201
|
+
else:
|
202
|
+
ct = f.type
|
203
|
+
locals[cn] = ct
|
197
204
|
lines.append(
|
198
205
|
f'if not __dataclass_builtins_isinstance__({value}, {cn}): '
|
199
206
|
f'raise __dataclass_builtins_TypeError__({value}, {cn})',
|
@@ -45,7 +45,7 @@ class FieldExtras(lang.Final):
|
|
45
45
|
derive: ta.Callable[..., ta.Any] | None = None # TODO
|
46
46
|
coerce: bool | ta.Callable[[ta.Any], ta.Any] | None = None
|
47
47
|
validate: ta.Callable[[ta.Any], bool] | None = None
|
48
|
-
check_type: bool | None = None
|
48
|
+
check_type: bool | type | None = None
|
49
49
|
override: bool = False
|
50
50
|
repr_fn: ta.Callable[[ta.Any], str | None] | None = None
|
51
51
|
frozen: bool | None = None # TODO
|
omlish/lang/__init__.py
CHANGED
omlish/lang/cached.py
CHANGED
@@ -17,6 +17,7 @@ from .descriptors import unwrap_func_with_partials
|
|
17
17
|
|
18
18
|
P = ta.ParamSpec('P')
|
19
19
|
T = ta.TypeVar('T')
|
20
|
+
CallableT = ta.TypeVar('CallableT', bound=ta.Callable)
|
20
21
|
|
21
22
|
_IGNORE = object()
|
22
23
|
|
@@ -217,6 +218,12 @@ def cached_function(fn=None, **kwargs): # noqa
|
|
217
218
|
return _CachedFunctionDescriptor(fn, scope, opts=opts)
|
218
219
|
|
219
220
|
|
221
|
+
def static_init(fn: CallableT) -> CallableT:
|
222
|
+
fn = cached_function(fn)
|
223
|
+
fn()
|
224
|
+
return fn
|
225
|
+
|
226
|
+
|
220
227
|
##
|
221
228
|
|
222
229
|
|
omlish/lang/classes/simple.py
CHANGED
omlish/marshal/__init__.py
CHANGED
@@ -88,6 +88,14 @@ from .standard import ( # noqa
|
|
88
88
|
new_standard_unmarshaler_factory,
|
89
89
|
)
|
90
90
|
|
91
|
+
from .unions import ( # noqa
|
92
|
+
PRIMITIVE_UNION_TYPES,
|
93
|
+
PrimitiveUnionMarshaler,
|
94
|
+
PrimitiveUnionMarshalerFactory,
|
95
|
+
PrimitiveUnionUnmarshaler,
|
96
|
+
PrimitiveUnionUnmarshalerFactory,
|
97
|
+
)
|
98
|
+
|
91
99
|
from .values import ( # noqa
|
92
100
|
Value,
|
93
101
|
)
|
omlish/marshal/base.py
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
"""
|
2
2
|
TODO:
|
3
|
-
- mappings
|
4
3
|
- redacted
|
5
4
|
- strongly typed MarshalerFactory base class?
|
6
5
|
- strongly typed Composite/Cached Marshaler/Unmarshaler factories - footgun
|
7
6
|
- streaming? Start/EndObject, etc..
|
7
|
+
- lang.Marker - class name, handle type[Foo]
|
8
|
+
- can't disambiguate from str - can't coexist in bare union
|
8
9
|
|
9
10
|
See:
|
10
11
|
- https://github.com/python-attrs/cattrs
|
omlish/marshal/dataclasses.py
CHANGED
@@ -67,6 +67,7 @@ def get_field_infos(
|
|
67
67
|
kw.update(
|
68
68
|
metadata=fmd,
|
69
69
|
omit_if=fmd.omit_if,
|
70
|
+
default=fmd.default,
|
70
71
|
)
|
71
72
|
|
72
73
|
if fmd.name is not None:
|
@@ -98,11 +99,14 @@ class DataclassMarshalerFactory(MarshalerFactory):
|
|
98
99
|
def fn(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
|
99
100
|
ty = check.isinstance(rty, type)
|
100
101
|
check.state(dc.is_dataclass(ty))
|
102
|
+
|
101
103
|
dc_md = get_dataclass_metadata(ty)
|
104
|
+
|
102
105
|
fields = [
|
103
106
|
(fi, _make_field_obj(ctx, fi.type, fi.metadata.marshaler, fi.metadata.marshaler_factory))
|
104
107
|
for fi in get_field_infos(ty, ctx.options)
|
105
108
|
]
|
109
|
+
|
106
110
|
return ObjectMarshaler(
|
107
111
|
fields,
|
108
112
|
unknown_field=dc_md.unknown_field,
|
@@ -119,16 +123,23 @@ class DataclassUnmarshalerFactory(UnmarshalerFactory):
|
|
119
123
|
def fn(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
|
120
124
|
ty = check.isinstance(rty, type)
|
121
125
|
check.state(dc.is_dataclass(ty))
|
126
|
+
|
122
127
|
dc_md = get_dataclass_metadata(ty)
|
128
|
+
|
123
129
|
d: dict[str, tuple[FieldInfo, Unmarshaler]] = {}
|
130
|
+
defaults: dict[str, ta.Any] = {}
|
124
131
|
for fi in get_field_infos(ty, ctx.options):
|
125
132
|
tup = (fi, _make_field_obj(ctx, fi.type, fi.metadata.unmarshaler, fi.metadata.unmarshaler_factory))
|
126
133
|
for un in fi.unmarshal_names:
|
127
134
|
if un in d:
|
128
135
|
raise KeyError(f'Duplicate fields for name {un!r}: {fi.name!r}, {d[un][0].name!r}')
|
129
136
|
d[un] = tup
|
137
|
+
if fi.default.present:
|
138
|
+
defaults[fi.name] = fi.default.must()
|
139
|
+
|
130
140
|
return ObjectUnmarshaler(
|
131
141
|
ty,
|
132
142
|
d,
|
133
143
|
unknown_field=dc_md.unknown_field,
|
144
|
+
defaults=defaults,
|
134
145
|
)
|
omlish/marshal/maybes.py
CHANGED
omlish/marshal/objects.py
CHANGED
@@ -3,12 +3,16 @@ TODO:
|
|
3
3
|
- cfg naming
|
4
4
|
- adapters for dataclasses / namedtuples / user objects (as confitured)
|
5
5
|
- mro-merge ObjectMetadata
|
6
|
+
- key ordering override - like slice, -1 means last
|
7
|
+
- dedupe omit_if/default fields on Metadata/Info - FieldOptions prob
|
8
|
+
- impl merge, update helpers:update_fields_metadata
|
6
9
|
"""
|
7
10
|
import collections.abc
|
8
11
|
import typing as ta
|
9
12
|
|
10
13
|
from .. import check
|
11
14
|
from .. import dataclasses as dc
|
15
|
+
from .. import lang
|
12
16
|
from .. import reflect as rfl
|
13
17
|
from .base import MarshalContext
|
14
18
|
from .base import Marshaler
|
@@ -29,6 +33,7 @@ class FieldMetadata:
|
|
29
33
|
alts: ta.Iterable[str] | None = None
|
30
34
|
|
31
35
|
omit_if: ta.Callable[[ta.Any], bool] | None = None
|
36
|
+
default: lang.Maybe[ta.Any] = dc.xfield(lang.empty(), check_type=lang.Maybe)
|
32
37
|
|
33
38
|
marshaler: Marshaler | None = None
|
34
39
|
marshaler_factory: MarshalerFactory | None = None
|
@@ -60,6 +65,7 @@ class FieldInfo:
|
|
60
65
|
metadata: FieldMetadata = FieldMetadata()
|
61
66
|
|
62
67
|
omit_if: ta.Callable[[ta.Any], bool] | None = None
|
68
|
+
default: lang.Maybe[ta.Any] = lang.empty()
|
63
69
|
|
64
70
|
|
65
71
|
##
|
@@ -68,6 +74,9 @@ class FieldInfo:
|
|
68
74
|
@dc.dataclass(frozen=True)
|
69
75
|
class ObjectMarshaler(Marshaler):
|
70
76
|
fields: ta.Sequence[tuple[FieldInfo, Marshaler]]
|
77
|
+
|
78
|
+
_: dc.KW_ONLY
|
79
|
+
|
71
80
|
unknown_field: str | None = None
|
72
81
|
|
73
82
|
def marshal(self, ctx: MarshalContext, o: ta.Any) -> Value:
|
@@ -91,6 +100,9 @@ class ObjectMarshaler(Marshaler):
|
|
91
100
|
@dc.dataclass(frozen=True)
|
92
101
|
class SimpleObjectMarshalerFactory(MarshalerFactory):
|
93
102
|
dct: ta.Mapping[type, ta.Sequence[FieldInfo]]
|
103
|
+
|
104
|
+
_: dc.KW_ONLY
|
105
|
+
|
94
106
|
unknown_field: str | None = None
|
95
107
|
|
96
108
|
def guard(self, ctx: MarshalContext, rty: rfl.Type) -> bool:
|
@@ -98,11 +110,14 @@ class SimpleObjectMarshalerFactory(MarshalerFactory):
|
|
98
110
|
|
99
111
|
def fn(self, ctx: MarshalContext, rty: rfl.Type) -> Marshaler:
|
100
112
|
ty = check.isinstance(rty, type)
|
113
|
+
|
101
114
|
flds = self.dct[ty]
|
115
|
+
|
102
116
|
fields = [
|
103
117
|
(fi, ctx.make(fi.type))
|
104
118
|
for fi in flds
|
105
119
|
]
|
120
|
+
|
106
121
|
return ObjectMarshaler(
|
107
122
|
fields,
|
108
123
|
unknown_field=self.unknown_field,
|
@@ -116,10 +131,15 @@ class SimpleObjectMarshalerFactory(MarshalerFactory):
|
|
116
131
|
class ObjectUnmarshaler(Unmarshaler):
|
117
132
|
cls: type
|
118
133
|
fields_by_unmarshal_name: ta.Mapping[str, tuple[FieldInfo, Unmarshaler]]
|
134
|
+
|
135
|
+
_: dc.KW_ONLY
|
136
|
+
|
119
137
|
unknown_field: str | None = None
|
138
|
+
defaults: ta.Mapping[str, ta.Any] | None = None
|
120
139
|
|
121
140
|
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any:
|
122
141
|
ma = check.isinstance(v, collections.abc.Mapping)
|
142
|
+
|
123
143
|
u: ta.Any
|
124
144
|
kw: dict[str, ta.Any] = {}
|
125
145
|
ukf: dict[str, ta.Any] | None = None
|
@@ -144,12 +164,19 @@ class ObjectUnmarshaler(Unmarshaler):
|
|
144
164
|
|
145
165
|
kw[fi.name] = u.unmarshal(ctx, mv)
|
146
166
|
|
167
|
+
if self.defaults:
|
168
|
+
for dk, dv in self.defaults.items():
|
169
|
+
kw.setdefault(dk, dv)
|
170
|
+
|
147
171
|
return self.cls(**kw)
|
148
172
|
|
149
173
|
|
150
174
|
@dc.dataclass(frozen=True)
|
151
175
|
class SimpleObjectUnmarshalerFactory(UnmarshalerFactory):
|
152
176
|
dct: ta.Mapping[type, ta.Sequence[FieldInfo]]
|
177
|
+
|
178
|
+
_: dc.KW_ONLY
|
179
|
+
|
153
180
|
unknown_field: str | None = None
|
154
181
|
|
155
182
|
def guard(self, ctx: UnmarshalContext, rty: rfl.Type) -> bool:
|
@@ -157,14 +184,24 @@ class SimpleObjectUnmarshalerFactory(UnmarshalerFactory):
|
|
157
184
|
|
158
185
|
def fn(self, ctx: UnmarshalContext, rty: rfl.Type) -> Unmarshaler:
|
159
186
|
ty = check.isinstance(rty, type)
|
187
|
+
|
160
188
|
flds = self.dct[ty]
|
189
|
+
|
161
190
|
fields_by_unmarshal_name = {
|
162
191
|
n: (fi, ctx.make(fi.type))
|
163
192
|
for fi in flds
|
164
193
|
for n in fi.unmarshal_names
|
165
194
|
}
|
195
|
+
|
196
|
+
defaults = {
|
197
|
+
fi.name: fi.default.must()
|
198
|
+
for fi in flds
|
199
|
+
if fi.default.present
|
200
|
+
}
|
201
|
+
|
166
202
|
return ObjectUnmarshaler(
|
167
203
|
ty,
|
168
204
|
fields_by_unmarshal_name,
|
169
205
|
unknown_field=self.unknown_field,
|
206
|
+
defaults=defaults,
|
170
207
|
)
|
omlish/marshal/unions.py
CHANGED
@@ -56,7 +56,9 @@ class PrimitiveUnionMarshaler(Marshaler):
|
|
56
56
|
tys: ta.Sequence[type]
|
57
57
|
|
58
58
|
def marshal(self, ctx: MarshalContext, o: ta.Any) -> Value:
|
59
|
-
|
59
|
+
if type(o) not in self.tys:
|
60
|
+
raise TypeError(o)
|
61
|
+
return o
|
60
62
|
|
61
63
|
|
62
64
|
@dc.dataclass(frozen=True)
|
@@ -79,7 +81,9 @@ class PrimitiveUnionUnmarshaler(Unmarshaler):
|
|
79
81
|
tys: ta.Sequence[type]
|
80
82
|
|
81
83
|
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any:
|
82
|
-
|
84
|
+
if type(v) not in self.tys:
|
85
|
+
raise TypeError(v)
|
86
|
+
return v
|
83
87
|
|
84
88
|
|
85
89
|
@dc.dataclass(frozen=True)
|
omlish/secrets/marshal.py
CHANGED
@@ -50,7 +50,7 @@ def marshal_secret_field(f: dc.Field) -> dc.Field:
|
|
50
50
|
})
|
51
51
|
|
52
52
|
|
53
|
-
@lang.
|
53
|
+
@lang.static_init
|
54
54
|
def _install_standard_marshalling() -> None:
|
55
55
|
msh.STANDARD_MARSHALER_FACTORIES[0:0] = [
|
56
56
|
msh.ForbiddenTypeMarshalerFactory({Secret}),
|
@@ -65,6 +65,3 @@ def _install_standard_marshalling() -> None:
|
|
65
65
|
rfl.type_(SecretRefOrStr): StrOrSecretRefMarshalerUnmarshaler(),
|
66
66
|
}),
|
67
67
|
]
|
68
|
-
|
69
|
-
|
70
|
-
_install_standard_marshalling()
|
@@ -0,0 +1,28 @@
|
|
1
|
+
from .errors import ( # noqa
|
2
|
+
CUSTOM_ERROR_BASE,
|
3
|
+
KnownError,
|
4
|
+
KnownErrors,
|
5
|
+
)
|
6
|
+
|
7
|
+
from .types import ( # noqa
|
8
|
+
Error,
|
9
|
+
Id,
|
10
|
+
NotSpecified,
|
11
|
+
Number,
|
12
|
+
Object,
|
13
|
+
Request,
|
14
|
+
Response,
|
15
|
+
VERSION,
|
16
|
+
error,
|
17
|
+
notification,
|
18
|
+
request,
|
19
|
+
result,
|
20
|
+
)
|
21
|
+
|
22
|
+
|
23
|
+
##
|
24
|
+
|
25
|
+
|
26
|
+
from ...lang.imports import _register_conditional_import # noqa
|
27
|
+
|
28
|
+
_register_conditional_import('...marshal', '.marshal', __package__)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
from ... import dataclasses as dc
|
2
|
+
from ... import lang
|
3
|
+
|
4
|
+
|
5
|
+
@dc.dataclass(frozen=True)
|
6
|
+
class KnownError:
|
7
|
+
code: int
|
8
|
+
message: str
|
9
|
+
meaning: str
|
10
|
+
|
11
|
+
|
12
|
+
class KnownErrors(lang.Namespace):
|
13
|
+
PARSE_ERROR = KnownError(-32700, 'Parse error', 'Invalid JSON was received by the server.')
|
14
|
+
INVALID_REQUEST = KnownError(-32600, 'Invalid Request', 'The JSON sent is not a valid Request object.')
|
15
|
+
METHOD_NOT_FOUND = KnownError(-32601, 'Method not found', 'The method does not exist / is not available.')
|
16
|
+
INVALID_PARAMS = KnownError(-32602, 'Invalid params', 'Invalid method parameter(s).')
|
17
|
+
INTERNAL_ERROR = KnownError(-32603, 'Internal error', 'Internal JSON-RPC error.')
|
18
|
+
|
19
|
+
|
20
|
+
CUSTOM_ERROR_BASE = -32000
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import typing as ta
|
2
|
+
|
3
|
+
from ... import check
|
4
|
+
from ... import dataclasses as dc
|
5
|
+
from ... import lang
|
6
|
+
from ... import marshal as msh
|
7
|
+
from ... import matchfns as mfs
|
8
|
+
from ... import reflect as rfl
|
9
|
+
from .types import NotSpecified
|
10
|
+
|
11
|
+
|
12
|
+
_NOT_SPECIFIED_RTY = rfl.type_(type[NotSpecified])
|
13
|
+
|
14
|
+
|
15
|
+
@dc.dataclass(frozen=True)
|
16
|
+
class NotSpecifiedUnionMarshaler(msh.Marshaler):
|
17
|
+
m: msh.Marshaler
|
18
|
+
|
19
|
+
def marshal(self, ctx: msh.MarshalContext, o: ta.Any) -> msh.Value:
|
20
|
+
if o is NotSpecified:
|
21
|
+
raise TypeError(o)
|
22
|
+
return self.m.marshal(ctx, o)
|
23
|
+
|
24
|
+
|
25
|
+
class NotSpecifiedUnionMarshalerFactory(msh.MarshalerFactoryMatchClass):
|
26
|
+
@mfs.simple(lambda _, ctx, rty: (
|
27
|
+
isinstance(rty, rfl.Union) and
|
28
|
+
not rty.is_optional and
|
29
|
+
_NOT_SPECIFIED_RTY in rty.args
|
30
|
+
))
|
31
|
+
def _build(self, ctx: msh.MarshalContext, rty: rfl.Type) -> msh.Marshaler:
|
32
|
+
args = set(check.isinstance(rty, rfl.Union).args) - {_NOT_SPECIFIED_RTY}
|
33
|
+
nty = rfl.type_(ta.Union[*args])
|
34
|
+
m = ctx.make(nty)
|
35
|
+
return NotSpecifiedUnionMarshaler(m)
|
36
|
+
|
37
|
+
|
38
|
+
class NotSpecifiedUnionUnmarshalerFactory(msh.UnmarshalerFactoryMatchClass):
|
39
|
+
@mfs.simple(lambda _, ctx, rty: (
|
40
|
+
isinstance(rty, rfl.Union) and
|
41
|
+
not rty.is_optional and
|
42
|
+
_NOT_SPECIFIED_RTY in rty.args
|
43
|
+
))
|
44
|
+
def _build(self, ctx: msh.UnmarshalContext, rty: rfl.Type) -> msh.Unmarshaler:
|
45
|
+
args = set(check.isinstance(rty, rfl.Union).args) - {_NOT_SPECIFIED_RTY}
|
46
|
+
nty = rfl.type_(ta.Union[*args])
|
47
|
+
return ctx.make(nty)
|
48
|
+
|
49
|
+
|
50
|
+
@lang.static_init
|
51
|
+
def _install_standard_marshalling() -> None:
|
52
|
+
msh.STANDARD_MARSHALER_FACTORIES[0:0] = [
|
53
|
+
msh.ForbiddenTypeMarshalerFactory({_NOT_SPECIFIED_RTY}),
|
54
|
+
NotSpecifiedUnionMarshalerFactory(),
|
55
|
+
]
|
56
|
+
msh.STANDARD_UNMARSHALER_FACTORIES[0:0] = [
|
57
|
+
msh.ForbiddenTypeUnmarshalerFactory({_NOT_SPECIFIED_RTY}),
|
58
|
+
NotSpecifiedUnionUnmarshalerFactory(),
|
59
|
+
]
|
@@ -0,0 +1,93 @@
|
|
1
|
+
"""
|
2
|
+
https://www.jsonrpc.org/specification
|
3
|
+
|
4
|
+
TODO:
|
5
|
+
- drop NotSpecified, use lang.Maybe, make marshal do that
|
6
|
+
- server/client impl
|
7
|
+
|
8
|
+
See:
|
9
|
+
- https://github.com/python-lsp/python-lsp-jsonrpc
|
10
|
+
"""
|
11
|
+
import operator
|
12
|
+
import typing as ta
|
13
|
+
|
14
|
+
from ... import dataclasses as dc
|
15
|
+
from ... import lang
|
16
|
+
from ... import marshal as msh
|
17
|
+
|
18
|
+
|
19
|
+
Number: ta.TypeAlias = int | float
|
20
|
+
Object: ta.TypeAlias = ta.Mapping[str, ta.Any]
|
21
|
+
Id: ta.TypeAlias = str | Number | None
|
22
|
+
|
23
|
+
|
24
|
+
##
|
25
|
+
|
26
|
+
|
27
|
+
VERSION = '2.0'
|
28
|
+
|
29
|
+
|
30
|
+
class NotSpecified(lang.Marker):
|
31
|
+
pass
|
32
|
+
|
33
|
+
|
34
|
+
def is_not_specified(v: ta.Any) -> bool:
|
35
|
+
return v is NotSpecified
|
36
|
+
|
37
|
+
|
38
|
+
##
|
39
|
+
|
40
|
+
|
41
|
+
@dc.dataclass(frozen=True)
|
42
|
+
@msh.update_fields_metadata(['id'], omit_if=is_not_specified, default=lang.just(NotSpecified))
|
43
|
+
@msh.update_fields_metadata(['params'], omit_if=operator.not_)
|
44
|
+
class Request(lang.Final):
|
45
|
+
id: Id | type[NotSpecified]
|
46
|
+
method: str
|
47
|
+
params: Object | None = None
|
48
|
+
|
49
|
+
jsonrpc: str = dc.field(default=VERSION, kw_only=True)
|
50
|
+
dc.validate(lambda self: self.jsonrpc == VERSION)
|
51
|
+
|
52
|
+
|
53
|
+
def request(id: Id, method: str, params: Object | None = None) -> Request: # noqa
|
54
|
+
return Request(id, method, params)
|
55
|
+
|
56
|
+
|
57
|
+
def notification(method: str, params: Object | None = None) -> Request:
|
58
|
+
return Request(NotSpecified, method, params)
|
59
|
+
|
60
|
+
|
61
|
+
##
|
62
|
+
|
63
|
+
|
64
|
+
@dc.dataclass(frozen=True)
|
65
|
+
@msh.update_fields_metadata(['result', 'error'], omit_if=is_not_specified)
|
66
|
+
class Response(lang.Final):
|
67
|
+
id: Id
|
68
|
+
dc.validate(lambda self: self.id is not NotSpecified)
|
69
|
+
|
70
|
+
_: dc.KW_ONLY
|
71
|
+
|
72
|
+
result: ta.Any = dc.field(default=NotSpecified)
|
73
|
+
error: ta.Union['Error', type[NotSpecified]] = dc.field(default=NotSpecified)
|
74
|
+
dc.validate(lambda self: is_not_specified(self.result) ^ is_not_specified(self.error))
|
75
|
+
|
76
|
+
jsonrpc: str = dc.field(default=VERSION)
|
77
|
+
dc.validate(lambda self: self.jsonrpc == VERSION)
|
78
|
+
|
79
|
+
|
80
|
+
def result(id: Id, result: ta.Any) -> Response: # noqa
|
81
|
+
return Response(id, result=result)
|
82
|
+
|
83
|
+
|
84
|
+
@dc.dataclass(frozen=True)
|
85
|
+
@msh.update_fields_metadata(['data'], omit_if=is_not_specified)
|
86
|
+
class Error(lang.Final):
|
87
|
+
code: int
|
88
|
+
message: str
|
89
|
+
data: ta.Any = NotSpecified
|
90
|
+
|
91
|
+
|
92
|
+
def error(id: Id, error: Error) -> Response: # noqa
|
93
|
+
return Response(id, error=error)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
omlish/.manifests.json,sha256=N1F-Xz3GaBn2H1p7uKzhkhKCQV8QVR0t76XD6wmFtXA,3
|
2
|
-
omlish/__about__.py,sha256=
|
2
|
+
omlish/__about__.py,sha256=b7600XQquCMS8-Z7-ZT_riO4xaBu1gI7P13vrDWamtY,2814
|
3
3
|
omlish/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
omlish/argparse.py,sha256=QRQmX9G0-L_nATkFtGHvpd4qrpYzKATdjuFLbBqzJPM,6224
|
5
5
|
omlish/c3.py,sha256=W5EwYx9Por3rWYLkKUitJ6OoRMLLgVTfLTyroOz41Y0,8047
|
@@ -34,7 +34,7 @@ omlish/bootstrap/base.py,sha256=koELbK6UmsZaRj-6Bng5_zPVmEBqDpFCduEdR5BddOs,1077
|
|
34
34
|
omlish/bootstrap/diag.py,sha256=x_BKS_uhfW8QFk1NeH_VIocHif-A6FVTZ37262qCgZ0,5052
|
35
35
|
omlish/bootstrap/harness.py,sha256=pIeSXKfMsF7-3ZkU0gGpde-PtLAKKcVrWaxcin7Xzy0,2041
|
36
36
|
omlish/bootstrap/main.py,sha256=u-TfxO4GkAK3LbRweQERogtO4kT0z3gqXRjnXvtJzC8,5328
|
37
|
-
omlish/bootstrap/marshal.py,sha256=
|
37
|
+
omlish/bootstrap/marshal.py,sha256=ZxdAeMNd2qXRZ1HUK89HmEhz8tqlS9OduW34QBscKw0,516
|
38
38
|
omlish/bootstrap/sys.py,sha256=U0MFxO9tLFV3cdN5Y-Zrink6_45sFvzPUYQXyBk7-ns,8741
|
39
39
|
omlish/collections/__init__.py,sha256=tGUzvS_ZjiqALsLRy7JX3h4KZRQX2CmtdAfTRD7UwMk,1677
|
40
40
|
omlish/collections/_abc.py,sha256=sP7BpTVhx6s6C59mTFeosBi4rHOWC6tbFBYbxdZmvh0,2365
|
@@ -69,12 +69,12 @@ omlish/dataclasses/__init__.py,sha256=L2kRMvsWgsennXVw7VgZdczCtdLsQzyPcMFit2rBpb
|
|
69
69
|
omlish/dataclasses/utils.py,sha256=qBKHyW2LSjnJYfPSAExEsVZ5EdmDBfp4napAhfWkZFs,3221
|
70
70
|
omlish/dataclasses/impl/LICENSE,sha256=Oy-B_iHRgcSZxZolbI4ZaEVdZonSaaqFNzv7avQdo78,13936
|
71
71
|
omlish/dataclasses/impl/__init__.py,sha256=rQJRcE9fVsGEvRUOZ18r4DE0xiLbSRjspyJRXgbLS3I,348
|
72
|
-
omlish/dataclasses/impl/api.py,sha256=
|
72
|
+
omlish/dataclasses/impl/api.py,sha256=6QtUAbP3DQZw8WEkgpsYfYKTn4CQBV9v0z2B4fTcR80,6405
|
73
73
|
omlish/dataclasses/impl/as_.py,sha256=CD-t7hkC1EP2F_jvZKIA_cVoDuwZ-Ln_xC4fJumPYX0,2598
|
74
74
|
omlish/dataclasses/impl/copy.py,sha256=Tn8_n6Vohs-w4otbGdubBEvhd3TsSTaM3EfNGdS2LYo,591
|
75
75
|
omlish/dataclasses/impl/descriptors.py,sha256=rEYE1Len99agTQCC25hSPMnM19BgPr0ZChABGi58Fdk,2476
|
76
76
|
omlish/dataclasses/impl/exceptions.py,sha256=DeiM6rcjgncudn-XVuph9TDbVDEwBtyYb1bcbO3FFcA,193
|
77
|
-
omlish/dataclasses/impl/fields.py,sha256=
|
77
|
+
omlish/dataclasses/impl/fields.py,sha256=NIu30OggZvKhqQaZWad9dAE-B9yt9qvWtPR5U_TJIbQ,6281
|
78
78
|
omlish/dataclasses/impl/frozen.py,sha256=x87DSM8FIMZ3c_BIUE8NooCkExFjPsabeqIueEP5qKs,2988
|
79
79
|
omlish/dataclasses/impl/hashing.py,sha256=FKnHuXCg9ylrzK2TLGqO5yfRN4HX3F415CSLlVYXtYE,3190
|
80
80
|
omlish/dataclasses/impl/init.py,sha256=IgxO9nwHaHF8jGrUAk-Y5xke9uV2OwzfEe-88McE1Wg,6161
|
@@ -83,7 +83,7 @@ omlish/dataclasses/impl/main.py,sha256=Ti0PKbFKraKvfmoPuR-G7nLVNzRC8mvEuXhCuC-M2
|
|
83
83
|
omlish/dataclasses/impl/metaclass.py,sha256=dlQEIN9MHBirll7Nx3StpzxYxXjrqxJ-QsorMcCNt7w,2828
|
84
84
|
omlish/dataclasses/impl/metadata.py,sha256=4veWwTr-aA0KP-Y1cPEeOcXHup9EKJTYNJ0ozIxtzD4,1401
|
85
85
|
omlish/dataclasses/impl/order.py,sha256=zWvWDkSTym8cc7vO1cLHqcBhhjOlucHOCUVJcdh4jt0,1369
|
86
|
-
omlish/dataclasses/impl/params.py,sha256=
|
86
|
+
omlish/dataclasses/impl/params.py,sha256=IDM9VK-b5x7VauwYwXtwb9cg94UNpRUoZ0OH-Bv_kmM,2674
|
87
87
|
omlish/dataclasses/impl/processing.py,sha256=DFxyFjL_h3awRyF_5eyTnB8QkuApx7Zc4QFnVoltlao,459
|
88
88
|
omlish/dataclasses/impl/reflect.py,sha256=a19BbNxrmjNTbXzWuAl_794RCIQSMYyVqQ2Bf-DnNnM,5305
|
89
89
|
omlish/dataclasses/impl/replace.py,sha256=wS9GHX4fIwaPv1JBJzIewdBfXyK3X3V7_t55Da87dYo,1217
|
@@ -163,8 +163,8 @@ omlish/inject/impl/privates.py,sha256=alpCYyk5VJ9lJknbRH2nLVNFYVvFhkj-VC1Vco3zCF
|
|
163
163
|
omlish/inject/impl/providers.py,sha256=QnwhsujJFIHC0JTgd2Wlo1kP53i3CWTrj1nKU2DNxwg,2375
|
164
164
|
omlish/inject/impl/proxy.py,sha256=1ko0VaKqzu9UG8bIldp9xtUrAVUOFTKWKTjOCqIGr4s,1636
|
165
165
|
omlish/inject/impl/scopes.py,sha256=ASfULXgP_ETlsAqFJfrZmyEaZt64Zr8tNn5ScA-EoXk,5900
|
166
|
-
omlish/lang/__init__.py,sha256=
|
167
|
-
omlish/lang/cached.py,sha256=
|
166
|
+
omlish/lang/__init__.py,sha256=jDIv9mr3Y85S3DpUroaLty7q9iwMUjUlKwyUxs-zlXg,3618
|
167
|
+
omlish/lang/cached.py,sha256=92TvRZQ6sWlm7dNn4hgl7aWKbX0J1XUEo3DRjBpgVQk,7834
|
168
168
|
omlish/lang/clsdct.py,sha256=AjtIWLlx2E6D5rC97zQ3Lwq2SOMkbg08pdO_AxpzEHI,1744
|
169
169
|
omlish/lang/cmp.py,sha256=5vbzWWbqdzDmNKAGL19z6ZfUKe5Ci49e-Oegf9f4BsE,1346
|
170
170
|
omlish/lang/contextmanagers.py,sha256=NEwaTLQMfhKawD5x_0HgI2RpeLXbMa5r9NqWqfDnUXI,10408
|
@@ -185,7 +185,7 @@ omlish/lang/typing.py,sha256=lJ2NGe4Pmb61I0Tx4A_rOqXNFTws1XHOzafg2knRUio,4155
|
|
185
185
|
omlish/lang/classes/__init__.py,sha256=h9QXrvAKD17_pIog0uF-7BCqZbSpJZYxL7kzVzvljp0,583
|
186
186
|
omlish/lang/classes/abstract.py,sha256=IRnjuLLNwpxvEJsp8fwoQdCIpw0MDAd0TiQfoDMgsn4,2306
|
187
187
|
omlish/lang/classes/restrict.py,sha256=pSK7ZT_kpwqS6lWRrxwuEe-tt07F0-uZVazgGh-HDco,3921
|
188
|
-
omlish/lang/classes/simple.py,sha256=
|
188
|
+
omlish/lang/classes/simple.py,sha256=roGxmtl5BAXl6_WAt89Hfd1Xmu-Cvnwo-YCZgs1Wq-s,3116
|
189
189
|
omlish/lang/classes/virtual.py,sha256=W-QJuKsDehOcrydwg6eMN0bFPTYbk3Tz84TSH3blb44,3367
|
190
190
|
omlish/lifecycles/__init__.py,sha256=1FjYceXs-4fc-S-C9zFYmc2axHs4znnQHcJVHdY7a6E,578
|
191
191
|
omlish/lifecycles/abstract.py,sha256=70CQyZy-c9a2o0ZJxPeUT7eYjWZTBrp2HpUBnrHdAOM,1109
|
@@ -214,11 +214,11 @@ omlish/logs/formatters.py,sha256=q79nMnR2mRIStPyGrydQHpYTXgC5HHptt8lH3W2Wwbs,671
|
|
214
214
|
omlish/logs/handlers.py,sha256=nyuFgmO05By_Xwq7es58ClzS51-F53lJL7gD0x5IqAg,228
|
215
215
|
omlish/logs/noisy.py,sha256=Ubc-eTH6ZbGYsLfUUi69JAotwuUwzb-SJBeGo_0dIZI,348
|
216
216
|
omlish/logs/utils.py,sha256=MgGovbP0zUrZ3FGD3qYNQWn-l0jy0Y0bStcQvv5BOmQ,391
|
217
|
-
omlish/marshal/__init__.py,sha256=
|
217
|
+
omlish/marshal/__init__.py,sha256=B2NLwxUuhvD17FfbipXmYo9yZmpBFcHqGPp-r8_Vuvs,1951
|
218
218
|
omlish/marshal/any.py,sha256=e82OyYK3Emm1P1ClnsnxP7fIWC2iNVyW0H5nK4mLmWM,779
|
219
|
-
omlish/marshal/base.py,sha256=
|
219
|
+
omlish/marshal/base.py,sha256=ceNjOFxCwLNuxkmxofk3Sh5rE39JGxnc4giN7NNr9kA,6121
|
220
220
|
omlish/marshal/base64.py,sha256=F-3ogJdcFCtWINRgJgWT0rErqgx6f4qahhcg8OrkqhE,1089
|
221
|
-
omlish/marshal/dataclasses.py,sha256=
|
221
|
+
omlish/marshal/dataclasses.py,sha256=TdpTCqAHs9hrTyUG__goSRcm848LZznJcDG4WY5wbgM,4109
|
222
222
|
omlish/marshal/datetimes.py,sha256=0ffg8cEvx9SMKIXZGD9b7MqpLfmgw0uKKdn6YTfoqok,3714
|
223
223
|
omlish/marshal/enums.py,sha256=-0fKutBbyz8ygEaA0_P_8IOJrI9jMGigmnPbutV9Bg4,1464
|
224
224
|
omlish/marshal/exceptions.py,sha256=jwQWn4LcPnadT2KRI_1JJCOSkwWh0yHnYK9BmSkNN4U,302
|
@@ -228,16 +228,16 @@ omlish/marshal/global_.py,sha256=8XCjPcIjA65StESshzNfQiSyuckVaEiiWROmC3qk0mo,111
|
|
228
228
|
omlish/marshal/helpers.py,sha256=YA0pNo-Fkc-_qKeoRNXUpP36js8oelU7uENkvoGD4hY,1206
|
229
229
|
omlish/marshal/iterables.py,sha256=6I_ZdJemLSQtJ4J5NrB9wi-eyxiJZS61HzHXp1yeiX8,2592
|
230
230
|
omlish/marshal/mappings.py,sha256=zhLtyot7tzQtBNj7C4RBxjMELxA5r2q2Mth8Br7xkFs,2803
|
231
|
-
omlish/marshal/maybes.py,sha256=
|
231
|
+
omlish/marshal/maybes.py,sha256=mgK3QsWHkXgRqo076KxYKH6elRxzJ_QDTodv93mgHR0,2198
|
232
232
|
omlish/marshal/naming.py,sha256=lIklR_Od4x1ghltAgOzqcKhHs-leeSv2YmFhCHO7GIs,613
|
233
233
|
omlish/marshal/numbers.py,sha256=oY_yMNJEnJhjfLh89gpPXvKqeUyhQcaTcQB6ecyHiG8,1704
|
234
|
-
omlish/marshal/objects.py,sha256=
|
234
|
+
omlish/marshal/objects.py,sha256=E5wvH1o0_edsVJ4HoUuTqPfnb21ou08IdL442OQUOUw,5235
|
235
235
|
omlish/marshal/optionals.py,sha256=r0XB5rqfasvgZJNrKYd6Unq2U4nHt3JURi26j0dYHlw,1499
|
236
236
|
omlish/marshal/polymorphism.py,sha256=doA8aLUhna6aco5b2Ok3jsem1V4NsF3rM5RTfJt0a7U,5708
|
237
237
|
omlish/marshal/primitives.py,sha256=wcvcs5GH_TWVmzAszh3dvyKibJgBxnXke-AlAXiwrrI,1107
|
238
238
|
omlish/marshal/registries.py,sha256=GI2KogcxawMkk02Ky7-TsnijChoe1I7YTOPIbUNwSAI,1665
|
239
239
|
omlish/marshal/standard.py,sha256=uQZIGiCwihmhB1tmhpKnZWZly0DDkdGjCnN0d41WHho,2985
|
240
|
-
omlish/marshal/unions.py,sha256=
|
240
|
+
omlish/marshal/unions.py,sha256=ZWl0maHwh1V_cSnNmuCbbCQZzqlNtOModsTwnVTXNPA,2735
|
241
241
|
omlish/marshal/utils.py,sha256=puKJpwPpuDlMOIrKMcLTRLJyMiL6n_Xs-p59AuDEymA,543
|
242
242
|
omlish/marshal/uuids.py,sha256=H4B7UX_EPNmP2tC8bubcKrPLTS4aQu98huvbXQ3Zv2g,910
|
243
243
|
omlish/marshal/values.py,sha256=ssHiWdg_L6M17kAn8GiGdPW7UeQOm3RDikWkvwblf5I,263
|
@@ -252,12 +252,16 @@ omlish/reflect/subst.py,sha256=JM2RGv2-Rcex8wCqhmgvRG59zD242P9jM3O2QLjKWWo,3586
|
|
252
252
|
omlish/reflect/types.py,sha256=R9AH5YnOvdZs6QhzJ6VmjvcvGibQEQi6YqK25f5VUxw,6862
|
253
253
|
omlish/secrets/__init__.py,sha256=VKB2IF9vz4h4RXcZxgXj36KXOLcGBzfqVnxPgPDWpmg,408
|
254
254
|
omlish/secrets/crypto.py,sha256=6CsLy0UEqCrBK8Xx_3-iFF6SKtu2GlEqUQ8-MliY3tk,3709
|
255
|
-
omlish/secrets/marshal.py,sha256=
|
255
|
+
omlish/secrets/marshal.py,sha256=U9uSRTWzZmumfNZeh_dROwVdGrARsp155TylRbjilP8,2048
|
256
256
|
omlish/secrets/openssl.py,sha256=wxA_wIlxtuOUy71ABxAJgavh-UI_taOfm-A0dVlmSwM,6219
|
257
257
|
omlish/secrets/passwords.py,sha256=3r-vEK6Gp6aq4L5Csnd06QnrjO9xfzHJP-g_7I9W_ao,4101
|
258
258
|
omlish/secrets/secrets.py,sha256=ClD7t_mkmWkseVk4ahLzYLuLXeTxiwwPiidYm42vLh4,6871
|
259
259
|
omlish/secrets/subprocesses.py,sha256=EcnKlHHtnUMHGrBWXDfu8tv28wlgZx4P4GOiuPW9Vo8,1105
|
260
260
|
omlish/specs/__init__.py,sha256=_CSPXx25uGhXkmqLs9CSdcWAkZaQnc3cJk3lb2dadgE,88
|
261
|
+
omlish/specs/jsonrpc/__init__.py,sha256=E0EogYSKmbj1D-V57tBgPDTyVuD8HosHqVg0Vh1CVwM,416
|
262
|
+
omlish/specs/jsonrpc/errors.py,sha256=-Zgmlo6bV6J8w5f8h9axQgLquIFBHDgIwcpufEH5NsE,707
|
263
|
+
omlish/specs/jsonrpc/marshal.py,sha256=iXZNR7n0vfL_yiPFFYN-ZyGlzknNXExs2qC1HFChGPU,1913
|
264
|
+
omlish/specs/jsonrpc/types.py,sha256=g19j2_FCVJDXFqAkQ5U4LICkL4Z7vEBMU0t_aOEqio4,2159
|
261
265
|
omlish/specs/jsonschema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
262
266
|
omlish/specs/jsonschema/types.py,sha256=qoxExgKfrI-UZXdk3qcVZIEyp1WckFbb85_eGInEoAY,467
|
263
267
|
omlish/specs/jsonschema/keywords/__init__.py,sha256=Zt2g1BXd654uU2AQ5P7_-x2Wrtf6cNbP9mxI1wGN4wo,596
|
@@ -315,9 +319,9 @@ omlish/text/delimit.py,sha256=ubPXcXQmtbOVrUsNh5gH1mDq5H-n1y2R4cPL5_DQf68,4928
|
|
315
319
|
omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,3296
|
316
320
|
omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
|
317
321
|
omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
|
318
|
-
omlish-0.0.0.
|
319
|
-
omlish-0.0.0.
|
320
|
-
omlish-0.0.0.
|
321
|
-
omlish-0.0.0.
|
322
|
-
omlish-0.0.0.
|
323
|
-
omlish-0.0.0.
|
322
|
+
omlish-0.0.0.dev34.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
323
|
+
omlish-0.0.0.dev34.dist-info/METADATA,sha256=I7vDtfM84K2N4kDVSw3x12AYk-w30aHskCD3NF5TNbQ,3786
|
324
|
+
omlish-0.0.0.dev34.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
325
|
+
omlish-0.0.0.dev34.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
326
|
+
omlish-0.0.0.dev34.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
327
|
+
omlish-0.0.0.dev34.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|