relib 1.2.4__py3-none-any.whl → 1.2.5__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.
- relib/__init__.py +8 -1
- relib/system.py +41 -2
- relib/utils.py +4 -10
- {relib-1.2.4.dist-info → relib-1.2.5.dist-info}/METADATA +1 -1
- relib-1.2.5.dist-info/RECORD +9 -0
- relib-1.2.4.dist-info/RECORD +0 -9
- {relib-1.2.4.dist-info → relib-1.2.5.dist-info}/WHEEL +0 -0
- {relib-1.2.4.dist-info → relib-1.2.5.dist-info}/licenses/LICENSE +0 -0
relib/__init__.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
from .utils import (
|
2
|
+
noop,
|
2
3
|
non_none,
|
3
4
|
as_any,
|
4
5
|
list_split,
|
@@ -31,8 +32,14 @@ from .utils import (
|
|
31
32
|
df_from_array,
|
32
33
|
StrFilter,
|
33
34
|
str_filterer,
|
35
|
+
)
|
36
|
+
from .system import (
|
37
|
+
read_json,
|
38
|
+
write_json,
|
39
|
+
clear_console,
|
40
|
+
console_link,
|
34
41
|
roll_tasks,
|
42
|
+
as_async,
|
35
43
|
)
|
36
|
-
from .system import read_json, write_json, clear_console, console_link
|
37
44
|
from .hashing import hash, hash_obj
|
38
45
|
from .measure_duration import measure_duration
|
relib/system.py
CHANGED
@@ -1,7 +1,16 @@
|
|
1
|
+
import asyncio
|
2
|
+
import contextvars
|
3
|
+
import functools
|
1
4
|
import json
|
2
5
|
import os
|
6
|
+
from concurrent.futures import ThreadPoolExecutor
|
3
7
|
from pathlib import Path
|
4
|
-
from typing import Any
|
8
|
+
from typing import Any, Awaitable, Callable, Iterable, ParamSpec, TypeVar
|
9
|
+
from .utils import noop
|
10
|
+
|
11
|
+
P = ParamSpec("P")
|
12
|
+
R = TypeVar("R")
|
13
|
+
default_num_workers = min(32, (os.cpu_count() or 1) + 4)
|
5
14
|
|
6
15
|
def read_json(path: Path) -> Any:
|
7
16
|
with path.open("r") as f:
|
@@ -14,5 +23,35 @@ def write_json(path: Path, obj: Any) -> None:
|
|
14
23
|
def clear_console() -> None:
|
15
24
|
os.system("cls" if os.name == "nt" else "clear")
|
16
25
|
|
17
|
-
def console_link(text, url) -> str:
|
26
|
+
def console_link(text: str, url: str) -> str:
|
18
27
|
return f"\033]8;;{url}\033\\{text}\033]8;;\033\\"
|
28
|
+
|
29
|
+
async def worker[T](task: Awaitable[T], semaphore: asyncio.Semaphore, update=noop) -> T:
|
30
|
+
async with semaphore:
|
31
|
+
result = await task
|
32
|
+
update()
|
33
|
+
return result
|
34
|
+
|
35
|
+
async def roll_tasks[T](tasks: Iterable[Awaitable[T]], workers: int, progress=False) -> list[T]:
|
36
|
+
semaphore = asyncio.Semaphore(workers)
|
37
|
+
if not progress:
|
38
|
+
return await asyncio.gather(*(worker(task, semaphore) for task in tasks))
|
39
|
+
from tqdm import tqdm
|
40
|
+
assert isinstance(tasks, (list, tuple, set, frozenset, dict))
|
41
|
+
with tqdm(total=len(tasks)) as pbar:
|
42
|
+
update = lambda: pbar.update(1)
|
43
|
+
return await asyncio.gather(*(worker(task, semaphore, update) for task in tasks))
|
44
|
+
|
45
|
+
def as_async(num_workers=default_num_workers) -> Callable[[Callable[P, R]], Callable[P, Awaitable[R]]]:
|
46
|
+
executor = ThreadPoolExecutor(max_workers=num_workers)
|
47
|
+
|
48
|
+
def on_fn(func: Callable[P, R]) -> Callable[P, Awaitable[R]]:
|
49
|
+
@functools.wraps(func)
|
50
|
+
async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
51
|
+
loop = asyncio.get_running_loop()
|
52
|
+
ctx = contextvars.copy_context()
|
53
|
+
fn_call = functools.partial(ctx.run, func, *args, **kwargs)
|
54
|
+
return await loop.run_in_executor(executor, fn_call)
|
55
|
+
return wrapper
|
56
|
+
|
57
|
+
return on_fn
|
relib/utils.py
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
import asyncio
|
2
1
|
import re
|
3
2
|
from itertools import chain
|
4
|
-
from typing import Any,
|
3
|
+
from typing import Any, Callable, Iterable, overload
|
4
|
+
|
5
|
+
def noop() -> None:
|
6
|
+
pass
|
5
7
|
|
6
8
|
def non_none[T](obj: T | None) -> T:
|
7
9
|
assert obj is not None
|
@@ -215,11 +217,3 @@ def str_filterer(
|
|
215
217
|
return any(pattern.search(string) for pattern in include_patterns)
|
216
218
|
|
217
219
|
return str_filter
|
218
|
-
|
219
|
-
async def worker(task, semaphore):
|
220
|
-
async with semaphore:
|
221
|
-
return await task
|
222
|
-
|
223
|
-
async def roll_tasks[T](tasks: Iterable[Awaitable[T]], workers: int) -> list[T]:
|
224
|
-
semaphore = asyncio.Semaphore(workers)
|
225
|
-
return await asyncio.gather(*(worker(task, semaphore) for task in tasks))
|
@@ -0,0 +1,9 @@
|
|
1
|
+
relib/__init__.py,sha256=E_ye3ZsGqW3xCibphEWtXhXjIJI58zVxX53VajgvG2Q,674
|
2
|
+
relib/hashing.py,sha256=DB_fnkj0ls01FgZbf4nPFHl4EBU8X_0OrmDvty4HlRE,6020
|
3
|
+
relib/measure_duration.py,sha256=LCTo_D_qReNprD3fhtJ0daeWycS6xQE_cwxeg2_h0xo,456
|
4
|
+
relib/system.py,sha256=YSovHakRl4VjERuoFgYKMZcuSpBVtuQHdjlc_p_Dfr4,1921
|
5
|
+
relib/utils.py,sha256=4fM0zsAdfrM2w9Q1YKcTfFG5kDzoNgD2amkgfTG39OY,6933
|
6
|
+
relib-1.2.5.dist-info/METADATA,sha256=xy2aVPv-Rhe5P93QDgxJzoJdvKvJoae5upeFwt5SgnE,1295
|
7
|
+
relib-1.2.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
8
|
+
relib-1.2.5.dist-info/licenses/LICENSE,sha256=9xVsdtv_-uSyY9Xl9yujwAPm4-mjcCLeVy-ljwXEWbo,1059
|
9
|
+
relib-1.2.5.dist-info/RECORD,,
|
relib-1.2.4.dist-info/RECORD
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
relib/__init__.py,sha256=eEycDD38L7RxEYrMyPvcJ-vWozI_x-mUxvqfbllnAPs,641
|
2
|
-
relib/hashing.py,sha256=DB_fnkj0ls01FgZbf4nPFHl4EBU8X_0OrmDvty4HlRE,6020
|
3
|
-
relib/measure_duration.py,sha256=LCTo_D_qReNprD3fhtJ0daeWycS6xQE_cwxeg2_h0xo,456
|
4
|
-
relib/system.py,sha256=H-SJccCVLNTDhWTT5jo1NFUiQJzHv2Z1xvq0OVrnJcM,431
|
5
|
-
relib/utils.py,sha256=kJ8P8zCbp2EhFTu4lpOUe8y8VEvwA7VWUQMkPRmdEIc,7212
|
6
|
-
relib-1.2.4.dist-info/METADATA,sha256=XwynajdyZ2ta3_1LdJqpHwkVmj4AreRiStQ-Us-0Msc,1295
|
7
|
-
relib-1.2.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
8
|
-
relib-1.2.4.dist-info/licenses/LICENSE,sha256=9xVsdtv_-uSyY9Xl9yujwAPm4-mjcCLeVy-ljwXEWbo,1059
|
9
|
-
relib-1.2.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|