omlish 0.0.0.dev141__py3-none-any.whl → 0.0.0.dev143__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- omlish/__about__.py +4 -2
- omlish/check.py +2 -0
- omlish/collections/coerce.py +1 -0
- omlish/docker/__init__.py +2 -1
- omlish/docker/helpers.py +0 -6
- omlish/funcs/pairs.py +2 -2
- omlish/io/compress/__init__.py +9 -0
- omlish/io/compress/abc.py +4 -4
- omlish/io/compress/adapters.py +12 -11
- omlish/io/compress/base.py +24 -0
- omlish/io/compress/brotli.py +33 -0
- omlish/io/compress/bz2.py +26 -21
- omlish/io/compress/gzip.py +43 -10
- omlish/io/compress/lz4.py +77 -0
- omlish/io/compress/lzma.py +51 -16
- omlish/io/compress/snappy.py +20 -0
- omlish/io/compress/zlib.py +60 -0
- omlish/io/compress/zstd.py +30 -0
- omlish/io/generators/__init__.py +53 -0
- omlish/io/generators/consts.py +1 -0
- omlish/io/generators/direct.py +13 -0
- omlish/io/generators/readers.py +15 -9
- omlish/io/generators/stepped.py +85 -14
- omlish/io/pyio.py +5 -2
- omlish/lang/__init__.py +1 -0
- omlish/lang/iterables.py +20 -0
- omlish/lite/docker.py +3 -0
- omlish/lite/marshal.py +213 -141
- omlish/lite/pycharm.py +48 -0
- omlish/lite/subprocesses.py +13 -0
- omlish/logs/abc.py +0 -1
- {omlish-0.0.0.dev141.dist-info → omlish-0.0.0.dev143.dist-info}/METADATA +3 -1
- {omlish-0.0.0.dev141.dist-info → omlish-0.0.0.dev143.dist-info}/RECORD +37 -29
- omlish/io/compress/types.py +0 -29
- {omlish-0.0.0.dev141.dist-info → omlish-0.0.0.dev143.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev141.dist-info → omlish-0.0.0.dev143.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev141.dist-info → omlish-0.0.0.dev143.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev141.dist-info → omlish-0.0.0.dev143.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
import dataclasses as dc
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from ... import lang
|
5
|
+
from .base import Compression
|
6
|
+
|
7
|
+
|
8
|
+
if ta.TYPE_CHECKING:
|
9
|
+
import zstandard
|
10
|
+
else:
|
11
|
+
zstandard = lang.proxy_import('zstandard')
|
12
|
+
|
13
|
+
|
14
|
+
@dc.dataclass(frozen=True, kw_only=True)
|
15
|
+
class ZstdCompression(Compression):
|
16
|
+
level: int | None = None
|
17
|
+
|
18
|
+
max_output_size: int = 0
|
19
|
+
|
20
|
+
def compress(self, d: bytes) -> bytes:
|
21
|
+
return zstandard.compress(
|
22
|
+
d,
|
23
|
+
**(dict(level=self.level) if self.level is not None else {}),
|
24
|
+
)
|
25
|
+
|
26
|
+
def decompress(self, d: bytes) -> bytes:
|
27
|
+
return zstandard.decompress(
|
28
|
+
d,
|
29
|
+
max_output_size=self.max_output_size,
|
30
|
+
)
|
omlish/io/generators/__init__.py
CHANGED
@@ -0,0 +1,53 @@
|
|
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
|
+
)
|
@@ -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]
|
omlish/io/generators/readers.py
CHANGED
@@ -8,21 +8,29 @@ import abc
|
|
8
8
|
import typing as ta
|
9
9
|
|
10
10
|
from ... import check
|
11
|
+
from .consts import DEFAULT_BUFFER_SIZE
|
11
12
|
|
12
13
|
|
13
14
|
T = ta.TypeVar('T')
|
15
|
+
|
16
|
+
O = ta.TypeVar('O')
|
14
17
|
I = ta.TypeVar('I')
|
15
18
|
R = ta.TypeVar('R')
|
19
|
+
|
16
20
|
AnyT = ta.TypeVar('AnyT', bound=ta.Any)
|
17
21
|
|
18
22
|
|
23
|
+
# Reader generators yield ints of amounts of data needed, or None for needing any amount of data.
|
19
24
|
ReaderGenerator: ta.TypeAlias = ta.Generator[int | None, I, R]
|
20
|
-
ExactReaderGenerator: ta.TypeAlias = ta.Generator[int, I, R]
|
21
25
|
|
22
26
|
BytesReaderGenerator: ta.TypeAlias = ReaderGenerator[bytes, R]
|
23
|
-
BytesExactReaderGenerator: ta.TypeAlias = ExactReaderGenerator[bytes, R]
|
24
|
-
|
25
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]
|
26
34
|
StrExactReaderGenerator: ta.TypeAlias = ExactReaderGenerator[str, R]
|
27
35
|
|
28
36
|
|
@@ -44,10 +52,10 @@ class _StrJoiner:
|
|
44
52
|
|
45
53
|
class GeneratorReader(abc.ABC, ta.Generic[T]):
|
46
54
|
@abc.abstractmethod
|
47
|
-
def read(self, sz: int | None) ->
|
55
|
+
def read(self, sz: int | None) -> ReaderGenerator[T, T]:
|
48
56
|
raise NotImplementedError
|
49
57
|
|
50
|
-
def read_exact(self, sz: int) ->
|
58
|
+
def read_exact(self, sz: int) -> ReaderGenerator[T, T]:
|
51
59
|
d: ta.Any = yield from self.read(sz)
|
52
60
|
if len(d) != sz:
|
53
61
|
raise EOFError(f'GeneratorReader got {len(d)}, expected {sz}')
|
@@ -67,7 +75,7 @@ class PrependableGeneratorReader(GeneratorReader[AnyT]):
|
|
67
75
|
def _join(self, lst: list[AnyT]) -> AnyT:
|
68
76
|
raise NotImplementedError
|
69
77
|
|
70
|
-
def read(self, sz: int | None) ->
|
78
|
+
def read(self, sz: int | None) -> ReaderGenerator[AnyT, AnyT]:
|
71
79
|
if not self._queue:
|
72
80
|
d: AnyT = check.not_none((yield sz))
|
73
81
|
return d
|
@@ -126,8 +134,6 @@ prependable_str_generator_reader = PrependableStrGeneratorReader
|
|
126
134
|
|
127
135
|
|
128
136
|
class BufferedGeneratorReader(PrependableGeneratorReader[AnyT], abc.ABC):
|
129
|
-
DEFAULT_BUFFER_SIZE = 4 * 0x1000
|
130
|
-
|
131
137
|
def __init__(
|
132
138
|
self,
|
133
139
|
buffer_size: int = DEFAULT_BUFFER_SIZE,
|
@@ -138,7 +144,7 @@ class BufferedGeneratorReader(PrependableGeneratorReader[AnyT], abc.ABC):
|
|
138
144
|
|
139
145
|
self._buffer_size = buffer_size
|
140
146
|
|
141
|
-
def read(self, sz: int | None) ->
|
147
|
+
def read(self, sz: int | None) -> ReaderGenerator[AnyT, AnyT]:
|
142
148
|
g = super().read(sz)
|
143
149
|
i: ta.Any = None
|
144
150
|
while True:
|
omlish/io/generators/stepped.py
CHANGED
@@ -1,18 +1,40 @@
|
|
1
1
|
import typing as ta
|
2
2
|
|
3
|
+
from ... import check
|
3
4
|
from ... import lang
|
5
|
+
from .consts import DEFAULT_BUFFER_SIZE
|
6
|
+
from .direct import BytesDirectGenerator
|
7
|
+
from .direct import StrDirectGenerator
|
4
8
|
|
5
9
|
|
6
10
|
T = ta.TypeVar('T')
|
7
|
-
|
11
|
+
|
8
12
|
O = ta.TypeVar('O')
|
13
|
+
I = ta.TypeVar('I')
|
14
|
+
R = ta.TypeVar('R')
|
15
|
+
|
9
16
|
OF = ta.TypeVar('OF')
|
10
17
|
OT = ta.TypeVar('OT')
|
11
|
-
R = ta.TypeVar('R')
|
12
18
|
|
13
19
|
|
20
|
+
# Stepped generators accept a non-None input, then in response yield zero or more non-None outputs, until yielding None
|
21
|
+
# to signal they need more input again.
|
14
22
|
SteppedGenerator: ta.TypeAlias = ta.Generator[O | None, I | None, R]
|
15
23
|
|
24
|
+
# Conventionally, these are sent and themselves yield an empty value to signify termination.
|
25
|
+
BytesSteppedGenerator: ta.TypeAlias = SteppedGenerator[bytes, bytes, R]
|
26
|
+
StrSteppedGenerator: ta.TypeAlias = SteppedGenerator[str, str, R]
|
27
|
+
|
28
|
+
BytesToStrSteppedGenerator: ta.TypeAlias = SteppedGenerator[str, bytes, R]
|
29
|
+
StrToBytesSteppedGenerator: ta.TypeAlias = SteppedGenerator[bytes, str, R]
|
30
|
+
|
31
|
+
|
32
|
+
# Stepped reader generators emit either an int or None to request input, or emit some other kind of output.
|
33
|
+
SteppedReaderGenerator: ta.TypeAlias = ta.Generator[int | None | O, I | None, R]
|
34
|
+
|
35
|
+
BytesSteppedReaderGenerator: ta.TypeAlias = SteppedReaderGenerator[bytes, bytes, R]
|
36
|
+
StrSteppedReaderGenerator: ta.TypeAlias = SteppedReaderGenerator[str, str, R]
|
37
|
+
|
16
38
|
|
17
39
|
##
|
18
40
|
|
@@ -25,10 +47,8 @@ def flatmap_stepped_generator(
|
|
25
47
|
terminate: ta.Callable[[OF], bool] | None = None,
|
26
48
|
) -> ta.Generator[OT, I, lang.Maybe[R]]:
|
27
49
|
"""
|
28
|
-
Given a
|
29
|
-
|
30
|
-
1:1 generator which accepts input, builds a list of yielded generator output, calls the given function with that
|
31
|
-
list, and yields the result.
|
50
|
+
Given a stepped generator and a function taking a list, returns a direct (1:1) generator which accepts input, builds
|
51
|
+
a list of yielded generator output, calls the given function with that list, and yields the result.
|
32
52
|
|
33
53
|
An optional terminate function may be provided which will cause this function to return early if it returns true for
|
34
54
|
an encountered yielded value. The encountered value causing termination will be included in the list sent to the
|
@@ -89,16 +109,67 @@ def _is_empty(o: T) -> bool:
|
|
89
109
|
return len(o) < 1 # type: ignore
|
90
110
|
|
91
111
|
|
112
|
+
def joined_bytes_stepped_generator(g: BytesSteppedGenerator[R]) -> BytesDirectGenerator[R]:
|
113
|
+
return flatmap_stepped_generator(_join_bytes, g, terminate=_is_empty)
|
114
|
+
|
115
|
+
|
116
|
+
def joined_str_stepped_generator(g: StrSteppedGenerator[R]) -> StrDirectGenerator[R]:
|
117
|
+
return flatmap_stepped_generator(_join_str, g, terminate=_is_empty)
|
118
|
+
|
119
|
+
|
92
120
|
##
|
93
121
|
|
94
122
|
|
95
|
-
def
|
96
|
-
g:
|
97
|
-
|
98
|
-
|
123
|
+
def read_into_bytes_stepped_generator(
|
124
|
+
g: BytesSteppedGenerator,
|
125
|
+
f: ta.IO,
|
126
|
+
*,
|
127
|
+
read_size: int = DEFAULT_BUFFER_SIZE,
|
128
|
+
) -> ta.Iterator[bytes]:
|
129
|
+
yield from lang.genmap( # type: ignore[misc]
|
130
|
+
joined_bytes_stepped_generator(g),
|
131
|
+
lang.readiter(f, read_size),
|
132
|
+
)
|
99
133
|
|
100
134
|
|
101
|
-
def
|
102
|
-
g:
|
103
|
-
|
104
|
-
|
135
|
+
def read_into_str_stepped_generator(
|
136
|
+
g: StrSteppedGenerator,
|
137
|
+
f: ta.TextIO,
|
138
|
+
*,
|
139
|
+
read_size: int = DEFAULT_BUFFER_SIZE,
|
140
|
+
) -> ta.Iterator[str]:
|
141
|
+
yield from lang.genmap(
|
142
|
+
joined_str_stepped_generator(g),
|
143
|
+
lang.readiter(f, read_size),
|
144
|
+
)
|
145
|
+
|
146
|
+
|
147
|
+
##
|
148
|
+
|
149
|
+
|
150
|
+
@lang.autostart
|
151
|
+
def buffer_bytes_stepped_reader_generator(g: BytesSteppedReaderGenerator) -> BytesSteppedGenerator:
|
152
|
+
o = g.send(None)
|
153
|
+
buf: ta.Any = None
|
154
|
+
|
155
|
+
while True:
|
156
|
+
if not buf:
|
157
|
+
buf = check.isinstance((yield None), bytes)
|
158
|
+
|
159
|
+
if o is None or not buf:
|
160
|
+
i = buf
|
161
|
+
elif isinstance(o, int):
|
162
|
+
if len(buf) < o:
|
163
|
+
raise NotImplementedError
|
164
|
+
i = buf[:o]
|
165
|
+
buf = buf[o:]
|
166
|
+
else:
|
167
|
+
raise TypeError(o)
|
168
|
+
|
169
|
+
while True:
|
170
|
+
o = g.send(i)
|
171
|
+
i = None
|
172
|
+
if isinstance(o, bytes):
|
173
|
+
check.none((yield o))
|
174
|
+
else:
|
175
|
+
break
|
omlish/io/pyio.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
"""
|
5
5
|
Python implementation of the io module.
|
6
6
|
|
7
|
-
https://github.com/python/cpython/blob/
|
7
|
+
https://github.com/python/cpython/blob/8b3cccf3f9508572d85b0044519f2bd5715dacad/Lib/_pyio.py
|
8
8
|
"""
|
9
9
|
# PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
10
10
|
# --------------------------------------------
|
@@ -2580,8 +2580,11 @@ class TextIOWrapper(TextIOBase):
|
|
2580
2580
|
decoder = self._decoder or self._get_decoder()
|
2581
2581
|
|
2582
2582
|
if size < 0:
|
2583
|
+
chunk = self.buffer.read()
|
2584
|
+
if chunk is None:
|
2585
|
+
raise BlockingIOError("Read returned None.")
|
2583
2586
|
# Read everything.
|
2584
|
-
result = self._get_decoded_chars() + decoder.decode(
|
2587
|
+
result = self._get_decoded_chars() + decoder.decode(chunk, final=True)
|
2585
2588
|
if self._snapshot is not None:
|
2586
2589
|
self._set_decoded_chars('')
|
2587
2590
|
self._snapshot = None
|
omlish/lang/__init__.py
CHANGED
omlish/lang/iterables.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import dataclasses as dc
|
2
|
+
import functools
|
2
3
|
import itertools
|
3
4
|
import typing as ta
|
4
5
|
|
@@ -46,6 +47,25 @@ def interleave(vs: ta.Iterable[T], d: T) -> ta.Iterable[T]:
|
|
46
47
|
yield v
|
47
48
|
|
48
49
|
|
50
|
+
@ta.overload
|
51
|
+
def readiter(f: ta.TextIO, sz: int) -> ta.Iterator[str]:
|
52
|
+
...
|
53
|
+
|
54
|
+
|
55
|
+
@ta.overload
|
56
|
+
def readiter(f: ta.BinaryIO, sz: int) -> ta.Iterator[bytes]:
|
57
|
+
...
|
58
|
+
|
59
|
+
|
60
|
+
@ta.overload
|
61
|
+
def readiter(f: ta.IO, sz: int) -> ta.Iterator[ta.AnyStr]:
|
62
|
+
...
|
63
|
+
|
64
|
+
|
65
|
+
def readiter(f, sz):
|
66
|
+
return iter(functools.partial(f.read, sz), None)
|
67
|
+
|
68
|
+
|
49
69
|
@dc.dataclass(frozen=True)
|
50
70
|
class IterGen(ta.Generic[T]):
|
51
71
|
fn: ta.Callable[[], ta.Iterable[T]]
|