omlish 0.0.0.dev28__py3-none-any.whl → 0.0.0.dev30__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 +7 -9
- omlish/collections/treap.py +0 -1
- omlish/dataclasses/impl/fields.py +3 -0
- omlish/diag/replserver/server.py +1 -1
- omlish/fnpipes.py +82 -0
- omlish/http/sessions.py +2 -2
- omlish/lang/__init__.py +6 -0
- omlish/lang/classes/abstract.py +1 -1
- omlish/lang/contextmanagers.py +35 -0
- omlish/lang/functions.py +17 -0
- omlish/lang/resources.py +1 -0
- omlish/lang/strings.py +49 -1
- omlish/lite/logs.py +20 -5
- omlish/lite/secrets.py +14 -0
- omlish/marshal/naming.py +5 -0
- omlish/marshal/polymorphism.py +20 -10
- omlish/math/__init__.py +0 -0
- omlish/{math.py → math/bits.py} +0 -13
- omlish/math/floats.py +13 -0
- omlish/{stats.py → math/stats.py} +3 -2
- omlish/os.py +17 -0
- omlish/specs/__init__.py +9 -0
- omlish/sql/__init__.py +0 -14
- omlish/sql/alchemy/__init__.py +13 -0
- omlish/sql/{asyncs.py → alchemy/asyncs.py} +1 -1
- omlish/sql/{duckdb.py → alchemy/duckdb.py} +1 -1
- omlish/sql/{secrets.py → alchemy/secrets.py} +1 -1
- omlish/testing/pytest/plugins/asyncs.py +5 -0
- omlish/text/asdl.py +5 -4
- omlish/text/parts.py +2 -2
- {omlish-0.0.0.dev28.dist-info → omlish-0.0.0.dev30.dist-info}/METADATA +17 -19
- {omlish-0.0.0.dev28.dist-info → omlish-0.0.0.dev30.dist-info}/RECORD +37 -33
- /omlish/sql/{exprs.py → alchemy/exprs.py} +0 -0
- /omlish/sql/{sqlean.py → alchemy/sqlean.py} +0 -0
- {omlish-0.0.0.dev28.dist-info → omlish-0.0.0.dev30.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev28.dist-info → omlish-0.0.0.dev30.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev28.dist-info → omlish-0.0.0.dev30.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.dev30'
|
2
|
+
__revision__ = '1378b0a61f7d3ec16204c06bc87e5215b062d378'
|
3
3
|
|
4
4
|
|
5
5
|
#
|
@@ -30,7 +30,7 @@ class Project(ProjectBase):
|
|
30
30
|
|
31
31
|
optional_dependencies = {
|
32
32
|
'async': [
|
33
|
-
'anyio ~= 4.
|
33
|
+
'anyio ~= 4.5',
|
34
34
|
'sniffio ~= 1.3',
|
35
35
|
|
36
36
|
'greenlet ~= 3.1',
|
@@ -39,7 +39,7 @@ class Project(ProjectBase):
|
|
39
39
|
'trio-asyncio ~= 0.15',
|
40
40
|
],
|
41
41
|
|
42
|
-
'
|
42
|
+
'compress': [
|
43
43
|
'lz4 ~= 4.0',
|
44
44
|
|
45
45
|
'python-snappy ~= 0.7; python_version < "3.13"',
|
@@ -70,8 +70,6 @@ class Project(ProjectBase):
|
|
70
70
|
],
|
71
71
|
|
72
72
|
'misc': [
|
73
|
-
'jinja2 ~= 3.1',
|
74
|
-
|
75
73
|
'wrapt ~= 1.14',
|
76
74
|
],
|
77
75
|
|
@@ -79,9 +77,11 @@ class Project(ProjectBase):
|
|
79
77
|
'cryptography ~= 43.0',
|
80
78
|
],
|
81
79
|
|
82
|
-
'
|
80
|
+
'sqlalchemy': [
|
83
81
|
'sqlalchemy[asyncio] ~= 2.0',
|
82
|
+
],
|
84
83
|
|
84
|
+
'sqlalchemy-drivers': [
|
85
85
|
'pg8000 ~= 1.31',
|
86
86
|
# 'psycopg2 ~= 2.9',
|
87
87
|
# 'psycopg ~= 3.2',
|
@@ -93,9 +93,7 @@ class Project(ProjectBase):
|
|
93
93
|
'aiomysql ~= 0.2',
|
94
94
|
'aiosqlite ~= 0.20',
|
95
95
|
'asyncpg ~= 0.29; python_version < "3.13"',
|
96
|
-
],
|
97
96
|
|
98
|
-
'sqlx': [
|
99
97
|
'sqlean.py ~= 3.45; python_version < "3.13"',
|
100
98
|
|
101
99
|
'duckdb ~= 1.1',
|
omlish/collections/treap.py
CHANGED
omlish/diag/replserver/server.py
CHANGED
@@ -9,7 +9,7 @@ TODO:
|
|
9
9
|
- optional ipython embed
|
10
10
|
- https://github.com/python/cpython/tree/56470004e58911b146c016fc9fec4461b8f69454/Lib/_pyrepl
|
11
11
|
|
12
|
-
|
12
|
+
See:
|
13
13
|
- https://github.com/vxgmichel/aioconsole/blob/e55f4b0601da3b3a40a88c965526d35ab38b5841/aioconsole/server.py
|
14
14
|
- https://github.com/nhoad/aiomanhole
|
15
15
|
- https://github.com/twisted/twisted/blob/00aa56f5257060304d41f09651c6ab58ee6104d6/src/twisted/conch/manhole.py
|
omlish/fnpipes.py
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
import abc
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
|
5
|
+
T = ta.TypeVar('T')
|
6
|
+
U = ta.TypeVar('U')
|
7
|
+
|
8
|
+
|
9
|
+
class Fn(abc.ABC, ta.Generic[T]):
|
10
|
+
@abc.abstractmethod
|
11
|
+
def __call__(self, *args: ta.Any, **kwargs: ta.Any) -> T:
|
12
|
+
raise NotImplementedError
|
13
|
+
|
14
|
+
def pipe(self, fn: ta.Callable[..., U], *args: ta.Any, **kwargs: ta.Any) -> 'Fn[U]':
|
15
|
+
return Pipe([self], Bind(fn, *args, **kwargs))
|
16
|
+
|
17
|
+
def __or__(self, fn: ta.Callable[..., U]) -> 'Fn[U]':
|
18
|
+
return self.pipe(fn)
|
19
|
+
|
20
|
+
def apply(self, fn: ta.Callable[[T], ta.Any], *args: ta.Any, **kwargs: ta.Any) -> 'Fn[T]':
|
21
|
+
return Pipe([self], Apply(Bind(fn, *args, **kwargs)))
|
22
|
+
|
23
|
+
def __and__(self, fn: ta.Callable[[T], ta.Any]) -> 'Fn[T]':
|
24
|
+
return self.apply(fn)
|
25
|
+
|
26
|
+
|
27
|
+
class Bind(Fn[T]):
|
28
|
+
def __init__(self, fn: ta.Callable[..., T], *args: ta.Any, **kwargs: ta.Any) -> None:
|
29
|
+
super().__init__()
|
30
|
+
if Ellipsis not in args and Ellipsis not in kwargs:
|
31
|
+
args += (Ellipsis,)
|
32
|
+
self._fn = fn
|
33
|
+
self._args = args
|
34
|
+
self._kwargs = kwargs
|
35
|
+
|
36
|
+
def __call__(self, *args: ta.Any, **kwargs: ta.Any) -> T:
|
37
|
+
fa: list = []
|
38
|
+
for a in self._args:
|
39
|
+
if a is Ellipsis:
|
40
|
+
fa.extend(args)
|
41
|
+
else:
|
42
|
+
fa.append(a)
|
43
|
+
|
44
|
+
fkw = {}
|
45
|
+
for k, v in self._kwargs.items():
|
46
|
+
if v is Ellipsis:
|
47
|
+
if len(args) != 1:
|
48
|
+
raise ValueError(args)
|
49
|
+
fkw[k] = args[0]
|
50
|
+
else:
|
51
|
+
fkw[k] = v
|
52
|
+
fkw.update(kwargs)
|
53
|
+
|
54
|
+
return self._fn(*fa, **fkw)
|
55
|
+
|
56
|
+
|
57
|
+
class Pipe(Fn[T]):
|
58
|
+
def __init__(self, lfns: ta.Sequence[ta.Callable], rfn: ta.Callable[..., T]) -> None:
|
59
|
+
super().__init__()
|
60
|
+
self._lfn, *self._rfns = [*lfns, rfn]
|
61
|
+
|
62
|
+
def __call__(self, *args: ta.Any, **kwargs: ta.Any) -> T:
|
63
|
+
o = self._lfn(*args, **kwargs)
|
64
|
+
for fn in self._rfns:
|
65
|
+
o = fn(o)
|
66
|
+
return o
|
67
|
+
|
68
|
+
|
69
|
+
class Apply(Fn[T]):
|
70
|
+
def __init__(self, *fns: ta.Callable[[T], ta.Any]) -> None:
|
71
|
+
super().__init__()
|
72
|
+
self._fns = fns
|
73
|
+
|
74
|
+
def __call__(self, o: T) -> T: # noqa
|
75
|
+
for fn in self._fns:
|
76
|
+
fn(o)
|
77
|
+
return o
|
78
|
+
|
79
|
+
|
80
|
+
bind = Bind
|
81
|
+
pipe = Pipe
|
82
|
+
apply = Apply
|
omlish/http/sessions.py
CHANGED
@@ -8,7 +8,7 @@ import time
|
|
8
8
|
import typing as ta
|
9
9
|
import zlib
|
10
10
|
|
11
|
-
from .. import fnpairs as
|
11
|
+
from .. import fnpairs as fpa
|
12
12
|
from .. import lang
|
13
13
|
from .. import secrets as sec
|
14
14
|
from .cookies import dump_cookie
|
@@ -92,7 +92,7 @@ class SessionMarshal:
|
|
92
92
|
def __init__(
|
93
93
|
self,
|
94
94
|
signer: Signer,
|
95
|
-
serializer:
|
95
|
+
serializer: fpa.ObjectStr = fpa.of(JSON_TAGGER.dumps, JSON_TAGGER.loads),
|
96
96
|
) -> None:
|
97
97
|
super().__init__()
|
98
98
|
|
omlish/lang/__init__.py
CHANGED
@@ -60,6 +60,7 @@ from .contextmanagers import ( # noqa
|
|
60
60
|
NOP_CONTEXT_MANAGER,
|
61
61
|
NopContextManaged,
|
62
62
|
NopContextManager,
|
63
|
+
Timer,
|
63
64
|
a_defer,
|
64
65
|
attr_setting,
|
65
66
|
breakpoint_on_exception,
|
@@ -98,6 +99,7 @@ from .functions import ( # noqa
|
|
98
99
|
Args,
|
99
100
|
VoidError,
|
100
101
|
as_async,
|
102
|
+
coalesce,
|
101
103
|
constant,
|
102
104
|
finally_,
|
103
105
|
identity,
|
@@ -107,6 +109,7 @@ from .functions import ( # noqa
|
|
107
109
|
isinstance_of,
|
108
110
|
issubclass_of,
|
109
111
|
maybe_call,
|
112
|
+
opt_coalesce,
|
110
113
|
periodically,
|
111
114
|
raise_,
|
112
115
|
raising,
|
@@ -186,8 +189,11 @@ from .strings import ( # noqa
|
|
186
189
|
is_ident_cont,
|
187
190
|
is_ident_start,
|
188
191
|
is_sunder,
|
192
|
+
prefix_delimited,
|
189
193
|
prefix_lines,
|
190
194
|
snake_case,
|
195
|
+
strip_prefix,
|
196
|
+
strip_suffix,
|
191
197
|
)
|
192
198
|
|
193
199
|
from .sys import ( # noqa
|
omlish/lang/classes/abstract.py
CHANGED
@@ -47,7 +47,7 @@ class Abstract(abc.ABC): # noqa
|
|
47
47
|
seen.update(dir(b))
|
48
48
|
if ams:
|
49
49
|
raise TypeError(
|
50
|
-
f'Cannot subclass abstract class {cls.__name__} with abstract methods'
|
50
|
+
f'Cannot subclass abstract class {cls.__name__} with abstract methods: '
|
51
51
|
f'{", ".join(map(str, sorted(ams)))}',
|
52
52
|
)
|
53
53
|
|
omlish/lang/contextmanagers.py
CHANGED
@@ -7,6 +7,7 @@ import contextlib
|
|
7
7
|
import contextvars
|
8
8
|
import functools
|
9
9
|
import threading
|
10
|
+
import time
|
10
11
|
import types
|
11
12
|
import typing as ta
|
12
13
|
|
@@ -367,3 +368,37 @@ def default_lock(value: DefaultLockable, default: DefaultLockable = None) -> Loc
|
|
367
368
|
|
368
369
|
else:
|
369
370
|
raise TypeError(value)
|
371
|
+
|
372
|
+
|
373
|
+
##
|
374
|
+
|
375
|
+
|
376
|
+
class Timer:
|
377
|
+
def __init__(
|
378
|
+
self,
|
379
|
+
clock: ta.Callable[[], float] | None = None,
|
380
|
+
) -> None:
|
381
|
+
super().__init__()
|
382
|
+
self._clock = clock if clock is not None else time.monotonic
|
383
|
+
|
384
|
+
_start: float
|
385
|
+
_end: float
|
386
|
+
|
387
|
+
@property
|
388
|
+
def start(self) -> float:
|
389
|
+
return self._start
|
390
|
+
|
391
|
+
@property
|
392
|
+
def end(self) -> float:
|
393
|
+
return self._end
|
394
|
+
|
395
|
+
@property
|
396
|
+
def elapsed(self) -> float:
|
397
|
+
return self._end - self._start
|
398
|
+
|
399
|
+
def __enter__(self) -> ta.Self:
|
400
|
+
self._start = self._clock()
|
401
|
+
return self
|
402
|
+
|
403
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
404
|
+
self._end = self._clock()
|
omlish/lang/functions.py
CHANGED
@@ -183,3 +183,20 @@ class Args:
|
|
183
183
|
|
184
184
|
def __call__(self, fn: ta.Callable[..., T]) -> T:
|
185
185
|
return fn(*self.args, **self.kwargs)
|
186
|
+
|
187
|
+
|
188
|
+
##
|
189
|
+
|
190
|
+
|
191
|
+
def coalesce(*vs: T | None) -> T:
|
192
|
+
for v in vs:
|
193
|
+
if v is not None:
|
194
|
+
return v
|
195
|
+
raise ValueError('No value given')
|
196
|
+
|
197
|
+
|
198
|
+
def opt_coalesce(*vs: T | None) -> T | None:
|
199
|
+
for v in vs:
|
200
|
+
if v is not None:
|
201
|
+
return v
|
202
|
+
return None
|
omlish/lang/resources.py
CHANGED
omlish/lang/strings.py
CHANGED
@@ -4,9 +4,22 @@ import unicodedata
|
|
4
4
|
|
5
5
|
##
|
6
6
|
|
7
|
+
@ta.overload
|
8
|
+
def prefix_delimited(s: str, p: str, d: str) -> str:
|
9
|
+
...
|
10
|
+
|
11
|
+
|
12
|
+
@ta.overload
|
13
|
+
def prefix_delimited(s: bytes, p: bytes, d: bytes) -> bytes:
|
14
|
+
...
|
15
|
+
|
16
|
+
|
17
|
+
def prefix_delimited(s, p, d):
|
18
|
+
return d.join([p + l for l in s.split(d)])
|
19
|
+
|
7
20
|
|
8
21
|
def prefix_lines(s: str, p: str) -> str:
|
9
|
-
return
|
22
|
+
return prefix_delimited(s, p, '\n')
|
10
23
|
|
11
24
|
|
12
25
|
def indent_lines(s: str, num: int) -> str:
|
@@ -16,6 +29,41 @@ def indent_lines(s: str, num: int) -> str:
|
|
16
29
|
##
|
17
30
|
|
18
31
|
|
32
|
+
@ta.overload
|
33
|
+
def strip_prefix(s: str, pfx: str) -> str:
|
34
|
+
...
|
35
|
+
|
36
|
+
|
37
|
+
@ta.overload
|
38
|
+
def strip_prefix(s: bytes, pfx: bytes) -> bytes:
|
39
|
+
...
|
40
|
+
|
41
|
+
|
42
|
+
def strip_prefix(s, pfx):
|
43
|
+
if not s.startswith(pfx):
|
44
|
+
raise ValueError(f'{s!r} does not start with {pfx!r}')
|
45
|
+
return s[len(pfx):]
|
46
|
+
|
47
|
+
|
48
|
+
@ta.overload
|
49
|
+
def strip_suffix(s: str, sfx: str) -> str:
|
50
|
+
...
|
51
|
+
|
52
|
+
|
53
|
+
@ta.overload
|
54
|
+
def strip_suffix(s: bytes, sfx: bytes) -> bytes:
|
55
|
+
...
|
56
|
+
|
57
|
+
|
58
|
+
def strip_suffix(s, sfx):
|
59
|
+
if not s.endswith(sfx):
|
60
|
+
raise ValueError(f'{s!r} does not end with {sfx!r}')
|
61
|
+
return s[:-len(sfx)]
|
62
|
+
|
63
|
+
|
64
|
+
##
|
65
|
+
|
66
|
+
|
19
67
|
def camel_case(name: str) -> str:
|
20
68
|
return ''.join(map(str.capitalize, name.split('_'))) # noqa
|
21
69
|
|
omlish/lite/logs.py
CHANGED
@@ -4,6 +4,7 @@ TODO:
|
|
4
4
|
- debug
|
5
5
|
"""
|
6
6
|
# ruff: noqa: UP006 UP007 N802
|
7
|
+
import contextlib
|
7
8
|
import datetime
|
8
9
|
import logging
|
9
10
|
import threading
|
@@ -203,6 +204,24 @@ class StandardLogHandler(ProxyLogHandler):
|
|
203
204
|
##
|
204
205
|
|
205
206
|
|
207
|
+
@contextlib.contextmanager
|
208
|
+
def _locking_logging_module_lock() -> ta.Iterator[None]:
|
209
|
+
if hasattr(logging, '_acquireLock'):
|
210
|
+
logging._acquireLock() # noqa
|
211
|
+
try:
|
212
|
+
yield
|
213
|
+
finally:
|
214
|
+
logging._releaseLock() # type: ignore # noqa
|
215
|
+
|
216
|
+
elif hasattr(logging, '_lock'):
|
217
|
+
# https://github.com/python/cpython/commit/74723e11109a320e628898817ab449b3dad9ee96
|
218
|
+
with logging._lock: # noqa
|
219
|
+
yield
|
220
|
+
|
221
|
+
else:
|
222
|
+
raise Exception("Can't find lock in logging module")
|
223
|
+
|
224
|
+
|
206
225
|
def configure_standard_logging(
|
207
226
|
level: ta.Union[int, str] = logging.INFO,
|
208
227
|
*,
|
@@ -210,8 +229,7 @@ def configure_standard_logging(
|
|
210
229
|
target: ta.Optional[logging.Logger] = None,
|
211
230
|
force: bool = False,
|
212
231
|
) -> ta.Optional[StandardLogHandler]:
|
213
|
-
|
214
|
-
try:
|
232
|
+
with _locking_logging_module_lock():
|
215
233
|
if target is None:
|
216
234
|
target = logging.root
|
217
235
|
|
@@ -250,6 +268,3 @@ def configure_standard_logging(
|
|
250
268
|
#
|
251
269
|
|
252
270
|
return StandardLogHandler(handler)
|
253
|
-
|
254
|
-
finally:
|
255
|
-
logging._releaseLock() # type: ignore # noqa
|
omlish/lite/secrets.py
CHANGED
@@ -20,3 +20,17 @@ class Secret:
|
|
20
20
|
|
21
21
|
def reveal(self) -> str:
|
22
22
|
return getattr(self, self._VALUE_ATTR)()
|
23
|
+
|
24
|
+
#
|
25
|
+
|
26
|
+
def __reduce__(self) -> ta.NoReturn:
|
27
|
+
raise TypeError
|
28
|
+
|
29
|
+
def __reduce_ex__(self, protocol) -> ta.NoReturn:
|
30
|
+
raise TypeError
|
31
|
+
|
32
|
+
def __getstate__(self) -> ta.NoReturn:
|
33
|
+
raise TypeError
|
34
|
+
|
35
|
+
def __setstate__(self, state) -> ta.NoReturn:
|
36
|
+
raise TypeError
|
omlish/marshal/naming.py
CHANGED
omlish/marshal/polymorphism.py
CHANGED
@@ -98,24 +98,34 @@ def polymorphism_from_subclasses(
|
|
98
98
|
ty: type,
|
99
99
|
*,
|
100
100
|
naming: Naming | None = None,
|
101
|
+
strip_suffix: bool = False,
|
101
102
|
) -> Polymorphism:
|
102
103
|
dct: dict[str, Impl] = {}
|
104
|
+
|
103
105
|
seen: set[type] = set()
|
104
106
|
todo: list[type] = [ty]
|
105
107
|
while todo:
|
106
108
|
cur = todo.pop()
|
107
109
|
seen.add(cur)
|
108
|
-
|
109
|
-
nam = cur.__name__
|
110
|
-
if naming is not None:
|
111
|
-
nam = translate_name(nam, naming)
|
112
|
-
if nam in dct:
|
113
|
-
raise KeyError(f'Duplicate name: {nam}')
|
114
|
-
dct[nam] = Impl(
|
115
|
-
cur,
|
116
|
-
nam,
|
117
|
-
)
|
110
|
+
|
118
111
|
todo.extend(nxt for nxt in cur.__subclasses__() if nxt not in seen)
|
112
|
+
|
113
|
+
if lang.is_abstract_class(cur):
|
114
|
+
continue
|
115
|
+
|
116
|
+
name = cur.__name__
|
117
|
+
if strip_suffix:
|
118
|
+
name = lang.strip_suffix(name, ty.__name__)
|
119
|
+
if naming is not None:
|
120
|
+
name = translate_name(name, naming)
|
121
|
+
if name in dct:
|
122
|
+
raise KeyError(f'Duplicate name: {name}')
|
123
|
+
|
124
|
+
dct[name] = Impl(
|
125
|
+
cur,
|
126
|
+
name,
|
127
|
+
)
|
128
|
+
|
119
129
|
return Polymorphism(ty, dct.values())
|
120
130
|
|
121
131
|
|
omlish/math/__init__.py
ADDED
File without changes
|
omlish/{math.py → math/bits.py}
RENAMED
@@ -1,15 +1,10 @@
|
|
1
1
|
import functools
|
2
|
-
import struct
|
3
2
|
import typing as ta
|
4
3
|
|
5
4
|
|
6
5
|
##
|
7
6
|
|
8
7
|
|
9
|
-
def isclose(a: float, b: float, *, rel_tol: float = 1e-09, abs_tol: float = 0.0) -> float:
|
10
|
-
return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
|
11
|
-
|
12
|
-
|
13
8
|
def get_bit(bit: int, value: int) -> int:
|
14
9
|
return (value >> bit) & 1
|
15
10
|
|
@@ -29,14 +24,6 @@ def set_bits(bits_from: int, num_bits: int, bits_value: int, value: int) -> int:
|
|
29
24
|
return value & ~(((1 << num_bits) - 1) << bits_from) | (bits_value << bits_from)
|
30
25
|
|
31
26
|
|
32
|
-
def float_to_bytes(f: float) -> bytes:
|
33
|
-
return struct.pack('>f', f)
|
34
|
-
|
35
|
-
|
36
|
-
def bytes_to_float(b: bytes) -> float:
|
37
|
-
return struct.unpack('>f', b)[0]
|
38
|
-
|
39
|
-
|
40
27
|
##
|
41
28
|
|
42
29
|
|
omlish/math/floats.py
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
import struct
|
2
|
+
|
3
|
+
|
4
|
+
def isclose(a: float, b: float, *, rel_tol: float = 1e-09, abs_tol: float = 0.0) -> float:
|
5
|
+
return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
|
6
|
+
|
7
|
+
|
8
|
+
def float_to_bytes(f: float) -> bytes:
|
9
|
+
return struct.pack('>f', f)
|
10
|
+
|
11
|
+
|
12
|
+
def bytes_to_float(b: bytes) -> float:
|
13
|
+
return struct.unpack('>f', b)[0]
|
@@ -3,6 +3,7 @@ TODO:
|
|
3
3
|
- reservoir
|
4
4
|
- dep tdigest?
|
5
5
|
- struct-of-arrays - array.array('f', ...) - backed SamplingHistogram
|
6
|
+
- https://docs.python.org/3/library/statistics.html
|
6
7
|
"""
|
7
8
|
import bisect
|
8
9
|
import collections
|
@@ -14,8 +15,8 @@ import random
|
|
14
15
|
import time
|
15
16
|
import typing as ta
|
16
17
|
|
17
|
-
from
|
18
|
-
from
|
18
|
+
from .. import cached
|
19
|
+
from .. import check
|
19
20
|
|
20
21
|
|
21
22
|
##
|
omlish/os.py
CHANGED
@@ -103,3 +103,20 @@ class Pidfile:
|
|
103
103
|
def kill(self, sig: int = signal.SIGTERM) -> None:
|
104
104
|
pid = self.read()
|
105
105
|
os.kill(pid, sig) # Still racy
|
106
|
+
|
107
|
+
|
108
|
+
def touch(self, mode: int = 0o666, exist_ok: bool = True) -> None:
|
109
|
+
if exist_ok:
|
110
|
+
# First try to bump modification time
|
111
|
+
# Implementation note: GNU touch uses the UTIME_NOW option of the utimensat() / futimens() functions.
|
112
|
+
try:
|
113
|
+
os.utime(self, None)
|
114
|
+
except OSError:
|
115
|
+
pass
|
116
|
+
else:
|
117
|
+
return
|
118
|
+
flags = os.O_CREAT | os.O_WRONLY
|
119
|
+
if not exist_ok:
|
120
|
+
flags |= os.O_EXCL
|
121
|
+
fd = os.open(self, flags, mode)
|
122
|
+
os.close(fd)
|
omlish/specs/__init__.py
CHANGED
omlish/sql/__init__.py
CHANGED
@@ -1,13 +1,3 @@
|
|
1
|
-
from .asyncs import ( # noqa
|
2
|
-
AsyncConnection,
|
3
|
-
AsyncConnectionLike,
|
4
|
-
AsyncEngine,
|
5
|
-
AsyncEngineLike,
|
6
|
-
AsyncTransaction,
|
7
|
-
AsyncTransactionLike,
|
8
|
-
async_adapt,
|
9
|
-
)
|
10
|
-
|
11
1
|
from .dbs import ( # noqa
|
12
2
|
DbLoc,
|
13
3
|
DbSpec,
|
@@ -17,10 +7,6 @@ from .dbs import ( # noqa
|
|
17
7
|
UrlDbLoc,
|
18
8
|
)
|
19
9
|
|
20
|
-
from .exprs import ( # noqa
|
21
|
-
paren,
|
22
|
-
)
|
23
|
-
|
24
10
|
from .qualifiedname import ( # noqa
|
25
11
|
QualifiedName,
|
26
12
|
qn,
|
@@ -111,6 +111,11 @@ class AsyncsPlugin:
|
|
111
111
|
else:
|
112
112
|
return
|
113
113
|
|
114
|
+
if 'trio_asyncio' in bes:
|
115
|
+
# NOTE: Importing it here is apparently necessary to get its patching working - otherwise fails later with
|
116
|
+
# `no running event loop` in anyio._backends._asyncio and such.
|
117
|
+
import trio_asyncio # noqa
|
118
|
+
|
114
119
|
if pdu.is_present():
|
115
120
|
pdu.patch_for_trio_asyncio()
|
116
121
|
|
omlish/text/asdl.py
CHANGED
@@ -217,7 +217,7 @@ class TokenKind(enum.IntEnum):
|
|
217
217
|
COMMA = enum.auto()
|
218
218
|
QUESTION = enum.auto()
|
219
219
|
PIPE = enum.auto()
|
220
|
-
|
220
|
+
ASTERISK = enum.auto()
|
221
221
|
L_PAREN = enum.auto()
|
222
222
|
R_PAREN = enum.auto()
|
223
223
|
L_BRACE = enum.auto()
|
@@ -231,7 +231,7 @@ OPERATOR_TABLE: ta.Mapping[str, TokenKind] = {
|
|
231
231
|
'|': TokenKind.PIPE,
|
232
232
|
'(': TokenKind.L_PAREN,
|
233
233
|
')': TokenKind.R_PAREN,
|
234
|
-
'*': TokenKind.
|
234
|
+
'*': TokenKind.ASTERISK,
|
235
235
|
'{': TokenKind.L_BRACE,
|
236
236
|
'}': TokenKind.R_BRACE,
|
237
237
|
}
|
@@ -373,7 +373,7 @@ class AsdlParser:
|
|
373
373
|
|
374
374
|
def _parse_optional_field_quantifier(self) -> tuple[bool, bool]: # (seq, opt)
|
375
375
|
is_seq, is_opt = False, False
|
376
|
-
if self.cur().kind == TokenKind.
|
376
|
+
if self.cur().kind == TokenKind.ASTERISK:
|
377
377
|
is_seq = True
|
378
378
|
self._advance()
|
379
379
|
elif self.cur().kind == TokenKind.QUESTION:
|
@@ -394,7 +394,8 @@ class AsdlParser:
|
|
394
394
|
_id_kinds = (TokenKind.CONSTRUCTOR_ID, TokenKind.TYPE_ID)
|
395
395
|
|
396
396
|
def _match(self, kind: TokenKind | tuple[TokenKind, ...]) -> str:
|
397
|
-
"""
|
397
|
+
"""
|
398
|
+
The 'match' primitive of RD parsers.
|
398
399
|
|
399
400
|
* Verifies that the current token is of the given kind (kind can be a tuple, in which the kind must match one of
|
400
401
|
its members).
|
omlish/text/parts.py
CHANGED
@@ -30,7 +30,7 @@ def _check_part(o: PartT) -> PartT:
|
|
30
30
|
return o
|
31
31
|
|
32
32
|
|
33
|
-
def
|
33
|
+
def _check_opt_part(o: PartT | None) -> PartT | None:
|
34
34
|
if o is None:
|
35
35
|
return None
|
36
36
|
return _check_part(o)
|
@@ -49,7 +49,7 @@ class Wrap(DataPart, lang.Final):
|
|
49
49
|
|
50
50
|
|
51
51
|
class List(DataPart, lang.Final):
|
52
|
-
parts: ta.Sequence[Part | None] = dc.xfield(coerce=col.seq_of(
|
52
|
+
parts: ta.Sequence[Part | None] = dc.xfield(coerce=col.seq_of(_check_opt_part))
|
53
53
|
delimiter: str = dc.field(default=',') # FIXME: , check_type=str)
|
54
54
|
trailer: bool = dc.field(default=False) # FIXME: , check_type=bool)
|
55
55
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: omlish
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev30
|
4
4
|
Summary: omlish
|
5
5
|
Author: wrmsr
|
6
6
|
License: BSD-3-Clause
|
@@ -13,7 +13,7 @@ Classifier: Operating System :: POSIX
|
|
13
13
|
Requires-Python: ~=3.12
|
14
14
|
License-File: LICENSE
|
15
15
|
Provides-Extra: all
|
16
|
-
Requires-Dist: anyio ~=4.
|
16
|
+
Requires-Dist: anyio ~=4.5 ; extra == 'all'
|
17
17
|
Requires-Dist: sniffio ~=1.3 ; extra == 'all'
|
18
18
|
Requires-Dist: greenlet ~=3.1 ; extra == 'all'
|
19
19
|
Requires-Dist: trio ~=0.26 ; extra == 'all'
|
@@ -29,7 +29,6 @@ Requires-Dist: json5 ~=0.9 ; extra == 'all'
|
|
29
29
|
Requires-Dist: pyyaml ~=5.0 ; extra == 'all'
|
30
30
|
Requires-Dist: cloudpickle ~=3.0 ; extra == 'all'
|
31
31
|
Requires-Dist: httpx[http2] ~=0.27 ; extra == 'all'
|
32
|
-
Requires-Dist: jinja2 ~=3.1 ; extra == 'all'
|
33
32
|
Requires-Dist: wrapt ~=1.14 ; extra == 'all'
|
34
33
|
Requires-Dist: cryptography ~=43.0 ; extra == 'all'
|
35
34
|
Requires-Dist: sqlalchemy[asyncio] ~=2.0 ; extra == 'all'
|
@@ -43,15 +42,15 @@ Requires-Dist: python-snappy ~=0.7 ; (python_version < "3.13") and extra == 'all
|
|
43
42
|
Requires-Dist: asyncpg ~=0.29 ; (python_version < "3.13") and extra == 'all'
|
44
43
|
Requires-Dist: sqlean.py ~=3.45 ; (python_version < "3.13") and extra == 'all'
|
45
44
|
Provides-Extra: async
|
46
|
-
Requires-Dist: anyio ~=4.
|
45
|
+
Requires-Dist: anyio ~=4.5 ; extra == 'async'
|
47
46
|
Requires-Dist: sniffio ~=1.3 ; extra == 'async'
|
48
47
|
Requires-Dist: greenlet ~=3.1 ; extra == 'async'
|
49
48
|
Requires-Dist: trio ~=0.26 ; extra == 'async'
|
50
49
|
Requires-Dist: trio-asyncio ~=0.15 ; extra == 'async'
|
51
|
-
Provides-Extra:
|
52
|
-
Requires-Dist: lz4 ~=4.0 ; extra == '
|
53
|
-
Requires-Dist: zstd ~=1.5 ; extra == '
|
54
|
-
Requires-Dist: python-snappy ~=0.7 ; (python_version < "3.13") and extra == '
|
50
|
+
Provides-Extra: compress
|
51
|
+
Requires-Dist: lz4 ~=4.0 ; extra == 'compress'
|
52
|
+
Requires-Dist: zstd ~=1.5 ; extra == 'compress'
|
53
|
+
Requires-Dist: python-snappy ~=0.7 ; (python_version < "3.13") and extra == 'compress'
|
55
54
|
Provides-Extra: diag
|
56
55
|
Requires-Dist: asttokens ~=2.4 ; extra == 'diag'
|
57
56
|
Requires-Dist: executing ~=2.1 ; extra == 'diag'
|
@@ -65,20 +64,19 @@ Requires-Dist: cloudpickle ~=3.0 ; extra == 'formats'
|
|
65
64
|
Provides-Extra: http
|
66
65
|
Requires-Dist: httpx[http2] ~=0.27 ; extra == 'http'
|
67
66
|
Provides-Extra: misc
|
68
|
-
Requires-Dist: jinja2 ~=3.1 ; extra == 'misc'
|
69
67
|
Requires-Dist: wrapt ~=1.14 ; extra == 'misc'
|
70
68
|
Provides-Extra: secrets
|
71
69
|
Requires-Dist: cryptography ~=43.0 ; extra == 'secrets'
|
72
|
-
Provides-Extra:
|
73
|
-
Requires-Dist: sqlalchemy[asyncio] ~=2.0 ; extra == '
|
74
|
-
|
75
|
-
Requires-Dist:
|
76
|
-
Requires-Dist:
|
77
|
-
Requires-Dist:
|
78
|
-
Requires-Dist:
|
79
|
-
|
80
|
-
Requires-Dist:
|
81
|
-
Requires-Dist: sqlean.py ~=3.45 ; (python_version < "3.13") and extra == '
|
70
|
+
Provides-Extra: sqlalchemy
|
71
|
+
Requires-Dist: sqlalchemy[asyncio] ~=2.0 ; extra == 'sqlalchemy'
|
72
|
+
Provides-Extra: sqlalchemy-drivers
|
73
|
+
Requires-Dist: pg8000 ~=1.31 ; extra == 'sqlalchemy-drivers'
|
74
|
+
Requires-Dist: pymysql ~=1.1 ; extra == 'sqlalchemy-drivers'
|
75
|
+
Requires-Dist: aiomysql ~=0.2 ; extra == 'sqlalchemy-drivers'
|
76
|
+
Requires-Dist: aiosqlite ~=0.20 ; extra == 'sqlalchemy-drivers'
|
77
|
+
Requires-Dist: duckdb ~=1.1 ; extra == 'sqlalchemy-drivers'
|
78
|
+
Requires-Dist: asyncpg ~=0.29 ; (python_version < "3.13") and extra == 'sqlalchemy-drivers'
|
79
|
+
Requires-Dist: sqlean.py ~=3.45 ; (python_version < "3.13") and extra == 'sqlalchemy-drivers'
|
82
80
|
Provides-Extra: testing
|
83
81
|
Requires-Dist: pytest ~=8.0 ; extra == 'testing'
|
84
82
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
omlish/.manifests.json,sha256=N1F-Xz3GaBn2H1p7uKzhkhKCQV8QVR0t76XD6wmFtXA,3
|
2
|
-
omlish/__about__.py,sha256=
|
2
|
+
omlish/__about__.py,sha256=fDFLSSMSxswk3iOzGDNumjsP4JcRrkaXRbp8w77f4ok,2709
|
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
|
@@ -10,15 +10,14 @@ omlish/defs.py,sha256=T3bq_7h_tO3nDB5RAFBn7DkdeQgqheXzkFColbOHZko,4890
|
|
10
10
|
omlish/docker.py,sha256=wipM7Xsx7rUv7-PoBTTT2v0uk3JVan0USljgm2QesXg,6227
|
11
11
|
omlish/dynamic.py,sha256=35C_cCX_Vq2HrHzGk5T-zbrMvmUdiIiwDzDNixczoDo,6541
|
12
12
|
omlish/fnpairs.py,sha256=hVuLqQFdRNNze3FYH2cAQO3GC7nK5yQP_GWPUSbL7nE,10601
|
13
|
+
omlish/fnpipes.py,sha256=AJkgz9nvRRm7oqw7ZgYyz21klu276LWi54oYCLg-vOg,2196
|
13
14
|
omlish/genmachine.py,sha256=LCMiqvK32dAWtrlB6lKw9tXdQFiXC8rRdk4TMQYIroU,1603
|
14
15
|
omlish/iterators.py,sha256=GGLC7RIT86uXMjhIIIqnff_Iu5SI_b9rXYywYGFyzmo,7292
|
15
16
|
omlish/libc.py,sha256=u0481imCiTFqP_e-v9g0pD-0WD249j5vYzhtn-fnNkY,15308
|
16
17
|
omlish/matchfns.py,sha256=ygqbqthRxgF9I1PJaw9Xl7FoZnAVMmnKBrYgimKQ0ag,6152
|
17
|
-
omlish/math.py,sha256=AVqp5Y8yxKA-wO0BgrzaxA0Ga3PZiCXnYcwivMneC-0,3804
|
18
18
|
omlish/multiprocessing.py,sha256=QZT4C7I-uThCAjaEY3xgUYb-5GagUlnE4etN01LDyU4,5186
|
19
|
-
omlish/os.py,sha256=
|
19
|
+
omlish/os.py,sha256=vO1sZCzAhVxo46tDFLrD52q2KuMFWQwu5MPJgSsnliI,3107
|
20
20
|
omlish/runmodule.py,sha256=PWvuAaJ9wQQn6bx9ftEL3_d04DyotNn8dR_twm2pgw0,700
|
21
|
-
omlish/stats.py,sha256=vJOJgYIW6DGDEgNm5AGWIp08GiLk61Cjld71fnC29fY,9998
|
22
21
|
omlish/sync.py,sha256=AqwIfIuCMVHLwlJUa7dmaSjfA4sM5AYPCD5-nsz3XVQ,1516
|
23
22
|
omlish/term.py,sha256=NEmxqAhicyInGtmFamZAizI2xdu819MzFYPEp0Fx97M,6111
|
24
23
|
omlish/asyncs/__init__.py,sha256=uUz9ziKh4_QrgmdhKFMgq6j7mFbiZd3LiogguDCQsGI,587
|
@@ -50,7 +49,7 @@ omlish/collections/ordered.py,sha256=RzEC3fHvrDeJQSWThVDNYQKke263Vje1II5YwtDwT1Q
|
|
50
49
|
omlish/collections/persistent.py,sha256=KG471s0bhhReQrjlmX0xaN9HeAIcrtT264ddZCxsExo,875
|
51
50
|
omlish/collections/skiplist.py,sha256=xjuKZtSScp1VnOi9lpf7I090vGp1DnjA5ELjFhMeGps,5987
|
52
51
|
omlish/collections/sorted.py,sha256=E5ZOdNn7Jju1EcQ7CX2Ltk9StIXsBOzqvh7EsT3ZA2U,3354
|
53
|
-
omlish/collections/treap.py,sha256=
|
52
|
+
omlish/collections/treap.py,sha256=A09ZPacGyJlyRB-Wi4TNj3tE0w-RpFNliPgpDaa6Vwg,7719
|
54
53
|
omlish/collections/treapmap.py,sha256=TxOM-ZRF5PK2xe5wRIhESNt7DGh9b_MeZfE7HLkCOs4,5804
|
55
54
|
omlish/collections/unmodifiable.py,sha256=QmUEi9IBXqiM_KGgH2rqg15VmkHJo1MZ6kwq2twEMho,4750
|
56
55
|
omlish/collections/utils.py,sha256=9o9STwzAn5YjZRZ9ns1kuo7NgLXLaoVPFu6AJd-3JT8,4336
|
@@ -75,7 +74,7 @@ omlish/dataclasses/impl/as_.py,sha256=CD-t7hkC1EP2F_jvZKIA_cVoDuwZ-Ln_xC4fJumPYX
|
|
75
74
|
omlish/dataclasses/impl/copy.py,sha256=Tn8_n6Vohs-w4otbGdubBEvhd3TsSTaM3EfNGdS2LYo,591
|
76
75
|
omlish/dataclasses/impl/descriptors.py,sha256=rEYE1Len99agTQCC25hSPMnM19BgPr0ZChABGi58Fdk,2476
|
77
76
|
omlish/dataclasses/impl/exceptions.py,sha256=DeiM6rcjgncudn-XVuph9TDbVDEwBtyYb1bcbO3FFcA,193
|
78
|
-
omlish/dataclasses/impl/fields.py,sha256=
|
77
|
+
omlish/dataclasses/impl/fields.py,sha256=DrFPLlPeJ4dCbbRsuwfx-y47Fx3iSllJP0YM5eq6nIE,6040
|
79
78
|
omlish/dataclasses/impl/frozen.py,sha256=x87DSM8FIMZ3c_BIUE8NooCkExFjPsabeqIueEP5qKs,2988
|
80
79
|
omlish/dataclasses/impl/hashing.py,sha256=FKnHuXCg9ylrzK2TLGqO5yfRN4HX3F415CSLlVYXtYE,3190
|
81
80
|
omlish/dataclasses/impl/init.py,sha256=IgxO9nwHaHF8jGrUAk-Y5xke9uV2OwzfEe-88McE1Wg,6161
|
@@ -103,7 +102,7 @@ omlish/diag/threads.py,sha256=1-x02VCDZ407gfbtXm1pWK-ubqhqfePm9PMqkHCVoqk,3642
|
|
103
102
|
omlish/diag/replserver/__init__.py,sha256=uLo6V2aQ29v9z3IMELlPDSlG3_2iOT4-_X8VniF-EgE,235
|
104
103
|
omlish/diag/replserver/__main__.py,sha256=LmU41lQ58bm1h4Mx7S8zhE_uEBSC6kPcp9mn5JRpulA,32
|
105
104
|
omlish/diag/replserver/console.py,sha256=XzBDVhYlr8FY6ym4OwoaIHuFOHnGK3dTYlMDIOMUUlA,7410
|
106
|
-
omlish/diag/replserver/server.py,sha256=
|
105
|
+
omlish/diag/replserver/server.py,sha256=5pRjBn-Vz8gtu45756ycdbJe58C_xrB9rElPytr6h5g,5345
|
107
106
|
omlish/dispatch/__init__.py,sha256=GsiGJ91NKiQptSROtnCSkrZExBkvfDwYvdoTu5dBqF0,117
|
108
107
|
omlish/dispatch/_dispatch2.py,sha256=v3tCNyxGpOwY8qTwdp54TlM8mG6OVwtQoUZfYJ_griU,1756
|
109
108
|
omlish/dispatch/_dispatch3.py,sha256=Vnu5DfoPWFJLodudBqoZBXGTi2wYk-Az56MXJgdQvwc,2608
|
@@ -132,7 +131,7 @@ omlish/http/cookies.py,sha256=uuOYlHR6e2SC3GM41V0aozK10nef9tYg83Scqpn5-HM,6351
|
|
132
131
|
omlish/http/dates.py,sha256=Otgp8wRxPgNGyzx8LFowu1vC4EKJYARCiAwLFncpfHM,2875
|
133
132
|
omlish/http/encodings.py,sha256=w2WoKajpaZnQH8j-IBvk5ZFL2O2pAU_iBvZnkocaTlw,164
|
134
133
|
omlish/http/json.py,sha256=9XwAsl4966Mxrv-1ytyCqhcE6lbBJw-0_tFZzGszgHE,7440
|
135
|
-
omlish/http/sessions.py,sha256=
|
134
|
+
omlish/http/sessions.py,sha256=VZ_WS5uiQG5y7i3u8oKuQMqf8dPKUOjFm_qk_0OvI8c,4793
|
136
135
|
omlish/http/wsgi.py,sha256=czZsVUX-l2YTlMrUjKN49wRoP4rVpS0qpeBn4O5BoMY,948
|
137
136
|
omlish/inject/__init__.py,sha256=JQ7x8l9MjU-kJ5ap7cPVq7SY7zbbCIrjyJAF0UeE5-s,1886
|
138
137
|
omlish/inject/binder.py,sha256=H8AQ4ecmBOtDL8fMgrU1yUJl1gBADLNcdysRbvO8Wso,4167
|
@@ -164,27 +163,27 @@ omlish/inject/impl/privates.py,sha256=alpCYyk5VJ9lJknbRH2nLVNFYVvFhkj-VC1Vco3zCF
|
|
164
163
|
omlish/inject/impl/providers.py,sha256=QnwhsujJFIHC0JTgd2Wlo1kP53i3CWTrj1nKU2DNxwg,2375
|
165
164
|
omlish/inject/impl/proxy.py,sha256=1ko0VaKqzu9UG8bIldp9xtUrAVUOFTKWKTjOCqIGr4s,1636
|
166
165
|
omlish/inject/impl/scopes.py,sha256=ASfULXgP_ETlsAqFJfrZmyEaZt64Zr8tNn5ScA-EoXk,5900
|
167
|
-
omlish/lang/__init__.py,sha256=
|
166
|
+
omlish/lang/__init__.py,sha256=0OCNjiSSyFL3RSNtakj0ILhC1K2P2WJkDTAgkC7xMjA,3601
|
168
167
|
omlish/lang/cached.py,sha256=LwsgWQjQ5op618rBvI8vbASOEGWDTt_SKq6Tc1vlgZM,7680
|
169
168
|
omlish/lang/clsdct.py,sha256=AjtIWLlx2E6D5rC97zQ3Lwq2SOMkbg08pdO_AxpzEHI,1744
|
170
169
|
omlish/lang/cmp.py,sha256=5vbzWWbqdzDmNKAGL19z6ZfUKe5Ci49e-Oegf9f4BsE,1346
|
171
|
-
omlish/lang/contextmanagers.py,sha256=
|
170
|
+
omlish/lang/contextmanagers.py,sha256=NEwaTLQMfhKawD5x_0HgI2RpeLXbMa5r9NqWqfDnUXI,10408
|
172
171
|
omlish/lang/datetimes.py,sha256=ehI_DhQRM-bDxAavnp470XcekbbXc4Gdw9y1KpHDJT0,223
|
173
172
|
omlish/lang/descriptors.py,sha256=OLM1qi14kY7PLGIJnvkd6CBEOzHgD9q8Cs2cB6Kzflk,6602
|
174
173
|
omlish/lang/exceptions.py,sha256=qJBo3NU1mOWWm-NhQUHCY5feYXR3arZVyEHinLsmRH4,47
|
175
|
-
omlish/lang/functions.py,sha256=
|
174
|
+
omlish/lang/functions.py,sha256=kkPfcdocg-OmyN7skIqrFxNvqAv89Zc_kXKYAN8vw8g,3895
|
176
175
|
omlish/lang/imports.py,sha256=04ugFC8NI5sbL7NH4V0r0q_nFsP_AMkHLz697CVkMtQ,6274
|
177
176
|
omlish/lang/iterables.py,sha256=_q6rHbdFfW3VBqez0IV3rUABoNxsA_oBv_sykm5zsbQ,2243
|
178
177
|
omlish/lang/maybes.py,sha256=NYHZDjqDtwPMheDrj2VtUVujxRPf8Qpgk4ZlZCTvBZc,3492
|
179
178
|
omlish/lang/objects.py,sha256=1dY8dX5voIZf5FBYUiN0BRsWg2JCdsgRbDl9fLG7OtY,4310
|
180
179
|
omlish/lang/resolving.py,sha256=OuN2mDTPNyBUbcrswtvFKtj4xgH4H4WglgqSKv3MTy0,1606
|
181
|
-
omlish/lang/resources.py,sha256
|
182
|
-
omlish/lang/strings.py,sha256=
|
180
|
+
omlish/lang/resources.py,sha256=-NmVTrSMKFZ6smVfOMz46ekZYVGgYh8cPooxQlFpG6s,2135
|
181
|
+
omlish/lang/strings.py,sha256=LqxR49cF5owHKpbUX8nUIBPsZ-4w7xqHPhlB-HIWqUg,3628
|
183
182
|
omlish/lang/sys.py,sha256=UoZz_PJYVKLQAKqYxxn-LHz1okK_38I__maZgnXMcxU,406
|
184
183
|
omlish/lang/timeouts.py,sha256=vECdWYhc_IZgcal1Ng1Y42wf2FV3KAx-i8As-MgGHIQ,1186
|
185
184
|
omlish/lang/typing.py,sha256=lJ2NGe4Pmb61I0Tx4A_rOqXNFTws1XHOzafg2knRUio,4155
|
186
185
|
omlish/lang/classes/__init__.py,sha256=h9QXrvAKD17_pIog0uF-7BCqZbSpJZYxL7kzVzvljp0,583
|
187
|
-
omlish/lang/classes/abstract.py,sha256=
|
186
|
+
omlish/lang/classes/abstract.py,sha256=IRnjuLLNwpxvEJsp8fwoQdCIpw0MDAd0TiQfoDMgsn4,2306
|
188
187
|
omlish/lang/classes/restrict.py,sha256=pSK7ZT_kpwqS6lWRrxwuEe-tt07F0-uZVazgGh-HDco,3921
|
189
188
|
omlish/lang/classes/simple.py,sha256=JkWYrRWnSKil6kVMgXgRMJeCxkFHXQIKIzYtG1jK2Pk,3067
|
190
189
|
omlish/lang/classes/virtual.py,sha256=W-QJuKsDehOcrydwg6eMN0bFPTYbk3Tz84TSH3blb44,3367
|
@@ -201,11 +200,11 @@ omlish/lite/cached.py,sha256=dUm647FbIsoxWT23XUFM51F7i-C2Buxr5b5zzgbCtQI,546
|
|
201
200
|
omlish/lite/check.py,sha256=DYxkYkxpnQpjGpDwW_8M8YBXbswvnBUCr0UBPU7aNKo,642
|
202
201
|
omlish/lite/contextmanagers.py,sha256=HnQJiyrOmSvTL22XRJrFl5CLpCyHD9fsntEUAr9G-60,427
|
203
202
|
omlish/lite/json.py,sha256=7-02Ny4fq-6YAu5ynvqoijhuYXWpLmfCI19GUeZnb1c,740
|
204
|
-
omlish/lite/logs.py,sha256=
|
203
|
+
omlish/lite/logs.py,sha256=vkFkSX0Izb2P-NNMqqNLSec0BzeLOtHoQWgdXwQuDPU,6007
|
205
204
|
omlish/lite/marshal.py,sha256=u6jYUN_AndvI6__HJBvSw5ElHWC0CfHqgiDS28Vpqjg,8593
|
206
205
|
omlish/lite/reflect.py,sha256=9QYJwdINraq1JNMEgvoqeSlVvRRgOXpxAkpgX8EgRXc,1307
|
207
206
|
omlish/lite/runtime.py,sha256=VUhmNQvwf8QzkWSKj4Q0ReieJA_PzHaJNRBivfTseow,452
|
208
|
-
omlish/lite/secrets.py,sha256=
|
207
|
+
omlish/lite/secrets.py,sha256=3Mz3V2jf__XU9qNHcH56sBSw95L3U2UPL24bjvobG0c,816
|
209
208
|
omlish/lite/strings.py,sha256=9dO_A6EkhcTZ2xmOUGSOMT-mx9BnoOzYu1-ocSrDJaA,670
|
210
209
|
omlish/lite/subprocesses.py,sha256=KuGV3ImehMjCUK0JoV3pUtG_7o5wei1lRDn9HxzByAg,3063
|
211
210
|
omlish/logs/__init__.py,sha256=FbOyAW-lGH8gyBlSVArwljdYAU6RnwZLI5LwAfuNnrk,438
|
@@ -230,11 +229,11 @@ omlish/marshal/helpers.py,sha256=YA0pNo-Fkc-_qKeoRNXUpP36js8oelU7uENkvoGD4hY,120
|
|
230
229
|
omlish/marshal/iterables.py,sha256=6I_ZdJemLSQtJ4J5NrB9wi-eyxiJZS61HzHXp1yeiX8,2592
|
231
230
|
omlish/marshal/mappings.py,sha256=zhLtyot7tzQtBNj7C4RBxjMELxA5r2q2Mth8Br7xkFs,2803
|
232
231
|
omlish/marshal/maybes.py,sha256=tKkVsJATERgbVcEfBnsHBK_2_LCQIVyBzca-cA-9KH0,2112
|
233
|
-
omlish/marshal/naming.py,sha256=
|
232
|
+
omlish/marshal/naming.py,sha256=lIklR_Od4x1ghltAgOzqcKhHs-leeSv2YmFhCHO7GIs,613
|
234
233
|
omlish/marshal/numbers.py,sha256=oY_yMNJEnJhjfLh89gpPXvKqeUyhQcaTcQB6ecyHiG8,1704
|
235
234
|
omlish/marshal/objects.py,sha256=R-NPCT1-UZhONTnrsrAvZvAtM2qyQsKZ8CPLfqkSg5g,4494
|
236
235
|
omlish/marshal/optionals.py,sha256=r0XB5rqfasvgZJNrKYd6Unq2U4nHt3JURi26j0dYHlw,1499
|
237
|
-
omlish/marshal/polymorphism.py,sha256=
|
236
|
+
omlish/marshal/polymorphism.py,sha256=doA8aLUhna6aco5b2Ok3jsem1V4NsF3rM5RTfJt0a7U,5708
|
238
237
|
omlish/marshal/primitives.py,sha256=wcvcs5GH_TWVmzAszh3dvyKibJgBxnXke-AlAXiwrrI,1107
|
239
238
|
omlish/marshal/registries.py,sha256=GI2KogcxawMkk02Ky7-TsnijChoe1I7YTOPIbUNwSAI,1665
|
240
239
|
omlish/marshal/standard.py,sha256=uQZIGiCwihmhB1tmhpKnZWZly0DDkdGjCnN0d41WHho,2985
|
@@ -242,6 +241,10 @@ omlish/marshal/unions.py,sha256=m9uVp2HrkZKY9lDyGoWQGXFgan8mRuBaKimtWNksl64,2635
|
|
242
241
|
omlish/marshal/utils.py,sha256=puKJpwPpuDlMOIrKMcLTRLJyMiL6n_Xs-p59AuDEymA,543
|
243
242
|
omlish/marshal/uuids.py,sha256=H4B7UX_EPNmP2tC8bubcKrPLTS4aQu98huvbXQ3Zv2g,910
|
244
243
|
omlish/marshal/values.py,sha256=ssHiWdg_L6M17kAn8GiGdPW7UeQOm3RDikWkvwblf5I,263
|
244
|
+
omlish/math/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
245
|
+
omlish/math/bits.py,sha256=yip1l8agOYzT7bFyMGc0RR3XlnGCfHMpjw_SECLLh1I,3477
|
246
|
+
omlish/math/floats.py,sha256=UimhOT7KRl8LXTzOI5cQWoX_9h6WNWe_3vcOuO7-h_8,327
|
247
|
+
omlish/math/stats.py,sha256=MegzKVsmv2kra4jDWLOUgV0X7Ee2Tbl5u6ql1v4-dEY,10053
|
245
248
|
omlish/reflect/__init__.py,sha256=iWDCNJNP4afPcv-MxZRJSIRQ4NRw6XYPyRHhBXb5YIA,667
|
246
249
|
omlish/reflect/isinstance.py,sha256=x5T9S2634leinBT4hl3CZZkRttvdvvlxChkC_x9Qu2s,1176
|
247
250
|
omlish/reflect/ops.py,sha256=RJ6jzrM4ieFsXzWyNXWV43O_WgzEaUvlHSc5N2ezW2A,2044
|
@@ -254,7 +257,7 @@ omlish/secrets/openssl.py,sha256=wxA_wIlxtuOUy71ABxAJgavh-UI_taOfm-A0dVlmSwM,621
|
|
254
257
|
omlish/secrets/passwords.py,sha256=3r-vEK6Gp6aq4L5Csnd06QnrjO9xfzHJP-g_7I9W_ao,4101
|
255
258
|
omlish/secrets/secrets.py,sha256=ClD7t_mkmWkseVk4ahLzYLuLXeTxiwwPiidYm42vLh4,6871
|
256
259
|
omlish/secrets/subprocesses.py,sha256=EcnKlHHtnUMHGrBWXDfu8tv28wlgZx4P4GOiuPW9Vo8,1105
|
257
|
-
omlish/specs/__init__.py,sha256=
|
260
|
+
omlish/specs/__init__.py,sha256=_CSPXx25uGhXkmqLs9CSdcWAkZaQnc3cJk3lb2dadgE,88
|
258
261
|
omlish/specs/jsonschema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
259
262
|
omlish/specs/jsonschema/types.py,sha256=qoxExgKfrI-UZXdk3qcVZIEyp1WckFbb85_eGInEoAY,467
|
260
263
|
omlish/specs/jsonschema/keywords/__init__.py,sha256=Zt2g1BXd654uU2AQ5P7_-x2Wrtf6cNbP9mxI1wGN4wo,596
|
@@ -277,15 +280,16 @@ omlish/specs/jsonschema/schemas/draft202012/vocabularies/format.json,sha256=UOu_
|
|
277
280
|
omlish/specs/jsonschema/schemas/draft202012/vocabularies/meta-data.json,sha256=j3bW4U9Bubku-TO3CM3FFEyLUmhlGtEZGEhfsXVPHHY,892
|
278
281
|
omlish/specs/jsonschema/schemas/draft202012/vocabularies/unevaluated.json,sha256=Lb-8tzmUtnCwl2SSre4f_7RsIWgnhNL1pMpWH54tDLQ,506
|
279
282
|
omlish/specs/jsonschema/schemas/draft202012/vocabularies/validation.json,sha256=cBCjHlQfMtK-ch4t40jfdcmzaHaj7TBId_wKvaHTelg,2834
|
280
|
-
omlish/sql/__init__.py,sha256=
|
283
|
+
omlish/sql/__init__.py,sha256=TpZLsEJKJzvJ0eMzuV8hwOJJbkxBCV1RZPUMLAVB6io,173
|
281
284
|
omlish/sql/_abc.py,sha256=HLhnnLZ7l0r_N99I-RCqJe6VHth-9iluU7cR-7-5jfs,1519
|
282
|
-
omlish/sql/asyncs.py,sha256=Wye3dwh7oZEGYz2Y4DZQSHtW4xjI2AH5qjW-BSS2IfU,3688
|
283
285
|
omlish/sql/dbs.py,sha256=lpdFmm2vTwLoBiVYGj9yPsVcTEYYNCxlYZZpjfChzkY,1870
|
284
|
-
omlish/sql/duckdb.py,sha256=Z3wiZEn_21Lu1ElFRX0ATzoBMCw0KJxINjTRuTexYGM,3748
|
285
|
-
omlish/sql/exprs.py,sha256=gO4Fj4xEY-PuDgV-N8hBMy55glZz7O-4H7v1LWabfZY,323
|
286
286
|
omlish/sql/qualifiedname.py,sha256=rlW3gVmyucJbqwcxj_7BfK4X2HoXrMroZT2H45zPgJQ,2264
|
287
|
-
omlish/sql/
|
288
|
-
omlish/sql/
|
287
|
+
omlish/sql/alchemy/__init__.py,sha256=1ruDMiviH5fjevn2xVki-QspcE9O3VPy4hxOqpHjI2s,224
|
288
|
+
omlish/sql/alchemy/asyncs.py,sha256=C1bIzz9m2Qbgl4qYGQt_FRQg4BKRcxUqMsVg9RtnTPg,3689
|
289
|
+
omlish/sql/alchemy/duckdb.py,sha256=kr7pIhiBLNAuZrcigHDtFg9zHkVcrRW3LfryO9VJ4mk,3749
|
290
|
+
omlish/sql/alchemy/exprs.py,sha256=gO4Fj4xEY-PuDgV-N8hBMy55glZz7O-4H7v1LWabfZY,323
|
291
|
+
omlish/sql/alchemy/secrets.py,sha256=EMfy4EfTbEvrlv_41oOhn8qsoF-eTkY7HciPenIE6rI,178
|
292
|
+
omlish/sql/alchemy/sqlean.py,sha256=RbkuOuFIfM4fowwKk8-sQ6Dxk-tTUwxS94nY5Kxt52s,403
|
289
293
|
omlish/testing/__init__.py,sha256=kfiF10ykrjWXniedIl3g8j3pNAFyuSbp1D3ZXug3-Eo,168
|
290
294
|
omlish/testing/testing.py,sha256=pJUbZ0ymdrQoNG9r9UlGXypeU1x9ntEp9xcYBnyOHUs,3088
|
291
295
|
omlish/testing/pytest/__init__.py,sha256=b6ObMEHTZnvGEI_de6nN1x5FyitV6B2mNYkurA4Q7fo,336
|
@@ -295,7 +299,7 @@ omlish/testing/pytest/inject/__init__.py,sha256=pdRKv1HcDmJ_yArKJbYITPXXZthRSGgB
|
|
295
299
|
omlish/testing/pytest/inject/harness.py,sha256=sMKjP2EWHq-eeTB1YVXcANli2Czxt56_9ERg4HtkVPg,5810
|
296
300
|
omlish/testing/pytest/plugins/__init__.py,sha256=ys1zXrYrNm7Uo6YOIVJ6Bd3dQo6kv387k7MbTYlqZSI,467
|
297
301
|
omlish/testing/pytest/plugins/_registry.py,sha256=IK04KlBgiOJxKAyCCgjpX2R-9tE-btalYJkgjLc8Te8,77
|
298
|
-
omlish/testing/pytest/plugins/asyncs.py,sha256=
|
302
|
+
omlish/testing/pytest/plugins/asyncs.py,sha256=SV6oKCy50CGkzLGYX-CT4MfWNqsrH8ONEbIWC3tFcHA,5324
|
299
303
|
omlish/testing/pytest/plugins/depskip.py,sha256=xithY-OMtjwhv8mcRNkv-WI_PSQtHldQ8H1s60MIXkk,2673
|
300
304
|
omlish/testing/pytest/plugins/logging.py,sha256=1zs6Xe54wiaSjabCviaFXwKkoN97CKm3mA5mEoUeJGs,380
|
301
305
|
omlish/testing/pytest/plugins/managermarks.py,sha256=pDEcCNdDAcTS4jjZHSnAfmzqMJDBcJcSsM3QNhbJ6Gs,1485
|
@@ -306,13 +310,13 @@ omlish/testing/pytest/plugins/spacing.py,sha256=JQQhi9q3c523Ro1a_K_9RGAb7HotiO74
|
|
306
310
|
omlish/testing/pytest/plugins/switches.py,sha256=9FtN5qtPBoS-teEp54OHPF6jlZJakRJdq4pnLJpPj_A,3001
|
307
311
|
omlish/testing/pytest/plugins/utils.py,sha256=L5C622UXcA_AUKDcvyh5IMiRfqSGGz0McdhwZWvfMlU,261
|
308
312
|
omlish/text/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
309
|
-
omlish/text/asdl.py,sha256=
|
313
|
+
omlish/text/asdl.py,sha256=3v5UocAfxan_d9drkGNdH3AMfx_FFBpQu3ULGL4M6VM,16865
|
310
314
|
omlish/text/delimit.py,sha256=ubPXcXQmtbOVrUsNh5gH1mDq5H-n1y2R4cPL5_DQf68,4928
|
311
315
|
omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,3296
|
312
316
|
omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
|
313
|
-
omlish/text/parts.py,sha256=
|
314
|
-
omlish-0.0.0.
|
315
|
-
omlish-0.0.0.
|
316
|
-
omlish-0.0.0.
|
317
|
-
omlish-0.0.0.
|
318
|
-
omlish-0.0.0.
|
317
|
+
omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
|
318
|
+
omlish-0.0.0.dev30.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
319
|
+
omlish-0.0.0.dev30.dist-info/METADATA,sha256=IwpExBB3pJdmS4yOOGHNJjwusV5Xj5KOyW5aY9cHxV8,3694
|
320
|
+
omlish-0.0.0.dev30.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
321
|
+
omlish-0.0.0.dev30.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
322
|
+
omlish-0.0.0.dev30.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|