relib 1.2.4__tar.gz → 1.2.5__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: relib
3
- Version: 1.2.4
3
+ Version: 1.2.5
4
4
  Project-URL: Repository, https://github.com/Reddan/relib.git
5
5
  Author: Hampus Hallman
6
6
  License: Copyright 2018-2025 Hampus Hallman
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "relib"
3
- version = "1.2.4"
3
+ version = "1.2.5"
4
4
  requires-python = ">=3.12"
5
5
  dependencies = []
6
6
  authors = [
@@ -17,6 +17,7 @@ Repository = "https://github.com/Reddan/relib.git"
17
17
  dev = [
18
18
  "numpy>=2.1.3",
19
19
  "pandas>=2.2.3",
20
+ "tqdm>=4.67.1",
20
21
  ]
21
22
 
22
23
  [build-system]
@@ -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
@@ -0,0 +1,57 @@
1
+ import asyncio
2
+ import contextvars
3
+ import functools
4
+ import json
5
+ import os
6
+ from concurrent.futures import ThreadPoolExecutor
7
+ from pathlib import Path
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)
14
+
15
+ def read_json(path: Path) -> Any:
16
+ with path.open("r") as f:
17
+ return json.load(f)
18
+
19
+ def write_json(path: Path, obj: Any) -> None:
20
+ with path.open("w") as f:
21
+ return json.dump(obj, f)
22
+
23
+ def clear_console() -> None:
24
+ os.system("cls" if os.name == "nt" else "clear")
25
+
26
+ def console_link(text: str, url: str) -> str:
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
@@ -1,7 +1,9 @@
1
- import asyncio
2
1
  import re
3
2
  from itertools import chain
4
- from typing import Any, Awaitable, Callable, Iterable, overload
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))
@@ -1,6 +1,16 @@
1
1
  version = 1
2
+ revision = 1
2
3
  requires-python = ">=3.12"
3
4
 
5
+ [[package]]
6
+ name = "colorama"
7
+ version = "0.4.6"
8
+ source = { registry = "https://pypi.org/simple" }
9
+ sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
10
+ wheels = [
11
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
12
+ ]
13
+
4
14
  [[package]]
5
15
  name = "numpy"
6
16
  version = "2.1.3"
@@ -96,13 +106,14 @@ wheels = [
96
106
 
97
107
  [[package]]
98
108
  name = "relib"
99
- version = "1.2.4"
109
+ version = "1.2.5"
100
110
  source = { editable = "." }
101
111
 
102
112
  [package.dev-dependencies]
103
113
  dev = [
104
114
  { name = "numpy" },
105
115
  { name = "pandas" },
116
+ { name = "tqdm" },
106
117
  ]
107
118
 
108
119
  [package.metadata]
@@ -111,6 +122,7 @@ dev = [
111
122
  dev = [
112
123
  { name = "numpy", specifier = ">=2.1.3" },
113
124
  { name = "pandas", specifier = ">=2.2.3" },
125
+ { name = "tqdm", specifier = ">=4.67.1" },
114
126
  ]
115
127
 
116
128
  [[package]]
@@ -122,6 +134,18 @@ wheels = [
122
134
  { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 },
123
135
  ]
124
136
 
137
+ [[package]]
138
+ name = "tqdm"
139
+ version = "4.67.1"
140
+ source = { registry = "https://pypi.org/simple" }
141
+ dependencies = [
142
+ { name = "colorama", marker = "sys_platform == 'win32'" },
143
+ ]
144
+ sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 }
145
+ wheels = [
146
+ { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540 },
147
+ ]
148
+
125
149
  [[package]]
126
150
  name = "tzdata"
127
151
  version = "2024.2"
@@ -1,18 +0,0 @@
1
- import json
2
- import os
3
- from pathlib import Path
4
- from typing import Any
5
-
6
- def read_json(path: Path) -> Any:
7
- with path.open("r") as f:
8
- return json.load(f)
9
-
10
- def write_json(path: Path, obj: Any) -> None:
11
- with path.open("w") as f:
12
- return json.dump(obj, f)
13
-
14
- def clear_console() -> None:
15
- os.system("cls" if os.name == "nt" else "clear")
16
-
17
- def console_link(text, url) -> str:
18
- return f"\033]8;;{url}\033\\{text}\033]8;;\033\\"
File without changes
File without changes
File without changes
File without changes
File without changes