relib 1.2.9__py3-none-any.whl → 1.2.11__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/system.py CHANGED
@@ -31,7 +31,8 @@ def read_json(path: Path, default=default_sentinel) -> Any:
31
31
 
32
32
  def write_json(path: Path, obj: object, indent: None | int = None) -> None:
33
33
  with path.open("w") as f:
34
- return json.dump(obj, f, indent=indent)
34
+ separators = (",", ":") if indent is None else None
35
+ return json.dump(obj, f, indent=indent, separators=separators)
35
36
 
36
37
  def clear_console() -> None:
37
38
  os.system("cls" if os.name == "nt" else "clear")
relib/utils.py CHANGED
@@ -1,9 +1,10 @@
1
1
  import re
2
2
  from itertools import chain
3
- from typing import Any, Callable, Iterable, overload
3
+ from typing import Any, Callable, Iterable, Literal, overload
4
4
 
5
5
  __all__ = [
6
6
  "noop",
7
+ "clamp",
7
8
  "non_none",
8
9
  "as_any",
9
10
  "list_split",
@@ -11,6 +12,7 @@ __all__ = [
11
12
  "distinct",
12
13
  "dict_firsts",
13
14
  "distinct_by",
15
+ "sort_by",
14
16
  "first",
15
17
  "move_value",
16
18
  "transpose_dict",
@@ -43,6 +45,13 @@ __all__ = [
43
45
  def noop() -> None:
44
46
  pass
45
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
+
46
55
  def non_none[T](obj: T | None) -> T:
47
56
  assert obj is not None
48
57
  return obj
@@ -50,38 +59,42 @@ def non_none[T](obj: T | None) -> T:
50
59
  def as_any(obj: Any) -> Any:
51
60
  return obj
52
61
 
53
- def list_split[T](l: list[T], sep: T) -> list[list[T]]:
54
- l = [sep, *l, sep]
55
- split_at = [i for i, x in enumerate(l) if x is sep]
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]
56
65
  ranges = list(zip(split_at[0:-1], split_at[1:]))
57
66
  return [
58
- l[start + 1:end]
67
+ values[start + 1:end]
59
68
  for start, end in ranges
60
69
  ]
61
70
 
62
71
  def drop_none[T](iterable: Iterable[T | None]) -> list[T]:
63
72
  return [x for x in iterable if x is not None]
64
73
 
65
- def distinct[T](items: Iterable[T]) -> list[T]:
66
- return list(dict.fromkeys(items))
74
+ def distinct[T](iterable: Iterable[T]) -> list[T]:
75
+ return list(dict.fromkeys(iterable))
67
76
 
68
- def dict_firsts[T, K](items: Iterable[tuple[K, T]]) -> dict[K, T]:
77
+ def dict_firsts[T, K](pairs: Iterable[tuple[K, T]]) -> dict[K, T]:
69
78
  result: dict[K, T] = {}
70
- for key, item in items:
79
+ for key, item in pairs:
71
80
  if key not in result:
72
81
  result[key] = item
73
82
  return result
74
83
 
75
- def distinct_by[T](items: Iterable[tuple[object, T]]) -> list[T]:
76
- return list(dict_firsts(items).values())
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[Any, T]]) -> list[T]:
88
+ pairs = sorted(pairs, key=lambda p: p[0])
89
+ return [v for _, v in pairs]
77
90
 
78
91
  def first[T](iterable: Iterable[T]) -> T | None:
79
92
  return next(iter(iterable), None)
80
93
 
81
94
  def move_value[T](iterable: Iterable[T], from_i: int, to_i: int) -> list[T]:
82
- l = list(iterable)
83
- l.insert(to_i, l.pop(from_i))
84
- return l
95
+ values = list(iterable)
96
+ values.insert(to_i, values.pop(from_i))
97
+ return values
85
98
 
86
99
  def transpose_dict(des):
87
100
  if isinstance(des, list):
@@ -101,7 +114,7 @@ def transpose_dict(des):
101
114
  raise ValueError("transpose_dict only accepts dict or list")
102
115
 
103
116
  def make_combinations_by_dict(des, keys=None, pairs=[]):
104
- keys = sorted(des.keys()) if keys == None else keys
117
+ keys = sorted(des.keys()) if keys is None else keys
105
118
  if len(keys) == 0:
106
119
  return [dict(pairs)]
107
120
  key = keys[0]
@@ -145,10 +158,36 @@ def dict_by[T, K](keys: Iterable[K], values: Iterable[T]) -> dict[K, T]:
145
158
  def tuple_by[T, K](d: dict[K, T], keys: Iterable[K]) -> tuple[T, ...]:
146
159
  return tuple(d[key] for key in keys)
147
160
 
148
- def flatten[T](iterable: Iterable[Iterable[T]]) -> list[T]:
149
- return list(chain.from_iterable(iterable))
161
+ @overload
162
+ def flatten[T](iterable: Iterable[T], depth: Literal[0]) -> list[T]: ...
163
+ @overload
164
+ def flatten[T](iterable: Iterable[Iterable[T]], depth: Literal[1] = 1) -> list[T]: ...
165
+ @overload
166
+ def flatten[T](iterable: Iterable[Iterable[Iterable[T]]], depth: Literal[2]) -> list[T]: ...
167
+ @overload
168
+ def flatten[T](iterable: Iterable[Iterable[Iterable[Iterable[T]]]], depth: Literal[3]) -> list[T]: ...
169
+ @overload
170
+ def flatten[T](iterable: Iterable[Iterable[Iterable[Iterable[Iterable[T]]]]], depth: Literal[4]) -> list[T]: ...
171
+ @overload
172
+ def flatten(iterable: Iterable, depth: int) -> list: ...
173
+
174
+ def flatten(iterable: Iterable, depth: int = 1) -> list:
175
+ for _ in range(depth):
176
+ iterable = chain.from_iterable(iterable)
177
+ return list(iterable)
178
+
179
+ @overload
180
+ def transpose[T1, T2](tuples: Iterable[tuple[T1, T2]], default_num_returns: int = 0) -> tuple[list[T1], list[T2]]: ...
181
+ @overload
182
+ def transpose[T1, T2, T3](tuples: Iterable[tuple[T1, T2, T3]], default_num_returns: int = 0) -> tuple[list[T1], list[T2], list[T3]]: ...
183
+ @overload
184
+ def transpose[T1, T2, T3, T4](tuples: Iterable[tuple[T1, T2, T3, T4]], default_num_returns: int = 0) -> tuple[list[T1], list[T2], list[T3], list[T4]]: ...
185
+ @overload
186
+ def transpose[T1, T2, T3, T4, T5](tuples: Iterable[tuple[T1, T2, T3, T4, T5]], default_num_returns: int = 0) -> tuple[list[T1], list[T2], list[T3], list[T4], list[T5]]: ...
187
+ @overload
188
+ def transpose(tuples: Iterable[tuple], default_num_returns: int = 0) -> tuple[list, ...]: ...
150
189
 
151
- def transpose(tuples, default_num_returns=0):
190
+ def transpose(tuples: Iterable[tuple], default_num_returns=0) -> tuple[list, ...]:
152
191
  output = tuple(zip(*tuples))
153
192
  if not output:
154
193
  return ([],) * default_num_returns
@@ -196,8 +235,8 @@ def group[T, K](pairs: Iterable[tuple[K, T]]) -> dict[K, list[T]]:
196
235
  values_by_key.setdefault(key, []).append(value)
197
236
  return values_by_key
198
237
 
199
- def reversed_enumerate[T](l: list[T] | tuple[T, ...]) -> Iterable[tuple[int, T]]:
200
- return zip(reversed(range(len(l))), reversed(l))
238
+ def reversed_enumerate[T](values: list[T] | tuple[T, ...]) -> Iterable[tuple[int, T]]:
239
+ return zip(reversed(range(len(values))), reversed(values))
201
240
 
202
241
  def get_at[T](d: dict, keys: Iterable[Any], default: T) -> T:
203
242
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: relib
3
- Version: 1.2.9
3
+ Version: 1.2.11
4
4
  Project-URL: Repository, https://github.com/Reddan/relib.git
5
5
  Author: Hampus Hallman
6
6
  License: Copyright 2018-2025 Hampus Hallman
@@ -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=bwOJXfsNx5nZf1fZxWtT_hLwjTbWo2cP9qfsqca1aHI,9680
6
+ relib-1.2.11.dist-info/METADATA,sha256=WxEfPUA2Ox2t1ulJZFIXX5ynIOf1jw1u6iWbvtcx9HI,1296
7
+ relib-1.2.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
+ relib-1.2.11.dist-info/licenses/LICENSE,sha256=9xVsdtv_-uSyY9Xl9yujwAPm4-mjcCLeVy-ljwXEWbo,1059
9
+ relib-1.2.11.dist-info/RECORD,,
@@ -1,9 +0,0 @@
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=JOqH4oBM8XMzCfG65um9gQz9CHhEQ4JOaTwywIRgS8Q,2654
5
- relib/utils.py,sha256=QGAse1K_K9qaRyL7AOdkpNmATcUSNOcHECLiJKuMxgo,7803
6
- relib-1.2.9.dist-info/METADATA,sha256=idOhfbgIelWndDu3mSpUINq5EOag0O18WbDDJy2d8rc,1295
7
- relib-1.2.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
- relib-1.2.9.dist-info/licenses/LICENSE,sha256=9xVsdtv_-uSyY9Xl9yujwAPm4-mjcCLeVy-ljwXEWbo,1059
9
- relib-1.2.9.dist-info/RECORD,,
File without changes