omlish 0.0.0.dev75__py3-none-any.whl → 0.0.0.dev76__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/.manifests.json +12 -0
- omlish/__about__.py +3 -3
- omlish/dataclasses/impl/exceptions.py +44 -2
- omlish/dataclasses/impl/fields.py +22 -1
- omlish/dataclasses/impl/init.py +2 -2
- omlish/formats/yaml.py +1 -1
- omlish/graphs/dags.py +1 -1
- omlish/graphs/domination.py +1 -1
- omlish/http/__init__.py +6 -0
- omlish/http/clients.py +15 -2
- omlish/http/headers.py +4 -0
- omlish/http/multipart.py +82 -0
- omlish/lang/__init__.py +1 -0
- omlish/lang/objects.py +7 -0
- omlish/lifecycles/controller.py +1 -1
- omlish/marshal/mappings.py +1 -1
- omlish/marshal/numbers.py +2 -2
- omlish/marshal/objects.py +1 -1
- omlish/marshal/polymorphism.py +4 -4
- omlish/secrets/pwgen.py +83 -0
- omlish/secrets/secrets.py +9 -0
- {omlish-0.0.0.dev75.dist-info → omlish-0.0.0.dev76.dist-info}/METADATA +3 -3
- {omlish-0.0.0.dev75.dist-info → omlish-0.0.0.dev76.dist-info}/RECORD +28 -27
- omlish/http/collections.py +0 -15
- /omlish/secrets/{passwords.py → pwhash.py} +0 -0
- {omlish-0.0.0.dev75.dist-info → omlish-0.0.0.dev76.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev75.dist-info → omlish-0.0.0.dev76.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev75.dist-info → omlish-0.0.0.dev76.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev75.dist-info → omlish-0.0.0.dev76.dist-info}/top_level.txt +0 -0
omlish/.manifests.json
CHANGED
@@ -47,6 +47,18 @@
|
|
47
47
|
}
|
48
48
|
}
|
49
49
|
},
|
50
|
+
{
|
51
|
+
"module": ".secrets.pwgen",
|
52
|
+
"attr": "_CLI_MODULE",
|
53
|
+
"file": "omlish/secrets/pwgen.py",
|
54
|
+
"line": 75,
|
55
|
+
"value": {
|
56
|
+
"$omdev.cli.types.CliModule": {
|
57
|
+
"cmd_name": "pwgen",
|
58
|
+
"mod_name": "omlish.secrets.pwgen"
|
59
|
+
}
|
60
|
+
}
|
61
|
+
},
|
50
62
|
{
|
51
63
|
"module": ".specs.jmespath.__main__",
|
52
64
|
"attr": "_CLI_MODULE",
|
omlish/__about__.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
__version__ = '0.0.0.
|
2
|
-
__revision__ = '
|
1
|
+
__version__ = '0.0.0.dev76'
|
2
|
+
__revision__ = 'f7a91a7adb0b3e2018caef9de1ec592d87644c60'
|
3
3
|
|
4
4
|
|
5
5
|
#
|
@@ -97,7 +97,7 @@ class Project(ProjectBase):
|
|
97
97
|
|
98
98
|
'aiomysql ~= 0.2',
|
99
99
|
'aiosqlite ~= 0.20',
|
100
|
-
'asyncpg ~= 0.
|
100
|
+
'asyncpg ~= 0.30; python_version < "3.13"',
|
101
101
|
|
102
102
|
'apsw ~= 3.46',
|
103
103
|
|
@@ -1,8 +1,50 @@
|
|
1
|
+
import types
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
|
1
5
|
class ValidationError(Exception):
|
2
6
|
pass
|
3
7
|
|
4
8
|
|
9
|
+
def _hands_off_repr(obj: ta.Any) -> str:
|
10
|
+
return f'{obj.__class__.__qualname__}@{hex(id(obj))[2:]}'
|
11
|
+
|
12
|
+
|
13
|
+
def _fn_repr(fn: ta.Callable) -> str:
|
14
|
+
if (co := getattr(fn, '__code__', None)) is None or not isinstance(co, types.CodeType):
|
15
|
+
return repr(fn)
|
16
|
+
|
17
|
+
if not (co_filename := co.co_filename):
|
18
|
+
return repr(fn)
|
19
|
+
|
20
|
+
return f'{fn!r} ({co_filename}:{co.co_firstlineno})'
|
21
|
+
|
22
|
+
|
5
23
|
class FieldValidationError(ValidationError):
|
6
|
-
def __init__(
|
7
|
-
|
24
|
+
def __init__(
|
25
|
+
self,
|
26
|
+
obj: ta.Any,
|
27
|
+
field: str,
|
28
|
+
fn: ta.Callable,
|
29
|
+
value: ta.Any,
|
30
|
+
) -> None:
|
31
|
+
super().__init__(
|
32
|
+
f'{self.__class__.__name__} '
|
33
|
+
f'for field {field!r} '
|
34
|
+
f'on object {_hands_off_repr(obj)} '
|
35
|
+
f'in validator {_fn_repr(fn)} '
|
36
|
+
f'with value {value!r}',
|
37
|
+
)
|
38
|
+
|
39
|
+
self.obj = obj
|
8
40
|
self.field = field
|
41
|
+
self.fn = fn
|
42
|
+
self.value = value
|
43
|
+
|
44
|
+
def __repr__(self) -> str:
|
45
|
+
return f'{self.__class__.__name__}({", ".join([
|
46
|
+
f"obj={_hands_off_repr(self.obj)}",
|
47
|
+
f"field={self.field!r}",
|
48
|
+
f"fn={_fn_repr(self.fn)}",
|
49
|
+
f"value={self.value!r}",
|
50
|
+
])})'
|
@@ -8,6 +8,7 @@ import typing as ta
|
|
8
8
|
|
9
9
|
from ... import check as check_
|
10
10
|
from ... import lang
|
11
|
+
from .exceptions import FieldValidationError
|
11
12
|
from .internals import FIELDS_ATTR
|
12
13
|
from .internals import FieldType
|
13
14
|
from .internals import is_classvar
|
@@ -29,6 +30,23 @@ MISSING = dc.MISSING
|
|
29
30
|
##
|
30
31
|
|
31
32
|
|
33
|
+
def raise_field_validation_error(
|
34
|
+
obj: ta.Any,
|
35
|
+
field: str,
|
36
|
+
fn: ta.Callable,
|
37
|
+
value: ta.Any,
|
38
|
+
):
|
39
|
+
raise FieldValidationError(
|
40
|
+
obj,
|
41
|
+
field,
|
42
|
+
fn,
|
43
|
+
value,
|
44
|
+
)
|
45
|
+
|
46
|
+
|
47
|
+
##
|
48
|
+
|
49
|
+
|
32
50
|
def field_type(f: dc.Field) -> FieldType:
|
33
51
|
if (ft := getattr(f, '_field_type')) is not None:
|
34
52
|
return FieldType(ft)
|
@@ -193,7 +211,10 @@ def field_init(
|
|
193
211
|
if fx.validate is not None:
|
194
212
|
cn = f'__dataclass_validate__{f.name}__'
|
195
213
|
locals[cn] = fx.validate
|
196
|
-
lines.append(
|
214
|
+
lines.append(
|
215
|
+
f'if not {cn}({value}): '
|
216
|
+
f'__dataclass_raise_field_validation_error__({self_name}, {f.name!r}, {cn}, {value})',
|
217
|
+
)
|
197
218
|
|
198
219
|
if fx.check_type:
|
199
220
|
cn = f'__dataclass_check_type__{f.name}__'
|
omlish/dataclasses/impl/init.py
CHANGED
@@ -3,11 +3,11 @@ import inspect
|
|
3
3
|
import typing as ta
|
4
4
|
|
5
5
|
from ... import lang
|
6
|
-
from .exceptions import FieldValidationError
|
7
6
|
from .exceptions import ValidationError
|
8
7
|
from .fields import field_init
|
9
8
|
from .fields import field_type
|
10
9
|
from .fields import has_default
|
10
|
+
from .fields import raise_field_validation_error
|
11
11
|
from .internals import HAS_DEFAULT_FACTORY
|
12
12
|
from .internals import POST_INIT_NAME
|
13
13
|
from .internals import FieldType
|
@@ -101,7 +101,7 @@ class InitBuilder:
|
|
101
101
|
'__dataclass_builtins_isinstance__': isinstance,
|
102
102
|
'__dataclass_builtins_TypeError__': TypeError,
|
103
103
|
'__dataclass_ValidationError__': ValidationError,
|
104
|
-
'
|
104
|
+
'__dataclass_raise_field_validation_error__': raise_field_validation_error,
|
105
105
|
})
|
106
106
|
|
107
107
|
body_lines: list[str] = []
|
omlish/formats/yaml.py
CHANGED
@@ -118,7 +118,7 @@ class NodeWrappingConstructorMixin:
|
|
118
118
|
yield omap
|
119
119
|
uomap = next(gen)
|
120
120
|
lang.exhaust(gen)
|
121
|
-
for key, value in uomap:
|
121
|
+
for key, value in uomap:
|
122
122
|
omap.append(NodeWrapped((key, value), node))
|
123
123
|
|
124
124
|
def construct_yaml_omap(self, node):
|
omlish/graphs/dags.py
CHANGED
@@ -80,7 +80,7 @@ class Subdag(ta.Generic[U]):
|
|
80
80
|
) -> None:
|
81
81
|
super().__init__()
|
82
82
|
|
83
|
-
self._dag: Dag[U] = check.isinstance(dag, Dag)
|
83
|
+
self._dag: Dag[U] = check.isinstance(dag, Dag)
|
84
84
|
self._targets = set(targets)
|
85
85
|
self._ignored = set(ignored or []) - self._targets
|
86
86
|
|
omlish/graphs/domination.py
CHANGED
@@ -195,7 +195,7 @@ class _ImmediateDominanceComputer(ta.Generic[V]):
|
|
195
195
|
def __init__(self, dfs: _Dfs[V]) -> None:
|
196
196
|
super().__init__()
|
197
197
|
|
198
|
-
self._dfs: _Dfs[V] = check.isinstance(dfs, _Dfs)
|
198
|
+
self._dfs: _Dfs[V] = check.isinstance(dfs, _Dfs)
|
199
199
|
|
200
200
|
self._ancestor: dict[V, V] = {}
|
201
201
|
self._semi = dict(self._dfs.semi)
|
omlish/http/__init__.py
CHANGED
omlish/http/clients.py
CHANGED
@@ -203,10 +203,14 @@ class HttpxHttpClient(HttpClient):
|
|
203
203
|
##
|
204
204
|
|
205
205
|
|
206
|
-
def
|
206
|
+
def _default_client() -> HttpClient:
|
207
207
|
return UrllibHttpClient()
|
208
208
|
|
209
209
|
|
210
|
+
def client() -> HttpClient:
|
211
|
+
return _default_client()
|
212
|
+
|
213
|
+
|
210
214
|
def request(
|
211
215
|
url: str,
|
212
216
|
method: str | None = None,
|
@@ -218,6 +222,8 @@ def request(
|
|
218
222
|
|
219
223
|
check: bool = False,
|
220
224
|
|
225
|
+
client: HttpClient | None = None,
|
226
|
+
|
221
227
|
**kwargs: ta.Any,
|
222
228
|
) -> HttpResponse:
|
223
229
|
req = HttpRequest(
|
@@ -232,9 +238,16 @@ def request(
|
|
232
238
|
**kwargs,
|
233
239
|
)
|
234
240
|
|
235
|
-
|
241
|
+
def do(cli: HttpClient) -> HttpResponse:
|
236
242
|
return cli.request(
|
237
243
|
req,
|
238
244
|
|
239
245
|
check=check,
|
240
246
|
)
|
247
|
+
|
248
|
+
if client is not None:
|
249
|
+
return do(client)
|
250
|
+
|
251
|
+
else:
|
252
|
+
with _default_client() as cli:
|
253
|
+
return do(cli)
|
omlish/http/headers.py
CHANGED
omlish/http/multipart.py
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
"""
|
2
|
+
https://datatracker.ietf.org/doc/html/rfc7578
|
3
|
+
"""
|
4
|
+
import dataclasses as dc
|
5
|
+
import io
|
6
|
+
import typing as ta
|
7
|
+
|
8
|
+
from .. import cached
|
9
|
+
|
10
|
+
|
11
|
+
MultipartData: ta.TypeAlias = ta.Any # bytes | file
|
12
|
+
|
13
|
+
|
14
|
+
@dc.dataclass(frozen=True)
|
15
|
+
class MultipartField:
|
16
|
+
data: MultipartData
|
17
|
+
name: bytes | None = None
|
18
|
+
file_name: bytes | None = None
|
19
|
+
headers: ta.Sequence[tuple[bytes, bytes]] | None = None
|
20
|
+
|
21
|
+
|
22
|
+
class MultipartEncoder:
|
23
|
+
def __init__(
|
24
|
+
self,
|
25
|
+
fields: ta.Sequence[MultipartField],
|
26
|
+
*,
|
27
|
+
boundary: bytes | None = None,
|
28
|
+
) -> None:
|
29
|
+
super().__init__()
|
30
|
+
self._fields = fields
|
31
|
+
self._boundary = boundary or b'----WebKitFormBoundary7MA4YWxkTrZu0gW'
|
32
|
+
|
33
|
+
class _Line(ta.NamedTuple):
|
34
|
+
data: MultipartData
|
35
|
+
sz: int
|
36
|
+
|
37
|
+
@cached.function
|
38
|
+
def _lines(self) -> ta.Sequence[_Line]:
|
39
|
+
l: list[MultipartEncoder._Line] = []
|
40
|
+
|
41
|
+
def add(d: MultipartData) -> None:
|
42
|
+
if isinstance(d, bytes):
|
43
|
+
sz = len(d)
|
44
|
+
else:
|
45
|
+
raise TypeError(d)
|
46
|
+
l.append(MultipartEncoder._Line(d, sz))
|
47
|
+
|
48
|
+
for f in self._fields:
|
49
|
+
add(b'--%s' % (self._boundary,))
|
50
|
+
ps = [b'form-data']
|
51
|
+
if f.name is not None:
|
52
|
+
ps.append(b'name="%s"' % (f.name,))
|
53
|
+
if f.file_name is not None:
|
54
|
+
ps.append(b'filename="%s"' % (f.file_name,))
|
55
|
+
add(b'Content-Disposition: ' + b'; '.join(ps))
|
56
|
+
for hk, hv in f.headers or ():
|
57
|
+
add(b'%s: %s' % (hk, hv))
|
58
|
+
add(b'')
|
59
|
+
add(f.data)
|
60
|
+
|
61
|
+
add(b'--%s--' % (self._boundary,))
|
62
|
+
|
63
|
+
return l
|
64
|
+
|
65
|
+
@cached.function
|
66
|
+
def content_type(self) -> bytes:
|
67
|
+
return b'multipart/form-data; boundary=%s' % (self._boundary,)
|
68
|
+
|
69
|
+
@cached.function
|
70
|
+
def content_length(self) -> int:
|
71
|
+
return sum(l.sz + 2 for l in self._lines())
|
72
|
+
|
73
|
+
@cached.function
|
74
|
+
def content(self) -> bytes:
|
75
|
+
buf = io.BytesIO()
|
76
|
+
for l in self._lines():
|
77
|
+
if isinstance(l.data, bytes):
|
78
|
+
buf.write(l.data)
|
79
|
+
else:
|
80
|
+
raise TypeError(l.data)
|
81
|
+
buf.write(b'\r\n')
|
82
|
+
return buf.getvalue()
|
omlish/lang/__init__.py
CHANGED
omlish/lang/objects.py
CHANGED
omlish/lifecycles/controller.py
CHANGED
@@ -55,7 +55,7 @@ class LifecycleController(Lifecycle, ta.Generic[LifecycleT]):
|
|
55
55
|
return self._state
|
56
56
|
|
57
57
|
def add_listener(self, listener: LifecycleListener[LifecycleT]) -> 'LifecycleController':
|
58
|
-
self._listeners.append(check.isinstance(listener, LifecycleListener))
|
58
|
+
self._listeners.append(check.isinstance(listener, LifecycleListener))
|
59
59
|
return self
|
60
60
|
|
61
61
|
def _advance(
|
omlish/marshal/mappings.py
CHANGED
@@ -53,7 +53,7 @@ class MappingUnmarshaler(Unmarshaler):
|
|
53
53
|
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Mapping:
|
54
54
|
dct: dict = {}
|
55
55
|
for mk, mv in check.isinstance(v, collections.abc.Mapping).items():
|
56
|
-
dct[self.ke.unmarshal(ctx, mk)] = self.ve.unmarshal(ctx, mv)
|
56
|
+
dct[self.ke.unmarshal(ctx, mk)] = self.ve.unmarshal(ctx, mv)
|
57
57
|
return self.ctor(dct)
|
58
58
|
|
59
59
|
|
omlish/marshal/numbers.py
CHANGED
@@ -18,7 +18,7 @@ class ComplexMarshalerUnmarshaler(Marshaler, Unmarshaler):
|
|
18
18
|
|
19
19
|
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any:
|
20
20
|
real, imag = check.isinstance(v, list)
|
21
|
-
return complex(real, imag)
|
21
|
+
return complex(real, imag)
|
22
22
|
|
23
23
|
|
24
24
|
class DecimalMarshalerUnmarshaler(Marshaler, Unmarshaler):
|
@@ -35,7 +35,7 @@ class FractionMarshalerUnmarshaler(Marshaler, Unmarshaler):
|
|
35
35
|
|
36
36
|
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any:
|
37
37
|
num, denom = check.isinstance(v, list)
|
38
|
-
return fractions.Fraction(num, denom)
|
38
|
+
return fractions.Fraction(num, denom)
|
39
39
|
|
40
40
|
|
41
41
|
NUMBERS_MARSHALER_FACTORY = TypeMapMarshalerFactory({
|
omlish/marshal/objects.py
CHANGED
@@ -167,7 +167,7 @@ class ObjectMarshaler(Marshaler):
|
|
167
167
|
|
168
168
|
if fi.options.embed:
|
169
169
|
for ek, ev in check.isinstance(mv, collections.abc.Mapping).items():
|
170
|
-
ret[mn + check.non_empty_str(ek)] = ev
|
170
|
+
ret[mn + check.non_empty_str(ek)] = ev
|
171
171
|
|
172
172
|
else:
|
173
173
|
ret[mn] = mv
|
omlish/marshal/polymorphism.py
CHANGED
@@ -183,8 +183,8 @@ class WrapperPolymorphismUnmarshaler(Unmarshaler):
|
|
183
183
|
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
|
184
184
|
ma = check.isinstance(v, collections.abc.Mapping)
|
185
185
|
[(tag, iv)] = ma.items()
|
186
|
-
u = self.m[tag]
|
187
|
-
return u.unmarshal(ctx, iv)
|
186
|
+
u = self.m[tag]
|
187
|
+
return u.unmarshal(ctx, iv)
|
188
188
|
|
189
189
|
|
190
190
|
@dc.dataclass(frozen=True)
|
@@ -194,8 +194,8 @@ class FieldPolymorphismUnmarshaler(Unmarshaler):
|
|
194
194
|
|
195
195
|
def unmarshal(self, ctx: UnmarshalContext, v: Value) -> ta.Any | None:
|
196
196
|
ma = dict(check.isinstance(v, collections.abc.Mapping))
|
197
|
-
tag = ma.pop(self.tf)
|
198
|
-
u = self.m[tag]
|
197
|
+
tag = ma.pop(self.tf)
|
198
|
+
u = self.m[tag]
|
199
199
|
return u.unmarshal(ctx, ma)
|
200
200
|
|
201
201
|
|
omlish/secrets/pwgen.py
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- len
|
4
|
+
- required character classes
|
5
|
+
- lowercase
|
6
|
+
- uppercase
|
7
|
+
- digits
|
8
|
+
- symbols
|
9
|
+
- move to omlish/secrets
|
10
|
+
- argparse, CliCmd
|
11
|
+
"""
|
12
|
+
import argparse
|
13
|
+
import random
|
14
|
+
import secrets
|
15
|
+
import string
|
16
|
+
import typing as ta
|
17
|
+
|
18
|
+
|
19
|
+
CHAR_CLASSES: ta.Mapping[str, str] = {
|
20
|
+
'lower': string.ascii_lowercase,
|
21
|
+
'upper': string.ascii_uppercase,
|
22
|
+
'digit': string.digits,
|
23
|
+
'special': string.punctuation,
|
24
|
+
}
|
25
|
+
|
26
|
+
|
27
|
+
ALL_CHAR_CLASSES = tuple(CHAR_CLASSES.values())
|
28
|
+
DEFAULT_LENGTH = 16
|
29
|
+
|
30
|
+
|
31
|
+
def generate_password(
|
32
|
+
char_classes: ta.Sequence[str] = ALL_CHAR_CLASSES,
|
33
|
+
length: int = DEFAULT_LENGTH,
|
34
|
+
*,
|
35
|
+
rand: random.Random | None = None,
|
36
|
+
) -> str:
|
37
|
+
if rand is None:
|
38
|
+
rand = secrets.SystemRandom()
|
39
|
+
l: list[str] = []
|
40
|
+
for cc in char_classes:
|
41
|
+
l.append(rand.choice(cc))
|
42
|
+
cs = ''.join(char_classes)
|
43
|
+
if not cs:
|
44
|
+
raise ValueError(cs)
|
45
|
+
while len(l) < length:
|
46
|
+
l.append(rand.choice(cs))
|
47
|
+
rand.shuffle(l)
|
48
|
+
return ''.join(l)
|
49
|
+
|
50
|
+
|
51
|
+
def _main() -> None:
|
52
|
+
parser = argparse.ArgumentParser()
|
53
|
+
parser.add_argument('length', type=int, nargs='?', default=DEFAULT_LENGTH)
|
54
|
+
for cc in CHAR_CLASSES:
|
55
|
+
parser.add_argument(f'-{cc[0]}', f'--{cc}', action='store_true')
|
56
|
+
args = parser.parse_args()
|
57
|
+
|
58
|
+
cs = {
|
59
|
+
cc
|
60
|
+
for cc in CHAR_CLASSES
|
61
|
+
if getattr(args, cc) is not None
|
62
|
+
}
|
63
|
+
if cs:
|
64
|
+
ccs = tuple(CHAR_CLASSES[cc] for cc in cs)
|
65
|
+
else:
|
66
|
+
ccs = ALL_CHAR_CLASSES
|
67
|
+
|
68
|
+
pw = generate_password(
|
69
|
+
ccs,
|
70
|
+
args.length,
|
71
|
+
)
|
72
|
+
print(pw)
|
73
|
+
|
74
|
+
|
75
|
+
# @omlish-manifest
|
76
|
+
_CLI_MODULE = {'$omdev.cli.types.CliModule': {
|
77
|
+
'cmd_name': 'pwgen',
|
78
|
+
'mod_name': __name__,
|
79
|
+
}}
|
80
|
+
|
81
|
+
|
82
|
+
if __name__ == '__main__':
|
83
|
+
_main()
|
omlish/secrets/secrets.py
CHANGED
@@ -36,6 +36,15 @@ class Secret(lang.NotPicklable, lang.Sensitive, lang.Final):
|
|
36
36
|
self._key = key
|
37
37
|
setattr(self, self._VALUE_ATTR, lambda: value)
|
38
38
|
|
39
|
+
@classmethod
|
40
|
+
def of(cls, src: ta.Union['Secret', str], *, key: str | None = None) -> 'Secret':
|
41
|
+
if isinstance(src, Secret):
|
42
|
+
return src
|
43
|
+
elif isinstance(src, str):
|
44
|
+
return cls(key=key, value=src)
|
45
|
+
else:
|
46
|
+
raise TypeError(src)
|
47
|
+
|
39
48
|
def __repr__(self) -> str:
|
40
49
|
return f'Secret<{self._key or ""}>'
|
41
50
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: omlish
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev76
|
4
4
|
Summary: omlish
|
5
5
|
Author: wrmsr
|
6
6
|
License: BSD-3-Clause
|
@@ -41,7 +41,7 @@ Requires-Dist: apsw ~=3.46 ; extra == 'all'
|
|
41
41
|
Requires-Dist: duckdb ~=1.1 ; extra == 'all'
|
42
42
|
Requires-Dist: pytest ~=8.0 ; extra == 'all'
|
43
43
|
Requires-Dist: python-snappy ~=0.7 ; (python_version < "3.13") and extra == 'all'
|
44
|
-
Requires-Dist: asyncpg ~=0.
|
44
|
+
Requires-Dist: asyncpg ~=0.30 ; (python_version < "3.13") and extra == 'all'
|
45
45
|
Requires-Dist: sqlean.py ~=3.45 ; (python_version < "3.13") and extra == 'all'
|
46
46
|
Provides-Extra: async
|
47
47
|
Requires-Dist: anyio ~=4.6 ; extra == 'async'
|
@@ -87,7 +87,7 @@ Requires-Dist: aiomysql ~=0.2 ; extra == 'sqldrivers'
|
|
87
87
|
Requires-Dist: aiosqlite ~=0.20 ; extra == 'sqldrivers'
|
88
88
|
Requires-Dist: apsw ~=3.46 ; extra == 'sqldrivers'
|
89
89
|
Requires-Dist: duckdb ~=1.1 ; extra == 'sqldrivers'
|
90
|
-
Requires-Dist: asyncpg ~=0.
|
90
|
+
Requires-Dist: asyncpg ~=0.30 ; (python_version < "3.13") and extra == 'sqldrivers'
|
91
91
|
Requires-Dist: sqlean.py ~=3.45 ; (python_version < "3.13") and extra == 'sqldrivers'
|
92
92
|
Provides-Extra: testing
|
93
93
|
Requires-Dist: pytest ~=8.0 ; extra == 'testing'
|
@@ -1,5 +1,5 @@
|
|
1
|
-
omlish/.manifests.json,sha256=
|
2
|
-
omlish/__about__.py,sha256=
|
1
|
+
omlish/.manifests.json,sha256=ucaSu1XcJPryi-AqINUejkVDeJAFk7Bp5ar5_tJTgME,1692
|
2
|
+
omlish/__about__.py,sha256=ndeBykRuOFL5NcUF-CXeCBZk1bdqwu15XuWzvQiIeHU,3420
|
3
3
|
omlish/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
omlish/argparse.py,sha256=Dc73G8lyoQBLvXhMYUbzQUh4SJu_OTvKUXjSUxq_ang,7499
|
5
5
|
omlish/c3.py,sha256=4vogWgwPb8TbNS2KkZxpoWbwjj7MuHG2lQG-hdtkvjI,8062
|
@@ -132,11 +132,11 @@ omlish/dataclasses/impl/api.py,sha256=p7W519_EnDAWlkOVS-4BpP4SxadWIiUzC3RldSoB28
|
|
132
132
|
omlish/dataclasses/impl/as_.py,sha256=CD-t7hkC1EP2F_jvZKIA_cVoDuwZ-Ln_xC4fJumPYX0,2598
|
133
133
|
omlish/dataclasses/impl/copy.py,sha256=Tn8_n6Vohs-w4otbGdubBEvhd3TsSTaM3EfNGdS2LYo,591
|
134
134
|
omlish/dataclasses/impl/descriptors.py,sha256=rEYE1Len99agTQCC25hSPMnM19BgPr0ZChABGi58Fdk,2476
|
135
|
-
omlish/dataclasses/impl/exceptions.py,sha256
|
136
|
-
omlish/dataclasses/impl/fields.py,sha256=
|
135
|
+
omlish/dataclasses/impl/exceptions.py,sha256=-vqxZmfXVflymVuiM553XTlJProse5HEMktTpfdPCIY,1275
|
136
|
+
omlish/dataclasses/impl/fields.py,sha256=DbdTUnwFNL7KxNZBmEAGg4muMyFWbiMR8BUtUAOLrrc,6863
|
137
137
|
omlish/dataclasses/impl/frozen.py,sha256=x87DSM8FIMZ3c_BIUE8NooCkExFjPsabeqIueEP5qKs,2988
|
138
138
|
omlish/dataclasses/impl/hashing.py,sha256=FKnHuXCg9ylrzK2TLGqO5yfRN4HX3F415CSLlVYXtYE,3190
|
139
|
-
omlish/dataclasses/impl/init.py,sha256=
|
139
|
+
omlish/dataclasses/impl/init.py,sha256=t8wFWS5jw1XaY8KwL5iLSoeON0iILA2sqa-lDair0Ck,6181
|
140
140
|
omlish/dataclasses/impl/internals.py,sha256=UvZYjrLT1S8ntyxJ_vRPIkPOF00K8HatGAygErgoXTU,2990
|
141
141
|
omlish/dataclasses/impl/main.py,sha256=Ti0PKbFKraKvfmoPuR-G7nLVNzRC8mvEuXhCuC-M2kc,2574
|
142
142
|
omlish/dataclasses/impl/metaclass.py,sha256=Fb0ExFiyYdOpvck4ayXMr_vEVDvHLhe28Ns3F4aduM8,3222
|
@@ -182,7 +182,7 @@ omlish/docker/manifests.py,sha256=LR4FpOGNUT3bZQ-gTjB6r_-1C3YiG30QvevZjrsVUQM,70
|
|
182
182
|
omlish/formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
183
183
|
omlish/formats/dotenv.py,sha256=UjZl3gac-0U24sDjCCGMcCqO1UCWG2Zs8PZ4JdAg2YE,17348
|
184
184
|
omlish/formats/props.py,sha256=JwFJbKblqzqnzXf7YKFzQSDfcAXzkKsfoYvad6FPy98,18945
|
185
|
-
omlish/formats/yaml.py,sha256=
|
185
|
+
omlish/formats/yaml.py,sha256=wTW8ECG9jyA7qIFUqKZUro4KAKpN4IvcW_qhlrKveXM,6836
|
186
186
|
omlish/formats/json/__init__.py,sha256=moSR67Qkju2eYb_qVDtaivepe44mxAnYuC8OCSbtETg,298
|
187
187
|
omlish/formats/json/__main__.py,sha256=1wxxKZVkj_u7HCcewwMIbGuZj_Wph95yrUbm474Op9M,188
|
188
188
|
omlish/formats/json/cli.py,sha256=pHFvYji6h_kMUyTgHCuDFofeDVY_5Em0wBqqVOJzDmI,3504
|
@@ -193,24 +193,24 @@ omlish/formats/json/backends/orjson.py,sha256=GYZx0zgpxwkJbFh4EJLGa6VMoEK-Q6mf5t
|
|
193
193
|
omlish/formats/json/backends/std.py,sha256=00NdUFT9GeWL1EWbgKhWLboDBIuDxr7EiizPZXbRWrc,1973
|
194
194
|
omlish/formats/json/backends/ujson.py,sha256=m5-hlEQCMLhat3Hg_8QTyfMH-rSsQGJYdWRWoTWkfhM,1029
|
195
195
|
omlish/graphs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
196
|
-
omlish/graphs/dags.py,sha256=
|
197
|
-
omlish/graphs/domination.py,sha256=
|
196
|
+
omlish/graphs/dags.py,sha256=zp55lYgUdRCxmADwiGDHeehMJczZFA_tzdWqy77icOk,3047
|
197
|
+
omlish/graphs/domination.py,sha256=oCGoWzWTxLwow0LDyGjjEf2AjFiOiDz4WaBtczwSbsQ,7576
|
198
198
|
omlish/graphs/trees.py,sha256=t9kzLy33ynYV0TowVkyDvkkRBQV5x--1vtNBSB4Auus,8156
|
199
199
|
omlish/graphs/dot/__init__.py,sha256=Y1MZRQBZkcYyG1Tn7K2FhL8aYbm4v4tk6f5g9AqEkUw,359
|
200
200
|
omlish/graphs/dot/items.py,sha256=OWPf0-hjBgS1uyy2QgAEn4IgFHJcEg7sHVWeTx1ghZc,4083
|
201
201
|
omlish/graphs/dot/make.py,sha256=RN30gHfJPiXx5Q51kbDdhVJYf59Fr84Lz9J-mXRt9sI,360
|
202
202
|
omlish/graphs/dot/rendering.py,sha256=2UgXvMRN4Z9cfIqLlC7Iu_8bWbwUDEL4opHHkFfSqTw,3630
|
203
203
|
omlish/graphs/dot/utils.py,sha256=_FMwn77WfiiAfLsRTOKWm4IYbNv5kQN22YJ5psw6CWg,801
|
204
|
-
omlish/http/__init__.py,sha256
|
204
|
+
omlish/http/__init__.py,sha256=OqCovZi_jv1Mnk975idaXA8FCGy4laoQIvNZ3hdKpRQ,722
|
205
205
|
omlish/http/asgi.py,sha256=wXhBZ21bEl32Kv9yBrRwUR_7pHEgVtHP8ZZwbasQ6-4,3307
|
206
|
-
omlish/http/clients.py,sha256=
|
207
|
-
omlish/http/collections.py,sha256=s8w5s4Gewgxxhe2Ai0R45PgJYYifrLgTbU3VXVflHj4,260
|
206
|
+
omlish/http/clients.py,sha256=WRtCNIt9Y790xpem69HiXJY9W-vPlpGPKZwpHusa2EE,6280
|
208
207
|
omlish/http/consts.py,sha256=FTolezLknKU6WJjk_x2T3a5LEMlnZSqv7gzTq55lxcU,2147
|
209
208
|
omlish/http/cookies.py,sha256=uuOYlHR6e2SC3GM41V0aozK10nef9tYg83Scqpn5-HM,6351
|
210
209
|
omlish/http/dates.py,sha256=Otgp8wRxPgNGyzx8LFowu1vC4EKJYARCiAwLFncpfHM,2875
|
211
210
|
omlish/http/encodings.py,sha256=w2WoKajpaZnQH8j-IBvk5ZFL2O2pAU_iBvZnkocaTlw,164
|
212
|
-
omlish/http/headers.py,sha256=
|
211
|
+
omlish/http/headers.py,sha256=ZMmjrEiYjzo0YTGyK0YsvjdwUazktGqzVVYorY4fd44,5081
|
213
212
|
omlish/http/json.py,sha256=9XwAsl4966Mxrv-1ytyCqhcE6lbBJw-0_tFZzGszgHE,7440
|
213
|
+
omlish/http/multipart.py,sha256=vUU1OlYghsODs_OAJiz9nrWTBGXk1WIuk4FtSDykDqk,2205
|
214
214
|
omlish/http/sessions.py,sha256=VZ_WS5uiQG5y7i3u8oKuQMqf8dPKUOjFm_qk_0OvI8c,4793
|
215
215
|
omlish/http/sse.py,sha256=T2_EXTcDfEhCF4E9B68YtEYLFb803MPnh8eCNjdPlRo,2223
|
216
216
|
omlish/http/wsgi.py,sha256=czZsVUX-l2YTlMrUjKN49wRoP4rVpS0qpeBn4O5BoMY,948
|
@@ -244,7 +244,7 @@ omlish/inject/impl/privates.py,sha256=alpCYyk5VJ9lJknbRH2nLVNFYVvFhkj-VC1Vco3zCF
|
|
244
244
|
omlish/inject/impl/providers.py,sha256=QnwhsujJFIHC0JTgd2Wlo1kP53i3CWTrj1nKU2DNxwg,2375
|
245
245
|
omlish/inject/impl/proxy.py,sha256=1ko0VaKqzu9UG8bIldp9xtUrAVUOFTKWKTjOCqIGr4s,1636
|
246
246
|
omlish/inject/impl/scopes.py,sha256=ASfULXgP_ETlsAqFJfrZmyEaZt64Zr8tNn5ScA-EoXk,5900
|
247
|
-
omlish/lang/__init__.py,sha256=
|
247
|
+
omlish/lang/__init__.py,sha256=pCZoKj7wnFeyl_f7AKBg3Ajl1vrInkqP7miRcjIy6tI,3666
|
248
248
|
omlish/lang/cached.py,sha256=92TvRZQ6sWlm7dNn4hgl7aWKbX0J1XUEo3DRjBpgVQk,7834
|
249
249
|
omlish/lang/clsdct.py,sha256=AjtIWLlx2E6D5rC97zQ3Lwq2SOMkbg08pdO_AxpzEHI,1744
|
250
250
|
omlish/lang/cmp.py,sha256=5vbzWWbqdzDmNKAGL19z6ZfUKe5Ci49e-Oegf9f4BsE,1346
|
@@ -256,7 +256,7 @@ omlish/lang/functions.py,sha256=kkPfcdocg-OmyN7skIqrFxNvqAv89Zc_kXKYAN8vw8g,3895
|
|
256
256
|
omlish/lang/imports.py,sha256=Oy7iInOTqgZv6nyRbnvGrPv4cKKIAzPbhfDXCajDUcc,6626
|
257
257
|
omlish/lang/iterables.py,sha256=xRwktm6i2RHSb_ELfAXdjITIfE69qDyMEzgeZqvQXiU,2386
|
258
258
|
omlish/lang/maybes.py,sha256=NYHZDjqDtwPMheDrj2VtUVujxRPf8Qpgk4ZlZCTvBZc,3492
|
259
|
-
omlish/lang/objects.py,sha256=
|
259
|
+
omlish/lang/objects.py,sha256=LOC3JvX1g5hPxJ7Sv2TK9kNkAo9c8J-Jw2NmClR_rkA,4576
|
260
260
|
omlish/lang/resolving.py,sha256=OuN2mDTPNyBUbcrswtvFKtj4xgH4H4WglgqSKv3MTy0,1606
|
261
261
|
omlish/lang/resources.py,sha256=-NmVTrSMKFZ6smVfOMz46ekZYVGgYh8cPooxQlFpG6s,2135
|
262
262
|
omlish/lang/strings.py,sha256=BsciSYnckD4vGtC6kmtnugR9IN6CIHdcjO4nZu-pSAw,3898
|
@@ -272,7 +272,7 @@ omlish/lifecycles/__init__.py,sha256=1FjYceXs-4fc-S-C9zFYmc2axHs4znnQHcJVHdY7a6E
|
|
272
272
|
omlish/lifecycles/abstract.py,sha256=70CQyZy-c9a2o0ZJxPeUT7eYjWZTBrp2HpUBnrHdAOM,1109
|
273
273
|
omlish/lifecycles/base.py,sha256=ceXrNSzuv7iiTlX96UI1fvsQ70OgOmZl-UisDPyA3NA,1394
|
274
274
|
omlish/lifecycles/contextmanagers.py,sha256=W0trOo6atbPSCoswmtUVOayAYnJ722qHBgda1oYxUEc,2073
|
275
|
-
omlish/lifecycles/controller.py,sha256=
|
275
|
+
omlish/lifecycles/controller.py,sha256=ToYNJKH1Mxr7HyyF1cJrrec8NV_m84jrcvTMX0V5emM,3464
|
276
276
|
omlish/lifecycles/manager.py,sha256=Au66KaO-fI-SEJALaPUJsCHYW2GE20xextk1wKn2BEU,5445
|
277
277
|
omlish/lifecycles/states.py,sha256=zqMOU2ZU-MDNnWuwauM3_anIAiXM8LoBDElDEraptFg,1292
|
278
278
|
omlish/lifecycles/transitions.py,sha256=qQtFby-h4VzbvgaUqT2NnbNumlcOx9FVVADP9t83xj4,1939
|
@@ -308,14 +308,14 @@ omlish/marshal/forbidden.py,sha256=BNshzm4lN5O8sUZ1YvxrSYq3WPklq9NMQCRZ7RC3DLM,8
|
|
308
308
|
omlish/marshal/global_.py,sha256=K76wB1-pdg4VWgiqR7wyxRNYr-voJApexYW2nV-R4DM,1127
|
309
309
|
omlish/marshal/helpers.py,sha256=-SOgYJmrURILHpPK6Wu3cCvhj8RJrqfJxuKhh9UMs7o,1102
|
310
310
|
omlish/marshal/iterables.py,sha256=6I_ZdJemLSQtJ4J5NrB9wi-eyxiJZS61HzHXp1yeiX8,2592
|
311
|
-
omlish/marshal/mappings.py,sha256=
|
311
|
+
omlish/marshal/mappings.py,sha256=s2cFSLyo0PM1eoQ2-SONtFSOldk5ARsBj55-icvWZ5o,2787
|
312
312
|
omlish/marshal/maybes.py,sha256=mgK3QsWHkXgRqo076KxYKH6elRxzJ_QDTodv93mgHR0,2198
|
313
313
|
omlish/marshal/naming.py,sha256=lIklR_Od4x1ghltAgOzqcKhHs-leeSv2YmFhCHO7GIs,613
|
314
314
|
omlish/marshal/nop.py,sha256=2mWve_dicFAiUQ2Y5asKkUW-XGmEE9Qi2ClIasFad0c,461
|
315
|
-
omlish/marshal/numbers.py,sha256=
|
316
|
-
omlish/marshal/objects.py,sha256=
|
315
|
+
omlish/marshal/numbers.py,sha256=kFRIX9l1yofiYzafV6SnYfEg0PiCsAqeRHOeT6BSxlM,1672
|
316
|
+
omlish/marshal/objects.py,sha256=74tUmMymimSqgd4a6kyMh_owJe6J7YQXwCXEF-JWt1c,8419
|
317
317
|
omlish/marshal/optionals.py,sha256=r0XB5rqfasvgZJNrKYd6Unq2U4nHt3JURi26j0dYHlw,1499
|
318
|
-
omlish/marshal/polymorphism.py,sha256=
|
318
|
+
omlish/marshal/polymorphism.py,sha256=gCQ4_uzuqOcWstihK3twiMc-10G1ZHWLuLZxbajbecY,5644
|
319
319
|
omlish/marshal/primitives.py,sha256=f_6m24Cb-FDGsZpYSas11nLt3xCCEUXugw3Hv4-aNhg,1291
|
320
320
|
omlish/marshal/registries.py,sha256=FvC6qXHCizNB2QmU_N3orxW7iqfGYkiUXYYdTRWS6HA,2353
|
321
321
|
omlish/marshal/standard.py,sha256=uQZIGiCwihmhB1tmhpKnZWZly0DDkdGjCnN0d41WHho,2985
|
@@ -336,8 +336,9 @@ omlish/secrets/__init__.py,sha256=SGB1KrlNrxlNpazEHYy95NTzteLi8ndoEgMhU7luBl8,42
|
|
336
336
|
omlish/secrets/crypto.py,sha256=6CsLy0UEqCrBK8Xx_3-iFF6SKtu2GlEqUQ8-MliY3tk,3709
|
337
337
|
omlish/secrets/marshal.py,sha256=U9uSRTWzZmumfNZeh_dROwVdGrARsp155TylRbjilP8,2048
|
338
338
|
omlish/secrets/openssl.py,sha256=wxA_wIlxtuOUy71ABxAJgavh-UI_taOfm-A0dVlmSwM,6219
|
339
|
-
omlish/secrets/
|
340
|
-
omlish/secrets/
|
339
|
+
omlish/secrets/pwgen.py,sha256=v-5ztnOTHTAWXLGR-3H6HkMj2nPIZBMbo5xWR3q0rDY,1707
|
340
|
+
omlish/secrets/pwhash.py,sha256=3r-vEK6Gp6aq4L5Csnd06QnrjO9xfzHJP-g_7I9W_ao,4101
|
341
|
+
omlish/secrets/secrets.py,sha256=cnDGBoPknVxsCN04_gqcJT_7Ebk3iO3VPkRZ2oMjkMw,7868
|
341
342
|
omlish/secrets/subprocesses.py,sha256=EcnKlHHtnUMHGrBWXDfu8tv28wlgZx4P4GOiuPW9Vo8,1105
|
342
343
|
omlish/specs/__init__.py,sha256=Xl4fT1o1MlcEIAjMt5EifgMuO4UBSa9Suj5NE9eMX1A,87
|
343
344
|
omlish/specs/jmespath/LICENSE,sha256=IH-ZZlZkS8XMkf_ubNVD1aYHQ2l_wd0tmHtXrCcYpRU,1113
|
@@ -438,9 +439,9 @@ omlish/text/delimit.py,sha256=ubPXcXQmtbOVrUsNh5gH1mDq5H-n1y2R4cPL5_DQf68,4928
|
|
438
439
|
omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,3296
|
439
440
|
omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
|
440
441
|
omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
|
441
|
-
omlish-0.0.0.
|
442
|
-
omlish-0.0.0.
|
443
|
-
omlish-0.0.0.
|
444
|
-
omlish-0.0.0.
|
445
|
-
omlish-0.0.0.
|
446
|
-
omlish-0.0.0.
|
442
|
+
omlish-0.0.0.dev76.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
443
|
+
omlish-0.0.0.dev76.dist-info/METADATA,sha256=w0ccpB3fCgf6T797VrwXYnw7tUxFswGFbwRA4qKLWTc,4167
|
444
|
+
omlish-0.0.0.dev76.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
445
|
+
omlish-0.0.0.dev76.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
446
|
+
omlish-0.0.0.dev76.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
447
|
+
omlish-0.0.0.dev76.dist-info/RECORD,,
|
omlish/http/collections.py
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
import typing as ta
|
2
|
-
|
3
|
-
|
4
|
-
V = ta.TypeVar('V')
|
5
|
-
|
6
|
-
|
7
|
-
class HttpMap(ta.Mapping[str, V]):
|
8
|
-
def __getitem__(self, k):
|
9
|
-
raise NotImplementedError
|
10
|
-
|
11
|
-
def __len__(self):
|
12
|
-
raise NotImplementedError
|
13
|
-
|
14
|
-
def __iter__(self):
|
15
|
-
raise NotImplementedError
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|