dycw-utilities 0.134.4__py3-none-any.whl → 0.135.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.134.4
3
+ Version: 0.135.0
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -1,4 +1,4 @@
1
- utilities/__init__.py,sha256=aGENX9jJ-5Lnfpi2UfGD4tuv49MbTmIMv6OGK_-O8lM,60
1
+ utilities/__init__.py,sha256=ZNWx_k_4ER3p4DVbJX8DEVVB_Qth1GiAAheIk1f0wkY,60
2
2
  utilities/aiolimiter.py,sha256=mD0wEiqMgwpty4XTbawFpnkkmJS6R4JRsVXFUaoitSU,628
3
3
  utilities/altair.py,sha256=HeZBVUocjkrTNwwKrClppsIqgNFF-ykv05HfZSoHYno,9104
4
4
  utilities/arq.py,sha256=S-sfBfY-E1ErRKf4sSXt2YyCjKvu-pBlOECDfjBebRA,6399
@@ -37,7 +37,7 @@ utilities/luigi.py,sha256=wK7cB3y8NXeSa8d6r_yTKRmjMguNmIPmy52yg10vPaI,4774
37
37
  utilities/math.py,sha256=_6vrDyjtaqE_OFE-F2DNWrDG_J_kMl3nFAJsok9v_bY,26862
38
38
  utilities/memory_profiler.py,sha256=XzN56jDCa5aqXS_DxEjb_K4L6aIWh_5zyKi6OhcIxw0,853
39
39
  utilities/modules.py,sha256=iuvLluJya-hvl1Q25-Jk3dLgx2Es3ck4SjJiEkAlVTs,3195
40
- utilities/more_itertools.py,sha256=QCPzZvdsPbbd_ypPP06odqfyK79Vp4oQG9DQbaI205A,8644
40
+ utilities/more_itertools.py,sha256=EX4P5JTc3p9fF3Ia3ZzPy9CEUe6OZcFqrrVplZ4pMaQ,10937
41
41
  utilities/numpy.py,sha256=Xn23sA2ZbVNqwUYEgNJD3XBYH6IbCri_WkHSNhg3NkY,26122
42
42
  utilities/operator.py,sha256=fZM2DBZdjtU8Lh9Z-eHC4ktNr0vO3JfX8hXgIYwdvBI,3826
43
43
  utilities/optuna.py,sha256=C-fhWYiXHVPo1l8QctYkFJ4DyhbSrGorzP1dJb_qvd8,1933
@@ -90,7 +90,7 @@ utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
90
90
  utilities/whenever.py,sha256=A-yoOqBqrcVD1yDINDsTFDw7dq9-zgUGn_f8CxVUQJs,23332
91
91
  utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
92
92
  utilities/zoneinfo.py,sha256=oEH-nL3t4h9uawyZqWDtNtDAl6M-CLpLYGI_nI6DulM,1971
93
- dycw_utilities-0.134.4.dist-info/METADATA,sha256=bayiwKsZUr-VMVW1EI2cLFL3rbWrqqftZXA1PrXoe3c,1584
94
- dycw_utilities-0.134.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
95
- dycw_utilities-0.134.4.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
96
- dycw_utilities-0.134.4.dist-info/RECORD,,
93
+ dycw_utilities-0.135.0.dist-info/METADATA,sha256=USiapXRoQLG5Wl1CftVIV6nKma65HtH3nIoU7n8OMl8,1584
94
+ dycw_utilities-0.135.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
95
+ dycw_utilities-0.135.0.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
96
+ dycw_utilities-0.135.0.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.134.4"
3
+ __version__ = "0.135.0"
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- import builtins
4
- from collections.abc import Hashable
3
+ from collections.abc import Callable, Hashable
5
4
  from dataclasses import dataclass
6
5
  from itertools import islice
7
6
  from textwrap import indent
@@ -25,7 +24,7 @@ from utilities.reprlib import get_repr
25
24
  from utilities.sentinel import Sentinel, sentinel
26
25
 
27
26
  if TYPE_CHECKING:
28
- from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence
27
+ from collections.abc import Iterable, Iterator, Mapping, Sequence
29
28
 
30
29
 
31
30
  @overload
@@ -34,55 +33,107 @@ def bucket_mapping[T, U, UH: Hashable](
34
33
  func: Callable[[T], UH],
35
34
  /,
36
35
  *,
37
- transform: Callable[[T], U],
38
- list: bool = False,
39
- unique: Literal[True],
40
- ) -> Mapping[UH, U]: ...
36
+ pre: Callable[[T], U],
37
+ post: Literal["list"],
38
+ ) -> Mapping[UH, list[U]]: ...
41
39
  @overload
42
40
  def bucket_mapping[T, U, UH: Hashable](
43
41
  iterable: Iterable[T],
44
42
  func: Callable[[T], UH],
45
43
  /,
46
44
  *,
47
- transform: Callable[[T], U] | None = None,
48
- list: bool = False,
49
- unique: Literal[True],
50
- ) -> Mapping[UH, T]: ...
45
+ pre: Callable[[T], U],
46
+ post: Literal["tuple"],
47
+ ) -> Mapping[UH, tuple[U, ...]]: ...
51
48
  @overload
52
49
  def bucket_mapping[T, U, UH: Hashable](
53
50
  iterable: Iterable[T],
54
51
  func: Callable[[T], UH],
55
52
  /,
56
53
  *,
57
- transform: Callable[[T], U],
58
- list: Literal[True],
59
- ) -> Mapping[UH, Sequence[U]]: ...
54
+ pre: Callable[[T], U],
55
+ post: Literal["set"],
56
+ ) -> Mapping[UH, set[U]]: ...
60
57
  @overload
61
58
  def bucket_mapping[T, U, UH: Hashable](
62
59
  iterable: Iterable[T],
63
60
  func: Callable[[T], UH],
64
61
  /,
65
62
  *,
66
- transform: Callable[[T], U],
67
- list: bool = False,
68
- ) -> Mapping[UH, Iterator[U]]: ...
63
+ pre: Callable[[T], U],
64
+ post: Literal["frozenset"],
65
+ ) -> Mapping[UH, frozenset[U]]: ...
69
66
  @overload
70
67
  def bucket_mapping[T, U, UH: Hashable](
71
68
  iterable: Iterable[T],
72
69
  func: Callable[[T], UH],
73
70
  /,
74
71
  *,
75
- transform: Callable[[T], U] | None = None,
76
- list: Literal[True],
77
- ) -> Mapping[UH, Sequence[T]]: ...
72
+ pre: Callable[[T], U] | None = None,
73
+ post: Literal["unique"],
74
+ ) -> Mapping[UH, U]: ...
78
75
  @overload
79
76
  def bucket_mapping[T, U, UH: Hashable](
80
77
  iterable: Iterable[T],
81
78
  func: Callable[[T], UH],
82
79
  /,
83
80
  *,
84
- transform: Callable[[T], U] | None = None,
85
- list: bool = False,
81
+ pre: Callable[[T], U] | None = None,
82
+ post: None = None,
83
+ ) -> Mapping[UH, Iterator[U]]: ...
84
+ @overload
85
+ def bucket_mapping[T, UH: Hashable](
86
+ iterable: Iterable[T],
87
+ func: Callable[[T], UH],
88
+ /,
89
+ *,
90
+ pre: None = None,
91
+ post: Literal["list"],
92
+ ) -> Mapping[UH, list[T]]: ...
93
+ @overload
94
+ def bucket_mapping[T, UH: Hashable](
95
+ iterable: Iterable[T],
96
+ func: Callable[[T], UH],
97
+ /,
98
+ *,
99
+ pre: None = None,
100
+ post: Literal["tuple"],
101
+ ) -> Mapping[UH, tuple[T, ...]]: ...
102
+ @overload
103
+ def bucket_mapping[T, UH: Hashable](
104
+ iterable: Iterable[T],
105
+ func: Callable[[T], UH],
106
+ /,
107
+ *,
108
+ pre: None = None,
109
+ post: Literal["set"],
110
+ ) -> Mapping[UH, set[T]]: ...
111
+ @overload
112
+ def bucket_mapping[T, UH: Hashable](
113
+ iterable: Iterable[T],
114
+ func: Callable[[T], UH],
115
+ /,
116
+ *,
117
+ pre: None = None,
118
+ post: Literal["frozenset"],
119
+ ) -> Mapping[UH, frozenset[T]]: ...
120
+ @overload
121
+ def bucket_mapping[T, UH: Hashable](
122
+ iterable: Iterable[T],
123
+ func: Callable[[T], UH],
124
+ /,
125
+ *,
126
+ pre: None = None,
127
+ post: Literal["unique"],
128
+ ) -> Mapping[UH, T]: ...
129
+ @overload
130
+ def bucket_mapping[T, UH: Hashable](
131
+ iterable: Iterable[T],
132
+ func: Callable[[T], UH],
133
+ /,
134
+ *,
135
+ pre: None = None,
136
+ post: None = None,
86
137
  ) -> Mapping[UH, Iterator[T]]: ...
87
138
  @overload
88
139
  def bucket_mapping[T, U, UH: Hashable](
@@ -90,15 +141,20 @@ def bucket_mapping[T, U, UH: Hashable](
90
141
  func: Callable[[T], UH],
91
142
  /,
92
143
  *,
93
- transform: Callable[[T], U] | None = None,
94
- list: bool = False,
95
- unique: bool = False,
144
+ pre: Callable[[T], U] | None = None,
145
+ post: Literal["list", "tuple", "set", "frozenset", "unique"] | None = None,
96
146
  ) -> (
97
147
  Mapping[UH, Iterator[T]]
98
- | Mapping[UH, Iterator[U]]
99
- | Mapping[UH, Sequence[T]]
100
- | Mapping[UH, Sequence[U]]
148
+ | Mapping[UH, list[T]]
149
+ | Mapping[UH, tuple[T, ...]]
150
+ | Mapping[UH, set[T]]
151
+ | Mapping[UH, frozenset[T]]
101
152
  | Mapping[UH, T]
153
+ | Mapping[UH, Iterator[U]]
154
+ | Mapping[UH, list[U]]
155
+ | Mapping[UH, tuple[U, ...]]
156
+ | Mapping[UH, set[U]]
157
+ | Mapping[UH, frozenset[U]]
102
158
  | Mapping[UH, U]
103
159
  ): ...
104
160
  def bucket_mapping[T, U, UH: Hashable](
@@ -106,42 +162,66 @@ def bucket_mapping[T, U, UH: Hashable](
106
162
  func: Callable[[T], UH],
107
163
  /,
108
164
  *,
109
- transform: Callable[[T], U] | None = None,
110
- list: bool = False, # noqa: A002
111
- unique: bool = False,
165
+ pre: Callable[[T], U] | None = None,
166
+ post: Literal["list", "tuple", "set", "frozenset", "unique"] | None = None,
112
167
  ) -> (
113
168
  Mapping[UH, Iterator[T]]
114
- | Mapping[UH, Iterator[U]]
115
- | Mapping[UH, Sequence[T]]
116
- | Mapping[UH, Sequence[U]]
169
+ | Mapping[UH, list[T]]
170
+ | Mapping[UH, tuple[T, ...]]
171
+ | Mapping[UH, set[T]]
172
+ | Mapping[UH, frozenset[T]]
117
173
  | Mapping[UH, T]
174
+ | Mapping[UH, Iterator[U]]
175
+ | Mapping[UH, list[U]]
176
+ | Mapping[UH, tuple[U, ...]]
177
+ | Mapping[UH, set[U]]
178
+ | Mapping[UH, frozenset[U]]
118
179
  | Mapping[UH, U]
119
180
  ):
120
181
  """Bucket the values of iterable into a mapping."""
121
- b = bucket(iterable, func)
122
- mapping = {key: b[key] for key in b}
123
- match transform, list:
124
- case None, False:
125
- ...
126
- case None, True:
127
- mapping = {k: builtins.list(v) for k, v in mapping.items()}
128
- case _, False:
129
- mapping = {k: map(transform, v) for k, v in mapping.items()}
130
- case _, True:
131
- mapping = {k: builtins.list(map(transform, v)) for k, v in mapping.items()}
182
+ bckt = bucket(iterable, func)
183
+ mapping = {key: bckt[key] for key in bckt}
184
+ match pre, post:
185
+ case None, None:
186
+ return mapping
187
+ case None, "list":
188
+ return {k: list(v) for k, v in mapping.items()}
189
+ case None, "tuple":
190
+ return {k: tuple(v) for k, v in mapping.items()}
191
+ case None, "set":
192
+ return {k: set(v) for k, v in mapping.items()}
193
+ case None, "frozenset":
194
+ return {k: frozenset(v) for k, v in mapping.items()}
195
+ case None, "unique":
196
+ return _bucket_mapping_unique(mapping)
197
+ case Callable(), None:
198
+ return {k: map(pre, v) for k, v in mapping.items()}
199
+ case Callable(), "list":
200
+ return {k: list(map(pre, v)) for k, v in mapping.items()}
201
+ case Callable(), "tuple":
202
+ return {k: tuple(map(pre, v)) for k, v in mapping.items()}
203
+ case Callable(), "set":
204
+ return {k: set(map(pre, v)) for k, v in mapping.items()}
205
+ case Callable(), "frozenset":
206
+ return {k: frozenset(map(pre, v)) for k, v in mapping.items()}
207
+ case Callable(), "unique":
208
+ return _bucket_mapping_unique({k: map(pre, v) for k, v in mapping.items()})
132
209
  case _ as never:
133
210
  assert_never(never)
134
- if not unique:
135
- return mapping
136
- results = {}
137
- error_no_transform: dict[UH, tuple[T, T]] = {}
211
+
212
+
213
+ def _bucket_mapping_unique[K: Hashable, V](
214
+ mapping: Mapping[K, Iterable[V]], /
215
+ ) -> Mapping[K, V]:
216
+ results: dict[K, V] = {}
217
+ errors: dict[K, tuple[V, V]] = {}
138
218
  for key, value in mapping.items():
139
219
  try:
140
220
  results[key] = one(value)
141
221
  except OneNonUniqueError as error:
142
- error_no_transform[key] = (error.first, error.second)
143
- if len(error_no_transform) >= 1:
144
- raise BucketMappingError(errors=error_no_transform)
222
+ errors[key] = (error.first, error.second)
223
+ if len(errors) >= 1:
224
+ raise BucketMappingError(errors=errors)
145
225
  return results
146
226
 
147
227