omlish 0.0.0.dev447__py3-none-any.whl → 0.0.0.dev484__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.
Potentially problematic release.
This version of omlish might be problematic. Click here for more details.
- omlish/.omlish-manifests.json +12 -0
- omlish/__about__.py +15 -15
- omlish/argparse/all.py +17 -9
- omlish/argparse/cli.py +16 -3
- omlish/argparse/utils.py +21 -0
- omlish/asyncs/asyncio/rlock.py +110 -0
- omlish/asyncs/asyncio/sync.py +43 -0
- omlish/asyncs/asyncio/utils.py +2 -0
- omlish/asyncs/sync.py +25 -0
- omlish/bootstrap/_marshal.py +1 -1
- omlish/bootstrap/diag.py +12 -21
- omlish/bootstrap/main.py +2 -5
- omlish/bootstrap/sys.py +27 -28
- omlish/cexts/__init__.py +0 -0
- omlish/cexts/include/omlish/omlish.hh +1 -0
- omlish/collections/__init__.py +13 -1
- omlish/collections/attrregistry.py +210 -0
- omlish/collections/cache/impl.py +1 -0
- omlish/collections/identity.py +1 -0
- omlish/collections/mappings.py +28 -0
- omlish/collections/trie.py +5 -1
- omlish/collections/utils.py +77 -0
- omlish/concurrent/all.py +2 -1
- omlish/concurrent/futures.py +25 -0
- omlish/concurrent/threadlets.py +1 -1
- omlish/daemons/reparent.py +2 -3
- omlish/daemons/spawning.py +2 -3
- omlish/dataclasses/__init__.py +2 -0
- omlish/dataclasses/impl/api/classes/decorator.py +3 -0
- omlish/dataclasses/impl/api/classes/make.py +3 -0
- omlish/dataclasses/impl/concerns/repr.py +15 -2
- omlish/dataclasses/impl/configs.py +97 -37
- omlish/dataclasses/impl/generation/compilation.py +21 -19
- omlish/dataclasses/impl/generation/globals.py +1 -0
- omlish/dataclasses/impl/generation/ops.py +1 -0
- omlish/dataclasses/impl/generation/processor.py +105 -24
- omlish/dataclasses/impl/processing/base.py +8 -0
- omlish/dataclasses/impl/processing/driving.py +8 -8
- omlish/dataclasses/specs.py +1 -0
- omlish/dataclasses/tools/modifiers.py +5 -0
- omlish/diag/cmds/__init__.py +0 -0
- omlish/diag/{lslocks.py → cmds/lslocks.py} +6 -6
- omlish/diag/{lsof.py → cmds/lsof.py} +6 -6
- omlish/diag/{ps.py → cmds/ps.py} +6 -6
- omlish/diag/pycharm.py +16 -2
- omlish/diag/pydevd.py +58 -40
- omlish/diag/replserver/console.py +1 -1
- omlish/dispatch/__init__.py +18 -12
- omlish/dispatch/methods.py +50 -140
- omlish/dom/rendering.py +1 -1
- omlish/formats/dotenv.py +1 -1
- omlish/formats/json/stream/__init__.py +13 -0
- omlish/funcs/guard.py +225 -0
- omlish/graphs/dot/rendering.py +1 -1
- omlish/http/all.py +44 -4
- omlish/http/clients/asyncs.py +33 -27
- omlish/http/clients/base.py +17 -1
- omlish/http/clients/coro/__init__.py +0 -0
- omlish/http/clients/coro/sync.py +171 -0
- omlish/http/clients/default.py +208 -29
- omlish/http/clients/executor.py +56 -0
- omlish/http/clients/httpx.py +72 -11
- omlish/http/clients/middleware.py +181 -0
- omlish/http/clients/sync.py +33 -27
- omlish/http/clients/syncasync.py +49 -0
- omlish/http/clients/urllib.py +6 -3
- omlish/http/coro/client/connection.py +15 -6
- omlish/http/coro/io.py +2 -0
- omlish/http/flasky/__init__.py +40 -0
- omlish/http/flasky/_compat.py +2 -0
- omlish/http/flasky/api.py +82 -0
- omlish/http/flasky/app.py +203 -0
- omlish/http/flasky/cvs.py +59 -0
- omlish/http/flasky/requests.py +20 -0
- omlish/http/flasky/responses.py +23 -0
- omlish/http/flasky/routes.py +23 -0
- omlish/http/flasky/types.py +15 -0
- omlish/http/urls.py +67 -0
- omlish/inject/__init__.py +38 -18
- omlish/inject/_dataclasses.py +4986 -0
- omlish/inject/binder.py +4 -48
- omlish/inject/elements.py +27 -0
- omlish/inject/helpers/__init__.py +0 -0
- omlish/inject/{utils.py → helpers/constfn.py} +3 -3
- omlish/inject/{tags.py → helpers/id.py} +2 -2
- omlish/inject/helpers/multis.py +143 -0
- omlish/inject/helpers/wrappers.py +54 -0
- omlish/inject/impl/elements.py +47 -17
- omlish/inject/impl/injector.py +20 -19
- omlish/inject/impl/inspect.py +10 -1
- omlish/inject/impl/maysync.py +3 -4
- omlish/inject/impl/multis.py +3 -0
- omlish/inject/impl/sync.py +3 -4
- omlish/inject/injector.py +31 -2
- omlish/inject/inspect.py +35 -0
- omlish/inject/maysync.py +2 -4
- omlish/inject/multis.py +8 -0
- omlish/inject/overrides.py +3 -3
- omlish/inject/privates.py +6 -0
- omlish/inject/providers.py +3 -2
- omlish/inject/sync.py +5 -4
- omlish/io/buffers.py +118 -0
- omlish/io/readers.py +29 -0
- omlish/iterators/transforms.py +2 -2
- omlish/lang/__init__.py +178 -97
- omlish/lang/_asyncs.cc +186 -0
- omlish/lang/asyncs.py +17 -0
- omlish/lang/casing.py +11 -0
- omlish/lang/contextmanagers.py +28 -4
- omlish/lang/functions.py +31 -22
- omlish/lang/imports/_capture.cc +11 -9
- omlish/lang/imports/capture.py +363 -170
- omlish/lang/imports/proxy.py +455 -152
- omlish/lang/lazyglobals.py +22 -9
- omlish/lang/params.py +17 -0
- omlish/lang/recursion.py +0 -1
- omlish/lang/sequences.py +124 -0
- omlish/lite/abstract.py +54 -24
- omlish/lite/asyncs.py +2 -2
- omlish/lite/attrops.py +2 -0
- omlish/lite/contextmanagers.py +4 -4
- omlish/lite/dataclasses.py +44 -0
- omlish/lite/maybes.py +8 -0
- omlish/lite/maysync.py +1 -5
- omlish/lite/pycharm.py +1 -1
- omlish/lite/typing.py +6 -0
- omlish/logs/all.py +1 -1
- omlish/logs/utils.py +1 -1
- omlish/manifests/loading.py +2 -1
- omlish/marshal/__init__.py +33 -13
- omlish/marshal/_dataclasses.py +2774 -0
- omlish/marshal/base/configs.py +12 -0
- omlish/marshal/base/contexts.py +36 -21
- omlish/marshal/base/funcs.py +8 -11
- omlish/marshal/base/options.py +8 -0
- omlish/marshal/base/registries.py +146 -44
- omlish/marshal/base/types.py +40 -16
- omlish/marshal/composite/iterables.py +33 -20
- omlish/marshal/composite/literals.py +20 -18
- omlish/marshal/composite/mappings.py +36 -23
- omlish/marshal/composite/maybes.py +29 -19
- omlish/marshal/composite/newtypes.py +16 -16
- omlish/marshal/composite/optionals.py +14 -14
- omlish/marshal/composite/special.py +15 -15
- omlish/marshal/composite/unions/__init__.py +0 -0
- omlish/marshal/composite/unions/literals.py +93 -0
- omlish/marshal/composite/unions/primitives.py +103 -0
- omlish/marshal/factories/invalidate.py +18 -68
- omlish/marshal/factories/method.py +26 -0
- omlish/marshal/factories/moduleimport/factories.py +22 -65
- omlish/marshal/factories/multi.py +13 -25
- omlish/marshal/factories/recursive.py +42 -56
- omlish/marshal/factories/typecache.py +29 -74
- omlish/marshal/factories/typemap.py +42 -43
- omlish/marshal/objects/dataclasses.py +129 -106
- omlish/marshal/objects/marshal.py +18 -14
- omlish/marshal/objects/namedtuples.py +48 -42
- omlish/marshal/objects/unmarshal.py +19 -15
- omlish/marshal/polymorphism/marshal.py +9 -11
- omlish/marshal/polymorphism/metadata.py +16 -5
- omlish/marshal/polymorphism/standard.py +13 -1
- omlish/marshal/polymorphism/unions.py +15 -105
- omlish/marshal/polymorphism/unmarshal.py +9 -10
- omlish/marshal/singular/enums.py +14 -18
- omlish/marshal/standard.py +10 -6
- omlish/marshal/trivial/any.py +1 -1
- omlish/marshal/trivial/forbidden.py +21 -26
- omlish/metadata.py +23 -1
- omlish/os/forkhooks.py +4 -0
- omlish/os/pidfiles/pinning.py +2 -2
- omlish/reflect/types.py +1 -0
- omlish/secrets/marshal.py +1 -1
- omlish/specs/jmespath/__init__.py +12 -3
- omlish/specs/jmespath/_dataclasses.py +2893 -0
- omlish/specs/jmespath/ast.py +1 -1
- omlish/specs/jsonrpc/__init__.py +13 -0
- omlish/specs/jsonrpc/_marshal.py +32 -23
- omlish/specs/jsonrpc/conns.py +10 -7
- omlish/specs/jsonschema/_marshal.py +1 -1
- omlish/specs/jsonschema/keywords/__init__.py +7 -0
- omlish/specs/jsonschema/keywords/_dataclasses.py +1644 -0
- omlish/specs/openapi/_marshal.py +31 -22
- omlish/sql/{tabledefs/alchemy.py → alchemy/tabledefs.py} +2 -2
- omlish/sql/queries/_marshal.py +2 -2
- omlish/sql/queries/rendering.py +1 -1
- omlish/sql/tabledefs/_marshal.py +1 -1
- omlish/subprocesses/base.py +4 -0
- omlish/subprocesses/editor.py +1 -1
- omlish/sync.py +155 -21
- omlish/term/alt.py +60 -0
- omlish/term/confirm.py +8 -8
- omlish/term/pager.py +235 -0
- omlish/term/terminfo.py +935 -0
- omlish/term/termstate.py +67 -0
- omlish/term/vt100/terminal.py +0 -3
- omlish/testing/pytest/plugins/asyncs/fixtures.py +4 -1
- omlish/testing/pytest/plugins/skips.py +2 -1
- omlish/testing/unittest/main.py +3 -3
- omlish/text/docwrap/__init__.py +3 -0
- omlish/text/docwrap/__main__.py +11 -0
- omlish/text/docwrap/api.py +83 -0
- omlish/text/docwrap/cli.py +86 -0
- omlish/text/docwrap/groups.py +84 -0
- omlish/text/docwrap/lists.py +167 -0
- omlish/text/docwrap/parts.py +146 -0
- omlish/text/docwrap/reflowing.py +106 -0
- omlish/text/docwrap/rendering.py +151 -0
- omlish/text/docwrap/utils.py +11 -0
- omlish/text/docwrap/wrapping.py +59 -0
- omlish/text/filecache.py +2 -2
- omlish/text/lorem.py +6 -0
- omlish/text/parts.py +2 -2
- omlish/text/textwrap.py +51 -0
- omlish/typedvalues/marshal.py +85 -59
- omlish/typedvalues/values.py +2 -1
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev484.dist-info}/METADATA +29 -28
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev484.dist-info}/RECORD +222 -171
- omlish/dataclasses/impl/generation/mangling.py +0 -18
- omlish/funcs/match.py +0 -227
- omlish/marshal/factories/match.py +0 -34
- omlish/marshal/factories/simple.py +0 -28
- /omlish/inject/impl/{providers2.py → providersmap.py} +0 -0
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev484.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev484.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev484.dist-info}/licenses/LICENSE +0 -0
- {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev484.dist-info}/top_level.txt +0 -0
omlish/inject/injector.py
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import abc
|
|
2
2
|
import typing as ta
|
|
3
3
|
|
|
4
|
+
from .. import check
|
|
4
5
|
from .. import lang
|
|
6
|
+
from .elements import CollectedElements
|
|
5
7
|
from .elements import Elemental
|
|
6
8
|
from .elements import as_elements
|
|
9
|
+
from .elements import collect_elements
|
|
7
10
|
from .inspect import KwargsTarget
|
|
8
11
|
from .keys import Key
|
|
9
12
|
|
|
@@ -44,5 +47,31 @@ class AsyncInjector(lang.Abstract):
|
|
|
44
47
|
return self.provide(target)
|
|
45
48
|
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
##
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@ta.final
|
|
54
|
+
class _InjectorCreator(ta.Generic[T]):
|
|
55
|
+
def __init__(self, fac: ta.Callable[[CollectedElements], T]) -> None:
|
|
56
|
+
self._fac = fac
|
|
57
|
+
|
|
58
|
+
@ta.overload
|
|
59
|
+
def __call__(self, es: CollectedElements, /) -> T: ...
|
|
60
|
+
|
|
61
|
+
@ta.overload
|
|
62
|
+
def __call__(self, *es: Elemental) -> T: ...
|
|
63
|
+
|
|
64
|
+
def __call__(self, arg0, *argv):
|
|
65
|
+
ce: CollectedElements
|
|
66
|
+
if isinstance(arg0, CollectedElements):
|
|
67
|
+
check.arg(not argv)
|
|
68
|
+
ce = arg0
|
|
69
|
+
else:
|
|
70
|
+
ce = collect_elements(as_elements(arg0, *argv))
|
|
71
|
+
return self._fac(ce)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
##
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
create_async_injector = _InjectorCreator[ta.Awaitable[AsyncInjector]](lambda ce: _injector.create_async_injector(ce))
|
omlish/inject/inspect.py
CHANGED
|
@@ -2,6 +2,7 @@ import typing as ta
|
|
|
2
2
|
|
|
3
3
|
from .. import lang
|
|
4
4
|
from .keys import Key
|
|
5
|
+
from .keys import as_key
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
if ta.TYPE_CHECKING:
|
|
@@ -21,11 +22,45 @@ class Kwarg(ta.NamedTuple):
|
|
|
21
22
|
key: Key
|
|
22
23
|
has_default: bool
|
|
23
24
|
|
|
25
|
+
@classmethod
|
|
26
|
+
def of(
|
|
27
|
+
cls,
|
|
28
|
+
name: str,
|
|
29
|
+
key: Key,
|
|
30
|
+
*,
|
|
31
|
+
has_default: bool = False,
|
|
32
|
+
) -> 'Kwarg':
|
|
33
|
+
return cls(
|
|
34
|
+
name,
|
|
35
|
+
key,
|
|
36
|
+
has_default,
|
|
37
|
+
)
|
|
38
|
+
|
|
24
39
|
|
|
25
40
|
class KwargsTarget(ta.NamedTuple):
|
|
26
41
|
obj: ta.Any
|
|
27
42
|
kwargs: ta.Sequence[Kwarg]
|
|
28
43
|
|
|
44
|
+
@classmethod
|
|
45
|
+
def of(
|
|
46
|
+
cls,
|
|
47
|
+
obj: ta.Any,
|
|
48
|
+
*kws: Kwarg,
|
|
49
|
+
**kwargs: tuple[Key, bool] | Key | ta.Any,
|
|
50
|
+
) -> 'KwargsTarget':
|
|
51
|
+
kw_kwargs: list[Kwarg] = []
|
|
52
|
+
for n, v in kwargs.items():
|
|
53
|
+
if isinstance(v, tuple):
|
|
54
|
+
kw_k, kw_hd = v
|
|
55
|
+
kw_kwargs.append(Kwarg.of(n, kw_k, has_default=kw_hd))
|
|
56
|
+
else:
|
|
57
|
+
kw_kwargs.append(Kwarg.of(n, as_key(v)))
|
|
58
|
+
|
|
59
|
+
return cls(
|
|
60
|
+
obj,
|
|
61
|
+
[*kws, *kw_kwargs],
|
|
62
|
+
)
|
|
63
|
+
|
|
29
64
|
|
|
30
65
|
def tag(obj: T, **kwargs: ta.Any) -> T:
|
|
31
66
|
return _inspect.tag(obj, **kwargs)
|
omlish/inject/maysync.py
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import typing as ta
|
|
2
2
|
|
|
3
3
|
from .. import lang
|
|
4
|
-
from .
|
|
5
|
-
from .elements import as_elements
|
|
4
|
+
from .injector import _InjectorCreator
|
|
6
5
|
from .sync import Injector
|
|
7
6
|
|
|
8
7
|
|
|
@@ -25,5 +24,4 @@ class MaysyncInjector(Injector, lang.Abstract):
|
|
|
25
24
|
##
|
|
26
25
|
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
return _maysync.create_maysync_injector(as_elements(*args))
|
|
27
|
+
create_maysync_injector = _InjectorCreator[MaysyncInjector](lambda ce: _maysync.create_maysync_injector(ce))
|
omlish/inject/multis.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
TODO:
|
|
3
|
+
- DynamicSetBinding / DynamicMapBinding ? provider of set[T] / map[K, V] ?
|
|
4
|
+
- doable not guicey - too much dynamism
|
|
3
5
|
- scopes
|
|
4
6
|
"""
|
|
5
7
|
import collections.abc
|
|
@@ -94,6 +96,9 @@ class SetBinder(ElementGenerator, ta.Generic[T]):
|
|
|
94
96
|
yield from self._sbs
|
|
95
97
|
|
|
96
98
|
|
|
99
|
+
set_binder = SetBinder
|
|
100
|
+
|
|
101
|
+
|
|
97
102
|
#
|
|
98
103
|
|
|
99
104
|
|
|
@@ -123,3 +128,6 @@ class MapBinder(ElementGenerator, ta.Generic[K, V]):
|
|
|
123
128
|
def __iter__(self) -> ta.Iterator[Element]:
|
|
124
129
|
yield self._map_provider_binding
|
|
125
130
|
yield from self._mbs
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
map_binder = MapBinder
|
omlish/inject/overrides.py
CHANGED
|
@@ -14,9 +14,9 @@ from .elements import as_elements
|
|
|
14
14
|
@dc.dataclass(frozen=True)
|
|
15
15
|
@dc.extra_class_params(cache_hash=True)
|
|
16
16
|
class Overrides(Element, lang.Final):
|
|
17
|
-
ovr: Elements = dc.xfield(coerce=check.of_isinstance(Elements))
|
|
18
17
|
src: Elements = dc.xfield(coerce=check.of_isinstance(Elements))
|
|
18
|
+
ovr: Elements = dc.xfield(coerce=check.of_isinstance(Elements))
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
def override(
|
|
22
|
-
return Overrides(as_elements(
|
|
21
|
+
def override(src: ta.Any, *ovr: ta.Any) -> Element:
|
|
22
|
+
return Overrides(as_elements(src), as_elements(*ovr))
|
omlish/inject/privates.py
CHANGED
omlish/inject/providers.py
CHANGED
|
@@ -3,6 +3,7 @@ import typing as ta
|
|
|
3
3
|
from .. import check
|
|
4
4
|
from .. import dataclasses as dc
|
|
5
5
|
from .. import lang
|
|
6
|
+
from .inspect import KwargsTarget
|
|
6
7
|
from .keys import Key
|
|
7
8
|
|
|
8
9
|
|
|
@@ -20,13 +21,13 @@ class Provider(lang.Abstract):
|
|
|
20
21
|
@dc.dataclass(frozen=True)
|
|
21
22
|
@dc.extra_class_params(cache_hash=True)
|
|
22
23
|
class AsyncFnProvider(Provider):
|
|
23
|
-
fn: ta.Any = dc.xfield(validate=callable)
|
|
24
|
+
fn: ta.Any = dc.xfield(validate=lambda v: callable(v) or isinstance(v, KwargsTarget))
|
|
24
25
|
|
|
25
26
|
|
|
26
27
|
@dc.dataclass(frozen=True)
|
|
27
28
|
@dc.extra_class_params(cache_hash=True)
|
|
28
29
|
class FnProvider(Provider):
|
|
29
|
-
fn: ta.Any = dc.xfield(validate=callable)
|
|
30
|
+
fn: ta.Any = dc.xfield(validate=lambda v: callable(v) or isinstance(v, KwargsTarget))
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
@dc.dataclass(frozen=True)
|
omlish/inject/sync.py
CHANGED
|
@@ -2,8 +2,7 @@ import abc
|
|
|
2
2
|
import typing as ta
|
|
3
3
|
|
|
4
4
|
from .. import lang
|
|
5
|
-
from .
|
|
6
|
-
from .elements import as_elements
|
|
5
|
+
from .injector import _InjectorCreator
|
|
7
6
|
from .inspect import KwargsTarget
|
|
8
7
|
from .keys import Key
|
|
9
8
|
|
|
@@ -44,5 +43,7 @@ class Injector(lang.Abstract):
|
|
|
44
43
|
return self.provide(target)
|
|
45
44
|
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
##
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
create_injector = _InjectorCreator[Injector](lambda ce: _sync.create_injector(ce))
|
omlish/io/buffers.py
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
# ruff: noqa: UP006 UP007 UP043 UP045
|
|
2
2
|
# @omlish-lite
|
|
3
|
+
"""
|
|
4
|
+
TODO:
|
|
5
|
+
- overhaul and just coro-ify pyio?
|
|
6
|
+
"""
|
|
3
7
|
import io
|
|
4
8
|
import typing as ta
|
|
5
9
|
|
|
6
10
|
from ..lite.attrops import attr_repr
|
|
7
11
|
from ..lite.check import check
|
|
12
|
+
from .readers import AsyncBufferedBytesReader
|
|
13
|
+
from .readers import AsyncRawBytesReader
|
|
14
|
+
from .readers import BufferedBytesReader
|
|
15
|
+
from .readers import RawBytesReader
|
|
8
16
|
|
|
9
17
|
|
|
10
18
|
##
|
|
@@ -183,6 +191,9 @@ class ReadableListBuffer:
|
|
|
183
191
|
|
|
184
192
|
self._lst: list[bytes] = []
|
|
185
193
|
|
|
194
|
+
def __bool__(self) -> ta.NoReturn:
|
|
195
|
+
raise TypeError("Use 'buf is not None' or 'len(buf)'.")
|
|
196
|
+
|
|
186
197
|
def __len__(self) -> int:
|
|
187
198
|
return sum(map(len, self._lst))
|
|
188
199
|
|
|
@@ -208,6 +219,9 @@ class ReadableListBuffer:
|
|
|
208
219
|
|
|
209
220
|
def read(self, n: ta.Optional[int] = None) -> ta.Optional[bytes]:
|
|
210
221
|
if n is None:
|
|
222
|
+
if not self._lst:
|
|
223
|
+
return b''
|
|
224
|
+
|
|
211
225
|
o = b''.join(self._lst)
|
|
212
226
|
self._lst = []
|
|
213
227
|
return o
|
|
@@ -246,6 +260,110 @@ class ReadableListBuffer:
|
|
|
246
260
|
r = self.read_until_(delim)
|
|
247
261
|
return r if isinstance(r, bytes) else None
|
|
248
262
|
|
|
263
|
+
#
|
|
264
|
+
|
|
265
|
+
DEFAULT_BUFFERED_READER_CHUNK_SIZE: ta.ClassVar[int] = -1
|
|
266
|
+
|
|
267
|
+
@ta.final
|
|
268
|
+
class _BufferedBytesReader(BufferedBytesReader):
|
|
269
|
+
def __init__(
|
|
270
|
+
self,
|
|
271
|
+
raw: RawBytesReader,
|
|
272
|
+
buf: 'ReadableListBuffer',
|
|
273
|
+
*,
|
|
274
|
+
chunk_size: ta.Optional[int] = None,
|
|
275
|
+
) -> None:
|
|
276
|
+
self._raw = raw
|
|
277
|
+
self._buf = buf
|
|
278
|
+
self._chunk_size = chunk_size or ReadableListBuffer.DEFAULT_BUFFERED_READER_CHUNK_SIZE
|
|
279
|
+
|
|
280
|
+
def read1(self, n: int = -1, /) -> bytes:
|
|
281
|
+
if n < 0:
|
|
282
|
+
n = self._chunk_size
|
|
283
|
+
if not n:
|
|
284
|
+
return b''
|
|
285
|
+
if 0 < n <= len(self._buf):
|
|
286
|
+
return self._buf.read(n) or b''
|
|
287
|
+
return self._raw.read1(n)
|
|
288
|
+
|
|
289
|
+
def read(self, /, n: int = -1) -> bytes:
|
|
290
|
+
if n < 0:
|
|
291
|
+
return self.readall()
|
|
292
|
+
while len(self._buf) < n:
|
|
293
|
+
if not (b := self._raw.read1(n)):
|
|
294
|
+
break
|
|
295
|
+
self._buf.feed(b)
|
|
296
|
+
return self._buf.read(n) or b''
|
|
297
|
+
|
|
298
|
+
def readall(self) -> bytes:
|
|
299
|
+
buf = io.BytesIO()
|
|
300
|
+
buf.write(self._buf.read() or b'')
|
|
301
|
+
while (b := self._raw.read1(self._chunk_size)):
|
|
302
|
+
buf.write(b)
|
|
303
|
+
return buf.getvalue()
|
|
304
|
+
|
|
305
|
+
def new_buffered_reader(
|
|
306
|
+
self,
|
|
307
|
+
raw: RawBytesReader,
|
|
308
|
+
*,
|
|
309
|
+
chunk_size: ta.Optional[int] = None,
|
|
310
|
+
) -> BufferedBytesReader:
|
|
311
|
+
return self._BufferedBytesReader(
|
|
312
|
+
raw,
|
|
313
|
+
self,
|
|
314
|
+
chunk_size=chunk_size,
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
@ta.final
|
|
318
|
+
class _AsyncBufferedBytesReader(AsyncBufferedBytesReader):
|
|
319
|
+
def __init__(
|
|
320
|
+
self,
|
|
321
|
+
raw: AsyncRawBytesReader,
|
|
322
|
+
buf: 'ReadableListBuffer',
|
|
323
|
+
*,
|
|
324
|
+
chunk_size: ta.Optional[int] = None,
|
|
325
|
+
) -> None:
|
|
326
|
+
self._raw = raw
|
|
327
|
+
self._buf = buf
|
|
328
|
+
self._chunk_size = chunk_size or ReadableListBuffer.DEFAULT_BUFFERED_READER_CHUNK_SIZE
|
|
329
|
+
|
|
330
|
+
async def read1(self, n: int = -1, /) -> bytes:
|
|
331
|
+
if n < 0:
|
|
332
|
+
n = self._chunk_size
|
|
333
|
+
if not n:
|
|
334
|
+
return b''
|
|
335
|
+
if 0 < n <= len(self._buf):
|
|
336
|
+
return self._buf.read(n) or b''
|
|
337
|
+
return await self._raw.read1(n)
|
|
338
|
+
|
|
339
|
+
async def read(self, /, n: int = -1) -> bytes:
|
|
340
|
+
if n < 0:
|
|
341
|
+
return await self.readall()
|
|
342
|
+
while len(self._buf) < n:
|
|
343
|
+
if not (b := await self._raw.read1(n)):
|
|
344
|
+
break
|
|
345
|
+
self._buf.feed(b)
|
|
346
|
+
return self._buf.read(n) or b''
|
|
347
|
+
|
|
348
|
+
async def readall(self) -> bytes:
|
|
349
|
+
buf = io.BytesIO()
|
|
350
|
+
buf.write(self._buf.read() or b'')
|
|
351
|
+
while b := await self._raw.read1(self._chunk_size):
|
|
352
|
+
buf.write(b)
|
|
353
|
+
return buf.getvalue()
|
|
354
|
+
|
|
355
|
+
def new_async_buffered_reader(
|
|
356
|
+
self,
|
|
357
|
+
raw: AsyncRawBytesReader,
|
|
358
|
+
*,
|
|
359
|
+
chunk_size: ta.Optional[int] = None,
|
|
360
|
+
) -> AsyncBufferedBytesReader:
|
|
361
|
+
return self._AsyncBufferedBytesReader(
|
|
362
|
+
raw,
|
|
363
|
+
self,
|
|
364
|
+
chunk_size=chunk_size,
|
|
365
|
+
)
|
|
366
|
+
|
|
249
367
|
|
|
250
368
|
##
|
|
251
369
|
|
omlish/io/readers.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# ruff: noqa: UP045
|
|
2
|
+
# @omlish-lite
|
|
3
|
+
import typing as ta
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
##
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class RawBytesReader(ta.Protocol):
|
|
10
|
+
def read1(self, n: int = -1, /) -> bytes: ...
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BufferedBytesReader(RawBytesReader, ta.Protocol):
|
|
14
|
+
def read(self, n: int = -1, /) -> bytes: ...
|
|
15
|
+
|
|
16
|
+
def readall(self) -> bytes: ...
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
#
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class AsyncRawBytesReader(ta.Protocol):
|
|
23
|
+
def read1(self, n: int = -1, /) -> ta.Awaitable[bytes]: ...
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AsyncBufferedBytesReader(AsyncRawBytesReader, ta.Protocol):
|
|
27
|
+
def read(self, n: int = -1, /) -> ta.Awaitable[bytes]: ...
|
|
28
|
+
|
|
29
|
+
def readall(self) -> ta.Awaitable[bytes]: ...
|
omlish/iterators/transforms.py
CHANGED
|
@@ -83,8 +83,8 @@ apply = Apply
|
|
|
83
83
|
|
|
84
84
|
@dc.dataclass(frozen=True)
|
|
85
85
|
class Flatten(Transform_[ta.Iterable[T], T]):
|
|
86
|
-
def __call__(self, it: ta.Iterable[ta.Iterable[T]]) -> ta.Iterable[
|
|
87
|
-
return itertools.chain.from_iterable(it)
|
|
86
|
+
def __call__(self, it: ta.Iterable[ta.Iterable[T]]) -> ta.Iterable[T]:
|
|
87
|
+
return itertools.chain.from_iterable(it)
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
flatten = Flatten
|