omlish 0.0.0.dev19__py3-none-any.whl → 0.0.0.dev20__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 +3 -3
- omlish/asyncs/anyio.py +13 -6
- omlish/dataclasses/__init__.py +2 -0
- omlish/dataclasses/impl/metadata.py +2 -1
- omlish/dataclasses/utils.py +45 -0
- omlish/fnpairs.py +1 -1
- omlish/formats/json.py +1 -0
- omlish/lang/descriptors.py +2 -0
- omlish/lite/logs.py +2 -2
- omlish/marshal/__init__.py +4 -0
- omlish/marshal/dataclasses.py +16 -3
- omlish/marshal/helpers.py +22 -0
- omlish/marshal/objects.py +33 -14
- omlish/multiprocessing.py +32 -0
- omlish/specs/__init__.py +0 -0
- omlish/specs/jsonschema/__init__.py +0 -0
- omlish/specs/jsonschema/keywords/__init__.py +42 -0
- omlish/specs/jsonschema/keywords/base.py +86 -0
- omlish/specs/jsonschema/keywords/core.py +26 -0
- omlish/specs/jsonschema/keywords/metadata.py +22 -0
- omlish/specs/jsonschema/keywords/parse.py +69 -0
- omlish/specs/jsonschema/keywords/render.py +47 -0
- omlish/specs/jsonschema/keywords/validation.py +68 -0
- omlish/specs/jsonschema/schemas/__init__.py +0 -0
- omlish/specs/jsonschema/schemas/draft202012/__init__.py +0 -0
- omlish/specs/jsonschema/schemas/draft202012/vocabularies/__init__.py +0 -0
- omlish/specs/jsonschema/types.py +10 -0
- {omlish-0.0.0.dev19.dist-info → omlish-0.0.0.dev20.dist-info}/METADATA +3 -3
- {omlish-0.0.0.dev19.dist-info → omlish-0.0.0.dev20.dist-info}/RECORD +32 -18
- {omlish-0.0.0.dev19.dist-info → omlish-0.0.0.dev20.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev19.dist-info → omlish-0.0.0.dev20.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev19.dist-info → omlish-0.0.0.dev20.dist-info}/top_level.txt +0 -0
omlish/__about__.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
__version__ = '0.0.0.
|
2
|
-
__revision__ = '
|
1
|
+
__version__ = '0.0.0.dev20'
|
2
|
+
__revision__ = '56a3421b375112818e306f2c17d467c7aac1d26b'
|
3
3
|
|
4
4
|
|
5
5
|
#
|
@@ -88,7 +88,7 @@ class Project(ProjectBase):
|
|
88
88
|
'sqlx': [
|
89
89
|
'sqlean.py ~= 3.45; python_version < "3.13"',
|
90
90
|
|
91
|
-
'duckdb ~= 1.
|
91
|
+
'duckdb ~= 1.1',
|
92
92
|
],
|
93
93
|
|
94
94
|
'testing': [
|
omlish/asyncs/anyio.py
CHANGED
@@ -23,6 +23,7 @@ async def killer(shutdown: anyio.Event, sleep_s: float) -> None:
|
|
23
23
|
shutdown.set()
|
24
24
|
|
25
25
|
""" # noqa
|
26
|
+
import dataclasses as dc
|
26
27
|
import signal
|
27
28
|
import typing as ta
|
28
29
|
|
@@ -44,6 +45,12 @@ StapledByteStream: ta.TypeAlias = anyio.streams.stapled.StapledByteStream
|
|
44
45
|
StapledObjectStream: ta.TypeAlias = anyio.streams.stapled.StapledObjectStream
|
45
46
|
|
46
47
|
|
48
|
+
@dc.dataclass(eq=False)
|
49
|
+
class MemoryStapledObjectStream(StapledObjectStream[T]):
|
50
|
+
send_stream: MemoryObjectSendStream[T]
|
51
|
+
receive_stream: MemoryObjectReceiveStream[T]
|
52
|
+
|
53
|
+
|
47
54
|
##
|
48
55
|
|
49
56
|
|
@@ -143,8 +150,8 @@ def split_memory_object_streams(
|
|
143
150
|
return tup
|
144
151
|
|
145
152
|
|
146
|
-
def create_stapled_memory_object_stream(max_buffer_size: float = 0) ->
|
147
|
-
return
|
153
|
+
def create_stapled_memory_object_stream(max_buffer_size: float = 0) -> MemoryStapledObjectStream:
|
154
|
+
return MemoryStapledObjectStream(*anyio.create_memory_object_stream(max_buffer_size))
|
148
155
|
|
149
156
|
|
150
157
|
# FIXME: https://github.com/python/mypy/issues/15238
|
@@ -158,9 +165,9 @@ def create_memory_object_stream[T](max_buffer_size: float = 0) -> tuple[
|
|
158
165
|
|
159
166
|
def staple_memory_object_stream(
|
160
167
|
*args: anyio.create_memory_object_stream[T],
|
161
|
-
) ->
|
168
|
+
) -> MemoryStapledObjectStream[T]:
|
162
169
|
send, receive = args
|
163
|
-
return
|
170
|
+
return MemoryStapledObjectStream(
|
164
171
|
check.isinstance(send, MemoryObjectSendStream), # type: ignore
|
165
172
|
check.isinstance(receive, MemoryObjectReceiveStream), # type: ignore
|
166
173
|
)
|
@@ -168,9 +175,9 @@ def staple_memory_object_stream(
|
|
168
175
|
|
169
176
|
# FIXME: https://github.com/python/mypy/issues/15238
|
170
177
|
# FIXME: https://youtrack.jetbrains.com/issues?q=tag:%20%7BPEP%20695%7D
|
171
|
-
def staple_memory_object_stream2[T](max_buffer_size: float = 0) ->
|
178
|
+
def staple_memory_object_stream2[T](max_buffer_size: float = 0) -> MemoryStapledObjectStream[T]:
|
172
179
|
send, receive = anyio.create_memory_object_stream[T](max_buffer_size)
|
173
|
-
return
|
180
|
+
return MemoryStapledObjectStream(
|
174
181
|
check.isinstance(send, MemoryObjectSendStream), # type: ignore
|
175
182
|
check.isinstance(receive, MemoryObjectReceiveStream), # type: ignore
|
176
183
|
)
|
omlish/dataclasses/__init__.py
CHANGED
omlish/dataclasses/utils.py
CHANGED
@@ -12,6 +12,9 @@ from .impl.params import get_field_extras
|
|
12
12
|
T = ta.TypeVar('T')
|
13
13
|
|
14
14
|
|
15
|
+
#
|
16
|
+
|
17
|
+
|
15
18
|
def maybe_post_init(sup: ta.Any) -> bool:
|
16
19
|
try:
|
17
20
|
fn = sup.__post_init__
|
@@ -21,10 +24,16 @@ def maybe_post_init(sup: ta.Any) -> bool:
|
|
21
24
|
return True
|
22
25
|
|
23
26
|
|
27
|
+
#
|
28
|
+
|
29
|
+
|
24
30
|
def opt_repr(o: ta.Any) -> str | None:
|
25
31
|
return repr(o) if o is not None else None
|
26
32
|
|
27
33
|
|
34
|
+
#
|
35
|
+
|
36
|
+
|
28
37
|
class field_modifier: # noqa
|
29
38
|
def __init__(self, fn: ta.Callable[[dc.Field], dc.Field]) -> None:
|
30
39
|
super().__init__()
|
@@ -58,6 +67,42 @@ def update_field_extras(f: dc.Field, *, unless_non_default: bool = False, **kwar
|
|
58
67
|
})
|
59
68
|
|
60
69
|
|
70
|
+
def update_fields(
|
71
|
+
fn: ta.Callable[[str, dc.Field], dc.Field],
|
72
|
+
fields: ta.Iterable[str] | None = None,
|
73
|
+
) -> ta.Callable[[type[T]], type[T]]:
|
74
|
+
def inner(cls):
|
75
|
+
if fields is None:
|
76
|
+
for a, v in list(cls.__dict__.items()):
|
77
|
+
if isinstance(v, dc.Field):
|
78
|
+
setattr(cls, a, fn(a, v))
|
79
|
+
|
80
|
+
else:
|
81
|
+
for a in fields:
|
82
|
+
v = cls.__dict__[a]
|
83
|
+
if not isinstance(v, dc.Field):
|
84
|
+
v = dc.field(default=v)
|
85
|
+
setattr(cls, a, fn(a, v))
|
86
|
+
|
87
|
+
return cls
|
88
|
+
|
89
|
+
check.not_isinstance(fields, str)
|
90
|
+
return inner
|
91
|
+
|
92
|
+
|
93
|
+
def update_fields_metadata(
|
94
|
+
nmd: ta.Mapping,
|
95
|
+
fields: ta.Iterable[str] | None = None,
|
96
|
+
) -> ta.Callable[[type[T]], type[T]]:
|
97
|
+
def inner(a: str, f: dc.Field) -> dc.Field:
|
98
|
+
return update_field_metadata(f, nmd)
|
99
|
+
|
100
|
+
return update_fields(inner, fields)
|
101
|
+
|
102
|
+
|
103
|
+
#
|
104
|
+
|
105
|
+
|
61
106
|
def deep_replace(o: T, *args: str | ta.Callable[[ta.Any], ta.Mapping[str, ta.Any]]) -> T:
|
62
107
|
if not args:
|
63
108
|
return o
|
omlish/fnpairs.py
CHANGED
omlish/formats/json.py
CHANGED
omlish/lang/descriptors.py
CHANGED
@@ -125,11 +125,13 @@ class _decorator_descriptor: # noqa
|
|
125
125
|
|
126
126
|
def __get__(self, instance, owner=None):
|
127
127
|
fn = self._fn.__get__(instance, owner)
|
128
|
+
|
128
129
|
if self._md or instance is not None:
|
129
130
|
@functools.wraps(fn)
|
130
131
|
def inner(*args, **kwargs):
|
131
132
|
return self._wrapper(fn, *args, **kwargs)
|
132
133
|
return inner
|
134
|
+
|
133
135
|
else:
|
134
136
|
@functools.wraps(fn)
|
135
137
|
def outer(this, *args, **kwargs):
|
omlish/lite/logs.py
CHANGED
@@ -69,8 +69,8 @@ class JsonLogFormatter(logging.Formatter):
|
|
69
69
|
STANDARD_LOG_FORMAT_PARTS = [
|
70
70
|
('asctime', '%(asctime)-15s'),
|
71
71
|
('process', 'pid=%(process)-6s'),
|
72
|
-
('thread', 'tid=%(thread)
|
73
|
-
('levelname', '%(levelname)
|
72
|
+
('thread', 'tid=%(thread)x'),
|
73
|
+
('levelname', '%(levelname)s'),
|
74
74
|
('name', '%(name)s'),
|
75
75
|
('separator', '::'),
|
76
76
|
('message', '%(message)s'),
|
omlish/marshal/__init__.py
CHANGED
omlish/marshal/dataclasses.py
CHANGED
@@ -31,10 +31,19 @@ def get_dataclass_metadata(ty: type) -> ObjectMetadata:
|
|
31
31
|
) or ObjectMetadata()
|
32
32
|
|
33
33
|
|
34
|
-
def get_field_infos(
|
34
|
+
def get_field_infos(
|
35
|
+
ty: type,
|
36
|
+
opts: col.TypeMap[Option] = col.TypeMap(),
|
37
|
+
) -> ta.Sequence[FieldInfo]:
|
35
38
|
dc_md = get_dataclass_metadata(ty)
|
36
39
|
dc_naming = dc_md.field_naming or opts.get(Naming)
|
37
40
|
|
41
|
+
fi_defaults = {
|
42
|
+
k: v
|
43
|
+
for k, v in dc.asdict(dc_md.field_defaults).items()
|
44
|
+
if v is not None
|
45
|
+
}
|
46
|
+
|
38
47
|
type_hints = ta.get_type_hints(ty)
|
39
48
|
|
40
49
|
ret: list[FieldInfo] = []
|
@@ -44,7 +53,8 @@ def get_field_infos(ty: type, opts: col.TypeMap[Option] = col.TypeMap()) -> ta.S
|
|
44
53
|
else:
|
45
54
|
um_name = field.name
|
46
55
|
|
47
|
-
kw = dict(
|
56
|
+
kw = dict(fi_defaults)
|
57
|
+
kw.update(
|
48
58
|
name=field.name,
|
49
59
|
type=type_hints[field.name],
|
50
60
|
metadata=FieldMetadata(),
|
@@ -54,7 +64,10 @@ def get_field_infos(ty: type, opts: col.TypeMap[Option] = col.TypeMap()) -> ta.S
|
|
54
64
|
)
|
55
65
|
|
56
66
|
if (fmd := field.metadata.get(FieldMetadata)) is not None:
|
57
|
-
kw.update(
|
67
|
+
kw.update(
|
68
|
+
metadata=fmd,
|
69
|
+
omit_if=fmd.omit_if,
|
70
|
+
)
|
58
71
|
|
59
72
|
if fmd.name is not None:
|
60
73
|
kw.update(
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import typing as ta
|
2
|
+
|
3
|
+
from .. import dataclasses as dc
|
4
|
+
from .objects import FieldMetadata
|
5
|
+
|
6
|
+
|
7
|
+
T = ta.TypeVar('T')
|
8
|
+
|
9
|
+
|
10
|
+
def update_fields_metadata(
|
11
|
+
fields: ta.Iterable[str] | None = None,
|
12
|
+
**kwargs: ta.Any,
|
13
|
+
) -> ta.Callable[[type[T]], type[T]]:
|
14
|
+
def inner(a: str, f: dc.Field) -> dc.Field:
|
15
|
+
return dc.update_field_metadata(f, {
|
16
|
+
FieldMetadata: dc.replace(
|
17
|
+
f.metadata.get(FieldMetadata, FieldMetadata()),
|
18
|
+
**kwargs,
|
19
|
+
),
|
20
|
+
})
|
21
|
+
|
22
|
+
return dc.update_fields(inner, fields)
|
omlish/marshal/objects.py
CHANGED
@@ -22,18 +22,13 @@ from .values import Value
|
|
22
22
|
##
|
23
23
|
|
24
24
|
|
25
|
-
@dc.dataclass(frozen=True)
|
26
|
-
class ObjectMetadata:
|
27
|
-
field_naming: Naming | None = None
|
28
|
-
|
29
|
-
unknown_field: str | None = None
|
30
|
-
|
31
|
-
|
32
|
-
@dc.dataclass(frozen=True)
|
25
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
33
26
|
class FieldMetadata:
|
34
27
|
name: str | None = None
|
35
28
|
alts: ta.Iterable[str] | None = None
|
36
29
|
|
30
|
+
omit_if: ta.Callable[[ta.Any], bool] | None = None
|
31
|
+
|
37
32
|
marshaler: Marshaler | None = None
|
38
33
|
marshaler_factory: MarshalerFactory | None = None
|
39
34
|
|
@@ -41,18 +36,30 @@ class FieldMetadata:
|
|
41
36
|
unmarshaler_factory: UnmarshalerFactory | None = None
|
42
37
|
|
43
38
|
|
39
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
40
|
+
class ObjectMetadata:
|
41
|
+
field_naming: Naming | None = None
|
42
|
+
|
43
|
+
unknown_field: str | None = None
|
44
|
+
|
45
|
+
field_defaults: FieldMetadata = FieldMetadata()
|
46
|
+
|
47
|
+
|
44
48
|
##
|
45
49
|
|
46
50
|
|
47
|
-
@dc.dataclass(frozen=True)
|
51
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
48
52
|
class FieldInfo:
|
49
53
|
name: str
|
50
54
|
type: ta.Any
|
51
|
-
metadata: FieldMetadata
|
52
55
|
|
53
56
|
marshal_name: str
|
54
57
|
unmarshal_names: ta.Sequence[str]
|
55
58
|
|
59
|
+
metadata: FieldMetadata = FieldMetadata()
|
60
|
+
|
61
|
+
omit_if: ta.Callable[[ta.Any], bool] | None = None
|
62
|
+
|
56
63
|
|
57
64
|
##
|
58
65
|
|
@@ -63,15 +70,20 @@ class ObjectMarshaler(Marshaler):
|
|
63
70
|
unknown_field: str | None = None
|
64
71
|
|
65
72
|
def marshal(self, ctx: MarshalContext, o: ta.Any) -> Value:
|
66
|
-
ret = {
|
67
|
-
|
68
|
-
|
69
|
-
|
73
|
+
ret = {}
|
74
|
+
for fi, m in self.fields:
|
75
|
+
v = getattr(o, fi.name)
|
76
|
+
if fi.omit_if is not None and fi.omit_if(v):
|
77
|
+
continue
|
78
|
+
ret[fi.marshal_name] = m.marshal(ctx, v)
|
79
|
+
|
70
80
|
if self.unknown_field is not None:
|
71
81
|
if (ukf := getattr(o, self.unknown_field)):
|
72
82
|
if (dks := set(ret) & set(ukf)):
|
73
83
|
raise KeyError(f'Unknown field keys duplicate fields: {dks!r}')
|
84
|
+
|
74
85
|
ret.update(ukf) # FIXME: marshal?
|
86
|
+
|
75
87
|
return ret
|
76
88
|
|
77
89
|
|
@@ -89,18 +101,25 @@ class ObjectUnmarshaler(Unmarshaler):
|
|
89
101
|
u: ta.Any
|
90
102
|
kw: dict[str, ta.Any] = {}
|
91
103
|
ukf: dict[str, ta.Any] | None = None
|
104
|
+
|
92
105
|
if self.unknown_field is not None:
|
93
106
|
kw[self.unknown_field] = ukf = {}
|
107
|
+
|
94
108
|
for k, mv in ma.items():
|
95
109
|
ks = check.isinstance(k, str)
|
110
|
+
|
96
111
|
try:
|
97
112
|
fi, u = self.fields_by_unmarshal_name[ks]
|
113
|
+
|
98
114
|
except KeyError:
|
99
115
|
if ukf is not None:
|
100
116
|
ukf[ks] = mv # FIXME: unmarshal?
|
101
117
|
continue
|
102
118
|
raise
|
119
|
+
|
103
120
|
if fi.name in kw:
|
104
121
|
raise KeyError(f'Duplicate keys for field {fi.name!r}: {ks!r}')
|
122
|
+
|
105
123
|
kw[fi.name] = u.unmarshal(ctx, mv)
|
124
|
+
|
106
125
|
return self.cls(**kw)
|
omlish/multiprocessing.py
CHANGED
@@ -9,6 +9,7 @@ import time
|
|
9
9
|
import typing as ta
|
10
10
|
|
11
11
|
from . import check
|
12
|
+
from . import lang
|
12
13
|
from . import libc
|
13
14
|
|
14
15
|
|
@@ -18,6 +19,32 @@ T = ta.TypeVar('T')
|
|
18
19
|
##
|
19
20
|
|
20
21
|
|
22
|
+
@ta.runtime_checkable
|
23
|
+
class ValueProxy(ta.Protocol[T]):
|
24
|
+
# value = property(get, set)
|
25
|
+
|
26
|
+
def get(self) -> T:
|
27
|
+
...
|
28
|
+
|
29
|
+
def set(self, value: T) -> None:
|
30
|
+
...
|
31
|
+
|
32
|
+
|
33
|
+
@dc.dataclass()
|
34
|
+
@lang.protocol_check(ValueProxy)
|
35
|
+
class DummyValueProxy(ValueProxy[T]):
|
36
|
+
value: T
|
37
|
+
|
38
|
+
def get(self) -> T:
|
39
|
+
return self.value
|
40
|
+
|
41
|
+
def set(self, value: T) -> None:
|
42
|
+
self.value = value
|
43
|
+
|
44
|
+
|
45
|
+
##
|
46
|
+
|
47
|
+
|
21
48
|
@dc.dataclass(frozen=True, kw_only=True)
|
22
49
|
class SpawnExtras:
|
23
50
|
fds: ta.AbstractSet[int] | None = None
|
@@ -75,6 +102,11 @@ class Deathpact(abc.ABC):
|
|
75
102
|
raise NotImplementedError
|
76
103
|
|
77
104
|
|
105
|
+
class NopDeathpact(Deathpact):
|
106
|
+
def poll(self) -> None:
|
107
|
+
pass
|
108
|
+
|
109
|
+
|
78
110
|
#
|
79
111
|
|
80
112
|
|
omlish/specs/__init__.py
ADDED
File without changes
|
File without changes
|
@@ -0,0 +1,42 @@
|
|
1
|
+
from .base import ( # noqa
|
2
|
+
Keyword,
|
3
|
+
Keywords,
|
4
|
+
)
|
5
|
+
|
6
|
+
from .core import ( # noqa
|
7
|
+
CoreKeyword,
|
8
|
+
Id,
|
9
|
+
Ref,
|
10
|
+
SchemaKeyword,
|
11
|
+
)
|
12
|
+
|
13
|
+
from .metadata import ( # noqa
|
14
|
+
Description,
|
15
|
+
MetadataKeyword,
|
16
|
+
Title,
|
17
|
+
)
|
18
|
+
|
19
|
+
from .parse import ( # noqa
|
20
|
+
parse_keyword,
|
21
|
+
parse_keywords,
|
22
|
+
)
|
23
|
+
|
24
|
+
from .render import ( # noqa
|
25
|
+
render_keyword,
|
26
|
+
render_keywords,
|
27
|
+
)
|
28
|
+
|
29
|
+
from .validation import ( # noqa
|
30
|
+
ExclusiveMaximum,
|
31
|
+
ExclusiveMinimum,
|
32
|
+
Items,
|
33
|
+
MaxItems,
|
34
|
+
Maximum,
|
35
|
+
MinItems,
|
36
|
+
Minimum,
|
37
|
+
Properties,
|
38
|
+
Required,
|
39
|
+
Type,
|
40
|
+
UniqueItems,
|
41
|
+
ValidationKeyword,
|
42
|
+
)
|
@@ -0,0 +1,86 @@
|
|
1
|
+
import operator
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from omlish import cached
|
5
|
+
from omlish import check
|
6
|
+
from omlish import collections as col
|
7
|
+
from omlish import dataclasses as dc
|
8
|
+
from omlish import lang
|
9
|
+
|
10
|
+
|
11
|
+
KeywordT = ta.TypeVar('KeywordT', bound='Keyword')
|
12
|
+
|
13
|
+
|
14
|
+
##
|
15
|
+
|
16
|
+
|
17
|
+
class Keyword(lang.Abstract, lang.PackageSealed):
|
18
|
+
tag: ta.ClassVar[str]
|
19
|
+
|
20
|
+
def __init_subclass__(cls, *, tag: str | None = None, **kwargs: ta.Any) -> None:
|
21
|
+
super().__init_subclass__(**kwargs)
|
22
|
+
check.not_in('tag', dir(cls))
|
23
|
+
if not lang.is_abstract_class(cls):
|
24
|
+
check.issubclass(cls, lang.Final)
|
25
|
+
cls.tag = check.non_empty_str(tag)
|
26
|
+
else:
|
27
|
+
check.none(tag)
|
28
|
+
|
29
|
+
|
30
|
+
##
|
31
|
+
|
32
|
+
|
33
|
+
@dc.dataclass(frozen=True)
|
34
|
+
class Keywords(lang.Final):
|
35
|
+
lst: ta.Sequence[Keyword]
|
36
|
+
|
37
|
+
@cached.property
|
38
|
+
@dc.init
|
39
|
+
def by_type(self) -> ta.Mapping[type[Keyword], Keyword]:
|
40
|
+
return col.unique_map_by(type, self.lst, strict=True) # noqa
|
41
|
+
|
42
|
+
@cached.property
|
43
|
+
@dc.init
|
44
|
+
def by_tag(self) -> ta.Mapping[str, Keyword]:
|
45
|
+
return col.unique_map_by(operator.attrgetter('tag'), self.lst, strict=True) # noqa
|
46
|
+
|
47
|
+
def __getitem__(self, item: type[KeywordT] | str) -> KeywordT:
|
48
|
+
if isinstance(item, type):
|
49
|
+
return self.by_type[item] # noqa
|
50
|
+
elif isinstance(item, str):
|
51
|
+
return self.by_tag[item]
|
52
|
+
else:
|
53
|
+
raise TypeError(item)
|
54
|
+
|
55
|
+
|
56
|
+
##
|
57
|
+
|
58
|
+
|
59
|
+
@dc.dataclass(frozen=True)
|
60
|
+
class BooleanKeyword(Keyword, lang.Abstract):
|
61
|
+
b: bool
|
62
|
+
|
63
|
+
|
64
|
+
@dc.dataclass(frozen=True)
|
65
|
+
class NumberKeyword(Keyword, lang.Abstract):
|
66
|
+
n: int | float
|
67
|
+
|
68
|
+
|
69
|
+
@dc.dataclass(frozen=True)
|
70
|
+
class StrKeyword(Keyword, lang.Abstract):
|
71
|
+
s: str
|
72
|
+
|
73
|
+
|
74
|
+
@dc.dataclass(frozen=True)
|
75
|
+
class StrOrStrsKeyword(Keyword, lang.Abstract):
|
76
|
+
ss: str | ta.Sequence[str]
|
77
|
+
|
78
|
+
|
79
|
+
@dc.dataclass(frozen=True)
|
80
|
+
class KeywordsKeyword(Keyword, lang.Abstract):
|
81
|
+
kw: Keywords
|
82
|
+
|
83
|
+
|
84
|
+
@dc.dataclass(frozen=True)
|
85
|
+
class StrToKeywordsKeyword(Keyword, lang.Abstract):
|
86
|
+
m: ta.Mapping[str, Keywords]
|
@@ -0,0 +1,26 @@
|
|
1
|
+
from omlish import lang
|
2
|
+
|
3
|
+
from .base import Keyword
|
4
|
+
from .base import StrKeyword
|
5
|
+
|
6
|
+
|
7
|
+
##
|
8
|
+
|
9
|
+
|
10
|
+
class CoreKeyword(Keyword, lang.Abstract):
|
11
|
+
pass
|
12
|
+
|
13
|
+
|
14
|
+
##
|
15
|
+
|
16
|
+
|
17
|
+
class Id(StrKeyword, CoreKeyword, lang.Final, tag='$id'):
|
18
|
+
pass
|
19
|
+
|
20
|
+
|
21
|
+
class SchemaKeyword(StrKeyword, CoreKeyword, lang.Final, tag='$schema'):
|
22
|
+
pass
|
23
|
+
|
24
|
+
|
25
|
+
class Ref(StrKeyword, CoreKeyword, lang.Final, tag='$ref'):
|
26
|
+
pass
|
@@ -0,0 +1,22 @@
|
|
1
|
+
from omlish import lang
|
2
|
+
|
3
|
+
from .base import Keyword
|
4
|
+
from .base import StrKeyword
|
5
|
+
|
6
|
+
|
7
|
+
##
|
8
|
+
|
9
|
+
|
10
|
+
class MetadataKeyword(Keyword, lang.Abstract):
|
11
|
+
pass
|
12
|
+
|
13
|
+
|
14
|
+
##
|
15
|
+
|
16
|
+
|
17
|
+
class Title(StrKeyword, MetadataKeyword, lang.Final, tag='title'):
|
18
|
+
pass
|
19
|
+
|
20
|
+
|
21
|
+
class Description(StrKeyword, MetadataKeyword, lang.Final, tag='description'):
|
22
|
+
pass
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import operator
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from omlish import check
|
5
|
+
from omlish import collections as col
|
6
|
+
from omlish import lang
|
7
|
+
|
8
|
+
from . import core # noqa
|
9
|
+
from . import metadata # noqa
|
10
|
+
from . import validation # noqa
|
11
|
+
from .base import BooleanKeyword
|
12
|
+
from .base import Keyword
|
13
|
+
from .base import Keywords
|
14
|
+
from .base import KeywordsKeyword
|
15
|
+
from .base import NumberKeyword
|
16
|
+
from .base import StrKeyword
|
17
|
+
from .base import StrOrStrsKeyword
|
18
|
+
from .base import StrToKeywordsKeyword
|
19
|
+
|
20
|
+
|
21
|
+
KeywordT = ta.TypeVar('KeywordT', bound=Keyword)
|
22
|
+
|
23
|
+
|
24
|
+
##
|
25
|
+
|
26
|
+
|
27
|
+
KEYWORD_TYPES_BY_TAG: ta.Mapping[str, type[Keyword]] = col.unique_map_by( # noqa
|
28
|
+
operator.attrgetter('tag'),
|
29
|
+
(cls for cls in lang.deep_subclasses(Keyword) if not lang.is_abstract_class(cls)),
|
30
|
+
strict=True,
|
31
|
+
)
|
32
|
+
|
33
|
+
|
34
|
+
def parse_keyword(cls: type[KeywordT], v: ta.Any) -> KeywordT:
|
35
|
+
if issubclass(cls, BooleanKeyword):
|
36
|
+
return cls(check.isinstance(v, bool)) # type: ignore
|
37
|
+
|
38
|
+
elif issubclass(cls, NumberKeyword):
|
39
|
+
return cls(check.isinstance(v, (int, float))) # type: ignore
|
40
|
+
|
41
|
+
elif issubclass(cls, StrKeyword):
|
42
|
+
return cls(check.isinstance(v, str)) # type: ignore
|
43
|
+
|
44
|
+
elif issubclass(cls, StrOrStrsKeyword):
|
45
|
+
ss: str | ta.Sequence[str]
|
46
|
+
if isinstance(v, str):
|
47
|
+
ss = v
|
48
|
+
elif isinstance(v, ta.Iterable):
|
49
|
+
ss = col.seq_of(check.of_isinstance(str))(v)
|
50
|
+
else:
|
51
|
+
raise TypeError(v)
|
52
|
+
return cls(ss) # type: ignore
|
53
|
+
|
54
|
+
elif issubclass(cls, KeywordsKeyword):
|
55
|
+
return cls(parse_keywords(v)) # type: ignore
|
56
|
+
|
57
|
+
elif issubclass(cls, StrToKeywordsKeyword):
|
58
|
+
return cls({k: parse_keywords(mv) for k, mv in v.items()}) # type: ignore
|
59
|
+
|
60
|
+
else:
|
61
|
+
raise TypeError(cls)
|
62
|
+
|
63
|
+
|
64
|
+
def parse_keywords(dct: ta.Mapping[str, ta.Any]) -> Keywords:
|
65
|
+
lst: list[Keyword] = []
|
66
|
+
for k, v in dct.items():
|
67
|
+
cls = KEYWORD_TYPES_BY_TAG[k]
|
68
|
+
lst.append(parse_keyword(cls, v))
|
69
|
+
return Keywords(lst)
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import typing as ta
|
2
|
+
|
3
|
+
from .base import BooleanKeyword
|
4
|
+
from .base import Keyword
|
5
|
+
from .base import Keywords
|
6
|
+
from .base import KeywordsKeyword
|
7
|
+
from .base import NumberKeyword
|
8
|
+
from .base import StrKeyword
|
9
|
+
from .base import StrOrStrsKeyword
|
10
|
+
from .base import StrToKeywordsKeyword
|
11
|
+
|
12
|
+
|
13
|
+
def render_keyword(kw: Keyword) -> dict[str, ta.Any]:
|
14
|
+
if isinstance(kw, BooleanKeyword):
|
15
|
+
return {kw.tag: kw.b}
|
16
|
+
|
17
|
+
elif isinstance(kw, NumberKeyword):
|
18
|
+
return {kw.tag: kw.n}
|
19
|
+
|
20
|
+
elif isinstance(kw, StrKeyword):
|
21
|
+
return {kw.tag: kw.s}
|
22
|
+
|
23
|
+
elif isinstance(kw, StrOrStrsKeyword):
|
24
|
+
if isinstance(kw.ss, str):
|
25
|
+
return {kw.tag: kw.ss}
|
26
|
+
else:
|
27
|
+
return {kw.tag: list(kw.ss)}
|
28
|
+
|
29
|
+
elif isinstance(kw, KeywordsKeyword):
|
30
|
+
return {kw.tag: render_keywords(kw.kw)}
|
31
|
+
|
32
|
+
elif isinstance(kw, StrToKeywordsKeyword):
|
33
|
+
return {kw.tag: {k: render_keywords(v) for k, v in kw.m.items()}}
|
34
|
+
|
35
|
+
else:
|
36
|
+
raise TypeError(kw)
|
37
|
+
|
38
|
+
|
39
|
+
def render_keywords(kws: Keywords) -> dict[str, ta.Any]:
|
40
|
+
dct: dict[str, ta.Any] = {}
|
41
|
+
for kw in kws.lst:
|
42
|
+
kwd = render_keyword(kw)
|
43
|
+
[(tag, val)] = kwd.items()
|
44
|
+
if tag in dct:
|
45
|
+
raise KeyError(tag)
|
46
|
+
dct[tag] = val
|
47
|
+
return dct
|
@@ -0,0 +1,68 @@
|
|
1
|
+
from omlish import lang
|
2
|
+
|
3
|
+
from .base import BooleanKeyword
|
4
|
+
from .base import Keyword
|
5
|
+
from .base import KeywordsKeyword
|
6
|
+
from .base import NumberKeyword
|
7
|
+
from .base import StrOrStrsKeyword
|
8
|
+
from .base import StrToKeywordsKeyword
|
9
|
+
|
10
|
+
|
11
|
+
##
|
12
|
+
|
13
|
+
|
14
|
+
class ValidationKeyword(Keyword, lang.Abstract):
|
15
|
+
pass
|
16
|
+
|
17
|
+
|
18
|
+
##
|
19
|
+
|
20
|
+
|
21
|
+
class Type(StrOrStrsKeyword, ValidationKeyword, lang.Final, tag='type'):
|
22
|
+
pass
|
23
|
+
|
24
|
+
|
25
|
+
class Items(KeywordsKeyword, ValidationKeyword, lang.Final, tag='items'):
|
26
|
+
pass
|
27
|
+
|
28
|
+
|
29
|
+
class Required(StrOrStrsKeyword, ValidationKeyword, lang.Final, tag='required'):
|
30
|
+
pass
|
31
|
+
|
32
|
+
|
33
|
+
class Properties(StrToKeywordsKeyword, ValidationKeyword, lang.Final, tag='properties'):
|
34
|
+
pass
|
35
|
+
|
36
|
+
|
37
|
+
##
|
38
|
+
|
39
|
+
|
40
|
+
class MaxItems(NumberKeyword, ValidationKeyword, lang.Final, tag='maxItems'):
|
41
|
+
pass
|
42
|
+
|
43
|
+
|
44
|
+
class MinItems(NumberKeyword, ValidationKeyword, lang.Final, tag='minItems'):
|
45
|
+
pass
|
46
|
+
|
47
|
+
|
48
|
+
class UniqueItems(BooleanKeyword, ValidationKeyword, lang.Final, tag='uniqueItems'):
|
49
|
+
pass
|
50
|
+
|
51
|
+
|
52
|
+
#
|
53
|
+
|
54
|
+
|
55
|
+
class Maximum(NumberKeyword, ValidationKeyword, lang.Final, tag='maximum'):
|
56
|
+
pass
|
57
|
+
|
58
|
+
|
59
|
+
class ExclusiveMaximum(NumberKeyword, ValidationKeyword, lang.Final, tag='exclusiveMaximum'):
|
60
|
+
pass
|
61
|
+
|
62
|
+
|
63
|
+
class Minimum(NumberKeyword, ValidationKeyword, lang.Final, tag='minimum'):
|
64
|
+
pass
|
65
|
+
|
66
|
+
|
67
|
+
class ExclusiveMinimum(NumberKeyword, ValidationKeyword, lang.Final, tag='exclusiveMinimum'):
|
68
|
+
pass
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: omlish
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev20
|
4
4
|
Summary: omlish
|
5
5
|
Author: wrmsr
|
6
6
|
License: BSD-3-Clause
|
@@ -31,7 +31,7 @@ Requires-Dist: pg8000 ~=1.31 ; extra == 'all'
|
|
31
31
|
Requires-Dist: pymysql ~=1.1 ; extra == 'all'
|
32
32
|
Requires-Dist: aiomysql ~=0.2 ; extra == 'all'
|
33
33
|
Requires-Dist: aiosqlite ~=0.20 ; extra == 'all'
|
34
|
-
Requires-Dist: duckdb ~=1.
|
34
|
+
Requires-Dist: duckdb ~=1.1 ; extra == 'all'
|
35
35
|
Requires-Dist: pytest ~=8.0 ; extra == 'all'
|
36
36
|
Requires-Dist: greenlet ~=3.0 ; (python_version < "3.13") and extra == 'all'
|
37
37
|
Requires-Dist: trio-asyncio ~=0.15 ; (python_version < "3.13") and extra == 'all'
|
@@ -73,7 +73,7 @@ Requires-Dist: sqlalchemy[asyncio] ~=2.0 ; (python_version < "3.13") and extra =
|
|
73
73
|
Requires-Dist: asyncpg ~=0.29 ; (python_version < "3.13") and extra == 'sql'
|
74
74
|
Requires-Dist: sqlalchemy ~=2.0 ; (python_version ~= "3.13") and extra == 'sql'
|
75
75
|
Provides-Extra: sqlx
|
76
|
-
Requires-Dist: duckdb ~=1.
|
76
|
+
Requires-Dist: duckdb ~=1.1 ; extra == 'sqlx'
|
77
77
|
Requires-Dist: sqlean.py ~=3.45 ; (python_version < "3.13") and extra == 'sqlx'
|
78
78
|
Provides-Extra: testing
|
79
79
|
Requires-Dist: pytest ~=8.0 ; extra == 'testing'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
omlish/__about__.py,sha256=
|
1
|
+
omlish/__about__.py,sha256=aaPwsrPbNAl3zQVkQ9n1ZeBGXbeIaqkXe-qJK-YhMn4,2451
|
2
2
|
omlish/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
omlish/argparse.py,sha256=QRQmX9G0-L_nATkFtGHvpd4qrpYzKATdjuFLbBqzJPM,6224
|
4
4
|
omlish/c3.py,sha256=W5EwYx9Por3rWYLkKUitJ6OoRMLLgVTfLTyroOz41Y0,8047
|
@@ -9,19 +9,19 @@ omlish/datetimes.py,sha256=HajeM1kBvwlTa-uR1TTZHmZ3zTPnnUr1uGGQhiO1XQ0,2152
|
|
9
9
|
omlish/defs.py,sha256=T3bq_7h_tO3nDB5RAFBn7DkdeQgqheXzkFColbOHZko,4890
|
10
10
|
omlish/docker.py,sha256=5WyXJyFwqIJJ11QWwPIjHjDHnsaOVZszZAjyTvg3xew,4693
|
11
11
|
omlish/dynamic.py,sha256=35C_cCX_Vq2HrHzGk5T-zbrMvmUdiIiwDzDNixczoDo,6541
|
12
|
-
omlish/fnpairs.py,sha256=
|
12
|
+
omlish/fnpairs.py,sha256=hVuLqQFdRNNze3FYH2cAQO3GC7nK5yQP_GWPUSbL7nE,10601
|
13
13
|
omlish/iterators.py,sha256=GGLC7RIT86uXMjhIIIqnff_Iu5SI_b9rXYywYGFyzmo,7292
|
14
14
|
omlish/libc.py,sha256=u0481imCiTFqP_e-v9g0pD-0WD249j5vYzhtn-fnNkY,15308
|
15
15
|
omlish/matchfns.py,sha256=o2evI7q0CAMHR8RQ_Jks6L0UoNpEDltnLjOiamJDtmU,6155
|
16
16
|
omlish/math.py,sha256=AVqp5Y8yxKA-wO0BgrzaxA0Ga3PZiCXnYcwivMneC-0,3804
|
17
|
-
omlish/multiprocessing.py,sha256=
|
17
|
+
omlish/multiprocessing.py,sha256=Jbcr71p_HlsM5rIFl9obzSv9TCusPhxciwpBXLTYpmc,5179
|
18
18
|
omlish/os.py,sha256=cz4nL2ujaxH_-XRq3JUD8af8mSe1JXGPIoXP9XAEd0M,2607
|
19
19
|
omlish/runmodule.py,sha256=PWvuAaJ9wQQn6bx9ftEL3_d04DyotNn8dR_twm2pgw0,700
|
20
20
|
omlish/stats.py,sha256=uqjN-focDVssFZMagj22HqmyJ1TBO4Wt-XnHp8-EtVw,9927
|
21
21
|
omlish/sync.py,sha256=AqwIfIuCMVHLwlJUa7dmaSjfA4sM5AYPCD5-nsz3XVQ,1516
|
22
22
|
omlish/term.py,sha256=NEmxqAhicyInGtmFamZAizI2xdu819MzFYPEp0Fx97M,6111
|
23
23
|
omlish/asyncs/__init__.py,sha256=uUz9ziKh4_QrgmdhKFMgq6j7mFbiZd3LiogguDCQsGI,587
|
24
|
-
omlish/asyncs/anyio.py,sha256=
|
24
|
+
omlish/asyncs/anyio.py,sha256=Hqdi1iCopKoaAWGx-AYTRLEwnavLWx1esfJISK1IVF0,8024
|
25
25
|
omlish/asyncs/asyncio.py,sha256=JfM59QgB3asgEbrps0zoVbNjWD4kL2XdsEkRMEIoFos,971
|
26
26
|
omlish/asyncs/asyncs.py,sha256=Tf7ZodTGepkM7HAuFcDNh9lLzzrMw6rELWvopGmFkh4,2035
|
27
27
|
omlish/asyncs/bridge.py,sha256=AabrRVz5k75dTB59M70DWkl6JrLusjhpvsaj5jld9io,8151
|
@@ -60,8 +60,8 @@ omlish/configs/__init__.py,sha256=3uh09ezodTwkMI0nRmAMP0eEuJ_0VdF-LYyNmPjHiCE,77
|
|
60
60
|
omlish/configs/classes.py,sha256=GLbB8xKjHjjoUQRCUQm3nEjM8z1qNTx9gPV7ODSt5dg,1317
|
61
61
|
omlish/configs/flattening.py,sha256=AOlRpBHm449MxwMp3CiIRGunStOC1DUNs1f3CLou0wc,4731
|
62
62
|
omlish/configs/strings.py,sha256=0brx1duL85r1GpfbNvbHcSvH4jWzutwuvMFXda9NeI0,2651
|
63
|
-
omlish/dataclasses/__init__.py,sha256=
|
64
|
-
omlish/dataclasses/utils.py,sha256=
|
63
|
+
omlish/dataclasses/__init__.py,sha256=pnIEFM-2aWoN9yLLThAzVJUT7YzdGaAcfqWUVGF9WDk,1294
|
64
|
+
omlish/dataclasses/utils.py,sha256=G5kRFc6QPNQLdehsdH-2m6Fjba_k1OFjx72zSHtfccI,2781
|
65
65
|
omlish/dataclasses/impl/__init__.py,sha256=rQJRcE9fVsGEvRUOZ18r4DE0xiLbSRjspyJRXgbLS3I,348
|
66
66
|
omlish/dataclasses/impl/api.py,sha256=NOuw5dlwztG5AA_gwdF2PJAqvouMdbUf1Si80G26qAY,6244
|
67
67
|
omlish/dataclasses/impl/as_.py,sha256=CD-t7hkC1EP2F_jvZKIA_cVoDuwZ-Ln_xC4fJumPYX0,2598
|
@@ -75,7 +75,7 @@ omlish/dataclasses/impl/init.py,sha256=yw9iInFHaR_TFWRzsryr8vgStHMQwqubL-s7pY5k1
|
|
75
75
|
omlish/dataclasses/impl/internals.py,sha256=LTCqGT8AhyGTWwioGrBpTJzDzPvAtizQKb0NBNKcNs0,2989
|
76
76
|
omlish/dataclasses/impl/main.py,sha256=vAVdqb4cgvyssA7rCFl9i2D0MAffX45YtQbGQ2te5_c,5189
|
77
77
|
omlish/dataclasses/impl/metaclass.py,sha256=dlQEIN9MHBirll7Nx3StpzxYxXjrqxJ-QsorMcCNt7w,2828
|
78
|
-
omlish/dataclasses/impl/metadata.py,sha256=
|
78
|
+
omlish/dataclasses/impl/metadata.py,sha256=binwdG0cyKdGEypRKYTbcDyH_be4aTaSnVnK2V5rwB8,1402
|
79
79
|
omlish/dataclasses/impl/order.py,sha256=zWvWDkSTym8cc7vO1cLHqcBhhjOlucHOCUVJcdh4jt0,1369
|
80
80
|
omlish/dataclasses/impl/params.py,sha256=M-xg9IeFftVy795oqlp7Yw8jE-7wG2K4vaFhXHKmL1k,2538
|
81
81
|
omlish/dataclasses/impl/processing.py,sha256=iUvaNwRAt8rQsLIIkvRye5rfk6xhgR35EbcdwZCZec8,366
|
@@ -103,7 +103,7 @@ omlish/dispatch/functions.py,sha256=S8ElsLi6DKxTdtFGigWaF0vAquwy2sK-3f4iRLaYq70,
|
|
103
103
|
omlish/dispatch/methods.py,sha256=XHjwwC9Gn4iDWxbyLAcbdSwRgVaq-8Bnn5cAwf5oZdA,5403
|
104
104
|
omlish/formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
105
105
|
omlish/formats/dotenv.py,sha256=UjZl3gac-0U24sDjCCGMcCqO1UCWG2Zs8PZ4JdAg2YE,17348
|
106
|
-
omlish/formats/json.py,sha256=
|
106
|
+
omlish/formats/json.py,sha256=61XG6rveb3SSXmYrKvUmRdaVDyMD6C-7yVqXBBMu8t8,1017
|
107
107
|
omlish/formats/props.py,sha256=diYjZDsG1s50ImJhkpeinMwjr8952nIVI-0gYhBIvCY,18897
|
108
108
|
omlish/formats/yaml.py,sha256=5gvH-e9fVn6C-xpcagnrtM0bSLOsuk3sAQT-aaE4PD4,6653
|
109
109
|
omlish/graphs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -159,7 +159,7 @@ omlish/lang/cached.py,sha256=0gjdxVELu69oRQ3kqSV3cGIHg6Nf4pcCIIRTEU52tCc,7607
|
|
159
159
|
omlish/lang/clsdct.py,sha256=LXwLCULeI_8Np-7-pZkyNAHpUZLcQiBEQiHwKYQ0WRo,1742
|
160
160
|
omlish/lang/cmp.py,sha256=5vbzWWbqdzDmNKAGL19z6ZfUKe5Ci49e-Oegf9f4BsE,1346
|
161
161
|
omlish/lang/contextmanagers.py,sha256=C6FU_1ftMvp_Zbz9ixf_HsCSYQot_TZ7mpZBJEBc3Xc,8333
|
162
|
-
omlish/lang/descriptors.py,sha256=
|
162
|
+
omlish/lang/descriptors.py,sha256=J0oRWys9smHp9UYeearBATA7u-6t5pDnQgPfWiXN3B4,5902
|
163
163
|
omlish/lang/exceptions.py,sha256=qJBo3NU1mOWWm-NhQUHCY5feYXR3arZVyEHinLsmRH4,47
|
164
164
|
omlish/lang/functions.py,sha256=T4nPl46EHHGjMkz3FTRjsVhS9Y8HKcwM0jROU6_-Rv0,3619
|
165
165
|
omlish/lang/imports.py,sha256=04ugFC8NI5sbL7NH4V0r0q_nFsP_AMkHLz697CVkMtQ,6274
|
@@ -189,7 +189,7 @@ omlish/lite/cached.py,sha256=dUm647FbIsoxWT23XUFM51F7i-C2Buxr5b5zzgbCtQI,546
|
|
189
189
|
omlish/lite/check.py,sha256=DR3Zj-7o4Y7pNheln68nN_BdX9zaotGQ2y8v97GDiWQ,535
|
190
190
|
omlish/lite/contextmanagers.py,sha256=HnQJiyrOmSvTL22XRJrFl5CLpCyHD9fsntEUAr9G-60,427
|
191
191
|
omlish/lite/json.py,sha256=7-02Ny4fq-6YAu5ynvqoijhuYXWpLmfCI19GUeZnb1c,740
|
192
|
-
omlish/lite/logs.py,sha256=
|
192
|
+
omlish/lite/logs.py,sha256=qgP0pNjkoG5gjQ6xuXM7qpsLwZX3WbS7WaZlDqQKry4,2641
|
193
193
|
omlish/lite/marshal.py,sha256=5uwri-KzPiktnbYORkGXcJ4kulZvp_nS4MxPsU1Y-G0,8608
|
194
194
|
omlish/lite/reflect.py,sha256=9QYJwdINraq1JNMEgvoqeSlVvRRgOXpxAkpgX8EgRXc,1307
|
195
195
|
omlish/lite/runtime.py,sha256=VUhmNQvwf8QzkWSKj4Q0ReieJA_PzHaJNRBivfTseow,452
|
@@ -202,23 +202,24 @@ omlish/logs/configs.py,sha256=VfZjhyA4CeMYNhlsv5oD2IZ6Iv4d_lbUgZzcnLAkxNA,1052
|
|
202
202
|
omlish/logs/formatters.py,sha256=AFs9C6-qrFkgXZ0nL39wih_LGck1Tc79alvGyibBdQo,720
|
203
203
|
omlish/logs/noisy.py,sha256=8JORjI1dH38yU2MddM54OB6qt32Xozfocdb88vY4wro,335
|
204
204
|
omlish/logs/utils.py,sha256=MgGovbP0zUrZ3FGD3qYNQWn-l0jy0Y0bStcQvv5BOmQ,391
|
205
|
-
omlish/marshal/__init__.py,sha256=
|
205
|
+
omlish/marshal/__init__.py,sha256=Co5UUlCyd3eDToQTOvTURmCICKzuULnR5B6ylgb2nFM,1515
|
206
206
|
omlish/marshal/any.py,sha256=e82OyYK3Emm1P1ClnsnxP7fIWC2iNVyW0H5nK4mLmWM,779
|
207
207
|
omlish/marshal/base.py,sha256=EIgrqsQ1OQ4mVUMuDH5zRBCwJpn8ijVS98Nmoka_Mrs,6025
|
208
208
|
omlish/marshal/base64.py,sha256=Q3ibujdhgFgDaeHahSe7WdcqvOyalWigwUlV-U-2ckQ,1018
|
209
|
-
omlish/marshal/dataclasses.py,sha256=
|
209
|
+
omlish/marshal/dataclasses.py,sha256=cqHfzkQe7T-A_eAx-xZm6AIOZLnqE-alMUXMtRTYxuI,3910
|
210
210
|
omlish/marshal/datetimes.py,sha256=0ffg8cEvx9SMKIXZGD9b7MqpLfmgw0uKKdn6YTfoqok,3714
|
211
211
|
omlish/marshal/enums.py,sha256=-0fKutBbyz8ygEaA0_P_8IOJrI9jMGigmnPbutV9Bg4,1464
|
212
212
|
omlish/marshal/exceptions.py,sha256=jwQWn4LcPnadT2KRI_1JJCOSkwWh0yHnYK9BmSkNN4U,302
|
213
213
|
omlish/marshal/factories.py,sha256=UV2Svjok-lTWsRqKGh-CeuAhvlohw9uJe7ZLyoKMvTM,2968
|
214
214
|
omlish/marshal/forbidden.py,sha256=BNshzm4lN5O8sUZ1YvxrSYq3WPklq9NMQCRZ7RC3DLM,865
|
215
215
|
omlish/marshal/global_.py,sha256=8XCjPcIjA65StESshzNfQiSyuckVaEiiWROmC3qk0mo,1117
|
216
|
+
omlish/marshal/helpers.py,sha256=L9U40zeo4pKsNtohKaLHHiGz-aitOFQI1Xwii1ZsLOE,545
|
216
217
|
omlish/marshal/iterables.py,sha256=6I_ZdJemLSQtJ4J5NrB9wi-eyxiJZS61HzHXp1yeiX8,2592
|
217
218
|
omlish/marshal/mappings.py,sha256=zhLtyot7tzQtBNj7C4RBxjMELxA5r2q2Mth8Br7xkFs,2803
|
218
219
|
omlish/marshal/maybes.py,sha256=tKkVsJATERgbVcEfBnsHBK_2_LCQIVyBzca-cA-9KH0,2112
|
219
220
|
omlish/marshal/naming.py,sha256=UCviMAXTTUpW1lyAGymybGP2rFUAW44P1X0zrIVbvi4,464
|
220
221
|
omlish/marshal/numbers.py,sha256=oY_yMNJEnJhjfLh89gpPXvKqeUyhQcaTcQB6ecyHiG8,1704
|
221
|
-
omlish/marshal/objects.py,sha256=
|
222
|
+
omlish/marshal/objects.py,sha256=T3prlm0HESpOLXHWcdsYekfmythJRZQOvaoL0is8J_o,3097
|
222
223
|
omlish/marshal/optionals.py,sha256=r0XB5rqfasvgZJNrKYd6Unq2U4nHt3JURi26j0dYHlw,1499
|
223
224
|
omlish/marshal/polymorphism.py,sha256=gyvNYUAkmQVhWrcXBLzXINxqx6RHyulf9n16Iv38PFI,5597
|
224
225
|
omlish/marshal/primitives.py,sha256=-gLR_RTPTM8YP6t6PL5sNM1lAtwcZDHc9lxkimoQ9jw,1097
|
@@ -239,6 +240,19 @@ omlish/secrets/openssl.py,sha256=nAA_wxk86G92B7027AoAlAiFliMjxLVs7xlaOAFGayE,622
|
|
239
240
|
omlish/secrets/passwords.py,sha256=3r-vEK6Gp6aq4L5Csnd06QnrjO9xfzHJP-g_7I9W_ao,4101
|
240
241
|
omlish/secrets/secrets.py,sha256=hFN82uYiBVx8YSE86leWNxb4IRp3qdwZPOi4w04h8u0,6855
|
241
242
|
omlish/secrets/subprocesses.py,sha256=EcnKlHHtnUMHGrBWXDfu8tv28wlgZx4P4GOiuPW9Vo8,1105
|
243
|
+
omlish/specs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
244
|
+
omlish/specs/jsonschema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
245
|
+
omlish/specs/jsonschema/types.py,sha256=aJrZq2oqjmbGa32YnWyGFPbEyNfm0YO9ixNy7qU-snE,189
|
246
|
+
omlish/specs/jsonschema/keywords/__init__.py,sha256=Zt2g1BXd654uU2AQ5P7_-x2Wrtf6cNbP9mxI1wGN4wo,596
|
247
|
+
omlish/specs/jsonschema/keywords/base.py,sha256=HA4OvsdvAl4o5JgJI_tuaHBGURjxT5QeFN6_ja5Z5xQ,1957
|
248
|
+
omlish/specs/jsonschema/keywords/core.py,sha256=irJ5Rreg9hTeXu3FovSdzhFb3vUly-hYQVYflEgST3g,368
|
249
|
+
omlish/specs/jsonschema/keywords/metadata.py,sha256=55jlunXosdcM1IQ256KfUIEwFzDPah448ZOeQhJE1c8,316
|
250
|
+
omlish/specs/jsonschema/keywords/parse.py,sha256=3XzHE5gN6usVUMw2DrvbNZrGDYdM8EefVyfQ0cEMKEA,1936
|
251
|
+
omlish/specs/jsonschema/keywords/render.py,sha256=enGkw1S8Zxfn1IBkKqZTK81yG21MVKk54B8rqiTY30c,1236
|
252
|
+
omlish/specs/jsonschema/keywords/validation.py,sha256=ghewVUSG5qPYnmexy1Ylc-XouiQXobsXLYvkaGgZLqg,1322
|
253
|
+
omlish/specs/jsonschema/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
254
|
+
omlish/specs/jsonschema/schemas/draft202012/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
255
|
+
omlish/specs/jsonschema/schemas/draft202012/vocabularies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
242
256
|
omlish/sql/__init__.py,sha256=pLv2EQmAwcGXN0Y3AE8K5JjyN_4GaHRMHyExaDFm5yU,181
|
243
257
|
omlish/sql/_abc.py,sha256=HLhnnLZ7l0r_N99I-RCqJe6VHth-9iluU7cR-7-5jfs,1519
|
244
258
|
omlish/sql/asyncs.py,sha256=Wye3dwh7oZEGYz2Y4DZQSHtW4xjI2AH5qjW-BSS2IfU,3688
|
@@ -271,8 +285,8 @@ omlish/text/delimit.py,sha256=ubPXcXQmtbOVrUsNh5gH1mDq5H-n1y2R4cPL5_DQf68,4928
|
|
271
285
|
omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,3296
|
272
286
|
omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
|
273
287
|
omlish/text/parts.py,sha256=KGgo0wHOIMVMZtDso-rhSWKAcAkYAH2IGpg9tULabu8,6505
|
274
|
-
omlish-0.0.0.
|
275
|
-
omlish-0.0.0.
|
276
|
-
omlish-0.0.0.
|
277
|
-
omlish-0.0.0.
|
278
|
-
omlish-0.0.0.
|
288
|
+
omlish-0.0.0.dev20.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
289
|
+
omlish-0.0.0.dev20.dist-info/METADATA,sha256=BBHZ7D3ieK9P1cgSW23jGabeqRXDnzccCc8Tsby0J5Y,3718
|
290
|
+
omlish-0.0.0.dev20.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
291
|
+
omlish-0.0.0.dev20.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
292
|
+
omlish-0.0.0.dev20.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|