omlish 0.0.0.dev151__py3-none-any.whl → 0.0.0.dev153__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- omlish/__about__.py +2 -2
- omlish/argparse/cli.py +54 -13
- omlish/asyncs/__init__.py +0 -35
- omlish/asyncs/all.py +35 -0
- omlish/asyncs/asyncio/__init__.py +0 -0
- omlish/asyncs/asyncio/all.py +7 -0
- omlish/asyncs/asyncio/channels.py +40 -0
- omlish/{lite/asyncio/asyncio.py → asyncs/asyncio/streams.py} +2 -20
- omlish/asyncs/asyncio/timeouts.py +16 -0
- omlish/bootstrap/sys.py +2 -2
- omlish/diag/procfs.py +8 -8
- omlish/inject/managed.py +2 -2
- omlish/lite/asyncio/subprocesses.py +16 -8
- omlish/lite/subprocesses.py +1 -1
- omlish/os/__init__.py +0 -0
- omlish/{lite → os}/deathsig.py +1 -0
- omlish/{os.py → os/files.py} +0 -9
- omlish/{lite → os}/journald.py +2 -1
- omlish/{lite → os}/pidfile.py +1 -0
- omlish/os/sizes.py +9 -0
- omlish/sql/alchemy/asyncs.py +1 -1
- omlish/testing/pytest/marks.py +2 -2
- {omlish-0.0.0.dev151.dist-info → omlish-0.0.0.dev153.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev151.dist-info → omlish-0.0.0.dev153.dist-info}/RECORD +29 -22
- /omlish/asyncs/{asyncio.py → asyncio/asyncio.py} +0 -0
- {omlish-0.0.0.dev151.dist-info → omlish-0.0.0.dev153.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev151.dist-info → omlish-0.0.0.dev153.dist-info}/WHEEL +0 -0
- {omlish-0.0.0.dev151.dist-info → omlish-0.0.0.dev153.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev151.dist-info → omlish-0.0.0.dev153.dist-info}/top_level.txt +0 -0
omlish/__about__.py
CHANGED
omlish/argparse/cli.py
CHANGED
@@ -4,6 +4,8 @@
|
|
4
4
|
TODO:
|
5
5
|
- default command
|
6
6
|
- auto match all underscores to hyphens
|
7
|
+
- pre-run, post-run hooks
|
8
|
+
- exitstack?
|
7
9
|
"""
|
8
10
|
import argparse
|
9
11
|
import dataclasses as dc
|
@@ -136,11 +138,12 @@ class ArgparseCli:
|
|
136
138
|
|
137
139
|
self._args, self._unknown_args = self.get_parser().parse_known_args(self._argv)
|
138
140
|
|
141
|
+
#
|
142
|
+
|
139
143
|
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
140
144
|
super().__init_subclass__(**kwargs)
|
141
145
|
|
142
146
|
ns = cls.__dict__
|
143
|
-
|
144
147
|
objs = {}
|
145
148
|
mro = cls.__mro__[::-1]
|
146
149
|
for bns in [bcls.__dict__ for bcls in reversed(mro)] + [ns]:
|
@@ -153,24 +156,33 @@ class ArgparseCli:
|
|
153
156
|
elif k in objs:
|
154
157
|
del [k]
|
155
158
|
|
159
|
+
#
|
160
|
+
|
156
161
|
anns = ta.get_type_hints(_ArgparseCliAnnotationBox({
|
157
162
|
**{k: v for bcls in reversed(mro) for k, v in getattr(bcls, '__annotations__', {}).items()},
|
158
163
|
**ns.get('__annotations__', {}),
|
159
164
|
}), globalns=ns.get('__globals__', {}))
|
160
165
|
|
166
|
+
#
|
167
|
+
|
161
168
|
if '_parser' in ns:
|
162
169
|
parser = check.isinstance(ns['_parser'], argparse.ArgumentParser)
|
163
170
|
else:
|
164
171
|
parser = argparse.ArgumentParser()
|
165
172
|
setattr(cls, '_parser', parser)
|
166
173
|
|
174
|
+
#
|
175
|
+
|
167
176
|
subparsers = parser.add_subparsers()
|
177
|
+
|
168
178
|
for att, obj in objs.items():
|
169
179
|
if isinstance(obj, ArgparseCommand):
|
170
180
|
if obj.parent is not None:
|
171
181
|
raise NotImplementedError
|
182
|
+
|
172
183
|
for cn in [obj.name, *(obj.aliases or [])]:
|
173
|
-
|
184
|
+
subparser = subparsers.add_parser(cn)
|
185
|
+
|
174
186
|
for arg in (obj.args or []):
|
175
187
|
if (
|
176
188
|
len(arg.args) == 1 and
|
@@ -178,29 +190,34 @@ class ArgparseCli:
|
|
178
190
|
not (n := check.isinstance(arg.args[0], str)).startswith('-') and
|
179
191
|
'metavar' not in arg.kwargs
|
180
192
|
):
|
181
|
-
|
193
|
+
subparser.add_argument(
|
182
194
|
n.replace('-', '_'),
|
183
195
|
**arg.kwargs,
|
184
196
|
metavar=n,
|
185
197
|
)
|
186
198
|
else:
|
187
|
-
|
188
|
-
|
199
|
+
subparser.add_argument(*arg.args, **arg.kwargs)
|
200
|
+
|
201
|
+
subparser.set_defaults(_cmd=obj)
|
189
202
|
|
190
203
|
elif isinstance(obj, ArgparseArg):
|
191
204
|
if att in anns:
|
192
|
-
|
193
|
-
obj.kwargs = {**
|
205
|
+
ann_kwargs = _get_argparse_arg_ann_kwargs(anns[att])
|
206
|
+
obj.kwargs = {**ann_kwargs, **obj.kwargs}
|
207
|
+
|
194
208
|
if not obj.dest:
|
195
209
|
if 'dest' in obj.kwargs:
|
196
210
|
obj.dest = obj.kwargs['dest']
|
197
211
|
else:
|
198
212
|
obj.dest = obj.kwargs['dest'] = att # type: ignore
|
213
|
+
|
199
214
|
parser.add_argument(*obj.args, **obj.kwargs)
|
200
215
|
|
201
216
|
else:
|
202
217
|
raise TypeError(obj)
|
203
218
|
|
219
|
+
#
|
220
|
+
|
204
221
|
_parser: ta.ClassVar[argparse.ArgumentParser]
|
205
222
|
|
206
223
|
@classmethod
|
@@ -219,10 +236,12 @@ class ArgparseCli:
|
|
219
236
|
def unknown_args(self) -> ta.Sequence[str]:
|
220
237
|
return self._unknown_args
|
221
238
|
|
222
|
-
|
223
|
-
|
239
|
+
#
|
240
|
+
|
241
|
+
def _bind_cli_cmd(self, cmd: ArgparseCommand) -> ta.Callable:
|
242
|
+
return cmd.__get__(self, type(self))
|
224
243
|
|
225
|
-
def
|
244
|
+
def prepare_cli_run(self) -> ta.Optional[ta.Callable]:
|
226
245
|
cmd = getattr(self.args, '_cmd', None)
|
227
246
|
|
228
247
|
if self._unknown_args and not (cmd is not None and cmd.accepts_unknown):
|
@@ -234,9 +253,31 @@ class ArgparseCli:
|
|
234
253
|
|
235
254
|
if cmd is None:
|
236
255
|
self.get_parser().print_help()
|
256
|
+
return None
|
257
|
+
|
258
|
+
return self._bind_cli_cmd(cmd)
|
259
|
+
|
260
|
+
#
|
261
|
+
|
262
|
+
def cli_run(self) -> ta.Optional[int]:
|
263
|
+
if (fn := self.prepare_cli_run()) is None:
|
237
264
|
return 0
|
238
265
|
|
239
|
-
return
|
266
|
+
return fn()
|
267
|
+
|
268
|
+
def cli_run_and_exit(self) -> ta.NoReturn:
|
269
|
+
sys.exit(rc if isinstance(rc := self.cli_run(), int) else 0)
|
270
|
+
|
271
|
+
def __call__(self, *, exit: bool = False) -> ta.Optional[int]: # noqa
|
272
|
+
if exit:
|
273
|
+
return self.cli_run_and_exit()
|
274
|
+
else:
|
275
|
+
return self.cli_run()
|
276
|
+
|
277
|
+
#
|
278
|
+
|
279
|
+
async def async_cli_run(self) -> ta.Optional[int]:
|
280
|
+
if (fn := self.prepare_cli_run()) is None:
|
281
|
+
return 0
|
240
282
|
|
241
|
-
|
242
|
-
sys.exit(rc if isinstance(rc := self(), int) else 0)
|
283
|
+
return await fn()
|
omlish/asyncs/__init__.py
CHANGED
@@ -1,35 +0,0 @@
|
|
1
|
-
from .asyncs import ( # noqa
|
2
|
-
SyncableIterable,
|
3
|
-
async_list,
|
4
|
-
sync_await,
|
5
|
-
sync_list,
|
6
|
-
syncable_iterable,
|
7
|
-
)
|
8
|
-
|
9
|
-
from .bridge import ( # noqa
|
10
|
-
a_to_s,
|
11
|
-
is_in_bridge,
|
12
|
-
s_to_a,
|
13
|
-
s_to_a_await,
|
14
|
-
trivial_a_to_s,
|
15
|
-
trivial_s_to_a,
|
16
|
-
)
|
17
|
-
|
18
|
-
from .flavors import ( # noqa
|
19
|
-
ContextManagerAdapter,
|
20
|
-
Flavor,
|
21
|
-
adapt,
|
22
|
-
adapt_context,
|
23
|
-
from_anyio,
|
24
|
-
from_anyio_context,
|
25
|
-
from_asyncio,
|
26
|
-
from_asyncio_context,
|
27
|
-
from_trio,
|
28
|
-
from_trio_context,
|
29
|
-
get_flavor,
|
30
|
-
mark_anyio,
|
31
|
-
mark_asyncio,
|
32
|
-
mark_flavor,
|
33
|
-
mark_trio,
|
34
|
-
with_adapter_loop,
|
35
|
-
)
|
omlish/asyncs/all.py
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
from .asyncs import ( # noqa
|
2
|
+
SyncableIterable,
|
3
|
+
async_list,
|
4
|
+
sync_await,
|
5
|
+
sync_list,
|
6
|
+
syncable_iterable,
|
7
|
+
)
|
8
|
+
|
9
|
+
from .bridge import ( # noqa
|
10
|
+
a_to_s,
|
11
|
+
is_in_bridge,
|
12
|
+
s_to_a,
|
13
|
+
s_to_a_await,
|
14
|
+
trivial_a_to_s,
|
15
|
+
trivial_s_to_a,
|
16
|
+
)
|
17
|
+
|
18
|
+
from .flavors import ( # noqa
|
19
|
+
ContextManagerAdapter,
|
20
|
+
Flavor,
|
21
|
+
adapt,
|
22
|
+
adapt_context,
|
23
|
+
from_anyio,
|
24
|
+
from_anyio_context,
|
25
|
+
from_asyncio,
|
26
|
+
from_asyncio_context,
|
27
|
+
from_trio,
|
28
|
+
from_trio_context,
|
29
|
+
get_flavor,
|
30
|
+
mark_anyio,
|
31
|
+
mark_asyncio,
|
32
|
+
mark_flavor,
|
33
|
+
mark_trio,
|
34
|
+
with_adapter_loop,
|
35
|
+
)
|
File without changes
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
# @omlish-lite
|
3
|
+
import asyncio
|
4
|
+
import typing as ta
|
5
|
+
|
6
|
+
|
7
|
+
class AsyncioBytesChannelTransport(asyncio.Transport):
|
8
|
+
def __init__(self, reader: asyncio.StreamReader) -> None:
|
9
|
+
super().__init__()
|
10
|
+
|
11
|
+
self.reader = reader
|
12
|
+
self.closed: asyncio.Future = asyncio.Future()
|
13
|
+
|
14
|
+
# @ta.override
|
15
|
+
def write(self, data: bytes) -> None:
|
16
|
+
self.reader.feed_data(data)
|
17
|
+
|
18
|
+
# @ta.override
|
19
|
+
def close(self) -> None:
|
20
|
+
self.reader.feed_eof()
|
21
|
+
if not self.closed.done():
|
22
|
+
self.closed.set_result(True)
|
23
|
+
|
24
|
+
# @ta.override
|
25
|
+
def is_closing(self) -> bool:
|
26
|
+
return self.closed.done()
|
27
|
+
|
28
|
+
|
29
|
+
def asyncio_create_bytes_channel(
|
30
|
+
loop: ta.Any = None,
|
31
|
+
) -> ta.Tuple[asyncio.StreamReader, asyncio.StreamWriter]:
|
32
|
+
if loop is None:
|
33
|
+
loop = asyncio.get_running_loop()
|
34
|
+
|
35
|
+
reader = asyncio.StreamReader()
|
36
|
+
protocol = asyncio.StreamReaderProtocol(reader)
|
37
|
+
transport = AsyncioBytesChannelTransport(reader)
|
38
|
+
writer = asyncio.StreamWriter(transport, protocol, reader, loop)
|
39
|
+
|
40
|
+
return reader, writer
|
@@ -1,15 +1,9 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
|
-
|
3
|
-
import asyncio
|
2
|
+
# @omlish-lite
|
3
|
+
import asyncio
|
4
4
|
import typing as ta
|
5
5
|
|
6
6
|
|
7
|
-
AwaitableT = ta.TypeVar('AwaitableT', bound=ta.Awaitable)
|
8
|
-
|
9
|
-
|
10
|
-
##
|
11
|
-
|
12
|
-
|
13
7
|
ASYNCIO_DEFAULT_BUFFER_LIMIT = 2 ** 16
|
14
8
|
|
15
9
|
|
@@ -49,15 +43,3 @@ async def asyncio_open_stream_writer(
|
|
49
43
|
None,
|
50
44
|
loop,
|
51
45
|
)
|
52
|
-
|
53
|
-
|
54
|
-
##
|
55
|
-
|
56
|
-
|
57
|
-
def asyncio_maybe_timeout(
|
58
|
-
fut: AwaitableT,
|
59
|
-
timeout: ta.Optional[float] = None,
|
60
|
-
) -> AwaitableT:
|
61
|
-
if timeout is not None:
|
62
|
-
fut = asyncio.wait_for(fut, timeout) # type: ignore
|
63
|
-
return fut
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
# @omlish-lite
|
3
|
+
import asyncio
|
4
|
+
import typing as ta
|
5
|
+
|
6
|
+
|
7
|
+
AwaitableT = ta.TypeVar('AwaitableT', bound=ta.Awaitable)
|
8
|
+
|
9
|
+
|
10
|
+
def asyncio_maybe_timeout(
|
11
|
+
fut: AwaitableT,
|
12
|
+
timeout: ta.Optional[float] = None,
|
13
|
+
) -> AwaitableT:
|
14
|
+
if timeout is not None:
|
15
|
+
fut = asyncio.wait_for(fut, timeout) # type: ignore
|
16
|
+
return fut
|
omlish/bootstrap/sys.py
CHANGED
@@ -23,13 +23,13 @@ if ta.TYPE_CHECKING:
|
|
23
23
|
from .. import libc
|
24
24
|
from .. import logs
|
25
25
|
from ..formats import dotenv
|
26
|
-
from ..
|
26
|
+
from ..os import pidfile
|
27
27
|
|
28
28
|
else:
|
29
29
|
libc = lang.proxy_import('..libc', __package__)
|
30
30
|
logs = lang.proxy_import('..logs', __package__)
|
31
31
|
dotenv = lang.proxy_import('..formats.dotenv', __package__)
|
32
|
-
pidfile = lang.proxy_import('..
|
32
|
+
pidfile = lang.proxy_import('..os.pidfile', __package__)
|
33
33
|
|
34
34
|
|
35
35
|
##
|
omlish/diag/procfs.py
CHANGED
@@ -13,8 +13,8 @@ import typing as ta
|
|
13
13
|
|
14
14
|
from .. import iterators as it
|
15
15
|
from .. import lang
|
16
|
-
from .. import os as oos
|
17
16
|
from ..formats import json
|
17
|
+
from ..os.sizes import PAGE_SIZE
|
18
18
|
from .procstats import ProcStats
|
19
19
|
|
20
20
|
|
@@ -239,8 +239,8 @@ def get_process_range_pagemaps(start: int, end: int, pid: PidLike = 'self') -> t
|
|
239
239
|
"""https://www.kernel.org/doc/Documentation/vm/pagemap.txt"""
|
240
240
|
|
241
241
|
_check_linux()
|
242
|
-
offset = (start //
|
243
|
-
npages = ((end - start) //
|
242
|
+
offset = (start // PAGE_SIZE) * 8
|
243
|
+
npages = ((end - start) // PAGE_SIZE)
|
244
244
|
size = npages * 8
|
245
245
|
with open(f'/proc/{pid}/pagemap', 'rb') as pagemap_file:
|
246
246
|
pagemap_file.seek(offset)
|
@@ -251,7 +251,7 @@ def get_process_range_pagemaps(start: int, end: int, pid: PidLike = 'self') -> t
|
|
251
251
|
for pagenum in range(npages):
|
252
252
|
[packed] = _struct_unpack('Q', pagemap_buf[pagenum * 8:(pagenum + 1) * 8])
|
253
253
|
yield {
|
254
|
-
'address': start + (pagenum *
|
254
|
+
'address': start + (pagenum * PAGE_SIZE),
|
255
255
|
'pfn': (packed & ((1 << (54 + 1)) - 1)),
|
256
256
|
'swap_type': (packed & ((1 << (4 + 1)) - 1)),
|
257
257
|
'swap_offset': (packed & ((1 << (54 + 1)) - 1)) >> 5,
|
@@ -280,7 +280,7 @@ def _dump_cmd(args: ta.Any) -> None:
|
|
280
280
|
sys.stdout.write('\n')
|
281
281
|
for pm in get_process_range_pagemaps(m['address'], m['end_address'], args.pid):
|
282
282
|
if pm['pte_soft_dirty']:
|
283
|
-
dirty_total +=
|
283
|
+
dirty_total += PAGE_SIZE
|
284
284
|
sys.stdout.write(json.dumps({'page': tuple(pm[k] for k in PAGEMAP_KEYS)}))
|
285
285
|
sys.stdout.write('\n')
|
286
286
|
dct = {
|
@@ -326,11 +326,11 @@ def _cmp_cmd(args: ta.Any) -> None:
|
|
326
326
|
r_pages += c_pages
|
327
327
|
dct = {
|
328
328
|
'l_pages': l_pages,
|
329
|
-
'l_bytes': l_pages *
|
329
|
+
'l_bytes': l_pages * PAGE_SIZE,
|
330
330
|
'r_pages': r_pages,
|
331
|
-
'r_bytes': r_pages *
|
331
|
+
'r_bytes': r_pages * PAGE_SIZE,
|
332
332
|
'c_pages': c_pages,
|
333
|
-
'c_bytes': c_pages *
|
333
|
+
'c_bytes': c_pages * PAGE_SIZE,
|
334
334
|
}
|
335
335
|
sys.stdout.write(json.dumps(dct))
|
336
336
|
sys.stdout.write('\n')
|
omlish/inject/managed.py
CHANGED
@@ -14,9 +14,9 @@ from .injector import create_injector
|
|
14
14
|
|
15
15
|
|
16
16
|
if ta.TYPE_CHECKING:
|
17
|
-
from .. import
|
17
|
+
from ..asyncs import all as _asyncs
|
18
18
|
else:
|
19
|
-
_asyncs = lang.proxy_import('..asyncs', __package__)
|
19
|
+
_asyncs = lang.proxy_import('..asyncs.all', __package__)
|
20
20
|
|
21
21
|
|
22
22
|
T = ta.TypeVar('T')
|
@@ -8,12 +8,12 @@ import subprocess
|
|
8
8
|
import sys
|
9
9
|
import typing as ta
|
10
10
|
|
11
|
+
from ...asyncs.asyncio.timeouts import asyncio_maybe_timeout
|
11
12
|
from ..check import check
|
12
13
|
from ..logs import log
|
13
14
|
from ..subprocesses import DEFAULT_SUBPROCESS_TRY_EXCEPTIONS
|
14
15
|
from ..subprocesses import prepare_subprocess_invocation
|
15
16
|
from ..subprocesses import subprocess_common_context
|
16
|
-
from .asyncio import asyncio_maybe_timeout
|
17
17
|
|
18
18
|
|
19
19
|
T = ta.TypeVar('T')
|
@@ -177,22 +177,25 @@ async def asyncio_subprocess_communicate(
|
|
177
177
|
return await AsyncioProcessCommunicator(proc).communicate(input, timeout) # noqa
|
178
178
|
|
179
179
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
async def _asyncio_subprocess_check_run(
|
180
|
+
async def asyncio_subprocess_run(
|
184
181
|
*args: str,
|
185
182
|
input: ta.Any = None, # noqa
|
186
183
|
timeout: ta.Optional[float] = None,
|
184
|
+
check: bool = False, # noqa
|
185
|
+
capture_output: ta.Optional[bool] = None,
|
187
186
|
**kwargs: ta.Any,
|
188
187
|
) -> ta.Tuple[ta.Optional[bytes], ta.Optional[bytes]]:
|
188
|
+
if capture_output:
|
189
|
+
kwargs.setdefault('stdout', subprocess.PIPE)
|
190
|
+
kwargs.setdefault('stderr', subprocess.PIPE)
|
191
|
+
|
189
192
|
args, kwargs = prepare_subprocess_invocation(*args, **kwargs)
|
190
193
|
|
191
194
|
proc: asyncio.subprocess.Process
|
192
195
|
async with asyncio_subprocess_popen(*args, **kwargs) as proc:
|
193
196
|
stdout, stderr = await asyncio_subprocess_communicate(proc, input, timeout)
|
194
197
|
|
195
|
-
if proc.returncode:
|
198
|
+
if check and proc.returncode:
|
196
199
|
raise subprocess.CalledProcessError(
|
197
200
|
proc.returncode,
|
198
201
|
args,
|
@@ -203,6 +206,9 @@ async def _asyncio_subprocess_check_run(
|
|
203
206
|
return stdout, stderr
|
204
207
|
|
205
208
|
|
209
|
+
##
|
210
|
+
|
211
|
+
|
206
212
|
async def asyncio_subprocess_check_call(
|
207
213
|
*args: str,
|
208
214
|
stdout: ta.Any = sys.stderr,
|
@@ -210,11 +216,12 @@ async def asyncio_subprocess_check_call(
|
|
210
216
|
timeout: ta.Optional[float] = None,
|
211
217
|
**kwargs: ta.Any,
|
212
218
|
) -> None:
|
213
|
-
_, _ = await
|
219
|
+
_, _ = await asyncio_subprocess_run(
|
214
220
|
*args,
|
215
221
|
stdout=stdout,
|
216
222
|
input=input,
|
217
223
|
timeout=timeout,
|
224
|
+
check=True,
|
218
225
|
**kwargs,
|
219
226
|
)
|
220
227
|
|
@@ -225,11 +232,12 @@ async def asyncio_subprocess_check_output(
|
|
225
232
|
timeout: ta.Optional[float] = None,
|
226
233
|
**kwargs: ta.Any,
|
227
234
|
) -> bytes:
|
228
|
-
stdout, stderr = await
|
235
|
+
stdout, stderr = await asyncio_subprocess_run(
|
229
236
|
*args,
|
230
237
|
stdout=asyncio.subprocess.PIPE,
|
231
238
|
input=input,
|
232
239
|
timeout=timeout,
|
240
|
+
check=True,
|
233
241
|
**kwargs,
|
234
242
|
)
|
235
243
|
|
omlish/lite/subprocesses.py
CHANGED
omlish/os/__init__.py
ADDED
File without changes
|
omlish/{lite → os}/deathsig.py
RENAMED
omlish/{os.py → os/files.py}
RENAMED
@@ -1,19 +1,10 @@
|
|
1
1
|
import contextlib
|
2
2
|
import os
|
3
|
-
import resource
|
4
3
|
import shutil
|
5
4
|
import tempfile
|
6
5
|
import typing as ta
|
7
6
|
|
8
7
|
|
9
|
-
PAGE_SIZE = resource.getpagesize()
|
10
|
-
|
11
|
-
|
12
|
-
def round_to_page_size(sz: int) -> int:
|
13
|
-
sz += PAGE_SIZE - 1
|
14
|
-
return sz - (sz % PAGE_SIZE)
|
15
|
-
|
16
|
-
|
17
8
|
@contextlib.contextmanager
|
18
9
|
def tmp_dir(
|
19
10
|
root_dir: str | None = None,
|
omlish/{lite → os}/journald.py
RENAMED
@@ -1,4 +1,5 @@
|
|
1
1
|
# ruff: noqa: UP007 UP012
|
2
|
+
# @omlish-lite
|
2
3
|
import ctypes as ct
|
3
4
|
import logging
|
4
5
|
import sys
|
@@ -6,7 +7,7 @@ import syslog
|
|
6
7
|
import threading
|
7
8
|
import typing as ta
|
8
9
|
|
9
|
-
from .cached import cached_nullary
|
10
|
+
from ..lite.cached import cached_nullary
|
10
11
|
|
11
12
|
|
12
13
|
##
|
omlish/{lite → os}/pidfile.py
RENAMED
omlish/os/sizes.py
ADDED
omlish/sql/alchemy/asyncs.py
CHANGED
omlish/testing/pytest/marks.py
CHANGED
@@ -7,9 +7,9 @@ from .plugins.managermarks import ManagerMark # noqa
|
|
7
7
|
|
8
8
|
|
9
9
|
if ta.TYPE_CHECKING:
|
10
|
-
from ...asyncs import
|
10
|
+
from ...asyncs.asyncio import all as aiu
|
11
11
|
else:
|
12
|
-
aiu = lang.proxy_import('...asyncs.asyncio', __package__)
|
12
|
+
aiu = lang.proxy_import('...asyncs.asyncio.all', __package__)
|
13
13
|
|
14
14
|
|
15
15
|
class drain_asyncio(ManagerMark): # noqa
|
@@ -1,5 +1,5 @@
|
|
1
1
|
omlish/.manifests.json,sha256=RX24SRc6DCEg77PUVnaXOKCWa5TF_c9RQJdGIf7gl9c,1135
|
2
|
-
omlish/__about__.py,sha256=
|
2
|
+
omlish/__about__.py,sha256=b3YvnZv7CD-eAnC8X8P0BTKSk3UmrhaMttytZs3utcs,3409
|
3
3
|
omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
|
4
4
|
omlish/c3.py,sha256=ubu7lHwss5V4UznbejAI0qXhXahrU01MysuHOZI9C4U,8116
|
5
5
|
omlish/cached.py,sha256=UI-XTFBwA6YXWJJJeBn-WkwBkfzDjLBBaZf4nIJA9y0,510
|
@@ -10,7 +10,6 @@ omlish/dynamic.py,sha256=35C_cCX_Vq2HrHzGk5T-zbrMvmUdiIiwDzDNixczoDo,6541
|
|
10
10
|
omlish/iterators.py,sha256=GGLC7RIT86uXMjhIIIqnff_Iu5SI_b9rXYywYGFyzmo,7292
|
11
11
|
omlish/libc.py,sha256=8r7Ejyhttk9ruCfBkxNTrlzir5WPbDE2vmY7VPlceMA,15362
|
12
12
|
omlish/multiprocessing.py,sha256=QZT4C7I-uThCAjaEY3xgUYb-5GagUlnE4etN01LDyU4,5186
|
13
|
-
omlish/os.py,sha256=5nJ-a9JKSMoaZVZ1eOa5BAbfL7o7CF7ue_PyJwufnwY,1460
|
14
13
|
omlish/runmodule.py,sha256=PWvuAaJ9wQQn6bx9ftEL3_d04DyotNn8dR_twm2pgw0,700
|
15
14
|
omlish/sync.py,sha256=QJ79kxmIqDP9SeHDoZAf--DpFIhDQe1jACy8H4N0yZI,2928
|
16
15
|
omlish/term.py,sha256=BXJSE9gfM461bh4z_gysx0oavZSafqcQs5ayZK-kTUo,9284
|
@@ -76,15 +75,21 @@ omlish/antlr/_runtime/xpath/XPathLexer.py,sha256=xFtdr4ZXMZxb2dnB_ggWyhvlQiC7RXQ
|
|
76
75
|
omlish/antlr/_runtime/xpath/__init__.py,sha256=lMd_BbXYdlDhZQN_q0TKN978XW5G0pq618F0NaLkpFE,71
|
77
76
|
omlish/argparse/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
78
77
|
omlish/argparse/all.py,sha256=EfUSf27vFWqa4Q93AycU5YRsrHt-Nx3pU3uNVapb-EE,1054
|
79
|
-
omlish/argparse/cli.py,sha256=
|
80
|
-
omlish/asyncs/__init__.py,sha256=
|
78
|
+
omlish/argparse/cli.py,sha256=RrFql1bS1Lw3GA1ooLCJDQX4bK_Ci-dDqD5nEkVgHGI,8072
|
79
|
+
omlish/asyncs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
80
|
+
omlish/asyncs/all.py,sha256=uUz9ziKh4_QrgmdhKFMgq6j7mFbiZd3LiogguDCQsGI,587
|
81
81
|
omlish/asyncs/anyio.py,sha256=gfpx-D8QGmUfhnQxHEaHXcAP8zSMQjcGw4COFTGNnHI,8021
|
82
|
-
omlish/asyncs/asyncio.py,sha256=JfM59QgB3asgEbrps0zoVbNjWD4kL2XdsEkRMEIoFos,971
|
83
82
|
omlish/asyncs/asyncs.py,sha256=Tf7ZodTGepkM7HAuFcDNh9lLzzrMw6rELWvopGmFkh4,2035
|
84
83
|
omlish/asyncs/bridge.py,sha256=GJOjXVwZJvpq2q9rCwRI2u7Tg-KLUx-SY92b873-M4c,9738
|
85
84
|
omlish/asyncs/flavors.py,sha256=1mNxGNRVmjUHzA13K5ht8vdJv4CLEmzYTQ6BZXr1520,4866
|
86
85
|
omlish/asyncs/trio.py,sha256=fmZ5b_lKdVV8NQ3euCUutWgnkqTFzSnOjvJSA_jvmrE,367
|
87
86
|
omlish/asyncs/trio_asyncio.py,sha256=oqdOHy0slj9PjVxaDf3gJkq9AAgg7wYZbB469jOftVw,1327
|
87
|
+
omlish/asyncs/asyncio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
88
|
+
omlish/asyncs/asyncio/all.py,sha256=cyfe1tOXxQYmgfyF9X1dwx0LPQ0Gsub3tFFZGjWGMr8,142
|
89
|
+
omlish/asyncs/asyncio/asyncio.py,sha256=JfM59QgB3asgEbrps0zoVbNjWD4kL2XdsEkRMEIoFos,971
|
90
|
+
omlish/asyncs/asyncio/channels.py,sha256=ZbmsEmdK1fV96liHdcVpRqA2dAMkXJt4Q3rFAg3YOIw,1074
|
91
|
+
omlish/asyncs/asyncio/streams.py,sha256=Uc9PCWSfBqrK2kdVtfjjQU1eaYTWYmZm8QISDj2xiuw,1004
|
92
|
+
omlish/asyncs/asyncio/timeouts.py,sha256=Rj5OU9BIAPcVZZKp74z7SzUXF5xokh4dgsWkUqOy1aE,355
|
88
93
|
omlish/bootstrap/__init__.py,sha256=-Rtsg7uPQNhh1dIT9nqrz96XlqizwoLnWf-FwOEstJI,730
|
89
94
|
omlish/bootstrap/__main__.py,sha256=4jCwsaogp0FrJjJZ85hzF4-WqluPeheHbfeoKynKvNs,194
|
90
95
|
omlish/bootstrap/base.py,sha256=d8hqn4hp1XMMi5PgcJBQXPKmW47epu8CxBlqDZiRZb4,1073
|
@@ -92,7 +97,7 @@ omlish/bootstrap/diag.py,sha256=iemH0nQEHEDzyZztvd_ygGGVpRpgn5UG6naxeQTvXp0,5347
|
|
92
97
|
omlish/bootstrap/harness.py,sha256=VW8YP-yENGyXIuJ8GL_xintArF13nafwpz-iAghPt34,1967
|
93
98
|
omlish/bootstrap/main.py,sha256=yZhOHDDlj4xB5a89dRdT8z58FsqqnpoBg1-tvY2CJe4,5903
|
94
99
|
omlish/bootstrap/marshal.py,sha256=ZxdAeMNd2qXRZ1HUK89HmEhz8tqlS9OduW34QBscKw0,516
|
95
|
-
omlish/bootstrap/sys.py,sha256=
|
100
|
+
omlish/bootstrap/sys.py,sha256=S6HgjfCKYNuC_iW6gIJNVp8-eJ_wm0JTBMyQRZLE6eQ,8758
|
96
101
|
omlish/collections/__init__.py,sha256=zeUvcAz073ekko37QKya6sElTMfKTuF1bKrdbMtaRpI,2142
|
97
102
|
omlish/collections/abc.py,sha256=sP7BpTVhx6s6C59mTFeosBi4rHOWC6tbFBYbxdZmvh0,2365
|
98
103
|
omlish/collections/coerce.py,sha256=g68ROb_-5HgH-vI8612mU2S0FZ8-wp2ZHK5_Zy_kVC0,7037
|
@@ -151,7 +156,7 @@ omlish/dataclasses/impl/utils.py,sha256=aER2iL3UAtgS1BdLuEvTr9Tr2wC28wk1kiOeO-jI
|
|
151
156
|
omlish/diag/__init__.py,sha256=4S8v0myJM4Zld6_FV6cPe_nSv0aJb6kXftEit0HkiGE,1141
|
152
157
|
omlish/diag/asts.py,sha256=BveUUNUcaAm4Hg55f4ZxGSI313E4L8cCZ5XjHpEkKVI,3325
|
153
158
|
omlish/diag/debug.py,sha256=ClED7kKXeVMyKrjGIxcq14kXk9kvUJfytBQwK9y7c4Q,1637
|
154
|
-
omlish/diag/procfs.py,sha256=
|
159
|
+
omlish/diag/procfs.py,sha256=KaGTAA2Gj8eEEp7MjClRe4aimwzd-HDABThFzvq2cBQ,9684
|
155
160
|
omlish/diag/procstats.py,sha256=UkqxREqfd-38xPYZ9T1SIJISz5ARQCEhTtOZrxtm2dE,777
|
156
161
|
omlish/diag/ps.py,sha256=1JWxZen3fVG-20R6ZZ8BtO_gpzw_5bhHZiKdoHkgxoU,1004
|
157
162
|
omlish/diag/pycharm.py,sha256=7-r_F-whXt8v-0dehxAX-MeMFPM3iZXX9IfeL0GfUtk,4643
|
@@ -246,7 +251,7 @@ omlish/inject/injector.py,sha256=CoCUeMm1Oot4sG4Ti1sKCWrhlvtJ5QAeAI22AFWu2RQ,106
|
|
246
251
|
omlish/inject/inspect.py,sha256=tw49r1RJVHrEHmT8WWA3_Bl9Z0L3lEGRqlLhbM5OmAM,592
|
247
252
|
omlish/inject/keys.py,sha256=BczsGcNvoziQYggGKX3_XpRZQ3b0F_pYWSDLBg5lRvE,654
|
248
253
|
omlish/inject/listeners.py,sha256=AIWUs4OTUPeURU1tS2CXeEbJwC1bZiuya9K6I2ElMns,581
|
249
|
-
omlish/inject/managed.py,sha256=
|
254
|
+
omlish/inject/managed.py,sha256=ASHaY57v9POUOpwgCiinTbE14U28ysl3D6RcFkLfcOQ,2114
|
250
255
|
omlish/inject/multis.py,sha256=a3DparPZjLdkAYFuEFTI6kM3BhNpJbtjeAMRdbeJx0c,3363
|
251
256
|
omlish/inject/origins.py,sha256=OVQkiuRxx6ZtE8ZliufdndtFexcfpj-wZSDkUeGUCYM,534
|
252
257
|
omlish/inject/overrides.py,sha256=hrm243slCw_DDRbn3dK5QK1jfHezVokG-WYO2JaQOV8,535
|
@@ -331,14 +336,11 @@ omlish/lite/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
|
331
336
|
omlish/lite/cached.py,sha256=hBW77-F7ZLtFqbLwVrlqaJ4-iFHMQleMWZXaZN1IubA,1308
|
332
337
|
omlish/lite/check.py,sha256=tAKB99X_oHG3JADUgZXMdPzgN8aNF9UBuJv4WeSgM_A,12877
|
333
338
|
omlish/lite/contextmanagers.py,sha256=4tKuBYyxn-aI31QowIuClHgpML8JsdzCW3j5ms_-uuY,1418
|
334
|
-
omlish/lite/deathsig.py,sha256=Etz04WX6R2PXQ-BgqJyVJ0C5Pqym6Ds6PAG7p1cqr5o,626
|
335
339
|
omlish/lite/inject.py,sha256=729Qi0TLbQgBtkvx97q1EUMe73VFYA1hu4woXkOTcwM,23572
|
336
|
-
omlish/lite/journald.py,sha256=f5Y2Q6-6O3iK_7MoGiwZwoQEOcP7LfkxxQNUR9tMjJM,3882
|
337
340
|
omlish/lite/json.py,sha256=7-02Ny4fq-6YAu5ynvqoijhuYXWpLmfCI19GUeZnb1c,740
|
338
341
|
omlish/lite/logs.py,sha256=1pcGu0ekhVCcLUckLSP16VccnAoprjtl5Vkdfm7y1Wg,6184
|
339
342
|
omlish/lite/marshal.py,sha256=6dCv_H4MF0BgzQ1XfIn30eE5jr4S96IfDi7anbBFl2c,13485
|
340
343
|
omlish/lite/maybes.py,sha256=7OlHJ8Q2r4wQ-aRbZSlJY7x0e8gDvufFdlohGEIJ3P4,833
|
341
|
-
omlish/lite/pidfile.py,sha256=PRSDOAXmNkNwxh-Vwif0Nrs8RAmWroiNhLKIbdjwzBc,1723
|
342
344
|
omlish/lite/pycharm.py,sha256=pUOJevrPClSqTCEOkQBO11LKX2003tfDcp18a03QFrc,1163
|
343
345
|
omlish/lite/reflect.py,sha256=ad_ya_zZJOQB8HoNjs9yc66R54zgflwJVPJqiBXMzqA,1681
|
344
346
|
omlish/lite/resources.py,sha256=YNSmX1Ohck1aoWRs55a-o5ChVbFJIQhtbqE-XwF55Oc,326
|
@@ -347,11 +349,10 @@ omlish/lite/secrets.py,sha256=3Mz3V2jf__XU9qNHcH56sBSw95L3U2UPL24bjvobG0c,816
|
|
347
349
|
omlish/lite/socket.py,sha256=7OYgkXTcQv0wq7TQuLnl9y6dJA1ZT6Vbc1JH59QlxgY,1792
|
348
350
|
omlish/lite/socketserver.py,sha256=doTXIctu_6c8XneFtzPFVG_Wq6xVmA3p9ymut8IvBoU,1586
|
349
351
|
omlish/lite/strings.py,sha256=QURcE4-1pKVW8eT_5VCJpXaHDWR2dW2pYOChTJnZDiQ,1504
|
350
|
-
omlish/lite/subprocesses.py,sha256=
|
352
|
+
omlish/lite/subprocesses.py,sha256=iN-HX44g9uxkZ7HII2Upvkfjp7YK6qQuhPrBqM4Hnp0,4934
|
351
353
|
omlish/lite/typing.py,sha256=U3-JaEnkDSYxK4tsu_MzUn3RP6qALBe5FXQXpD-licE,1090
|
352
354
|
omlish/lite/asyncio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
353
|
-
omlish/lite/asyncio/
|
354
|
-
omlish/lite/asyncio/subprocesses.py,sha256=uav2ZD70HQKGhRvFgDcptW_HFYwA_x0AKviCBwL0K_0,8163
|
355
|
+
omlish/lite/asyncio/subprocesses.py,sha256=FB9PbS17MCE2fvgbSUb30KOg8kiJe37DNioD51T8HOk,8427
|
355
356
|
omlish/logs/__init__.py,sha256=FbOyAW-lGH8gyBlSVArwljdYAU6RnwZLI5LwAfuNnrk,438
|
356
357
|
omlish/logs/abc.py,sha256=ho4ABKYMKX-V7g4sp1BByuOLzslYzLlQ0MESmjEpT-o,8005
|
357
358
|
omlish/logs/configs.py,sha256=EE0jlNaXJbGnM7V-y4xS5VwyTBSTzFzc0BYaVjg0JmA,1283
|
@@ -396,6 +397,12 @@ omlish/math/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
396
397
|
omlish/math/bits.py,sha256=yip1l8agOYzT7bFyMGc0RR3XlnGCfHMpjw_SECLLh1I,3477
|
397
398
|
omlish/math/floats.py,sha256=UimhOT7KRl8LXTzOI5cQWoX_9h6WNWe_3vcOuO7-h_8,327
|
398
399
|
omlish/math/stats.py,sha256=MegzKVsmv2kra4jDWLOUgV0X7Ee2Tbl5u6ql1v4-dEY,10053
|
400
|
+
omlish/os/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
401
|
+
omlish/os/deathsig.py,sha256=hk9Yq2kyDdI-cI7OQH7mOfpRbOKzY_TfPKEqgrjVYbA,641
|
402
|
+
omlish/os/files.py,sha256=1tNy1z5I_CgYKA5c6lOfsXc-hknP4tQDbSShdz8HArw,1308
|
403
|
+
omlish/os/journald.py,sha256=2nI8Res1poXkbLc31--MPUlzYMESnCcPUkIxDOCjZW0,3903
|
404
|
+
omlish/os/pidfile.py,sha256=S4Nbe00oSxckY0qCC9AeTEZe7NSw4eJudnQX7wCXzks,1738
|
405
|
+
omlish/os/sizes.py,sha256=ohkALLvqSqBX4iR-7DMKJ4pfOCRdZXV8htH4QywUNM0,152
|
399
406
|
omlish/reflect/__init__.py,sha256=4-EuCSX1qpEWfScCFzAJv_XghHFu4cXxpxKeBKrosQ4,720
|
400
407
|
omlish/reflect/inspect.py,sha256=veJ424-9oZrqyvhVpvxOi7hcKW-PDBkdYL2yjrFlk4o,495
|
401
408
|
omlish/reflect/ops.py,sha256=RJ6jzrM4ieFsXzWyNXWV43O_WgzEaUvlHSc5N2ezW2A,2044
|
@@ -457,7 +464,7 @@ omlish/sql/dbs.py,sha256=lpdFmm2vTwLoBiVYGj9yPsVcTEYYNCxlYZZpjfChzkY,1870
|
|
457
464
|
omlish/sql/params.py,sha256=Z4VPet6GhNqD1T_MXSWSHkdy3cpUEhST-OplC4B_fYI,4433
|
458
465
|
omlish/sql/qualifiedname.py,sha256=rlW3gVmyucJbqwcxj_7BfK4X2HoXrMroZT2H45zPgJQ,2264
|
459
466
|
omlish/sql/alchemy/__init__.py,sha256=1ruDMiviH5fjevn2xVki-QspcE9O3VPy4hxOqpHjI2s,224
|
460
|
-
omlish/sql/alchemy/asyncs.py,sha256=
|
467
|
+
omlish/sql/alchemy/asyncs.py,sha256=MwZwWIaZsUCQLcTA8mdHUPZmR-pXEVSAsvd15FCm3W4,3692
|
461
468
|
omlish/sql/alchemy/duckdb.py,sha256=kr7pIhiBLNAuZrcigHDtFg9zHkVcrRW3LfryO9VJ4mk,3749
|
462
469
|
omlish/sql/alchemy/exprs.py,sha256=gO4Fj4xEY-PuDgV-N8hBMy55glZz7O-4H7v1LWabfZY,323
|
463
470
|
omlish/sql/alchemy/secrets.py,sha256=EMfy4EfTbEvrlv_41oOhn8qsoF-eTkY7HciPenIE6rI,178
|
@@ -489,7 +496,7 @@ omlish/testing/__init__.py,sha256=M_BQrcCHkoL-ZvE-UpQ8XxXNYRRawhjUz4rCJnAqM2A,15
|
|
489
496
|
omlish/testing/testing.py,sha256=TT2wwSzPZ_KhIvKxpM1qc1yHKD-LHDNgGrcr_h8vs7c,2895
|
490
497
|
omlish/testing/pytest/__init__.py,sha256=B2nyJrjIoNcEopbg0IZ5UUDs4OHmQ8qqElFJfGcDdas,257
|
491
498
|
omlish/testing/pytest/helpers.py,sha256=TJpD60mBtLi9FtxX4TThfuXvg5FIRPSiZk1aeRwe-D4,197
|
492
|
-
omlish/testing/pytest/marks.py,sha256=
|
499
|
+
omlish/testing/pytest/marks.py,sha256=4-3WgunN_fcmhkmQ6mtX_AFo5QRDwflNSH7NoyoXui4,432
|
493
500
|
omlish/testing/pytest/skip.py,sha256=NxTkAQiS3HKZR3sfFdxOR2LCFwtCveY6Ap-qtexiZbw,839
|
494
501
|
omlish/testing/pytest/inject/__init__.py,sha256=pdRKv1HcDmJ_yArKJbYITPXXZthRSGgBJWqITr0Er38,117
|
495
502
|
omlish/testing/pytest/inject/harness.py,sha256=v4DaKJ0KL8oQjzIMK43Gh8GHP4hiI6-lY37O9lyOHRk,5724
|
@@ -512,9 +519,9 @@ omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,329
|
|
512
519
|
omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
|
513
520
|
omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
|
514
521
|
omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
|
515
|
-
omlish-0.0.0.
|
516
|
-
omlish-0.0.0.
|
517
|
-
omlish-0.0.0.
|
518
|
-
omlish-0.0.0.
|
519
|
-
omlish-0.0.0.
|
520
|
-
omlish-0.0.0.
|
522
|
+
omlish-0.0.0.dev153.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
523
|
+
omlish-0.0.0.dev153.dist-info/METADATA,sha256=NANx-xsYundThAIFYybGp0wnUqq1fd7AhbGDyQ4CJxQ,4264
|
524
|
+
omlish-0.0.0.dev153.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
525
|
+
omlish-0.0.0.dev153.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
|
526
|
+
omlish-0.0.0.dev153.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
|
527
|
+
omlish-0.0.0.dev153.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|