omlish 0.0.0.dev133__py3-none-any.whl → 0.0.0.dev177__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 +265 -7
- omlish/__about__.py +5 -3
- omlish/antlr/_runtime/__init__.py +0 -22
- omlish/antlr/_runtime/_all.py +24 -0
- omlish/antlr/_runtime/atn/ParserATNSimulator.py +1 -1
- omlish/antlr/_runtime/dfa/DFASerializer.py +1 -1
- omlish/antlr/_runtime/error/DiagnosticErrorListener.py +2 -1
- omlish/antlr/_runtime/xpath/XPath.py +7 -1
- omlish/antlr/_runtime/xpath/XPathLexer.py +1 -1
- omlish/antlr/delimit.py +106 -0
- omlish/antlr/dot.py +31 -0
- omlish/antlr/errors.py +11 -0
- omlish/antlr/input.py +96 -0
- omlish/antlr/parsing.py +19 -0
- omlish/antlr/runtime.py +102 -0
- omlish/antlr/utils.py +38 -0
- omlish/argparse/all.py +45 -0
- omlish/{argparse.py → argparse/cli.py} +112 -107
- omlish/asyncs/__init__.py +0 -35
- omlish/asyncs/all.py +35 -0
- omlish/asyncs/asyncio/all.py +7 -0
- omlish/asyncs/asyncio/channels.py +40 -0
- omlish/asyncs/asyncio/streams.py +45 -0
- omlish/asyncs/asyncio/subprocesses.py +238 -0
- omlish/asyncs/asyncio/timeouts.py +16 -0
- omlish/asyncs/bluelet/LICENSE +6 -0
- omlish/asyncs/bluelet/all.py +67 -0
- omlish/asyncs/bluelet/api.py +23 -0
- omlish/asyncs/bluelet/core.py +178 -0
- omlish/asyncs/bluelet/events.py +78 -0
- omlish/asyncs/bluelet/files.py +80 -0
- omlish/asyncs/bluelet/runner.py +416 -0
- omlish/asyncs/bluelet/sockets.py +214 -0
- omlish/bootstrap/sys.py +3 -3
- omlish/cached.py +2 -2
- omlish/check.py +49 -460
- omlish/codecs/__init__.py +72 -0
- omlish/codecs/base.py +106 -0
- omlish/codecs/bytes.py +119 -0
- omlish/codecs/chain.py +23 -0
- omlish/codecs/funcs.py +39 -0
- omlish/codecs/registry.py +139 -0
- omlish/codecs/standard.py +4 -0
- omlish/codecs/text.py +217 -0
- omlish/collections/cache/impl.py +50 -57
- omlish/collections/coerce.py +1 -0
- omlish/collections/mappings.py +1 -1
- omlish/configs/flattening.py +1 -1
- omlish/defs.py +1 -1
- omlish/diag/_pycharm/runhack.py +8 -2
- omlish/diag/procfs.py +8 -8
- omlish/docker/__init__.py +0 -36
- omlish/docker/all.py +31 -0
- omlish/docker/consts.py +4 -0
- omlish/{lite/docker.py → docker/detect.py} +18 -0
- omlish/docker/{helpers.py → timebomb.py} +0 -21
- omlish/formats/cbor.py +31 -0
- omlish/formats/cloudpickle.py +31 -0
- omlish/formats/codecs.py +93 -0
- omlish/formats/json/codecs.py +29 -0
- omlish/formats/json/delimted.py +4 -0
- omlish/formats/json/stream/errors.py +2 -0
- omlish/formats/json/stream/lex.py +12 -6
- omlish/formats/json/stream/parse.py +38 -22
- omlish/formats/json5.py +31 -0
- omlish/formats/pickle.py +31 -0
- omlish/formats/repr.py +25 -0
- omlish/formats/toml.py +17 -0
- omlish/formats/yaml.py +25 -0
- omlish/funcs/__init__.py +0 -0
- omlish/{genmachine.py → funcs/genmachine.py} +5 -4
- omlish/{matchfns.py → funcs/match.py} +1 -1
- omlish/funcs/pairs.py +215 -0
- omlish/http/__init__.py +0 -48
- omlish/http/all.py +48 -0
- omlish/http/coro/__init__.py +0 -0
- omlish/{lite/fdio/corohttp.py → http/coro/fdio.py} +21 -19
- omlish/{lite/http/coroserver.py → http/coro/server.py} +20 -21
- omlish/{lite/http → http}/handlers.py +3 -2
- omlish/{lite/http → http}/parsing.py +1 -0
- omlish/http/sessions.py +1 -1
- omlish/{lite/http → http}/versions.py +1 -0
- omlish/inject/managed.py +2 -2
- omlish/io/__init__.py +0 -3
- omlish/{lite/io.py → io/buffers.py} +8 -9
- omlish/io/compress/__init__.py +9 -0
- omlish/io/compress/abc.py +104 -0
- omlish/io/compress/adapters.py +148 -0
- omlish/io/compress/base.py +24 -0
- omlish/io/compress/brotli.py +47 -0
- omlish/io/compress/bz2.py +61 -0
- omlish/io/compress/codecs.py +78 -0
- omlish/io/compress/gzip.py +350 -0
- omlish/io/compress/lz4.py +91 -0
- omlish/io/compress/lzma.py +81 -0
- omlish/io/compress/snappy.py +34 -0
- omlish/io/compress/zlib.py +74 -0
- omlish/io/compress/zstd.py +44 -0
- omlish/io/fdio/__init__.py +1 -0
- omlish/{lite → io}/fdio/handlers.py +5 -5
- omlish/{lite → io}/fdio/kqueue.py +8 -8
- omlish/{lite → io}/fdio/manager.py +7 -7
- omlish/{lite → io}/fdio/pollers.py +13 -13
- omlish/io/generators/__init__.py +56 -0
- omlish/io/generators/consts.py +1 -0
- omlish/io/generators/direct.py +13 -0
- omlish/io/generators/readers.py +189 -0
- omlish/io/generators/stepped.py +191 -0
- omlish/io/pyio.py +5 -2
- omlish/iterators/__init__.py +24 -0
- omlish/iterators/iterators.py +132 -0
- omlish/iterators/recipes.py +18 -0
- omlish/iterators/tools.py +96 -0
- omlish/iterators/unique.py +67 -0
- omlish/lang/__init__.py +13 -1
- omlish/lang/functions.py +11 -2
- omlish/lang/generators.py +243 -0
- omlish/lang/iterables.py +46 -49
- omlish/lang/maybes.py +4 -4
- omlish/lite/cached.py +39 -6
- omlish/lite/check.py +438 -75
- omlish/lite/contextmanagers.py +17 -4
- omlish/lite/dataclasses.py +42 -0
- omlish/lite/inject.py +28 -45
- omlish/lite/logs.py +0 -270
- omlish/lite/marshal.py +309 -144
- omlish/lite/pycharm.py +47 -0
- omlish/lite/reflect.py +33 -0
- omlish/lite/resources.py +8 -0
- omlish/lite/runtime.py +4 -4
- omlish/lite/shlex.py +12 -0
- omlish/lite/socketserver.py +2 -2
- omlish/lite/strings.py +31 -0
- omlish/logs/__init__.py +0 -32
- omlish/logs/{_abc.py → abc.py} +0 -1
- omlish/logs/all.py +37 -0
- omlish/logs/{formatters.py → color.py} +1 -2
- omlish/logs/configs.py +7 -38
- omlish/logs/filters.py +10 -0
- omlish/logs/handlers.py +4 -1
- omlish/logs/json.py +56 -0
- omlish/logs/proxy.py +99 -0
- omlish/logs/standard.py +128 -0
- omlish/logs/utils.py +2 -2
- omlish/manifests/__init__.py +2 -0
- omlish/manifests/load.py +209 -0
- omlish/manifests/types.py +17 -0
- omlish/marshal/base.py +1 -1
- omlish/marshal/factories.py +1 -1
- omlish/marshal/forbidden.py +1 -1
- omlish/marshal/iterables.py +1 -1
- omlish/marshal/literals.py +50 -0
- omlish/marshal/mappings.py +1 -1
- omlish/marshal/maybes.py +1 -1
- omlish/marshal/standard.py +5 -1
- omlish/marshal/unions.py +1 -1
- omlish/os/__init__.py +0 -0
- omlish/os/atomics.py +205 -0
- omlish/os/deathsig.py +23 -0
- omlish/{os.py → os/files.py} +0 -9
- omlish/{lite → os}/journald.py +2 -1
- omlish/os/linux.py +484 -0
- omlish/os/paths.py +36 -0
- omlish/{lite → os}/pidfile.py +1 -0
- omlish/os/sizes.py +9 -0
- omlish/reflect/__init__.py +3 -0
- omlish/reflect/subst.py +2 -1
- omlish/reflect/types.py +126 -44
- omlish/secrets/pwhash.py +1 -1
- omlish/secrets/subprocesses.py +3 -1
- omlish/specs/jsonrpc/marshal.py +1 -1
- omlish/specs/openapi/marshal.py +1 -1
- omlish/sql/alchemy/asyncs.py +1 -1
- omlish/sql/queries/__init__.py +9 -1
- omlish/sql/queries/building.py +3 -0
- omlish/sql/queries/exprs.py +10 -27
- omlish/sql/queries/idents.py +48 -10
- omlish/sql/queries/names.py +80 -13
- omlish/sql/queries/params.py +64 -0
- omlish/sql/queries/rendering.py +1 -1
- omlish/subprocesses.py +340 -0
- omlish/term.py +29 -14
- omlish/testing/pytest/marks.py +2 -2
- omlish/testing/pytest/plugins/asyncs.py +6 -1
- omlish/testing/pytest/plugins/logging.py +1 -1
- omlish/testing/pytest/plugins/switches.py +1 -1
- {omlish-0.0.0.dev133.dist-info → omlish-0.0.0.dev177.dist-info}/METADATA +7 -5
- {omlish-0.0.0.dev133.dist-info → omlish-0.0.0.dev177.dist-info}/RECORD +200 -117
- omlish/fnpairs.py +0 -496
- omlish/formats/json/cli/__main__.py +0 -11
- omlish/formats/json/cli/cli.py +0 -298
- omlish/formats/json/cli/formats.py +0 -71
- omlish/formats/json/cli/io.py +0 -74
- omlish/formats/json/cli/parsing.py +0 -82
- omlish/formats/json/cli/processing.py +0 -48
- omlish/formats/json/cli/rendering.py +0 -92
- omlish/iterators.py +0 -300
- omlish/lite/subprocesses.py +0 -130
- /omlish/{formats/json/cli → argparse}/__init__.py +0 -0
- /omlish/{lite/fdio → asyncs/asyncio}/__init__.py +0 -0
- /omlish/asyncs/{asyncio.py → asyncio/asyncio.py} +0 -0
- /omlish/{lite/http → asyncs/bluelet}/__init__.py +0 -0
- /omlish/collections/{_abc.py → abc.py} +0 -0
- /omlish/{fnpipes.py → funcs/pipes.py} +0 -0
- /omlish/io/{_abc.py → abc.py} +0 -0
- /omlish/sql/{_abc.py → abc.py} +0 -0
- {omlish-0.0.0.dev133.dist-info → omlish-0.0.0.dev177.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev133.dist-info → omlish-0.0.0.dev177.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev133.dist-info → omlish-0.0.0.dev177.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev133.dist-info → omlish-0.0.0.dev177.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
import dataclasses as dc
|
2
|
+
import functools
|
3
|
+
import typing as ta
|
4
|
+
|
5
|
+
from ... import lang
|
6
|
+
from ..generators import BytesSteppedGenerator
|
7
|
+
from ..generators import BytesSteppedReaderGenerator
|
8
|
+
from .adapters import CompressorObjectIncrementalAdapter
|
9
|
+
from .adapters import DecompressorObjectIncrementalAdapter
|
10
|
+
from .base import Compression
|
11
|
+
from .base import IncrementalCompression
|
12
|
+
from .codecs import make_compression_codec
|
13
|
+
from .codecs import make_compression_lazy_loaded_codec
|
14
|
+
|
15
|
+
|
16
|
+
if ta.TYPE_CHECKING:
|
17
|
+
import zlib
|
18
|
+
else:
|
19
|
+
zlib = lang.proxy_import('zlib')
|
20
|
+
|
21
|
+
|
22
|
+
##
|
23
|
+
|
24
|
+
|
25
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
26
|
+
class ZlibCompression(Compression, IncrementalCompression):
|
27
|
+
level: int = 9
|
28
|
+
|
29
|
+
wbits: int | None = None
|
30
|
+
strategy: int | None = None
|
31
|
+
zdict: bytes | None = None
|
32
|
+
|
33
|
+
def compress(self, d: bytes) -> bytes:
|
34
|
+
return zlib.compress(
|
35
|
+
d,
|
36
|
+
self.level,
|
37
|
+
**(dict(wbits=self.wbits) if self.wbits is not None else {}),
|
38
|
+
)
|
39
|
+
|
40
|
+
def decompress(self, d: bytes) -> bytes:
|
41
|
+
return zlib.decompress(
|
42
|
+
d,
|
43
|
+
**(dict(wbits=self.wbits) if self.wbits is not None else {}),
|
44
|
+
)
|
45
|
+
|
46
|
+
def compress_incremental(self) -> BytesSteppedGenerator[None]:
|
47
|
+
return lang.nextgen(CompressorObjectIncrementalAdapter(
|
48
|
+
functools.partial(
|
49
|
+
zlib.compressobj, # type: ignore
|
50
|
+
self.level,
|
51
|
+
**(dict(wbits=self.wbits) if self.wbits is not None else {}), # type: ignore[arg-type]
|
52
|
+
**(dict(strategy=self.strategy) if self.strategy is not None else {}), # type: ignore[arg-type]
|
53
|
+
**(dict(zdict=self.zdict) if self.zdict is not None else {}), # type: ignore[arg-type]
|
54
|
+
),
|
55
|
+
)())
|
56
|
+
|
57
|
+
def decompress_incremental(self) -> BytesSteppedReaderGenerator[None]:
|
58
|
+
return DecompressorObjectIncrementalAdapter(
|
59
|
+
functools.partial( # type: ignore
|
60
|
+
zlib.decompressobj,
|
61
|
+
**(dict(wbits=self.wbits) if self.wbits is not None else {}), # type: ignore[arg-type]
|
62
|
+
**(dict(zdict=self.zdict) if self.zdict is not None else {}), # type: ignore[arg-type]
|
63
|
+
),
|
64
|
+
trailing_error=OSError,
|
65
|
+
)()
|
66
|
+
|
67
|
+
|
68
|
+
##
|
69
|
+
|
70
|
+
|
71
|
+
ZLIB_CODEC = make_compression_codec('zlib', ZlibCompression)
|
72
|
+
|
73
|
+
# @omlish-manifest
|
74
|
+
_ZLIB_LAZY_CODEC = make_compression_lazy_loaded_codec(__name__, 'ZLIB_CODEC', ZLIB_CODEC)
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import dataclasses as dc
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from ... import lang
|
5
|
+
from .base import Compression
|
6
|
+
from .codecs import make_compression_codec
|
7
|
+
from .codecs import make_compression_lazy_loaded_codec
|
8
|
+
|
9
|
+
|
10
|
+
if ta.TYPE_CHECKING:
|
11
|
+
import zstandard
|
12
|
+
else:
|
13
|
+
zstandard = lang.proxy_import('zstandard')
|
14
|
+
|
15
|
+
|
16
|
+
##
|
17
|
+
|
18
|
+
|
19
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
20
|
+
class ZstdCompression(Compression):
|
21
|
+
level: int | None = None
|
22
|
+
|
23
|
+
max_output_size: int = 0
|
24
|
+
|
25
|
+
def compress(self, d: bytes) -> bytes:
|
26
|
+
return zstandard.compress(
|
27
|
+
d,
|
28
|
+
**(dict(level=self.level) if self.level is not None else {}),
|
29
|
+
)
|
30
|
+
|
31
|
+
def decompress(self, d: bytes) -> bytes:
|
32
|
+
return zstandard.decompress(
|
33
|
+
d,
|
34
|
+
max_output_size=self.max_output_size,
|
35
|
+
)
|
36
|
+
|
37
|
+
|
38
|
+
##
|
39
|
+
|
40
|
+
|
41
|
+
ZSTD_CODEC = make_compression_codec('zstd', ZstdCompression)
|
42
|
+
|
43
|
+
# @omlish-manifest
|
44
|
+
_ZSTD_LAZY_CODEC = make_compression_lazy_loaded_codec(__name__, 'ZSTD_CODEC', ZSTD_CODEC)
|
@@ -0,0 +1 @@
|
|
1
|
+
# @omlish-lite
|
@@ -3,11 +3,11 @@ import abc
|
|
3
3
|
import socket
|
4
4
|
import typing as ta
|
5
5
|
|
6
|
-
from
|
7
|
-
from
|
6
|
+
from ...lite.check import check
|
7
|
+
from ...lite.socket import SocketAddress
|
8
8
|
|
9
9
|
|
10
|
-
class
|
10
|
+
class FdioHandler(abc.ABC):
|
11
11
|
@abc.abstractmethod
|
12
12
|
def fd(self) -> int:
|
13
13
|
raise NotImplementedError
|
@@ -43,7 +43,7 @@ class FdIoHandler(abc.ABC):
|
|
43
43
|
pass
|
44
44
|
|
45
45
|
|
46
|
-
class
|
46
|
+
class SocketFdioHandler(FdioHandler, abc.ABC):
|
47
47
|
def __init__(
|
48
48
|
self,
|
49
49
|
addr: SocketAddress,
|
@@ -55,7 +55,7 @@ class SocketFdIoHandler(FdIoHandler, abc.ABC):
|
|
55
55
|
self._sock: ta.Optional[socket.socket] = sock
|
56
56
|
|
57
57
|
def fd(self) -> int:
|
58
|
-
return
|
58
|
+
return check.not_none(self._sock).fileno()
|
59
59
|
|
60
60
|
@property
|
61
61
|
def closed(self) -> bool:
|
@@ -4,13 +4,13 @@ import select
|
|
4
4
|
import sys
|
5
5
|
import typing as ta
|
6
6
|
|
7
|
-
from .pollers import
|
7
|
+
from .pollers import FdioPoller
|
8
8
|
|
9
9
|
|
10
|
-
|
10
|
+
KqueueFdioPoller: ta.Optional[ta.Type[FdioPoller]]
|
11
11
|
if sys.platform == 'darwin' or sys.platform.startswith('freebsd'):
|
12
12
|
|
13
|
-
class
|
13
|
+
class _KqueueFdioPoller(FdioPoller):
|
14
14
|
DEFAULT_MAX_EVENTS = 1000
|
15
15
|
|
16
16
|
def __init__(
|
@@ -98,14 +98,14 @@ if sys.platform == 'darwin' or sys.platform.startswith('freebsd'):
|
|
98
98
|
|
99
99
|
#
|
100
100
|
|
101
|
-
def poll(self, timeout: ta.Optional[float]) ->
|
101
|
+
def poll(self, timeout: ta.Optional[float]) -> FdioPoller.PollResult:
|
102
102
|
kq = self._get_kqueue()
|
103
103
|
try:
|
104
104
|
kes = kq.control(None, self._max_events, timeout)
|
105
105
|
|
106
106
|
except OSError as exc:
|
107
107
|
if exc.errno == errno.EINTR:
|
108
|
-
return
|
108
|
+
return FdioPoller.PollResult(msg='EINTR encountered in poll', exc=exc)
|
109
109
|
else:
|
110
110
|
raise
|
111
111
|
|
@@ -117,8 +117,8 @@ if sys.platform == 'darwin' or sys.platform.startswith('freebsd'):
|
|
117
117
|
if ke.filter == select.KQ_FILTER_WRITE:
|
118
118
|
w.append(ke.ident)
|
119
119
|
|
120
|
-
return
|
120
|
+
return FdioPoller.PollResult(r, w)
|
121
121
|
|
122
|
-
|
122
|
+
KqueueFdioPoller = _KqueueFdioPoller
|
123
123
|
else:
|
124
|
-
|
124
|
+
KqueueFdioPoller = None
|
@@ -1,27 +1,27 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
2
|
import typing as ta
|
3
3
|
|
4
|
-
from .handlers import
|
5
|
-
from .pollers import
|
4
|
+
from .handlers import FdioHandler
|
5
|
+
from .pollers import FdioPoller
|
6
6
|
|
7
7
|
|
8
|
-
class
|
8
|
+
class FdioManager:
|
9
9
|
def __init__(
|
10
10
|
self,
|
11
|
-
poller:
|
11
|
+
poller: FdioPoller,
|
12
12
|
) -> None:
|
13
13
|
super().__init__()
|
14
14
|
|
15
15
|
self._poller = poller
|
16
16
|
|
17
|
-
self._handlers: ta.Dict[int,
|
17
|
+
self._handlers: ta.Dict[int, FdioHandler] = {} # Preserves insertion order
|
18
18
|
|
19
|
-
def register(self, h:
|
19
|
+
def register(self, h: FdioHandler) -> None:
|
20
20
|
if (hid := id(h)) in self._handlers:
|
21
21
|
raise KeyError(h)
|
22
22
|
self._handlers[hid] = h
|
23
23
|
|
24
|
-
def unregister(self, h:
|
24
|
+
def unregister(self, h: FdioHandler) -> None:
|
25
25
|
del self._handlers[id(h)]
|
26
26
|
|
27
27
|
def poll(self, *, timeout: float = 1.) -> None:
|
@@ -9,7 +9,7 @@ import typing as ta
|
|
9
9
|
##
|
10
10
|
|
11
11
|
|
12
|
-
class
|
12
|
+
class FdioPoller(abc.ABC):
|
13
13
|
def __init__(self) -> None:
|
14
14
|
super().__init__()
|
15
15
|
|
@@ -120,8 +120,8 @@ class FdIoPoller(abc.ABC):
|
|
120
120
|
##
|
121
121
|
|
122
122
|
|
123
|
-
class
|
124
|
-
def poll(self, timeout: ta.Optional[float]) ->
|
123
|
+
class SelectFdioPoller(FdioPoller):
|
124
|
+
def poll(self, timeout: ta.Optional[float]) -> FdioPoller.PollResult:
|
125
125
|
try:
|
126
126
|
r, w, x = select.select(
|
127
127
|
self._readable,
|
@@ -132,22 +132,22 @@ class SelectFdIoPoller(FdIoPoller):
|
|
132
132
|
|
133
133
|
except OSError as exc:
|
134
134
|
if exc.errno == errno.EINTR:
|
135
|
-
return
|
135
|
+
return FdioPoller.PollResult(msg='EINTR encountered in poll', exc=exc)
|
136
136
|
elif exc.errno == errno.EBADF:
|
137
|
-
return
|
137
|
+
return FdioPoller.PollResult(msg='EBADF encountered in poll', exc=exc)
|
138
138
|
else:
|
139
139
|
raise
|
140
140
|
|
141
|
-
return
|
141
|
+
return FdioPoller.PollResult(r, w)
|
142
142
|
|
143
143
|
|
144
144
|
##
|
145
145
|
|
146
146
|
|
147
|
-
|
147
|
+
PollFdioPoller: ta.Optional[ta.Type[FdioPoller]]
|
148
148
|
if hasattr(select, 'poll'):
|
149
149
|
|
150
|
-
class
|
150
|
+
class _PollFdioPoller(FdioPoller):
|
151
151
|
def __init__(self) -> None:
|
152
152
|
super().__init__()
|
153
153
|
|
@@ -180,14 +180,14 @@ if hasattr(select, 'poll'):
|
|
180
180
|
|
181
181
|
#
|
182
182
|
|
183
|
-
def poll(self, timeout: ta.Optional[float]) ->
|
183
|
+
def poll(self, timeout: ta.Optional[float]) -> FdioPoller.PollResult:
|
184
184
|
polled: ta.List[ta.Tuple[int, int]]
|
185
185
|
try:
|
186
186
|
polled = self._poller.poll(timeout * 1000 if timeout is not None else None)
|
187
187
|
|
188
188
|
except OSError as exc:
|
189
189
|
if exc.errno == errno.EINTR:
|
190
|
-
return
|
190
|
+
return FdioPoller.PollResult(msg='EINTR encountered in poll', exc=exc)
|
191
191
|
else:
|
192
192
|
raise
|
193
193
|
|
@@ -205,8 +205,8 @@ if hasattr(select, 'poll'):
|
|
205
205
|
r.append(fd)
|
206
206
|
if mask & self._WRITE:
|
207
207
|
w.append(fd)
|
208
|
-
return
|
208
|
+
return FdioPoller.PollResult(r, w, inv=inv)
|
209
209
|
|
210
|
-
|
210
|
+
PollFdioPoller = _PollFdioPoller
|
211
211
|
else:
|
212
|
-
|
212
|
+
PollFdioPoller = None
|
@@ -0,0 +1,56 @@
|
|
1
|
+
from .consts import ( # noqa
|
2
|
+
DEFAULT_BUFFER_SIZE,
|
3
|
+
)
|
4
|
+
|
5
|
+
from .direct import ( # noqa
|
6
|
+
DirectGenerator,
|
7
|
+
|
8
|
+
BytesDirectGenerator,
|
9
|
+
StrDirectGenerator,
|
10
|
+
)
|
11
|
+
|
12
|
+
from .readers import ( # noqa
|
13
|
+
ReaderGenerator,
|
14
|
+
BytesReaderGenerator,
|
15
|
+
StrReaderGenerator,
|
16
|
+
|
17
|
+
ExactReaderGenerator,
|
18
|
+
BytesExactReaderGenerator,
|
19
|
+
StrExactReaderGenerator,
|
20
|
+
|
21
|
+
GeneratorReader,
|
22
|
+
|
23
|
+
PrependableGeneratorReader,
|
24
|
+
PrependableBytesGeneratorReader,
|
25
|
+
PrependableStrGeneratorReader,
|
26
|
+
prependable_bytes_generator_reader,
|
27
|
+
prependable_str_generator_reader,
|
28
|
+
|
29
|
+
BufferedGeneratorReader,
|
30
|
+
BufferedBytesGeneratorReader,
|
31
|
+
BufferedStrGeneratorReader,
|
32
|
+
buffered_bytes_generator_reader,
|
33
|
+
buffered_str_generator_reader,
|
34
|
+
)
|
35
|
+
|
36
|
+
from .stepped import ( # noqa
|
37
|
+
SteppedGenerator,
|
38
|
+
BytesSteppedGenerator,
|
39
|
+
StrSteppedGenerator,
|
40
|
+
BytesToStrSteppedGenerator,
|
41
|
+
StrToBytesSteppedGenerator,
|
42
|
+
|
43
|
+
SteppedReaderGenerator,
|
44
|
+
BytesSteppedReaderGenerator,
|
45
|
+
StrSteppedReaderGenerator,
|
46
|
+
|
47
|
+
flatmap_stepped_generator,
|
48
|
+
|
49
|
+
joined_bytes_stepped_generator,
|
50
|
+
joined_str_stepped_generator,
|
51
|
+
|
52
|
+
read_into_bytes_stepped_generator,
|
53
|
+
read_into_str_stepped_generator,
|
54
|
+
|
55
|
+
buffer_bytes_stepped_reader_generator,
|
56
|
+
)
|
@@ -0,0 +1 @@
|
|
1
|
+
DEFAULT_BUFFER_SIZE = 4 * 0x1000
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import typing as ta
|
2
|
+
|
3
|
+
|
4
|
+
O = ta.TypeVar('O')
|
5
|
+
I = ta.TypeVar('I')
|
6
|
+
R = ta.TypeVar('R')
|
7
|
+
|
8
|
+
|
9
|
+
# Direct generators yield outputs 1:1 with inputs.
|
10
|
+
DirectGenerator: ta.TypeAlias = ta.Generator[O, I, R]
|
11
|
+
|
12
|
+
BytesDirectGenerator: ta.TypeAlias = DirectGenerator[bytes, bytes, R]
|
13
|
+
StrDirectGenerator: ta.TypeAlias = DirectGenerator[str, str, R]
|
@@ -0,0 +1,189 @@
|
|
1
|
+
"""
|
2
|
+
TODO:
|
3
|
+
- BufferedBytesGeneratorReader
|
4
|
+
- docstrings
|
5
|
+
- memoryviews
|
6
|
+
"""
|
7
|
+
import abc
|
8
|
+
import typing as ta
|
9
|
+
|
10
|
+
from ... import check
|
11
|
+
from .consts import DEFAULT_BUFFER_SIZE
|
12
|
+
|
13
|
+
|
14
|
+
T = ta.TypeVar('T')
|
15
|
+
|
16
|
+
O = ta.TypeVar('O')
|
17
|
+
I = ta.TypeVar('I')
|
18
|
+
R = ta.TypeVar('R')
|
19
|
+
|
20
|
+
AnyT = ta.TypeVar('AnyT', bound=ta.Any)
|
21
|
+
|
22
|
+
|
23
|
+
# Reader generators yield ints of amounts of data needed, or None for needing any amount of data.
|
24
|
+
ReaderGenerator: ta.TypeAlias = ta.Generator[int | None, I, R]
|
25
|
+
|
26
|
+
BytesReaderGenerator: ta.TypeAlias = ReaderGenerator[bytes, R]
|
27
|
+
StrReaderGenerator: ta.TypeAlias = ReaderGenerator[str, R]
|
28
|
+
|
29
|
+
|
30
|
+
# Exact reader generators always specify read sizes.
|
31
|
+
ExactReaderGenerator: ta.TypeAlias = ta.Generator[int, I, R]
|
32
|
+
|
33
|
+
BytesExactReaderGenerator: ta.TypeAlias = ExactReaderGenerator[bytes, R]
|
34
|
+
StrExactReaderGenerator: ta.TypeAlias = ExactReaderGenerator[str, R]
|
35
|
+
|
36
|
+
|
37
|
+
##
|
38
|
+
|
39
|
+
|
40
|
+
class _BytesJoiner:
|
41
|
+
def _join(self, lst: list[bytes]) -> bytes:
|
42
|
+
return b''.join(lst)
|
43
|
+
|
44
|
+
|
45
|
+
class _StrJoiner:
|
46
|
+
def _join(self, lst: list[str]) -> str:
|
47
|
+
return ''.join(lst)
|
48
|
+
|
49
|
+
|
50
|
+
##
|
51
|
+
|
52
|
+
|
53
|
+
class GeneratorReader(abc.ABC, ta.Generic[T]):
|
54
|
+
@abc.abstractmethod
|
55
|
+
def read(self, sz: int | None) -> ReaderGenerator[T, T]:
|
56
|
+
raise NotImplementedError
|
57
|
+
|
58
|
+
def read_exact(self, sz: int) -> ReaderGenerator[T, T]:
|
59
|
+
d: ta.Any = yield from self.read(sz)
|
60
|
+
if len(d) != sz:
|
61
|
+
raise EOFError(f'GeneratorReader got {len(d)}, expected {sz}')
|
62
|
+
return d
|
63
|
+
|
64
|
+
|
65
|
+
##
|
66
|
+
|
67
|
+
|
68
|
+
class PrependableGeneratorReader(GeneratorReader[AnyT]):
|
69
|
+
def __init__(self) -> None:
|
70
|
+
super().__init__()
|
71
|
+
|
72
|
+
self._queue: list[tuple[AnyT, int]] = []
|
73
|
+
|
74
|
+
@abc.abstractmethod
|
75
|
+
def _join(self, lst: list[AnyT]) -> AnyT:
|
76
|
+
raise NotImplementedError
|
77
|
+
|
78
|
+
def read(self, sz: int | None) -> ReaderGenerator[AnyT, AnyT]:
|
79
|
+
if not self._queue:
|
80
|
+
d: AnyT = check.not_none((yield sz))
|
81
|
+
return d
|
82
|
+
|
83
|
+
if sz is None:
|
84
|
+
return self._queue.pop(0)[0]
|
85
|
+
|
86
|
+
lst: list[AnyT] = []
|
87
|
+
rem = sz
|
88
|
+
while rem > 0 and self._queue:
|
89
|
+
c, p = self._queue[0]
|
90
|
+
|
91
|
+
if len(c) - p > rem:
|
92
|
+
lst.append(c[p:p + rem])
|
93
|
+
self._queue[0] = (c, p + rem)
|
94
|
+
return self._join(lst)
|
95
|
+
|
96
|
+
lst.append(c[p:])
|
97
|
+
rem -= len(c) - p
|
98
|
+
self._queue.pop(0)
|
99
|
+
|
100
|
+
if rem:
|
101
|
+
d = check.not_none((yield rem))
|
102
|
+
if d:
|
103
|
+
lst.append(d) # type: ignore[unreachable]
|
104
|
+
|
105
|
+
if len(lst) == 1:
|
106
|
+
return lst[0]
|
107
|
+
else:
|
108
|
+
return self._join(lst)
|
109
|
+
|
110
|
+
def prepend(self, d: AnyT, p: int | None = None) -> None:
|
111
|
+
if d:
|
112
|
+
self._queue.insert(0, (d, p or 0))
|
113
|
+
|
114
|
+
|
115
|
+
class PrependableBytesGeneratorReader(
|
116
|
+
_BytesJoiner,
|
117
|
+
PrependableGeneratorReader[bytes],
|
118
|
+
):
|
119
|
+
pass
|
120
|
+
|
121
|
+
|
122
|
+
class PrependableStrGeneratorReader(
|
123
|
+
_StrJoiner,
|
124
|
+
PrependableGeneratorReader[str],
|
125
|
+
):
|
126
|
+
pass
|
127
|
+
|
128
|
+
|
129
|
+
prependable_bytes_generator_reader = PrependableBytesGeneratorReader
|
130
|
+
prependable_str_generator_reader = PrependableStrGeneratorReader
|
131
|
+
|
132
|
+
|
133
|
+
##
|
134
|
+
|
135
|
+
|
136
|
+
class BufferedGeneratorReader(PrependableGeneratorReader[AnyT], abc.ABC):
|
137
|
+
def __init__(
|
138
|
+
self,
|
139
|
+
buffer_size: int = DEFAULT_BUFFER_SIZE,
|
140
|
+
) -> None:
|
141
|
+
check.arg(buffer_size > 0)
|
142
|
+
|
143
|
+
super().__init__()
|
144
|
+
|
145
|
+
self._buffer_size = buffer_size
|
146
|
+
|
147
|
+
def read(self, sz: int | None) -> ReaderGenerator[AnyT, AnyT]:
|
148
|
+
g = super().read(sz)
|
149
|
+
i: ta.Any = None
|
150
|
+
while True:
|
151
|
+
try:
|
152
|
+
q = g.send(i)
|
153
|
+
except StopIteration as e:
|
154
|
+
return e.value
|
155
|
+
|
156
|
+
check.state(not self._queue)
|
157
|
+
|
158
|
+
if q is None:
|
159
|
+
i = check.not_none((yield None))
|
160
|
+
continue
|
161
|
+
|
162
|
+
r = max(q, self._buffer_size)
|
163
|
+
d: AnyT = check.not_none((yield r))
|
164
|
+
if len(d) < q:
|
165
|
+
i = d
|
166
|
+
continue
|
167
|
+
|
168
|
+
i = d[:q]
|
169
|
+
self.prepend(d, q)
|
170
|
+
|
171
|
+
|
172
|
+
class BufferedBytesGeneratorReader(
|
173
|
+
_BytesJoiner,
|
174
|
+
BufferedGeneratorReader[bytes],
|
175
|
+
PrependableGeneratorReader[bytes],
|
176
|
+
):
|
177
|
+
pass
|
178
|
+
|
179
|
+
|
180
|
+
class BufferedStrGeneratorReader(
|
181
|
+
_StrJoiner,
|
182
|
+
BufferedGeneratorReader[str],
|
183
|
+
PrependableGeneratorReader[str],
|
184
|
+
):
|
185
|
+
pass
|
186
|
+
|
187
|
+
|
188
|
+
buffered_bytes_generator_reader = BufferedBytesGeneratorReader
|
189
|
+
buffered_str_generator_reader = BufferedStrGeneratorReader
|