omlish 0.0.0.dev132__py3-none-any.whl → 0.0.0.dev177__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- omlish/.manifests.json +265 -7
- omlish/__about__.py +7 -5
- 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.dev132.dist-info → omlish-0.0.0.dev177.dist-info}/METADATA +13 -11
- {omlish-0.0.0.dev132.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.dev132.dist-info → omlish-0.0.0.dev177.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev132.dist-info → omlish-0.0.0.dev177.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev132.dist-info → omlish-0.0.0.dev177.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev132.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
|