relib 1.3.11__py3-none-any.whl → 1.3.13__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/class_utils.py +9 -0
- relib/iter_utils.py +36 -9
- relib/runtime_tools.py +3 -3
- {relib-1.3.11.dist-info → relib-1.3.13.dist-info}/METADATA +1 -1
- {relib-1.3.11.dist-info → relib-1.3.13.dist-info}/RECORD +7 -6
- {relib-1.3.11.dist-info → relib-1.3.13.dist-info}/WHEEL +0 -0
- {relib-1.3.11.dist-info → relib-1.3.13.dist-info}/licenses/LICENSE +0 -0
relib/class_utils.py
ADDED
relib/iter_utils.py
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
from contextlib import contextmanager
|
3
|
-
from itertools import chain, islice
|
3
|
+
from itertools import chain, islice, tee
|
4
4
|
from typing import Any, Generic, Iterable, Literal, Sequence, overload
|
5
|
+
from .class_utils import slicer
|
5
6
|
from .dict_utils import dict_firsts
|
6
7
|
from .types import T1, T2, T3, T4, T5, T, U
|
7
8
|
|
@@ -17,6 +18,7 @@ __all__ = [
|
|
17
18
|
"range_of", "reversed_enumerate",
|
18
19
|
"seekable", "sort_by",
|
19
20
|
"transpose",
|
21
|
+
"unzip_iterable",
|
20
22
|
]
|
21
23
|
|
22
24
|
def as_list(iterable: Iterable[T]) -> list[T]:
|
@@ -81,6 +83,7 @@ class seekable(Generic[T]):
|
|
81
83
|
self.index = 0
|
82
84
|
self.source = iter(iterable)
|
83
85
|
self.sink: list[T] = []
|
86
|
+
self.abs = slicer(self.abs_getitem)
|
84
87
|
|
85
88
|
def __iter__(self):
|
86
89
|
return self
|
@@ -97,15 +100,16 @@ class seekable(Generic[T]):
|
|
97
100
|
def __bool__(self):
|
98
101
|
return bool(self[:1])
|
99
102
|
|
100
|
-
def clear(self):
|
103
|
+
def clear(self) -> seekable[T]:
|
101
104
|
self.sink[:self.index] = []
|
102
105
|
self.index = 0
|
106
|
+
return self
|
103
107
|
|
104
108
|
def seek(self, index: int) -> seekable[T]:
|
105
|
-
|
106
|
-
|
109
|
+
index = max(0, index)
|
110
|
+
self.index = min(index, len(self.sink))
|
111
|
+
if (remainder := index - self.index) > 0:
|
107
112
|
next(islice(self, remainder, remainder), None)
|
108
|
-
self.index = max(0, min(index, len(self.sink)))
|
109
113
|
return self
|
110
114
|
|
111
115
|
def step(self, count: int) -> seekable[T]:
|
@@ -130,10 +134,21 @@ class seekable(Generic[T]):
|
|
130
134
|
with self.freeze():
|
131
135
|
if isinstance(key, int):
|
132
136
|
return self[key:key + 1][0]
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
+
start, stop, step = key.start, key.stop, key.step
|
138
|
+
delta = min(self.index, -min(0, start or 0))
|
139
|
+
start = None if start is None else max(0, start + delta)
|
140
|
+
stop = None if stop is None else max(0, stop + delta)
|
141
|
+
self.step(-delta)
|
142
|
+
return list(islice(self, start, stop, step))
|
143
|
+
|
144
|
+
@overload
|
145
|
+
def abs_getitem(self, key: int) -> T: ...
|
146
|
+
@overload
|
147
|
+
def abs_getitem(self, key: slice[int | None]) -> list[T]: ...
|
148
|
+
def abs_getitem(self, key: int | slice[int | None]):
|
149
|
+
with self.freeze():
|
150
|
+
self.seek(0)
|
151
|
+
return self[key]
|
137
152
|
|
138
153
|
def consume(self) -> Iterable[T]:
|
139
154
|
for value in self:
|
@@ -185,3 +200,15 @@ def transpose(tuples: Iterable[tuple], default_num_returns=0) -> tuple[list, ...
|
|
185
200
|
if not output:
|
186
201
|
return ([],) * default_num_returns
|
187
202
|
return tuple(map(list, output))
|
203
|
+
|
204
|
+
@overload
|
205
|
+
def unzip_iterable(iterable: Iterable[tuple[T1, T2]], n: Literal[2]) -> tuple[Iterable[T1], Iterable[T2]]: ...
|
206
|
+
@overload
|
207
|
+
def unzip_iterable(iterable: Iterable[tuple[T1, T2, T3]], n: Literal[3]) -> tuple[Iterable[T1], Iterable[T2], Iterable[T3]]: ...
|
208
|
+
@overload
|
209
|
+
def unzip_iterable(iterable: Iterable[tuple[T1, T2, T3, T4]], n: Literal[4]) -> tuple[Iterable[T1], Iterable[T2], Iterable[T3], Iterable[T4]]: ...
|
210
|
+
@overload
|
211
|
+
def unzip_iterable(iterable: Iterable[tuple[T1, T2, T3, T4, T5]], n: Literal[5]) -> tuple[Iterable[T1], Iterable[T2], Iterable[T3], Iterable[T4], Iterable[T5]]: ...
|
212
|
+
def unzip_iterable(iterable: Iterable[tuple], n: int) -> tuple[Iterable, ...]:
|
213
|
+
iters = tee(iterable, n)
|
214
|
+
return tuple(map(lambda i, iter: (x[i] for x in iter), range(n), iters))
|
relib/runtime_tools.py
CHANGED
@@ -5,7 +5,7 @@ import sys
|
|
5
5
|
from concurrent.futures import ThreadPoolExecutor
|
6
6
|
from functools import partial, wraps
|
7
7
|
from time import time
|
8
|
-
from typing import Callable, Coroutine, Iterable, ParamSpec, TypeVar
|
8
|
+
from typing import Awaitable, Callable, Coroutine, Iterable, ParamSpec, TypeVar
|
9
9
|
from .iter_utils import as_list
|
10
10
|
from .processing_utils import noop
|
11
11
|
from .types import T
|
@@ -35,13 +35,13 @@ def clear_console() -> None:
|
|
35
35
|
def console_link(text: str, url: str) -> str:
|
36
36
|
return f"\033]8;;{url}\033\\{text}\033]8;;\033\\"
|
37
37
|
|
38
|
-
async def worker(task: Coro[T], semaphore: asyncio.Semaphore, update=noop) -> T:
|
38
|
+
async def worker(task: Coro[T] | Awaitable[T], semaphore: asyncio.Semaphore, update=noop) -> T:
|
39
39
|
async with semaphore:
|
40
40
|
result = await task
|
41
41
|
update()
|
42
42
|
return result
|
43
43
|
|
44
|
-
async def roll_tasks(tasks: Iterable[Coro[T]], workers=default_workers, progress=False) -> list[T]:
|
44
|
+
async def roll_tasks(tasks: Iterable[Coro[T] | Awaitable[T]], workers=default_workers, progress=False) -> list[T]:
|
45
45
|
semaphore = asyncio.Semaphore(workers)
|
46
46
|
if not progress:
|
47
47
|
return await asyncio.gather(*[worker(task, semaphore) for task in tasks])
|
@@ -1,12 +1,13 @@
|
|
1
1
|
relib/__init__.py,sha256=WerjUaM_sNvudjXFudLRtXB7viZWEW1RSinkDjrh4nE,163
|
2
|
+
relib/class_utils.py,sha256=3z23lxhjFbn68IM_YnJPlvGG2pkybZuK3o_C-9b_LCc,225
|
2
3
|
relib/dict_utils.py,sha256=ez8egTPvO05wVNWIyO-aJjtqaXUDYbzyw32M42q1D44,3677
|
3
4
|
relib/io_utils.py,sha256=cUyUFhrMCUDfkINhYo32QPaVGz3chqDO3ElymSCoWEg,1086
|
4
|
-
relib/iter_utils.py,sha256=
|
5
|
+
relib/iter_utils.py,sha256=O5NAHUWLPzCDJiAUe1I5mghIV5T4Q2OcSKvs6OClC_w,7562
|
5
6
|
relib/processing_utils.py,sha256=kFb4izrR8vec9BFWeGSb-TXR54bbA4X3dxAfIBZItuI,1911
|
6
|
-
relib/runtime_tools.py,sha256=
|
7
|
+
relib/runtime_tools.py,sha256=jK4L4uE3eyGtmLNHEOSE651nrFdql00w7ctudGN6mb8,3020
|
7
8
|
relib/type_utils.py,sha256=68yEhEIBCIKfsIT1u647avHVA_JjVvDYSdtLD3nCrJs,338
|
8
9
|
relib/types.py,sha256=JzSGDl2L6tUWizGSsUpuyCKf-VKgtgfK_n21azSSMLM,288
|
9
|
-
relib-1.3.
|
10
|
-
relib-1.3.
|
11
|
-
relib-1.3.
|
12
|
-
relib-1.3.
|
10
|
+
relib-1.3.13.dist-info/METADATA,sha256=KYD1MwW_CYoc38hMwsjoi5-DZgE7MiH20Qn1q-wvdVs,1296
|
11
|
+
relib-1.3.13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
12
|
+
relib-1.3.13.dist-info/licenses/LICENSE,sha256=9xVsdtv_-uSyY9Xl9yujwAPm4-mjcCLeVy-ljwXEWbo,1059
|
13
|
+
relib-1.3.13.dist-info/RECORD,,
|
File without changes
|
File without changes
|