relib 1.2.8__py3-none-any.whl → 1.2.10__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 +2 -44
- relib/system.py +20 -9
- relib/utils.py +76 -12
- {relib-1.2.8.dist-info → relib-1.2.10.dist-info}/METADATA +1 -1
- relib-1.2.10.dist-info/RECORD +9 -0
- relib-1.2.8.dist-info/RECORD +0 -9
- {relib-1.2.8.dist-info → relib-1.2.10.dist-info}/WHEEL +0 -0
- {relib-1.2.8.dist-info → relib-1.2.10.dist-info}/licenses/LICENSE +0 -0
relib/__init__.py
CHANGED
@@ -1,46 +1,4 @@
|
|
1
|
-
from .utils import
|
2
|
-
|
3
|
-
non_none,
|
4
|
-
as_any,
|
5
|
-
list_split,
|
6
|
-
drop_none,
|
7
|
-
distinct,
|
8
|
-
first,
|
9
|
-
move_value,
|
10
|
-
transpose_dict,
|
11
|
-
make_combinations_by_dict,
|
12
|
-
merge_dicts,
|
13
|
-
intersect,
|
14
|
-
ensure_tuple,
|
15
|
-
key_of,
|
16
|
-
omit,
|
17
|
-
pick,
|
18
|
-
dict_by,
|
19
|
-
tuple_by,
|
20
|
-
flatten,
|
21
|
-
transpose,
|
22
|
-
map_dict,
|
23
|
-
deepen_dict,
|
24
|
-
flatten_dict_inner,
|
25
|
-
flatten_dict,
|
26
|
-
group,
|
27
|
-
reversed_enumerate,
|
28
|
-
get_at,
|
29
|
-
for_each,
|
30
|
-
sized_partitions,
|
31
|
-
num_partitions,
|
32
|
-
df_from_array,
|
33
|
-
StrFilter,
|
34
|
-
str_filterer,
|
35
|
-
)
|
36
|
-
from .system import (
|
37
|
-
read_json,
|
38
|
-
write_json,
|
39
|
-
clear_console,
|
40
|
-
console_link,
|
41
|
-
roll_tasks,
|
42
|
-
as_async,
|
43
|
-
async_limit,
|
44
|
-
)
|
1
|
+
from .utils import *
|
2
|
+
from .system import *
|
45
3
|
from .hashing import hash, hash_obj
|
46
4
|
from .measure_duration import measure_duration
|
relib/system.py
CHANGED
@@ -8,20 +8,31 @@ from pathlib import Path
|
|
8
8
|
from typing import Any, Awaitable, Callable, Iterable, ParamSpec, TypeVar
|
9
9
|
from .utils import noop
|
10
10
|
|
11
|
+
__all__ = [
|
12
|
+
"read_json",
|
13
|
+
"write_json",
|
14
|
+
"clear_console",
|
15
|
+
"console_link",
|
16
|
+
"roll_tasks",
|
17
|
+
"as_async",
|
18
|
+
"async_limit",
|
19
|
+
]
|
20
|
+
|
11
21
|
P = ParamSpec("P")
|
12
22
|
R = TypeVar("R")
|
13
|
-
|
14
|
-
|
23
|
+
default_workers = min(32, (os.cpu_count() or 1) + 4)
|
24
|
+
default_sentinel = object()
|
15
25
|
|
16
|
-
def read_json(path: Path, default=
|
17
|
-
if default is not
|
26
|
+
def read_json(path: Path, default=default_sentinel) -> Any:
|
27
|
+
if default is not default_sentinel and not path.exists():
|
18
28
|
return default
|
19
29
|
with path.open("r") as f:
|
20
30
|
return json.load(f)
|
21
31
|
|
22
|
-
def write_json(path: Path, obj:
|
32
|
+
def write_json(path: Path, obj: object, indent: None | int = None) -> None:
|
23
33
|
with path.open("w") as f:
|
24
|
-
|
34
|
+
separators = (",", ":") if indent is None else None
|
35
|
+
return json.dump(obj, f, indent=indent, separators=separators)
|
25
36
|
|
26
37
|
def clear_console() -> None:
|
27
38
|
os.system("cls" if os.name == "nt" else "clear")
|
@@ -35,7 +46,7 @@ async def worker[T](task: Awaitable[T], semaphore: asyncio.Semaphore, update=noo
|
|
35
46
|
update()
|
36
47
|
return result
|
37
48
|
|
38
|
-
async def roll_tasks[T](tasks: Iterable[Awaitable[T]], workers=
|
49
|
+
async def roll_tasks[T](tasks: Iterable[Awaitable[T]], workers=default_workers, progress=False) -> list[T]:
|
39
50
|
semaphore = asyncio.Semaphore(workers)
|
40
51
|
if not progress:
|
41
52
|
return await asyncio.gather(*[worker(task, semaphore) for task in tasks])
|
@@ -46,7 +57,7 @@ async def roll_tasks[T](tasks: Iterable[Awaitable[T]], workers=default_num_worke
|
|
46
57
|
update = functools.partial(pbar.update, 1)
|
47
58
|
return await asyncio.gather(*[worker(task, semaphore, update) for task in tasks])
|
48
59
|
|
49
|
-
def as_async(workers=
|
60
|
+
def as_async(workers=default_workers) -> Callable[[Callable[P, R]], Callable[P, Awaitable[R]]]:
|
50
61
|
executor = ThreadPoolExecutor(max_workers=workers)
|
51
62
|
|
52
63
|
def on_fn(func: Callable[P, R]) -> Callable[P, Awaitable[R]]:
|
@@ -59,7 +70,7 @@ def as_async(workers=default_num_workers) -> Callable[[Callable[P, R]], Callable
|
|
59
70
|
return wrapper
|
60
71
|
return on_fn
|
61
72
|
|
62
|
-
def async_limit(workers=
|
73
|
+
def async_limit(workers=default_workers) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]:
|
63
74
|
semaphore = asyncio.Semaphore(workers)
|
64
75
|
|
65
76
|
def on_fn(func: Callable[P, Awaitable[R]]) -> Callable[P, Awaitable[R]]:
|
relib/utils.py
CHANGED
@@ -2,9 +2,56 @@ import re
|
|
2
2
|
from itertools import chain
|
3
3
|
from typing import Any, Callable, Iterable, overload
|
4
4
|
|
5
|
+
__all__ = [
|
6
|
+
"noop",
|
7
|
+
"clamp",
|
8
|
+
"non_none",
|
9
|
+
"as_any",
|
10
|
+
"list_split",
|
11
|
+
"drop_none",
|
12
|
+
"distinct",
|
13
|
+
"dict_firsts",
|
14
|
+
"distinct_by",
|
15
|
+
"sort_by",
|
16
|
+
"first",
|
17
|
+
"move_value",
|
18
|
+
"transpose_dict",
|
19
|
+
"make_combinations_by_dict",
|
20
|
+
"merge_dicts",
|
21
|
+
"intersect",
|
22
|
+
"ensure_tuple",
|
23
|
+
"key_of",
|
24
|
+
"omit",
|
25
|
+
"pick",
|
26
|
+
"dict_by",
|
27
|
+
"tuple_by",
|
28
|
+
"flatten",
|
29
|
+
"transpose",
|
30
|
+
"map_dict",
|
31
|
+
"deepen_dict",
|
32
|
+
"flatten_dict_inner",
|
33
|
+
"flatten_dict",
|
34
|
+
"group",
|
35
|
+
"reversed_enumerate",
|
36
|
+
"get_at",
|
37
|
+
"for_each",
|
38
|
+
"sized_partitions",
|
39
|
+
"num_partitions",
|
40
|
+
"df_from_array",
|
41
|
+
"StrFilter",
|
42
|
+
"str_filterer",
|
43
|
+
]
|
44
|
+
|
5
45
|
def noop() -> None:
|
6
46
|
pass
|
7
47
|
|
48
|
+
@overload
|
49
|
+
def clamp(value: int, low: int, high: int) -> int: ...
|
50
|
+
@overload
|
51
|
+
def clamp(value: float, low: float, high: float) -> float: ...
|
52
|
+
def clamp(value: float, low: float, high: float) -> float:
|
53
|
+
return max(low, min(value, high))
|
54
|
+
|
8
55
|
def non_none[T](obj: T | None) -> T:
|
9
56
|
assert obj is not None
|
10
57
|
return obj
|
@@ -12,28 +59,45 @@ def non_none[T](obj: T | None) -> T:
|
|
12
59
|
def as_any(obj: Any) -> Any:
|
13
60
|
return obj
|
14
61
|
|
15
|
-
def list_split[T](
|
16
|
-
|
17
|
-
split_at = [i for i, x in enumerate(
|
62
|
+
def list_split[T](iterable: Iterable[T], sep: T) -> list[list[T]]:
|
63
|
+
values = [sep, *iterable, sep]
|
64
|
+
split_at = [i for i, x in enumerate(values) if x is sep]
|
18
65
|
ranges = list(zip(split_at[0:-1], split_at[1:]))
|
19
66
|
return [
|
20
|
-
|
67
|
+
values[start + 1:end]
|
21
68
|
for start, end in ranges
|
22
69
|
]
|
23
70
|
|
24
71
|
def drop_none[T](iterable: Iterable[T | None]) -> list[T]:
|
25
72
|
return [x for x in iterable if x is not None]
|
26
73
|
|
27
|
-
def distinct[T](
|
28
|
-
return list(dict.fromkeys(
|
74
|
+
def distinct[T](iterable: Iterable[T]) -> list[T]:
|
75
|
+
return list(dict.fromkeys(iterable))
|
76
|
+
|
77
|
+
def dict_firsts[T, K](pairs: Iterable[tuple[K, T]]) -> dict[K, T]:
|
78
|
+
result: dict[K, T] = {}
|
79
|
+
for key, item in pairs:
|
80
|
+
if key not in result:
|
81
|
+
result[key] = item
|
82
|
+
return result
|
83
|
+
|
84
|
+
def distinct_by[T](pairs: Iterable[tuple[object, T]]) -> list[T]:
|
85
|
+
return list(dict_firsts(pairs).values())
|
86
|
+
|
87
|
+
def sort_by[T](pairs: Iterable[tuple[object, T]]) -> list[T]:
|
88
|
+
pair_list: list[Any] = list(pairs)
|
89
|
+
pair_list.sort(key=lambda p: p[0])
|
90
|
+
for i in range(len(pair_list)):
|
91
|
+
pair_list[i] = pair_list[i][1]
|
92
|
+
return pair_list
|
29
93
|
|
30
94
|
def first[T](iterable: Iterable[T]) -> T | None:
|
31
95
|
return next(iter(iterable), None)
|
32
96
|
|
33
97
|
def move_value[T](iterable: Iterable[T], from_i: int, to_i: int) -> list[T]:
|
34
|
-
|
35
|
-
|
36
|
-
return
|
98
|
+
values = list(iterable)
|
99
|
+
values.insert(to_i, values.pop(from_i))
|
100
|
+
return values
|
37
101
|
|
38
102
|
def transpose_dict(des):
|
39
103
|
if isinstance(des, list):
|
@@ -53,7 +117,7 @@ def transpose_dict(des):
|
|
53
117
|
raise ValueError("transpose_dict only accepts dict or list")
|
54
118
|
|
55
119
|
def make_combinations_by_dict(des, keys=None, pairs=[]):
|
56
|
-
keys = sorted(des.keys()) if keys
|
120
|
+
keys = sorted(des.keys()) if keys is None else keys
|
57
121
|
if len(keys) == 0:
|
58
122
|
return [dict(pairs)]
|
59
123
|
key = keys[0]
|
@@ -148,8 +212,8 @@ def group[T, K](pairs: Iterable[tuple[K, T]]) -> dict[K, list[T]]:
|
|
148
212
|
values_by_key.setdefault(key, []).append(value)
|
149
213
|
return values_by_key
|
150
214
|
|
151
|
-
def reversed_enumerate[T](
|
152
|
-
return zip(reversed(range(len(
|
215
|
+
def reversed_enumerate[T](values: list[T] | tuple[T, ...]) -> Iterable[tuple[int, T]]:
|
216
|
+
return zip(reversed(range(len(values))), reversed(values))
|
153
217
|
|
154
218
|
def get_at[T](d: dict, keys: Iterable[Any], default: T) -> T:
|
155
219
|
try:
|
@@ -0,0 +1,9 @@
|
|
1
|
+
relib/__init__.py,sha256=4_nmex7mRhCwdtLF8k0XLbxxPs-UeN2sP-EEImm5JGs,126
|
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=3RWmSweTCQtB1wzsgpUqcAsMo6TIhVRq2oSt28Ul_1E,2733
|
5
|
+
relib/utils.py,sha256=A6GenRxjzI-1R80QD3G8Xq-E72LezIbItuHeBSaYnHg,8362
|
6
|
+
relib-1.2.10.dist-info/METADATA,sha256=q2wmDYkUk7f_D3WxRQloVtqjOpI6_Z3h5AFt9qXFEto,1296
|
7
|
+
relib-1.2.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
8
|
+
relib-1.2.10.dist-info/licenses/LICENSE,sha256=9xVsdtv_-uSyY9Xl9yujwAPm4-mjcCLeVy-ljwXEWbo,1059
|
9
|
+
relib-1.2.10.dist-info/RECORD,,
|
relib-1.2.8.dist-info/RECORD
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
relib/__init__.py,sha256=pypVcr0ctaSdFZmwMnZvtioTbms3MlWfAcrnPVdZxog,689
|
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=RO8pd5eUmucbAxgfFi7UWHH5Cdp0aM6O1oe5cylrc4k,2527
|
5
|
-
relib/utils.py,sha256=4fM0zsAdfrM2w9Q1YKcTfFG5kDzoNgD2amkgfTG39OY,6933
|
6
|
-
relib-1.2.8.dist-info/METADATA,sha256=b8RvpgbcT7Y9zq6r-kwnnCZgql_eAdG41Y83-q2YIXg,1295
|
7
|
-
relib-1.2.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
8
|
-
relib-1.2.8.dist-info/licenses/LICENSE,sha256=9xVsdtv_-uSyY9Xl9yujwAPm4-mjcCLeVy-ljwXEWbo,1059
|
9
|
-
relib-1.2.8.dist-info/RECORD,,
|
File without changes
|
File without changes
|