dycw-utilities 0.166.30__py3-none-any.whl → 0.185.8__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.
- dycw_utilities-0.185.8.dist-info/METADATA +33 -0
- dycw_utilities-0.185.8.dist-info/RECORD +90 -0
- {dycw_utilities-0.166.30.dist-info → dycw_utilities-0.185.8.dist-info}/WHEEL +1 -1
- {dycw_utilities-0.166.30.dist-info → dycw_utilities-0.185.8.dist-info}/entry_points.txt +1 -0
- utilities/__init__.py +1 -1
- utilities/altair.py +17 -10
- utilities/asyncio.py +50 -72
- utilities/atools.py +9 -11
- utilities/cachetools.py +16 -11
- utilities/click.py +76 -19
- utilities/concurrent.py +1 -1
- utilities/constants.py +492 -0
- utilities/contextlib.py +23 -30
- utilities/contextvars.py +1 -23
- utilities/core.py +2581 -0
- utilities/dataclasses.py +16 -119
- utilities/docker.py +387 -0
- utilities/enum.py +1 -1
- utilities/errors.py +2 -16
- utilities/fastapi.py +5 -5
- utilities/fpdf2.py +2 -1
- utilities/functions.py +34 -265
- utilities/http.py +2 -3
- utilities/hypothesis.py +84 -29
- utilities/importlib.py +17 -1
- utilities/iterables.py +39 -575
- utilities/jinja2.py +145 -0
- utilities/jupyter.py +5 -3
- utilities/libcst.py +1 -1
- utilities/lightweight_charts.py +4 -6
- utilities/logging.py +24 -24
- utilities/math.py +1 -36
- utilities/more_itertools.py +4 -6
- utilities/numpy.py +2 -1
- utilities/operator.py +2 -2
- utilities/orjson.py +42 -43
- utilities/os.py +4 -147
- utilities/packaging.py +129 -0
- utilities/parse.py +35 -15
- utilities/pathlib.py +3 -120
- utilities/platform.py +8 -90
- utilities/polars.py +38 -32
- utilities/postgres.py +37 -33
- utilities/pottery.py +20 -18
- utilities/pqdm.py +3 -4
- utilities/psutil.py +2 -3
- utilities/pydantic.py +25 -0
- utilities/pydantic_settings.py +87 -16
- utilities/pydantic_settings_sops.py +16 -3
- utilities/pyinstrument.py +4 -4
- utilities/pytest.py +96 -125
- utilities/pytest_plugins/pytest_regressions.py +2 -2
- utilities/pytest_regressions.py +32 -11
- utilities/random.py +2 -8
- utilities/redis.py +98 -94
- utilities/reprlib.py +11 -118
- utilities/shellingham.py +66 -0
- utilities/shutil.py +25 -0
- utilities/slack_sdk.py +13 -12
- utilities/sqlalchemy.py +57 -30
- utilities/sqlalchemy_polars.py +16 -25
- utilities/subprocess.py +2590 -0
- utilities/tabulate.py +32 -0
- utilities/testbook.py +8 -8
- utilities/text.py +24 -99
- utilities/throttle.py +159 -0
- utilities/time.py +18 -0
- utilities/timer.py +31 -14
- utilities/traceback.py +16 -23
- utilities/types.py +42 -2
- utilities/typing.py +26 -14
- utilities/uuid.py +1 -1
- utilities/version.py +202 -45
- utilities/whenever.py +53 -150
- dycw_utilities-0.166.30.dist-info/METADATA +0 -41
- dycw_utilities-0.166.30.dist-info/RECORD +0 -98
- dycw_utilities-0.166.30.dist-info/licenses/LICENSE +0 -21
- utilities/aeventkit.py +0 -388
- utilities/atomicwrites.py +0 -182
- utilities/cryptography.py +0 -41
- utilities/getpass.py +0 -8
- utilities/git.py +0 -19
- utilities/gzip.py +0 -31
- utilities/json.py +0 -70
- utilities/pickle.py +0 -25
- utilities/re.py +0 -156
- utilities/sentinel.py +0 -73
- utilities/socket.py +0 -8
- utilities/string.py +0 -20
- utilities/tempfile.py +0 -77
- utilities/typed_settings.py +0 -152
- utilities/tzdata.py +0 -11
- utilities/tzlocal.py +0 -28
- utilities/warnings.py +0 -65
- utilities/zipfile.py +0 -25
- utilities/zoneinfo.py +0 -133
utilities/iterables.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import builtins
|
|
4
3
|
from collections import Counter
|
|
5
4
|
from collections.abc import (
|
|
6
5
|
Callable,
|
|
@@ -14,11 +13,10 @@ from collections.abc import (
|
|
|
14
13
|
from collections.abc import Set as AbstractSet
|
|
15
14
|
from contextlib import suppress
|
|
16
15
|
from dataclasses import dataclass
|
|
17
|
-
from
|
|
18
|
-
from
|
|
19
|
-
from itertools import accumulate, chain, groupby, islice, pairwise, product
|
|
16
|
+
from functools import cmp_to_key, reduce
|
|
17
|
+
from itertools import groupby
|
|
20
18
|
from math import isnan
|
|
21
|
-
from operator import
|
|
19
|
+
from operator import or_
|
|
22
20
|
from typing import (
|
|
23
21
|
TYPE_CHECKING,
|
|
24
22
|
Any,
|
|
@@ -30,6 +28,7 @@ from typing import (
|
|
|
30
28
|
override,
|
|
31
29
|
)
|
|
32
30
|
|
|
31
|
+
from utilities.core import OneStrEmptyError, always_iterable, one, one_str, repr_
|
|
33
32
|
from utilities.errors import ImpossibleCaseError
|
|
34
33
|
from utilities.math import (
|
|
35
34
|
_CheckIntegerEqualError,
|
|
@@ -38,9 +37,7 @@ from utilities.math import (
|
|
|
38
37
|
_CheckIntegerMinError,
|
|
39
38
|
check_integer,
|
|
40
39
|
)
|
|
41
|
-
from utilities.
|
|
42
|
-
from utilities.sentinel import Sentinel, is_sentinel, sentinel
|
|
43
|
-
from utilities.types import SupportsAdd, SupportsLT
|
|
40
|
+
from utilities.types import SupportsLT
|
|
44
41
|
|
|
45
42
|
if TYPE_CHECKING:
|
|
46
43
|
from types import NoneType
|
|
@@ -48,23 +45,6 @@ if TYPE_CHECKING:
|
|
|
48
45
|
from utilities.types import MaybeIterable, Sign, StrMapping
|
|
49
46
|
|
|
50
47
|
|
|
51
|
-
##
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def always_iterable[T](obj: MaybeIterable[T], /) -> Iterable[T]:
|
|
55
|
-
"""Typed version of `always_iterable`."""
|
|
56
|
-
obj = cast("Any", obj)
|
|
57
|
-
if isinstance(obj, str | bytes):
|
|
58
|
-
return cast("list[T]", [obj])
|
|
59
|
-
try:
|
|
60
|
-
return iter(cast("Iterable[T]", obj))
|
|
61
|
-
except TypeError:
|
|
62
|
-
return cast("list[T]", [obj])
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
##
|
|
66
|
-
|
|
67
|
-
|
|
68
48
|
def apply_bijection[T, U](
|
|
69
49
|
func: Callable[[T], U], iterable: Iterable[T], /
|
|
70
50
|
) -> Mapping[T, U]:
|
|
@@ -96,7 +76,7 @@ class ApplyBijectionError[T](Exception):
|
|
|
96
76
|
class _ApplyBijectionDuplicateKeysError[T](ApplyBijectionError[T]):
|
|
97
77
|
@override
|
|
98
78
|
def __str__(self) -> str:
|
|
99
|
-
return f"Keys {
|
|
79
|
+
return f"Keys {repr_(self.keys)} must not contain duplicates; got {repr_(self.counts)}"
|
|
100
80
|
|
|
101
81
|
|
|
102
82
|
@dataclass(kw_only=True, slots=True)
|
|
@@ -105,7 +85,7 @@ class _ApplyBijectionDuplicateValuesError[T, U](ApplyBijectionError[T]):
|
|
|
105
85
|
|
|
106
86
|
@override
|
|
107
87
|
def __str__(self) -> str:
|
|
108
|
-
return f"Values {
|
|
88
|
+
return f"Values {repr_(self.values)} must not contain duplicates; got {repr_(self.counts)}"
|
|
109
89
|
|
|
110
90
|
|
|
111
91
|
##
|
|
@@ -116,9 +96,6 @@ def apply_to_tuple[T](func: Callable[..., T], args: tuple[Any, ...], /) -> T:
|
|
|
116
96
|
return apply_to_varargs(func, *args)
|
|
117
97
|
|
|
118
98
|
|
|
119
|
-
##
|
|
120
|
-
|
|
121
|
-
|
|
122
99
|
def apply_to_varargs[T](func: Callable[..., T], *args: Any) -> T:
|
|
123
100
|
"""Apply a function to a variable number of arguments."""
|
|
124
101
|
return func(*args)
|
|
@@ -127,62 +104,6 @@ def apply_to_varargs[T](func: Callable[..., T], *args: Any) -> T:
|
|
|
127
104
|
##
|
|
128
105
|
|
|
129
106
|
|
|
130
|
-
@overload
|
|
131
|
-
def chain_mappings[K, V](
|
|
132
|
-
*mappings: Mapping[K, V], list: Literal[True]
|
|
133
|
-
) -> Mapping[K, Sequence[V]]: ...
|
|
134
|
-
@overload
|
|
135
|
-
def chain_mappings[K, V](
|
|
136
|
-
*mappings: Mapping[K, V], list: bool = False
|
|
137
|
-
) -> Mapping[K, Iterable[V]]: ...
|
|
138
|
-
def chain_mappings[K, V](
|
|
139
|
-
*mappings: Mapping[K, V],
|
|
140
|
-
list: bool = False, # noqa: A002
|
|
141
|
-
) -> Mapping[K, Iterable[V]]:
|
|
142
|
-
"""Chain the values of a set of mappings."""
|
|
143
|
-
try:
|
|
144
|
-
first, *rest = mappings
|
|
145
|
-
except ValueError:
|
|
146
|
-
return {}
|
|
147
|
-
initial = {k: [v] for k, v in first.items()}
|
|
148
|
-
reduced = reduce(_chain_mappings_one, rest, initial)
|
|
149
|
-
if list:
|
|
150
|
-
return {k: builtins.list(v) for k, v in reduced.items()}
|
|
151
|
-
return reduced
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
def _chain_mappings_one[K, V](
|
|
155
|
-
acc: Mapping[K, Iterable[V]], el: Mapping[K, V], /
|
|
156
|
-
) -> Mapping[K, Iterable[V]]:
|
|
157
|
-
"""Chain the values of a set of mappings."""
|
|
158
|
-
out = dict(acc)
|
|
159
|
-
for key, value in el.items():
|
|
160
|
-
out[key] = chain(out.get(key, []), [value])
|
|
161
|
-
return out
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
##
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
def chain_maybe_iterables[T](*maybe_iterables: MaybeIterable[T]) -> Iterable[T]:
|
|
168
|
-
"""Chain a set of maybe iterables."""
|
|
169
|
-
iterables = map(always_iterable, maybe_iterables)
|
|
170
|
-
return chain.from_iterable(iterables)
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
##
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
def chain_nullable[T](*maybe_iterables: Iterable[T | None] | None) -> Iterable[T]:
|
|
177
|
-
"""Chain a set of values; ignoring nulls."""
|
|
178
|
-
iterables = (mi for mi in maybe_iterables if mi is not None)
|
|
179
|
-
values = ((i for i in it if i is not None) for it in iterables)
|
|
180
|
-
return chain.from_iterable(values)
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
##
|
|
184
|
-
|
|
185
|
-
|
|
186
107
|
def check_bijection(mapping: Mapping[Any, Hashable], /) -> None:
|
|
187
108
|
"""Check if a mapping is a bijection."""
|
|
188
109
|
try:
|
|
@@ -198,7 +119,7 @@ class CheckBijectionError[THashable](Exception):
|
|
|
198
119
|
|
|
199
120
|
@override
|
|
200
121
|
def __str__(self) -> str:
|
|
201
|
-
return f"Mapping {
|
|
122
|
+
return f"Mapping {repr_(self.mapping)} must be a bijection; got duplicates {repr_(self.counts)}"
|
|
202
123
|
|
|
203
124
|
|
|
204
125
|
##
|
|
@@ -218,7 +139,7 @@ class CheckDuplicatesError[THashable](Exception):
|
|
|
218
139
|
|
|
219
140
|
@override
|
|
220
141
|
def __str__(self) -> str:
|
|
221
|
-
return f"Iterable {
|
|
142
|
+
return f"Iterable {repr_(self.iterable)} must not contain duplicates; got {repr_(self.counts)}"
|
|
222
143
|
|
|
223
144
|
|
|
224
145
|
##
|
|
@@ -270,12 +191,12 @@ class CheckIterablesEqualError[T](Exception):
|
|
|
270
191
|
desc = f"{first} and {second}"
|
|
271
192
|
case _: # pragma: no cover
|
|
272
193
|
raise ImpossibleCaseError(case=[f"{parts=}"])
|
|
273
|
-
return f"Iterables {
|
|
194
|
+
return f"Iterables {repr_(self.left)} and {repr_(self.right)} must be equal; {desc}"
|
|
274
195
|
|
|
275
196
|
def _yield_parts(self) -> Iterator[str]:
|
|
276
197
|
if len(self.errors) >= 1:
|
|
277
198
|
errors = [(f"{i=}", lv, rv) for i, lv, rv in self.errors]
|
|
278
|
-
yield f"differing items were {
|
|
199
|
+
yield f"differing items were {repr_(errors)}"
|
|
279
200
|
match self.state:
|
|
280
201
|
case "left_longer":
|
|
281
202
|
yield "left was longer"
|
|
@@ -326,7 +247,7 @@ class _CheckLengthEqualError(CheckLengthError):
|
|
|
326
247
|
|
|
327
248
|
@override
|
|
328
249
|
def __str__(self) -> str:
|
|
329
|
-
return f"Object {
|
|
250
|
+
return f"Object {repr_(self.obj)} must have length {self.equal}; got {len(self.obj)}"
|
|
330
251
|
|
|
331
252
|
|
|
332
253
|
@dataclass(kw_only=True, slots=True)
|
|
@@ -340,7 +261,7 @@ class _CheckLengthEqualOrApproxError(CheckLengthError):
|
|
|
340
261
|
desc = f"approximate length {target} (error {error:%})"
|
|
341
262
|
case target:
|
|
342
263
|
desc = f"length {target}"
|
|
343
|
-
return f"Object {
|
|
264
|
+
return f"Object {repr_(self.obj)} must have {desc}; got {len(self.obj)}"
|
|
344
265
|
|
|
345
266
|
|
|
346
267
|
@dataclass(kw_only=True, slots=True)
|
|
@@ -349,7 +270,7 @@ class _CheckLengthMinError(CheckLengthError):
|
|
|
349
270
|
|
|
350
271
|
@override
|
|
351
272
|
def __str__(self) -> str:
|
|
352
|
-
return f"Object {
|
|
273
|
+
return f"Object {repr_(self.obj)} must have minimum length {self.min_}; got {len(self.obj)}"
|
|
353
274
|
|
|
354
275
|
|
|
355
276
|
@dataclass(kw_only=True, slots=True)
|
|
@@ -358,7 +279,7 @@ class _CheckLengthMaxError(CheckLengthError):
|
|
|
358
279
|
|
|
359
280
|
@override
|
|
360
281
|
def __str__(self) -> str:
|
|
361
|
-
return f"Object {
|
|
282
|
+
return f"Object {repr_(self.obj)} must have maximum length {self.max_}; got {len(self.obj)}"
|
|
362
283
|
|
|
363
284
|
|
|
364
285
|
##
|
|
@@ -377,7 +298,7 @@ class CheckLengthsEqualError(Exception):
|
|
|
377
298
|
|
|
378
299
|
@override
|
|
379
300
|
def __str__(self) -> str:
|
|
380
|
-
return f"Sized objects {
|
|
301
|
+
return f"Sized objects {repr_(self.left)} and {repr_(self.right)} must have the same length; got {len(self.left)} and {len(self.right)}"
|
|
381
302
|
|
|
382
303
|
|
|
383
304
|
##
|
|
@@ -427,16 +348,18 @@ class CheckMappingsEqualError[K, V](Exception):
|
|
|
427
348
|
desc = f"{first}, {second} and {third}"
|
|
428
349
|
case _: # pragma: no cover
|
|
429
350
|
raise ImpossibleCaseError(case=[f"{parts=}"])
|
|
430
|
-
return
|
|
351
|
+
return (
|
|
352
|
+
f"Mappings {repr_(self.left)} and {repr_(self.right)} must be equal; {desc}"
|
|
353
|
+
)
|
|
431
354
|
|
|
432
355
|
def _yield_parts(self) -> Iterator[str]:
|
|
433
356
|
if len(self.left_extra) >= 1:
|
|
434
|
-
yield f"left had extra keys {
|
|
357
|
+
yield f"left had extra keys {repr_(self.left_extra)}"
|
|
435
358
|
if len(self.right_extra) >= 1:
|
|
436
|
-
yield f"right had extra keys {
|
|
359
|
+
yield f"right had extra keys {repr_(self.right_extra)}"
|
|
437
360
|
if len(self.errors) >= 1:
|
|
438
361
|
errors = [(f"{k=}", lv, rv) for k, lv, rv in self.errors]
|
|
439
|
-
yield f"differing values were {
|
|
362
|
+
yield f"differing values were {repr_(errors)}"
|
|
440
363
|
|
|
441
364
|
|
|
442
365
|
##
|
|
@@ -474,13 +397,13 @@ class CheckSetsEqualError[T](Exception):
|
|
|
474
397
|
desc = f"{first} and {second}"
|
|
475
398
|
case _: # pragma: no cover
|
|
476
399
|
raise ImpossibleCaseError(case=[f"{parts=}"])
|
|
477
|
-
return f"Sets {
|
|
400
|
+
return f"Sets {repr_(self.left)} and {repr_(self.right)} must be equal; {desc}"
|
|
478
401
|
|
|
479
402
|
def _yield_parts(self) -> Iterator[str]:
|
|
480
403
|
if len(self.left_extra) >= 1:
|
|
481
|
-
yield f"left had extra items {
|
|
404
|
+
yield f"left had extra items {repr_(self.left_extra)}"
|
|
482
405
|
if len(self.right_extra) >= 1:
|
|
483
|
-
yield f"right had extra items {
|
|
406
|
+
yield f"right had extra items {repr_(self.right_extra)}"
|
|
484
407
|
|
|
485
408
|
|
|
486
409
|
##
|
|
@@ -521,14 +444,14 @@ class CheckSubMappingError[K, V](Exception):
|
|
|
521
444
|
desc = f"{first} and {second}"
|
|
522
445
|
case _: # pragma: no cover
|
|
523
446
|
raise ImpossibleCaseError(case=[f"{parts=}"])
|
|
524
|
-
return f"Mapping {
|
|
447
|
+
return f"Mapping {repr_(self.left)} must be a submapping of {repr_(self.right)}; {desc}"
|
|
525
448
|
|
|
526
449
|
def _yield_parts(self) -> Iterator[str]:
|
|
527
450
|
if len(self.extra) >= 1:
|
|
528
|
-
yield f"left had extra keys {
|
|
451
|
+
yield f"left had extra keys {repr_(self.extra)}"
|
|
529
452
|
if len(self.errors) >= 1:
|
|
530
453
|
errors = [(f"{k=}", lv, rv) for k, lv, rv in self.errors]
|
|
531
|
-
yield f"differing values were {
|
|
454
|
+
yield f"differing values were {repr_(errors)}"
|
|
532
455
|
|
|
533
456
|
|
|
534
457
|
##
|
|
@@ -551,7 +474,7 @@ class CheckSubSetError[T](Exception):
|
|
|
551
474
|
|
|
552
475
|
@override
|
|
553
476
|
def __str__(self) -> str:
|
|
554
|
-
return f"Set {
|
|
477
|
+
return f"Set {repr_(self.left)} must be a subset of {repr_(self.right)}; left had extra items {repr_(self.extra)}"
|
|
555
478
|
|
|
556
479
|
|
|
557
480
|
##
|
|
@@ -592,14 +515,14 @@ class CheckSuperMappingError[K, V](Exception):
|
|
|
592
515
|
desc = f"{first} and {second}"
|
|
593
516
|
case _: # pragma: no cover
|
|
594
517
|
raise ImpossibleCaseError(case=[f"{parts=}"])
|
|
595
|
-
return f"Mapping {
|
|
518
|
+
return f"Mapping {repr_(self.left)} must be a supermapping of {repr_(self.right)}; {desc}"
|
|
596
519
|
|
|
597
520
|
def _yield_parts(self) -> Iterator[str]:
|
|
598
521
|
if len(self.extra) >= 1:
|
|
599
|
-
yield f"right had extra keys {
|
|
522
|
+
yield f"right had extra keys {repr_(self.extra)}"
|
|
600
523
|
if len(self.errors) >= 1:
|
|
601
524
|
errors = [(f"{k=}", lv, rv) for k, lv, rv in self.errors]
|
|
602
|
-
yield f"differing values were {
|
|
525
|
+
yield f"differing values were {repr_(errors)}"
|
|
603
526
|
|
|
604
527
|
|
|
605
528
|
##
|
|
@@ -622,7 +545,7 @@ class CheckSuperSetError[T](Exception):
|
|
|
622
545
|
|
|
623
546
|
@override
|
|
624
547
|
def __str__(self) -> str:
|
|
625
|
-
return f"Set {
|
|
548
|
+
return f"Set {repr_(self.left)} must be a superset of {repr_(self.right)}; right had extra items {repr_(self.extra)}."
|
|
626
549
|
|
|
627
550
|
|
|
628
551
|
##
|
|
@@ -652,7 +575,7 @@ class CheckUniqueModuloCaseError(Exception):
|
|
|
652
575
|
class _CheckUniqueModuloCaseDuplicateStringsError(CheckUniqueModuloCaseError):
|
|
653
576
|
@override
|
|
654
577
|
def __str__(self) -> str:
|
|
655
|
-
return f"Strings {
|
|
578
|
+
return f"Strings {repr_(self.keys)} must not contain duplicates; got {repr_(self.counts)}"
|
|
656
579
|
|
|
657
580
|
|
|
658
581
|
@dataclass(kw_only=True, slots=True)
|
|
@@ -661,7 +584,7 @@ class _CheckUniqueModuloCaseDuplicateLowerCaseStringsError(CheckUniqueModuloCase
|
|
|
661
584
|
|
|
662
585
|
@override
|
|
663
586
|
def __str__(self) -> str:
|
|
664
|
-
return f"Strings {
|
|
587
|
+
return f"Strings {repr_(self.values)} must not contain duplicates (modulo case); got {repr_(self.counts)}"
|
|
665
588
|
|
|
666
589
|
|
|
667
590
|
##
|
|
@@ -685,14 +608,6 @@ def cmp_nullable[T: SupportsLT](x: T | None, y: T | None, /) -> Sign:
|
|
|
685
608
|
##
|
|
686
609
|
|
|
687
610
|
|
|
688
|
-
def chunked[T](iterable: Iterable[T], n: int, /) -> Iterator[Sequence[T]]:
|
|
689
|
-
"""Break an iterable into lists of length n."""
|
|
690
|
-
return iter(partial(take, n, iter(iterable)), [])
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
##
|
|
694
|
-
|
|
695
|
-
|
|
696
611
|
def ensure_iterable(obj: Any, /) -> Iterable[Any]:
|
|
697
612
|
"""Ensure an object is iterable."""
|
|
698
613
|
if is_iterable(obj):
|
|
@@ -706,26 +621,7 @@ class EnsureIterableError(Exception):
|
|
|
706
621
|
|
|
707
622
|
@override
|
|
708
623
|
def __str__(self) -> str:
|
|
709
|
-
return f"Object {
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
##
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
def ensure_iterable_not_str(obj: Any, /) -> Iterable[Any]:
|
|
716
|
-
"""Ensure an object is iterable, but not a string."""
|
|
717
|
-
if is_iterable_not_str(obj):
|
|
718
|
-
return obj
|
|
719
|
-
raise EnsureIterableNotStrError(obj=obj)
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
@dataclass(kw_only=True, slots=True)
|
|
723
|
-
class EnsureIterableNotStrError(Exception):
|
|
724
|
-
obj: Any
|
|
725
|
-
|
|
726
|
-
@override
|
|
727
|
-
def __str__(self) -> str:
|
|
728
|
-
return f"Object {get_repr(self.obj)} must be iterable, but not a string"
|
|
624
|
+
return f"Object {repr_(self.obj)} must be iterable"
|
|
729
625
|
|
|
730
626
|
|
|
731
627
|
##
|
|
@@ -751,18 +647,6 @@ def enumerate_with_edge[T](
|
|
|
751
647
|
##
|
|
752
648
|
|
|
753
649
|
|
|
754
|
-
def expanding_window[T](iterable: Iterable[T], /) -> islice[list[T]]:
|
|
755
|
-
"""Yield an expanding window over an iterable."""
|
|
756
|
-
|
|
757
|
-
def func(acc: Iterable[T], el: T, /) -> list[T]:
|
|
758
|
-
return list(chain(acc, [el]))
|
|
759
|
-
|
|
760
|
-
return islice(accumulate(iterable, func=func, initial=[]), 1, None)
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
##
|
|
764
|
-
|
|
765
|
-
|
|
766
650
|
@overload
|
|
767
651
|
def filter_include_and_exclude[T, U](
|
|
768
652
|
iterable: Iterable[T],
|
|
@@ -830,14 +714,6 @@ def groupby_lists[T, U](
|
|
|
830
714
|
##
|
|
831
715
|
|
|
832
716
|
|
|
833
|
-
def hashable_to_iterable[T: Hashable](obj: T | None, /) -> tuple[T, ...] | None:
|
|
834
|
-
"""Lift a hashable singleton to an iterable of hashables."""
|
|
835
|
-
return None if obj is None else (obj,)
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
##
|
|
839
|
-
|
|
840
|
-
|
|
841
717
|
def is_iterable(obj: Any, /) -> TypeGuard[Iterable[Any]]:
|
|
842
718
|
"""Check if an object is iterable."""
|
|
843
719
|
try:
|
|
@@ -850,14 +726,6 @@ def is_iterable(obj: Any, /) -> TypeGuard[Iterable[Any]]:
|
|
|
850
726
|
##
|
|
851
727
|
|
|
852
728
|
|
|
853
|
-
def is_iterable_not_enum(obj: Any, /) -> TypeGuard[Iterable[Any]]:
|
|
854
|
-
"""Check if an object is iterable, but not an Enum."""
|
|
855
|
-
return is_iterable(obj) and not (isinstance(obj, type) and issubclass(obj, Enum))
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
##
|
|
859
|
-
|
|
860
|
-
|
|
861
729
|
def is_iterable_not_str(obj: Any, /) -> TypeGuard[Iterable[Any]]:
|
|
862
730
|
"""Check if an object is iterable, but not a string."""
|
|
863
731
|
return is_iterable(obj) and not isinstance(obj, str)
|
|
@@ -925,309 +793,7 @@ class MergeStrMappingsError(Exception):
|
|
|
925
793
|
|
|
926
794
|
@override
|
|
927
795
|
def __str__(self) -> str:
|
|
928
|
-
return f"Mapping {
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
##
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
def one[T](*iterables: Iterable[T]) -> T:
|
|
935
|
-
"""Return the unique value in a set of iterables."""
|
|
936
|
-
it = chain(*iterables)
|
|
937
|
-
try:
|
|
938
|
-
first = next(it)
|
|
939
|
-
except StopIteration:
|
|
940
|
-
raise OneEmptyError(iterables=iterables) from None
|
|
941
|
-
try:
|
|
942
|
-
second = next(it)
|
|
943
|
-
except StopIteration:
|
|
944
|
-
return first
|
|
945
|
-
raise OneNonUniqueError(iterables=iterables, first=first, second=second)
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
@dataclass(kw_only=True, slots=True)
|
|
949
|
-
class OneError[T](Exception):
|
|
950
|
-
iterables: tuple[Iterable[T], ...]
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
@dataclass(kw_only=True, slots=True)
|
|
954
|
-
class OneEmptyError[T](OneError[T]):
|
|
955
|
-
@override
|
|
956
|
-
def __str__(self) -> str:
|
|
957
|
-
return f"Iterable(s) {get_repr(self.iterables)} must not be empty"
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
@dataclass(kw_only=True, slots=True)
|
|
961
|
-
class OneNonUniqueError[T](OneError):
|
|
962
|
-
first: T
|
|
963
|
-
second: T
|
|
964
|
-
|
|
965
|
-
@override
|
|
966
|
-
def __str__(self) -> str:
|
|
967
|
-
return f"Iterable(s) {get_repr(self.iterables)} must contain exactly one item; got {self.first}, {self.second} and perhaps more"
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
##
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
def one_maybe[T](*objs: MaybeIterable[T]) -> T:
|
|
974
|
-
"""Return the unique value in a set of values/iterables."""
|
|
975
|
-
try:
|
|
976
|
-
return one(chain_maybe_iterables(*objs))
|
|
977
|
-
except OneEmptyError:
|
|
978
|
-
raise OneMaybeEmptyError from None
|
|
979
|
-
except OneNonUniqueError as error:
|
|
980
|
-
raise OneMaybeNonUniqueError(
|
|
981
|
-
objs=objs, first=error.first, second=error.second
|
|
982
|
-
) from None
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
@dataclass(kw_only=True, slots=True)
|
|
986
|
-
class OneMaybeError(Exception): ...
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
@dataclass(kw_only=True, slots=True)
|
|
990
|
-
class OneMaybeEmptyError(OneMaybeError):
|
|
991
|
-
@override
|
|
992
|
-
def __str__(self) -> str:
|
|
993
|
-
return "Object(s) must not be empty"
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
@dataclass(kw_only=True, slots=True)
|
|
997
|
-
class OneMaybeNonUniqueError[T](OneMaybeError):
|
|
998
|
-
objs: tuple[MaybeIterable[T], ...]
|
|
999
|
-
first: T
|
|
1000
|
-
second: T
|
|
1001
|
-
|
|
1002
|
-
@override
|
|
1003
|
-
def __str__(self) -> str:
|
|
1004
|
-
return f"Object(s) {get_repr(self.objs)} must contain exactly one item; got {self.first}, {self.second} and perhaps more"
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
##
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
def one_str(
|
|
1011
|
-
iterable: Iterable[str],
|
|
1012
|
-
text: str,
|
|
1013
|
-
/,
|
|
1014
|
-
*,
|
|
1015
|
-
head: bool = False,
|
|
1016
|
-
case_sensitive: bool = False,
|
|
1017
|
-
) -> str:
|
|
1018
|
-
"""Find the unique string in an iterable."""
|
|
1019
|
-
as_list = list(iterable)
|
|
1020
|
-
match head, case_sensitive:
|
|
1021
|
-
case False, True:
|
|
1022
|
-
it = (t for t in as_list if t == text)
|
|
1023
|
-
case False, False:
|
|
1024
|
-
it = (t for t in as_list if t.lower() == text.lower())
|
|
1025
|
-
case True, True:
|
|
1026
|
-
it = (t for t in as_list if t.startswith(text))
|
|
1027
|
-
case True, False:
|
|
1028
|
-
it = (t for t in as_list if t.lower().startswith(text.lower()))
|
|
1029
|
-
case never:
|
|
1030
|
-
assert_never(never)
|
|
1031
|
-
try:
|
|
1032
|
-
return one(it)
|
|
1033
|
-
except OneEmptyError:
|
|
1034
|
-
raise OneStrEmptyError(
|
|
1035
|
-
iterable=as_list, text=text, head=head, case_sensitive=case_sensitive
|
|
1036
|
-
) from None
|
|
1037
|
-
except OneNonUniqueError as error:
|
|
1038
|
-
raise OneStrNonUniqueError(
|
|
1039
|
-
iterable=as_list,
|
|
1040
|
-
text=text,
|
|
1041
|
-
head=head,
|
|
1042
|
-
case_sensitive=case_sensitive,
|
|
1043
|
-
first=error.first,
|
|
1044
|
-
second=error.second,
|
|
1045
|
-
) from None
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
@dataclass(kw_only=True, slots=True)
|
|
1049
|
-
class OneStrError(Exception):
|
|
1050
|
-
iterable: Iterable[str]
|
|
1051
|
-
text: str
|
|
1052
|
-
head: bool = False
|
|
1053
|
-
case_sensitive: bool = False
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
@dataclass(kw_only=True, slots=True)
|
|
1057
|
-
class OneStrEmptyError(OneStrError):
|
|
1058
|
-
@override
|
|
1059
|
-
def __str__(self) -> str:
|
|
1060
|
-
head = f"Iterable {get_repr(self.iterable)} does not contain"
|
|
1061
|
-
match self.head, self.case_sensitive:
|
|
1062
|
-
case False, True:
|
|
1063
|
-
tail = repr(self.text)
|
|
1064
|
-
case False, False:
|
|
1065
|
-
tail = f"{self.text!r} (modulo case)"
|
|
1066
|
-
case True, True:
|
|
1067
|
-
tail = f"any string starting with {self.text!r}"
|
|
1068
|
-
case True, False:
|
|
1069
|
-
tail = f"any string starting with {self.text!r} (modulo case)"
|
|
1070
|
-
case never:
|
|
1071
|
-
assert_never(never)
|
|
1072
|
-
return f"{head} {tail}"
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
@dataclass(kw_only=True, slots=True)
|
|
1076
|
-
class OneStrNonUniqueError(OneStrError):
|
|
1077
|
-
first: str
|
|
1078
|
-
second: str
|
|
1079
|
-
|
|
1080
|
-
@override
|
|
1081
|
-
def __str__(self) -> str:
|
|
1082
|
-
head = f"Iterable {get_repr(self.iterable)} must contain"
|
|
1083
|
-
match self.head, self.case_sensitive:
|
|
1084
|
-
case False, True:
|
|
1085
|
-
mid = f"{self.text!r} exactly once"
|
|
1086
|
-
case False, False:
|
|
1087
|
-
mid = f"{self.text!r} exactly once (modulo case)"
|
|
1088
|
-
case True, True:
|
|
1089
|
-
mid = f"exactly one string starting with {self.text!r}"
|
|
1090
|
-
case True, False:
|
|
1091
|
-
mid = f"exactly one string starting with {self.text!r} (modulo case)"
|
|
1092
|
-
case never:
|
|
1093
|
-
assert_never(never)
|
|
1094
|
-
return f"{head} {mid}; got {self.first!r}, {self.second!r} and perhaps more"
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
##
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
def one_unique[T: Hashable](*iterables: Iterable[T]) -> T:
|
|
1101
|
-
"""Return the set-unique value in a set of iterables."""
|
|
1102
|
-
try:
|
|
1103
|
-
return one(set(chain(*iterables)))
|
|
1104
|
-
except OneEmptyError:
|
|
1105
|
-
raise OneUniqueEmptyError from None
|
|
1106
|
-
except OneNonUniqueError as error:
|
|
1107
|
-
raise OneUniqueNonUniqueError(
|
|
1108
|
-
iterables=iterables, first=error.first, second=error.second
|
|
1109
|
-
) from None
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
@dataclass(kw_only=True, slots=True)
|
|
1113
|
-
class OneUniqueError(Exception): ...
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
@dataclass(kw_only=True, slots=True)
|
|
1117
|
-
class OneUniqueEmptyError(OneUniqueError):
|
|
1118
|
-
@override
|
|
1119
|
-
def __str__(self) -> str:
|
|
1120
|
-
return "Iterable(s) must not be empty"
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
@dataclass(kw_only=True, slots=True)
|
|
1124
|
-
class OneUniqueNonUniqueError[THashable](OneUniqueError):
|
|
1125
|
-
iterables: tuple[MaybeIterable[THashable], ...]
|
|
1126
|
-
first: THashable
|
|
1127
|
-
second: THashable
|
|
1128
|
-
|
|
1129
|
-
@override
|
|
1130
|
-
def __str__(self) -> str:
|
|
1131
|
-
return f"Iterable(s) {get_repr(self.iterables)} must contain exactly one item; got {self.first}, {self.second} and perhaps more"
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
##
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
def pairwise_tail[T](iterable: Iterable[T], /) -> Iterator[tuple[T, T | Sentinel]]:
|
|
1138
|
-
"""Return pairwise elements, with the last paired with the sentinel."""
|
|
1139
|
-
return pairwise(chain(iterable, [sentinel]))
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
##
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
def product_dicts[K, V](mapping: Mapping[K, Iterable[V]], /) -> Iterator[Mapping[K, V]]:
|
|
1146
|
-
"""Return the cartesian product of the values in a mapping, as mappings."""
|
|
1147
|
-
keys = list(mapping)
|
|
1148
|
-
for values in product(*mapping.values()):
|
|
1149
|
-
yield cast("Mapping[K, V]", dict(zip(keys, values, strict=True)))
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
##
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
def range_partitions(stop: int, num: int, total: int, /) -> range:
|
|
1156
|
-
"""Partition a range."""
|
|
1157
|
-
if stop <= 0:
|
|
1158
|
-
raise _RangePartitionsStopError(stop=stop)
|
|
1159
|
-
if not (1 <= total <= stop):
|
|
1160
|
-
raise _RangePartitionsTotalError(stop=stop, total=total)
|
|
1161
|
-
if not (0 <= num < total):
|
|
1162
|
-
raise _RangePartitionsNumError(num=num, total=total)
|
|
1163
|
-
q, r = divmod(stop, total)
|
|
1164
|
-
start = num * q + min(num, r)
|
|
1165
|
-
end = start + q + (1 if num < r else 0)
|
|
1166
|
-
return range(start, end)
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
@dataclass(kw_only=True, slots=True)
|
|
1170
|
-
class RangePartitionsError(Exception): ...
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
@dataclass(kw_only=True, slots=True)
|
|
1174
|
-
class _RangePartitionsStopError(RangePartitionsError):
|
|
1175
|
-
stop: int
|
|
1176
|
-
|
|
1177
|
-
@override
|
|
1178
|
-
def __str__(self) -> str:
|
|
1179
|
-
return f"'stop' must be positive; got {self.stop}"
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
@dataclass(kw_only=True, slots=True)
|
|
1183
|
-
class _RangePartitionsTotalError(RangePartitionsError):
|
|
1184
|
-
stop: int
|
|
1185
|
-
total: int
|
|
1186
|
-
|
|
1187
|
-
@override
|
|
1188
|
-
def __str__(self) -> str:
|
|
1189
|
-
return f"'total' must be in [1, {self.stop}]; got {self.total}"
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
@dataclass(kw_only=True, slots=True)
|
|
1193
|
-
class _RangePartitionsNumError(RangePartitionsError):
|
|
1194
|
-
num: int
|
|
1195
|
-
total: int
|
|
1196
|
-
|
|
1197
|
-
@override
|
|
1198
|
-
def __str__(self) -> str:
|
|
1199
|
-
return f"'num' must be in [0, {self.total - 1}]; got {self.num}"
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
##
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
@overload
|
|
1206
|
-
def reduce_mappings[K, V](
|
|
1207
|
-
func: Callable[[V, V], V], sequence: Iterable[Mapping[K, V]], /
|
|
1208
|
-
) -> Mapping[K, V]: ...
|
|
1209
|
-
@overload
|
|
1210
|
-
def reduce_mappings[K, V, W](
|
|
1211
|
-
func: Callable[[W, V], W],
|
|
1212
|
-
sequence: Iterable[Mapping[K, V]],
|
|
1213
|
-
/,
|
|
1214
|
-
*,
|
|
1215
|
-
initial: W | Sentinel = sentinel,
|
|
1216
|
-
) -> Mapping[K, W]: ...
|
|
1217
|
-
def reduce_mappings[K, V, W](
|
|
1218
|
-
func: Callable[[V, V], V] | Callable[[W, V], W],
|
|
1219
|
-
sequence: Iterable[Mapping[K, V]],
|
|
1220
|
-
/,
|
|
1221
|
-
*,
|
|
1222
|
-
initial: W | Sentinel = sentinel,
|
|
1223
|
-
) -> Mapping[K, V | W]:
|
|
1224
|
-
"""Reduce a function over the values of a set of mappings."""
|
|
1225
|
-
chained = chain_mappings(*sequence)
|
|
1226
|
-
if is_sentinel(initial):
|
|
1227
|
-
func2 = cast("Callable[[V, V], V]", func)
|
|
1228
|
-
return {k: reduce(func2, v) for k, v in chained.items()}
|
|
1229
|
-
func2 = cast("Callable[[W, V], W]", func)
|
|
1230
|
-
return {k: reduce(func2, v, initial) for k, v in chained.items()}
|
|
796
|
+
return f"Mapping {repr_(self.mapping)} keys must not contain duplicates (modulo case); got {repr_(self.counts)}"
|
|
1231
797
|
|
|
1232
798
|
|
|
1233
799
|
##
|
|
@@ -1258,7 +824,7 @@ class ResolveIncludeAndExcludeError[T](Exception):
|
|
|
1258
824
|
include = list(self.include)
|
|
1259
825
|
exclude = list(self.exclude)
|
|
1260
826
|
overlap = set(include) & set(exclude)
|
|
1261
|
-
return f"Iterables {
|
|
827
|
+
return f"Iterables {repr_(include)} and {repr_(exclude)} must not overlap; got {repr_(overlap)}"
|
|
1262
828
|
|
|
1263
829
|
|
|
1264
830
|
##
|
|
@@ -1325,7 +891,7 @@ class SortIterableError(Exception):
|
|
|
1325
891
|
|
|
1326
892
|
@override
|
|
1327
893
|
def __str__(self) -> str:
|
|
1328
|
-
return f"Unable to sort {
|
|
894
|
+
return f"Unable to sort {repr_(self.x)} and {repr_(self.y)}"
|
|
1329
895
|
|
|
1330
896
|
|
|
1331
897
|
def _sort_iterable_cmp_floats(x: float, y: float, /) -> Sign:
|
|
@@ -1347,74 +913,6 @@ def _sort_iterable_cmp_floats(x: float, y: float, /) -> Sign:
|
|
|
1347
913
|
##
|
|
1348
914
|
|
|
1349
915
|
|
|
1350
|
-
def sum_mappings[K: Hashable, V: SupportsAdd](
|
|
1351
|
-
*mappings: Mapping[K, V],
|
|
1352
|
-
) -> Mapping[K, V]:
|
|
1353
|
-
"""Sum the values of a set of mappings."""
|
|
1354
|
-
return reduce_mappings(add, mappings, initial=0)
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
##
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
def take[T](n: int, iterable: Iterable[T], /) -> Sequence[T]:
|
|
1361
|
-
"""Return first n items of the iterable as a list."""
|
|
1362
|
-
return list(islice(iterable, n))
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
##
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
@overload
|
|
1369
|
-
def transpose[T1](iterable: Iterable[tuple[T1]], /) -> tuple[list[T1]]: ...
|
|
1370
|
-
@overload
|
|
1371
|
-
def transpose[T1, T2](
|
|
1372
|
-
iterable: Iterable[tuple[T1, T2]], /
|
|
1373
|
-
) -> tuple[list[T1], list[T2]]: ...
|
|
1374
|
-
@overload
|
|
1375
|
-
def transpose[T1, T2, T3](
|
|
1376
|
-
iterable: Iterable[tuple[T1, T2, T3]], /
|
|
1377
|
-
) -> tuple[list[T1], list[T2], list[T3]]: ...
|
|
1378
|
-
@overload
|
|
1379
|
-
def transpose[T1, T2, T3, T4](
|
|
1380
|
-
iterable: Iterable[tuple[T1, T2, T3, T4]], /
|
|
1381
|
-
) -> tuple[list[T1], list[T2], list[T3], list[T4]]: ...
|
|
1382
|
-
@overload
|
|
1383
|
-
def transpose[T1, T2, T3, T4, T5](
|
|
1384
|
-
iterable: Iterable[tuple[T1, T2, T3, T4, T5]], /
|
|
1385
|
-
) -> tuple[list[T1], list[T2], list[T3], list[T4], list[T5]]: ...
|
|
1386
|
-
def transpose(iterable: Iterable[tuple[Any]]) -> tuple[list[Any], ...]: # pyright: ignore[reportInconsistentOverload]
|
|
1387
|
-
"""Typed verison of `transpose`."""
|
|
1388
|
-
return tuple(map(list, zip(*iterable, strict=True)))
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
##
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
def unique_everseen[T](
|
|
1395
|
-
iterable: Iterable[T], /, *, key: Callable[[T], Any] | None = None
|
|
1396
|
-
) -> Iterator[T]:
|
|
1397
|
-
"""Yield unique elements, preserving order."""
|
|
1398
|
-
seenset = set()
|
|
1399
|
-
seenset_add = seenset.add
|
|
1400
|
-
seenlist = []
|
|
1401
|
-
seenlist_add = seenlist.append
|
|
1402
|
-
use_key = key is not None
|
|
1403
|
-
for element in iterable:
|
|
1404
|
-
k = key(element) if use_key else element
|
|
1405
|
-
try:
|
|
1406
|
-
if k not in seenset:
|
|
1407
|
-
seenset_add(k)
|
|
1408
|
-
yield element
|
|
1409
|
-
except TypeError:
|
|
1410
|
-
if k not in seenlist:
|
|
1411
|
-
seenlist_add(k)
|
|
1412
|
-
yield element
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
##
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
916
|
__all__ = [
|
|
1419
917
|
"ApplyBijectionError",
|
|
1420
918
|
"CheckBijectionError",
|
|
@@ -1429,30 +927,13 @@ __all__ = [
|
|
|
1429
927
|
"CheckSuperSetError",
|
|
1430
928
|
"CheckUniqueModuloCaseError",
|
|
1431
929
|
"EnsureIterableError",
|
|
1432
|
-
"EnsureIterableNotStrError",
|
|
1433
930
|
"MergeStrMappingsError",
|
|
1434
|
-
"OneEmptyError",
|
|
1435
|
-
"OneError",
|
|
1436
|
-
"OneMaybeEmptyError",
|
|
1437
|
-
"OneMaybeError",
|
|
1438
|
-
"OneMaybeNonUniqueError",
|
|
1439
|
-
"OneNonUniqueError",
|
|
1440
|
-
"OneStrEmptyError",
|
|
1441
|
-
"OneStrError",
|
|
1442
|
-
"OneStrNonUniqueError",
|
|
1443
|
-
"OneUniqueEmptyError",
|
|
1444
|
-
"OneUniqueError",
|
|
1445
|
-
"OneUniqueNonUniqueError",
|
|
1446
|
-
"RangePartitionsError",
|
|
1447
931
|
"ResolveIncludeAndExcludeError",
|
|
1448
932
|
"SortIterableError",
|
|
1449
933
|
"always_iterable",
|
|
1450
934
|
"apply_bijection",
|
|
1451
935
|
"apply_to_tuple",
|
|
1452
936
|
"apply_to_varargs",
|
|
1453
|
-
"chain_mappings",
|
|
1454
|
-
"chain_maybe_iterables",
|
|
1455
|
-
"chain_nullable",
|
|
1456
937
|
"check_bijection",
|
|
1457
938
|
"check_duplicates",
|
|
1458
939
|
"check_iterables_equal",
|
|
@@ -1464,34 +945,17 @@ __all__ = [
|
|
|
1464
945
|
"check_supermapping",
|
|
1465
946
|
"check_superset",
|
|
1466
947
|
"check_unique_modulo_case",
|
|
1467
|
-
"chunked",
|
|
1468
948
|
"cmp_nullable",
|
|
1469
949
|
"ensure_iterable",
|
|
1470
|
-
"ensure_iterable_not_str",
|
|
1471
950
|
"enumerate_with_edge",
|
|
1472
|
-
"expanding_window",
|
|
1473
951
|
"filter_include_and_exclude",
|
|
1474
952
|
"groupby_lists",
|
|
1475
|
-
"hashable_to_iterable",
|
|
1476
953
|
"is_iterable",
|
|
1477
|
-
"is_iterable_not_enum",
|
|
1478
954
|
"is_iterable_not_str",
|
|
1479
955
|
"map_mapping",
|
|
1480
956
|
"merge_mappings",
|
|
1481
957
|
"merge_sets",
|
|
1482
958
|
"merge_str_mappings",
|
|
1483
|
-
"one",
|
|
1484
|
-
"one_maybe",
|
|
1485
|
-
"one_str",
|
|
1486
|
-
"one_unique",
|
|
1487
|
-
"pairwise_tail",
|
|
1488
|
-
"product_dicts",
|
|
1489
|
-
"range_partitions",
|
|
1490
|
-
"reduce_mappings",
|
|
1491
959
|
"resolve_include_and_exclude",
|
|
1492
960
|
"sort_iterable",
|
|
1493
|
-
"sum_mappings",
|
|
1494
|
-
"take",
|
|
1495
|
-
"transpose",
|
|
1496
|
-
"unique_everseen",
|
|
1497
961
|
]
|