omlish 0.0.0.dev194__py3-none-any.whl → 0.0.0.dev196__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 +3 -3
- omlish/asyncs/bluelet/runner.py +1 -1
- omlish/codecs/base.py +5 -5
- omlish/codecs/text.py +1 -2
- omlish/io/compress/adapters.py +4 -4
- omlish/io/compress/base.py +4 -4
- omlish/io/compress/bz2.py +4 -4
- omlish/io/compress/codecs.py +2 -2
- omlish/io/compress/gzip.py +10 -10
- omlish/io/compress/lz4.py +5 -5
- omlish/io/compress/lzma.py +4 -4
- omlish/io/compress/zlib.py +4 -4
- omlish/io/coro/__init__.py +56 -0
- omlish/io/coro/direct.py +13 -0
- omlish/io/{generators → coro}/readers.py +31 -31
- omlish/io/{generators → coro}/stepped.py +28 -28
- omlish/multiprocessing/__init__.py +32 -0
- omlish/{multiprocessing.py → multiprocessing/death.py} +3 -88
- omlish/multiprocessing/proxies.py +30 -0
- omlish/multiprocessing/spawn.py +59 -0
- omlish/os/atomics.py +2 -2
- omlish/outcome.py +250 -0
- omlish/sockets/server.py +1 -2
- omlish/term/vt100/terminal.py +1 -1
- omlish/testing/pytest/plugins/asyncs/__init__.py +1 -0
- omlish/testing/pytest/plugins/asyncs/backends/__init__.py +16 -0
- omlish/testing/pytest/plugins/asyncs/backends/asyncio.py +35 -0
- omlish/testing/pytest/plugins/asyncs/backends/base.py +30 -0
- omlish/testing/pytest/plugins/asyncs/backends/trio.py +91 -0
- omlish/testing/pytest/plugins/asyncs/backends/trio_asyncio.py +89 -0
- omlish/testing/pytest/plugins/asyncs/consts.py +3 -0
- omlish/testing/pytest/plugins/asyncs/fixtures.py +273 -0
- omlish/testing/pytest/plugins/asyncs/plugin.py +182 -0
- omlish/testing/pytest/plugins/asyncs/utils.py +10 -0
- omlish/text/indent.py +1 -1
- omlish/text/minja.py +2 -2
- {omlish-0.0.0.dev194.dist-info → omlish-0.0.0.dev196.dist-info}/METADATA +5 -5
- {omlish-0.0.0.dev194.dist-info → omlish-0.0.0.dev196.dist-info}/RECORD +43 -30
- {omlish-0.0.0.dev194.dist-info → omlish-0.0.0.dev196.dist-info}/WHEEL +1 -1
- omlish/io/generators/__init__.py +0 -56
- omlish/io/generators/direct.py +0 -13
- omlish/testing/pytest/plugins/asyncs.py +0 -162
- /omlish/io/{generators → coro}/consts.py +0 -0
- {omlish-0.0.0.dev194.dist-info → omlish-0.0.0.dev196.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev194.dist-info → omlish-0.0.0.dev196.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev194.dist-info → omlish-0.0.0.dev196.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.dev196'
|
2
|
+
__revision__ = 'c5eb72314e32c8694da771f815a207214d553c90'
|
3
3
|
|
4
4
|
|
5
5
|
#
|
@@ -32,7 +32,7 @@ class Project(ProjectBase):
|
|
32
32
|
|
33
33
|
optional_dependencies = {
|
34
34
|
'async': [
|
35
|
-
'anyio ~= 4.
|
35
|
+
'anyio ~= 4.8',
|
36
36
|
'sniffio ~= 1.3',
|
37
37
|
|
38
38
|
'greenlet ~= 3.1',
|
omlish/asyncs/bluelet/runner.py
CHANGED
omlish/codecs/base.py
CHANGED
@@ -7,11 +7,11 @@ TODO:
|
|
7
7
|
import abc
|
8
8
|
import typing as ta
|
9
9
|
|
10
|
-
from
|
11
|
-
from
|
12
|
-
from
|
13
|
-
from
|
14
|
-
from
|
10
|
+
from .. import check
|
11
|
+
from .. import dataclasses as dc
|
12
|
+
from .. import lang
|
13
|
+
from .. import reflect as rfl
|
14
|
+
from ..funcs import pairs as fps
|
15
15
|
|
16
16
|
|
17
17
|
I = ta.TypeVar('I')
|
omlish/codecs/text.py
CHANGED
omlish/io/compress/adapters.py
CHANGED
@@ -37,8 +37,8 @@
|
|
37
37
|
import typing as ta
|
38
38
|
|
39
39
|
from ... import check
|
40
|
-
from ..
|
41
|
-
from ..
|
40
|
+
from ..coro import BytesSteppedCoro
|
41
|
+
from ..coro import BytesSteppedReaderCoro
|
42
42
|
from .abc import CompressorObject
|
43
43
|
from .abc import NeedsInputDecompressorObject
|
44
44
|
from .abc import UnconsumedTailDecompressorObject
|
@@ -56,7 +56,7 @@ class CompressorObjectIncrementalAdapter:
|
|
56
56
|
|
57
57
|
self._factory = factory
|
58
58
|
|
59
|
-
def __call__(self) ->
|
59
|
+
def __call__(self) -> BytesSteppedCoro:
|
60
60
|
compressor = self._factory()
|
61
61
|
|
62
62
|
while True:
|
@@ -89,7 +89,7 @@ class DecompressorObjectIncrementalAdapter:
|
|
89
89
|
self._factory = factory
|
90
90
|
self._trailing_error = trailing_error
|
91
91
|
|
92
|
-
def __call__(self) ->
|
92
|
+
def __call__(self) -> BytesSteppedReaderCoro:
|
93
93
|
pos = 0
|
94
94
|
|
95
95
|
data = None # Default if EOF is encountered
|
omlish/io/compress/base.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import abc
|
2
2
|
|
3
|
-
from ..
|
4
|
-
from ..
|
3
|
+
from ..coro import BytesSteppedCoro
|
4
|
+
from ..coro import BytesSteppedReaderCoro
|
5
5
|
|
6
6
|
|
7
7
|
class Compression(abc.ABC):
|
@@ -16,9 +16,9 @@ class Compression(abc.ABC):
|
|
16
16
|
|
17
17
|
class IncrementalCompression(abc.ABC):
|
18
18
|
@abc.abstractmethod
|
19
|
-
def compress_incremental(self) ->
|
19
|
+
def compress_incremental(self) -> BytesSteppedCoro[None]:
|
20
20
|
raise NotImplementedError
|
21
21
|
|
22
22
|
@abc.abstractmethod
|
23
|
-
def decompress_incremental(self) ->
|
23
|
+
def decompress_incremental(self) -> BytesSteppedReaderCoro[None]:
|
24
24
|
raise NotImplementedError
|
omlish/io/compress/bz2.py
CHANGED
@@ -3,8 +3,8 @@ import functools
|
|
3
3
|
import typing as ta
|
4
4
|
|
5
5
|
from ... import lang
|
6
|
-
from ..
|
7
|
-
from ..
|
6
|
+
from ..coro import BytesSteppedCoro
|
7
|
+
from ..coro import BytesSteppedReaderCoro
|
8
8
|
from .adapters import CompressorObjectIncrementalAdapter
|
9
9
|
from .adapters import DecompressorObjectIncrementalAdapter
|
10
10
|
from .base import Compression
|
@@ -37,7 +37,7 @@ class Bz2Compression(Compression, IncrementalCompression):
|
|
37
37
|
d,
|
38
38
|
)
|
39
39
|
|
40
|
-
def compress_incremental(self) ->
|
40
|
+
def compress_incremental(self) -> BytesSteppedCoro[None]:
|
41
41
|
return lang.nextgen(CompressorObjectIncrementalAdapter(
|
42
42
|
functools.partial(
|
43
43
|
bz2.BZ2Compressor, # type: ignore
|
@@ -45,7 +45,7 @@ class Bz2Compression(Compression, IncrementalCompression):
|
|
45
45
|
),
|
46
46
|
)())
|
47
47
|
|
48
|
-
def decompress_incremental(self) ->
|
48
|
+
def decompress_incremental(self) -> BytesSteppedReaderCoro[None]:
|
49
49
|
return DecompressorObjectIncrementalAdapter(
|
50
50
|
bz2.BZ2Decompressor, # type: ignore
|
51
51
|
trailing_error=OSError,
|
omlish/io/compress/codecs.py
CHANGED
@@ -2,7 +2,7 @@ import dataclasses as dc
|
|
2
2
|
import typing as ta
|
3
3
|
|
4
4
|
from ... import codecs
|
5
|
-
from ..
|
5
|
+
from ..coro import buffer_bytes_stepped_reader_coro
|
6
6
|
from .base import Compression
|
7
7
|
from .base import IncrementalCompression
|
8
8
|
|
@@ -32,7 +32,7 @@ class CompressionIncrementalCodec(codecs.IncrementalCodec[bytes, bytes]):
|
|
32
32
|
return self.compression.compress_incremental()
|
33
33
|
|
34
34
|
def decode_incremental(self) -> ta.Generator[bytes | None, bytes, None]:
|
35
|
-
return
|
35
|
+
return buffer_bytes_stepped_reader_coro(self.compression.decompress_incremental())
|
36
36
|
|
37
37
|
|
38
38
|
##
|
omlish/io/compress/gzip.py
CHANGED
@@ -43,9 +43,9 @@ import typing as ta
|
|
43
43
|
from ... import cached
|
44
44
|
from ... import check
|
45
45
|
from ... import lang
|
46
|
-
from ..
|
47
|
-
from ..
|
48
|
-
from ..
|
46
|
+
from ..coro import BytesSteppedCoro
|
47
|
+
from ..coro import BytesSteppedReaderCoro
|
48
|
+
from ..coro.readers import PrependableBytesCoroReader
|
49
49
|
from .base import Compression
|
50
50
|
from .base import IncrementalCompression
|
51
51
|
from .codecs import make_compression_codec
|
@@ -86,13 +86,13 @@ class GzipCompression(Compression, IncrementalCompression):
|
|
86
86
|
d,
|
87
87
|
)
|
88
88
|
|
89
|
-
def compress_incremental(self) ->
|
89
|
+
def compress_incremental(self) -> BytesSteppedCoro[None]:
|
90
90
|
return lang.nextgen(IncrementalGzipCompressor(
|
91
91
|
level=self.level,
|
92
92
|
mtime=self.mtime,
|
93
93
|
)())
|
94
94
|
|
95
|
-
def decompress_incremental(self) ->
|
95
|
+
def decompress_incremental(self) -> BytesSteppedReaderCoro[None]:
|
96
96
|
return IncrementalGzipDecompressor()()
|
97
97
|
|
98
98
|
|
@@ -159,7 +159,7 @@ class IncrementalGzipCompressor:
|
|
159
159
|
if fname:
|
160
160
|
check.none((yield fname + b'\000'))
|
161
161
|
|
162
|
-
def __call__(self) ->
|
162
|
+
def __call__(self) -> BytesSteppedCoro:
|
163
163
|
crc = _zero_crc()
|
164
164
|
size = 0
|
165
165
|
offset = 0 # Current file offset for seek(), tell(), etc
|
@@ -222,7 +222,7 @@ class IncrementalGzipDecompressor:
|
|
222
222
|
|
223
223
|
def _read_gzip_header(
|
224
224
|
self,
|
225
|
-
rdr:
|
225
|
+
rdr: PrependableBytesCoroReader,
|
226
226
|
) -> ta.Generator[int | None, bytes, int | None]:
|
227
227
|
magic = yield from rdr.read(2)
|
228
228
|
if magic == b'':
|
@@ -264,7 +264,7 @@ class IncrementalGzipDecompressor:
|
|
264
264
|
|
265
265
|
def _read_eof(
|
266
266
|
self,
|
267
|
-
rdr:
|
267
|
+
rdr: PrependableBytesCoroReader,
|
268
268
|
crc: int,
|
269
269
|
stream_size: int,
|
270
270
|
) -> ta.Generator[int | None, bytes, None]:
|
@@ -286,8 +286,8 @@ class IncrementalGzipDecompressor:
|
|
286
286
|
if c:
|
287
287
|
rdr.prepend(c)
|
288
288
|
|
289
|
-
def __call__(self) ->
|
290
|
-
rdr =
|
289
|
+
def __call__(self) -> BytesSteppedReaderCoro:
|
290
|
+
rdr = PrependableBytesCoroReader()
|
291
291
|
|
292
292
|
pos = 0 # Current offset in decompressed stream
|
293
293
|
|
omlish/io/compress/lz4.py
CHANGED
@@ -3,7 +3,7 @@ import typing as ta
|
|
3
3
|
|
4
4
|
from ... import check
|
5
5
|
from ... import lang
|
6
|
-
from ..
|
6
|
+
from ..coro import BytesSteppedCoro
|
7
7
|
from .base import Compression
|
8
8
|
from .base import IncrementalCompression
|
9
9
|
from .codecs import make_compression_codec
|
@@ -46,7 +46,7 @@ class Lz4Compression(Compression, IncrementalCompression):
|
|
46
46
|
)
|
47
47
|
|
48
48
|
@lang.autostart
|
49
|
-
def compress_incremental(self) ->
|
49
|
+
def compress_incremental(self) -> BytesSteppedCoro[None]:
|
50
50
|
with lz4_frame.LZ4FrameCompressor(
|
51
51
|
compression_level=self.level,
|
52
52
|
block_size=self.block_size,
|
@@ -69,9 +69,9 @@ class Lz4Compression(Compression, IncrementalCompression):
|
|
69
69
|
yield o
|
70
70
|
|
71
71
|
@lang.autostart
|
72
|
-
def decompress_incremental(self) ->
|
73
|
-
# lz4 lib does internal buffering so this is simply a
|
74
|
-
#
|
72
|
+
def decompress_incremental(self) -> BytesSteppedCoro[None]:
|
73
|
+
# lz4 lib does internal buffering so this is simply a BytesSteppedCoro not a BytesSteppedReaderCoro as it
|
74
|
+
# only yields None, accepting any number of bytes at a time.
|
75
75
|
with lz4_frame.LZ4FrameDecompressor() as decompressor:
|
76
76
|
while True:
|
77
77
|
i = check.isinstance((yield None), bytes)
|
omlish/io/compress/lzma.py
CHANGED
@@ -3,8 +3,8 @@ import functools
|
|
3
3
|
import typing as ta
|
4
4
|
|
5
5
|
from ... import lang
|
6
|
-
from ..
|
7
|
-
from ..
|
6
|
+
from ..coro import BytesSteppedCoro
|
7
|
+
from ..coro import BytesSteppedReaderCoro
|
8
8
|
from .adapters import CompressorObjectIncrementalAdapter
|
9
9
|
from .adapters import DecompressorObjectIncrementalAdapter
|
10
10
|
from .base import Compression
|
@@ -49,7 +49,7 @@ class LzmaCompression(Compression, IncrementalCompression):
|
|
49
49
|
filters=self.filters, # type: ignore[arg-type]
|
50
50
|
)
|
51
51
|
|
52
|
-
def compress_incremental(self) ->
|
52
|
+
def compress_incremental(self) -> BytesSteppedCoro[None]:
|
53
53
|
return lang.nextgen(CompressorObjectIncrementalAdapter(
|
54
54
|
functools.partial( # type: ignore
|
55
55
|
lzma.LZMACompressor,
|
@@ -60,7 +60,7 @@ class LzmaCompression(Compression, IncrementalCompression):
|
|
60
60
|
),
|
61
61
|
)())
|
62
62
|
|
63
|
-
def decompress_incremental(self) ->
|
63
|
+
def decompress_incremental(self) -> BytesSteppedReaderCoro[None]:
|
64
64
|
return DecompressorObjectIncrementalAdapter(
|
65
65
|
functools.partial( # type: ignore
|
66
66
|
lzma.LZMADecompressor,
|
omlish/io/compress/zlib.py
CHANGED
@@ -3,8 +3,8 @@ import functools
|
|
3
3
|
import typing as ta
|
4
4
|
|
5
5
|
from ... import lang
|
6
|
-
from ..
|
7
|
-
from ..
|
6
|
+
from ..coro import BytesSteppedCoro
|
7
|
+
from ..coro import BytesSteppedReaderCoro
|
8
8
|
from .adapters import CompressorObjectIncrementalAdapter
|
9
9
|
from .adapters import DecompressorObjectIncrementalAdapter
|
10
10
|
from .base import Compression
|
@@ -43,7 +43,7 @@ class ZlibCompression(Compression, IncrementalCompression):
|
|
43
43
|
**(dict(wbits=self.wbits) if self.wbits is not None else {}),
|
44
44
|
)
|
45
45
|
|
46
|
-
def compress_incremental(self) ->
|
46
|
+
def compress_incremental(self) -> BytesSteppedCoro[None]:
|
47
47
|
return lang.nextgen(CompressorObjectIncrementalAdapter(
|
48
48
|
functools.partial(
|
49
49
|
zlib.compressobj, # type: ignore
|
@@ -54,7 +54,7 @@ class ZlibCompression(Compression, IncrementalCompression):
|
|
54
54
|
),
|
55
55
|
)())
|
56
56
|
|
57
|
-
def decompress_incremental(self) ->
|
57
|
+
def decompress_incremental(self) -> BytesSteppedReaderCoro[None]:
|
58
58
|
return DecompressorObjectIncrementalAdapter(
|
59
59
|
functools.partial( # type: ignore
|
60
60
|
zlib.decompressobj,
|
@@ -0,0 +1,56 @@
|
|
1
|
+
from .consts import ( # noqa
|
2
|
+
DEFAULT_BUFFER_SIZE,
|
3
|
+
)
|
4
|
+
|
5
|
+
from .direct import ( # noqa
|
6
|
+
DirectCoro,
|
7
|
+
|
8
|
+
BytesDirectCoro,
|
9
|
+
StrDirectCoro,
|
10
|
+
)
|
11
|
+
|
12
|
+
from .readers import ( # noqa
|
13
|
+
ReaderCoro,
|
14
|
+
BytesReaderCoro,
|
15
|
+
StrReaderCoro,
|
16
|
+
|
17
|
+
ExactReaderCoro,
|
18
|
+
BytesExactReaderCoro,
|
19
|
+
StrExactReaderCoro,
|
20
|
+
|
21
|
+
CoroReader,
|
22
|
+
|
23
|
+
PrependableCoroReader,
|
24
|
+
PrependableBytesCoroReader,
|
25
|
+
PrependableStrCoroReader,
|
26
|
+
prependable_bytes_coro_reader,
|
27
|
+
prependable_str_coro_reader,
|
28
|
+
|
29
|
+
BufferedCoroReader,
|
30
|
+
BufferedBytesCoroReader,
|
31
|
+
BufferedStrCoroReader,
|
32
|
+
buffered_bytes_coro_reader,
|
33
|
+
buffered_str_coro_reader,
|
34
|
+
)
|
35
|
+
|
36
|
+
from .stepped import ( # noqa
|
37
|
+
SteppedCoro,
|
38
|
+
BytesSteppedCoro,
|
39
|
+
StrSteppedCoro,
|
40
|
+
BytesToStrSteppedCoro,
|
41
|
+
StrToBytesSteppedCoro,
|
42
|
+
|
43
|
+
SteppedReaderCoro,
|
44
|
+
BytesSteppedReaderCoro,
|
45
|
+
StrSteppedReaderCoro,
|
46
|
+
|
47
|
+
flatmap_stepped_coro,
|
48
|
+
|
49
|
+
joined_bytes_stepped_coro,
|
50
|
+
joined_str_stepped_coro,
|
51
|
+
|
52
|
+
read_into_bytes_stepped_coro,
|
53
|
+
read_into_str_stepped_coro,
|
54
|
+
|
55
|
+
buffer_bytes_stepped_reader_coro,
|
56
|
+
)
|
omlish/io/coro/direct.py
ADDED
@@ -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 coros yield outputs 1:1 with inputs.
|
10
|
+
DirectCoro: ta.TypeAlias = ta.Generator[O, I, R]
|
11
|
+
|
12
|
+
BytesDirectCoro: ta.TypeAlias = DirectCoro[bytes, bytes, R]
|
13
|
+
StrDirectCoro: ta.TypeAlias = DirectCoro[str, str, R]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"""
|
2
2
|
TODO:
|
3
|
-
-
|
3
|
+
- BufferedBytesCoroReader
|
4
4
|
- docstrings
|
5
5
|
- memoryviews
|
6
6
|
"""
|
@@ -20,18 +20,18 @@ R = ta.TypeVar('R')
|
|
20
20
|
AnyT = ta.TypeVar('AnyT', bound=ta.Any)
|
21
21
|
|
22
22
|
|
23
|
-
# Reader
|
24
|
-
|
23
|
+
# Reader coros yield ints of amounts of data needed, or None for needing any amount of data.
|
24
|
+
ReaderCoro: ta.TypeAlias = ta.Generator[int | None, I, R]
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
BytesReaderCoro: ta.TypeAlias = ReaderCoro[bytes, R]
|
27
|
+
StrReaderCoro: ta.TypeAlias = ReaderCoro[str, R]
|
28
28
|
|
29
29
|
|
30
|
-
# Exact reader
|
31
|
-
|
30
|
+
# Exact reader coros always specify read sizes.
|
31
|
+
ExactReaderCoro: ta.TypeAlias = ta.Generator[int, I, R]
|
32
32
|
|
33
|
-
|
34
|
-
|
33
|
+
BytesExactReaderCoro: ta.TypeAlias = ExactReaderCoro[bytes, R]
|
34
|
+
StrExactReaderCoro: ta.TypeAlias = ExactReaderCoro[str, R]
|
35
35
|
|
36
36
|
|
37
37
|
##
|
@@ -50,22 +50,22 @@ class _StrJoiner:
|
|
50
50
|
##
|
51
51
|
|
52
52
|
|
53
|
-
class
|
53
|
+
class CoroReader(abc.ABC, ta.Generic[T]):
|
54
54
|
@abc.abstractmethod
|
55
|
-
def read(self, sz: int | None) ->
|
55
|
+
def read(self, sz: int | None) -> ReaderCoro[T, T]:
|
56
56
|
raise NotImplementedError
|
57
57
|
|
58
|
-
def read_exact(self, sz: int) ->
|
58
|
+
def read_exact(self, sz: int) -> ReaderCoro[T, T]:
|
59
59
|
d: ta.Any = yield from self.read(sz)
|
60
60
|
if len(d) != sz:
|
61
|
-
raise EOFError(f'
|
61
|
+
raise EOFError(f'CoroReader got {len(d)}, expected {sz}')
|
62
62
|
return d
|
63
63
|
|
64
64
|
|
65
65
|
##
|
66
66
|
|
67
67
|
|
68
|
-
class
|
68
|
+
class PrependableCoroReader(CoroReader[AnyT]):
|
69
69
|
def __init__(self) -> None:
|
70
70
|
super().__init__()
|
71
71
|
|
@@ -75,7 +75,7 @@ class PrependableGeneratorReader(GeneratorReader[AnyT]):
|
|
75
75
|
def _join(self, lst: list[AnyT]) -> AnyT:
|
76
76
|
raise NotImplementedError
|
77
77
|
|
78
|
-
def read(self, sz: int | None) ->
|
78
|
+
def read(self, sz: int | None) -> ReaderCoro[AnyT, AnyT]:
|
79
79
|
if not self._queue:
|
80
80
|
d: AnyT = check.not_none((yield sz))
|
81
81
|
return d
|
@@ -112,28 +112,28 @@ class PrependableGeneratorReader(GeneratorReader[AnyT]):
|
|
112
112
|
self._queue.insert(0, (d, p or 0))
|
113
113
|
|
114
114
|
|
115
|
-
class
|
115
|
+
class PrependableBytesCoroReader(
|
116
116
|
_BytesJoiner,
|
117
|
-
|
117
|
+
PrependableCoroReader[bytes],
|
118
118
|
):
|
119
119
|
pass
|
120
120
|
|
121
121
|
|
122
|
-
class
|
122
|
+
class PrependableStrCoroReader(
|
123
123
|
_StrJoiner,
|
124
|
-
|
124
|
+
PrependableCoroReader[str],
|
125
125
|
):
|
126
126
|
pass
|
127
127
|
|
128
128
|
|
129
|
-
|
130
|
-
|
129
|
+
prependable_bytes_coro_reader = PrependableBytesCoroReader
|
130
|
+
prependable_str_coro_reader = PrependableStrCoroReader
|
131
131
|
|
132
132
|
|
133
133
|
##
|
134
134
|
|
135
135
|
|
136
|
-
class
|
136
|
+
class BufferedCoroReader(PrependableCoroReader[AnyT], abc.ABC):
|
137
137
|
def __init__(
|
138
138
|
self,
|
139
139
|
buffer_size: int = DEFAULT_BUFFER_SIZE,
|
@@ -144,7 +144,7 @@ class BufferedGeneratorReader(PrependableGeneratorReader[AnyT], abc.ABC):
|
|
144
144
|
|
145
145
|
self._buffer_size = buffer_size
|
146
146
|
|
147
|
-
def read(self, sz: int | None) ->
|
147
|
+
def read(self, sz: int | None) -> ReaderCoro[AnyT, AnyT]:
|
148
148
|
g = super().read(sz)
|
149
149
|
i: ta.Any = None
|
150
150
|
while True:
|
@@ -169,21 +169,21 @@ class BufferedGeneratorReader(PrependableGeneratorReader[AnyT], abc.ABC):
|
|
169
169
|
self.prepend(d, q)
|
170
170
|
|
171
171
|
|
172
|
-
class
|
172
|
+
class BufferedBytesCoroReader(
|
173
173
|
_BytesJoiner,
|
174
|
-
|
175
|
-
|
174
|
+
BufferedCoroReader[bytes],
|
175
|
+
PrependableCoroReader[bytes],
|
176
176
|
):
|
177
177
|
pass
|
178
178
|
|
179
179
|
|
180
|
-
class
|
180
|
+
class BufferedStrCoroReader(
|
181
181
|
_StrJoiner,
|
182
|
-
|
183
|
-
|
182
|
+
BufferedCoroReader[str],
|
183
|
+
PrependableCoroReader[str],
|
184
184
|
):
|
185
185
|
pass
|
186
186
|
|
187
187
|
|
188
|
-
|
189
|
-
|
188
|
+
buffered_bytes_coro_reader = BufferedBytesCoroReader
|
189
|
+
buffered_str_coro_reader = BufferedStrCoroReader
|
@@ -4,8 +4,8 @@ from ... import check
|
|
4
4
|
from ... import lang
|
5
5
|
from ..buffers import ReadableListBuffer
|
6
6
|
from .consts import DEFAULT_BUFFER_SIZE
|
7
|
-
from .direct import
|
8
|
-
from .direct import
|
7
|
+
from .direct import BytesDirectCoro
|
8
|
+
from .direct import StrDirectCoro
|
9
9
|
|
10
10
|
|
11
11
|
T = ta.TypeVar('T')
|
@@ -18,44 +18,44 @@ OF = ta.TypeVar('OF')
|
|
18
18
|
OT = ta.TypeVar('OT')
|
19
19
|
|
20
20
|
|
21
|
-
# Stepped
|
22
|
-
#
|
23
|
-
|
21
|
+
# Stepped coros accept a non-None input, then in response yield zero or more non-None outputs, until yielding None to
|
22
|
+
# signal they need more input again.
|
23
|
+
SteppedCoro: ta.TypeAlias = ta.Generator[O | None, I | None, R]
|
24
24
|
|
25
25
|
# Conventionally, these are sent and themselves yield an empty value to signify termination.
|
26
|
-
|
27
|
-
|
26
|
+
BytesSteppedCoro: ta.TypeAlias = SteppedCoro[bytes, bytes, R]
|
27
|
+
StrSteppedCoro: ta.TypeAlias = SteppedCoro[str, str, R]
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
BytesToStrSteppedCoro: ta.TypeAlias = SteppedCoro[str, bytes, R]
|
30
|
+
StrToBytesSteppedCoro: ta.TypeAlias = SteppedCoro[bytes, str, R]
|
31
31
|
|
32
32
|
|
33
33
|
# Stepped reader generators emit either an int or None to request input, or emit some other kind of output.
|
34
|
-
|
34
|
+
SteppedReaderCoro: ta.TypeAlias = ta.Generator[int | None | O, I | None, R]
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
BytesSteppedReaderCoro: ta.TypeAlias = SteppedReaderCoro[bytes, bytes, R]
|
37
|
+
StrSteppedReaderCoro: ta.TypeAlias = SteppedReaderCoro[str, str, R]
|
38
38
|
|
39
39
|
|
40
40
|
##
|
41
41
|
|
42
42
|
|
43
43
|
@lang.autostart
|
44
|
-
def
|
44
|
+
def flatmap_stepped_coro(
|
45
45
|
fn: ta.Callable[[list[OF]], OT],
|
46
|
-
g:
|
46
|
+
g: SteppedCoro[OF, I, R],
|
47
47
|
*,
|
48
48
|
terminate: ta.Callable[[OF], bool] | None = None,
|
49
49
|
) -> ta.Generator[OT, I, lang.Maybe[R]]:
|
50
50
|
"""
|
51
|
-
Given a stepped
|
52
|
-
|
51
|
+
Given a stepped coro and a function taking a list, returns a direct (1:1) coro which accepts input, builds a list of
|
52
|
+
yielded coro output, calls the given function with that list, and yields the result.
|
53
53
|
|
54
54
|
An optional terminate function may be provided which will cause this function to return early if it returns true for
|
55
55
|
an encountered yielded value. The encountered value causing termination will be included in the list sent to the
|
56
56
|
given fn.
|
57
57
|
|
58
|
-
Returns a Maybe of either the given
|
58
|
+
Returns a Maybe of either the given coro's return value or empty if the terminator was encountered.
|
59
59
|
"""
|
60
60
|
|
61
61
|
l: list[OF]
|
@@ -110,37 +110,37 @@ def _is_empty(o: T) -> bool:
|
|
110
110
|
return len(o) < 1 # type: ignore
|
111
111
|
|
112
112
|
|
113
|
-
def
|
114
|
-
return
|
113
|
+
def joined_bytes_stepped_coro(g: BytesSteppedCoro[R]) -> BytesDirectCoro[R]:
|
114
|
+
return flatmap_stepped_coro(_join_bytes, g, terminate=_is_empty)
|
115
115
|
|
116
116
|
|
117
|
-
def
|
118
|
-
return
|
117
|
+
def joined_str_stepped_coro(g: StrSteppedCoro[R]) -> StrDirectCoro[R]:
|
118
|
+
return flatmap_stepped_coro(_join_str, g, terminate=_is_empty)
|
119
119
|
|
120
120
|
|
121
121
|
##
|
122
122
|
|
123
123
|
|
124
|
-
def
|
125
|
-
g:
|
124
|
+
def read_into_bytes_stepped_coro(
|
125
|
+
g: BytesSteppedCoro,
|
126
126
|
f: ta.IO,
|
127
127
|
*,
|
128
128
|
read_size: int = DEFAULT_BUFFER_SIZE,
|
129
129
|
) -> ta.Iterator[bytes]:
|
130
130
|
yield from lang.genmap( # type: ignore[misc]
|
131
|
-
|
131
|
+
joined_bytes_stepped_coro(g),
|
132
132
|
lang.readiter(f, read_size),
|
133
133
|
)
|
134
134
|
|
135
135
|
|
136
|
-
def
|
137
|
-
g:
|
136
|
+
def read_into_str_stepped_coro(
|
137
|
+
g: StrSteppedCoro,
|
138
138
|
f: ta.TextIO,
|
139
139
|
*,
|
140
140
|
read_size: int = DEFAULT_BUFFER_SIZE,
|
141
141
|
) -> ta.Iterator[str]:
|
142
142
|
yield from lang.genmap(
|
143
|
-
|
143
|
+
joined_str_stepped_coro(g),
|
144
144
|
lang.readiter(f, read_size),
|
145
145
|
)
|
146
146
|
|
@@ -149,7 +149,7 @@ def read_into_str_stepped_generator(
|
|
149
149
|
|
150
150
|
|
151
151
|
@lang.autostart
|
152
|
-
def
|
152
|
+
def buffer_bytes_stepped_reader_coro(g: BytesSteppedReaderCoro) -> BytesSteppedCoro:
|
153
153
|
i: bytes | None
|
154
154
|
o = g.send(None)
|
155
155
|
rlb = ReadableListBuffer()
|