dycw-utilities 0.129.10__py3-none-any.whl → 0.175.17__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.175.17.dist-info/METADATA +34 -0
- dycw_utilities-0.175.17.dist-info/RECORD +103 -0
- dycw_utilities-0.175.17.dist-info/WHEEL +4 -0
- dycw_utilities-0.175.17.dist-info/entry_points.txt +4 -0
- utilities/__init__.py +1 -1
- utilities/altair.py +14 -14
- utilities/asyncio.py +350 -819
- utilities/atomicwrites.py +18 -6
- utilities/atools.py +77 -22
- utilities/cachetools.py +24 -29
- utilities/click.py +393 -237
- utilities/concurrent.py +8 -11
- utilities/contextlib.py +216 -17
- utilities/contextvars.py +20 -1
- utilities/cryptography.py +3 -3
- utilities/dataclasses.py +83 -118
- utilities/docker.py +293 -0
- utilities/enum.py +26 -23
- utilities/errors.py +17 -3
- utilities/fastapi.py +29 -65
- utilities/fpdf2.py +3 -3
- utilities/functions.py +169 -416
- utilities/functools.py +18 -19
- utilities/git.py +9 -30
- utilities/grp.py +28 -0
- utilities/gzip.py +31 -0
- utilities/http.py +3 -2
- utilities/hypothesis.py +738 -589
- utilities/importlib.py +17 -1
- utilities/inflect.py +25 -0
- utilities/iterables.py +194 -262
- utilities/jinja2.py +148 -0
- utilities/json.py +70 -0
- utilities/libcst.py +38 -17
- utilities/lightweight_charts.py +5 -9
- utilities/logging.py +345 -543
- utilities/math.py +18 -13
- utilities/memory_profiler.py +11 -15
- utilities/more_itertools.py +200 -131
- utilities/operator.py +33 -29
- utilities/optuna.py +6 -6
- utilities/orjson.py +272 -137
- utilities/os.py +61 -4
- utilities/parse.py +59 -61
- utilities/pathlib.py +281 -40
- utilities/permissions.py +298 -0
- utilities/pickle.py +2 -2
- utilities/platform.py +24 -5
- utilities/polars.py +1214 -430
- utilities/polars_ols.py +1 -1
- utilities/postgres.py +408 -0
- utilities/pottery.py +113 -26
- utilities/pqdm.py +10 -11
- utilities/psutil.py +6 -57
- utilities/pwd.py +28 -0
- utilities/pydantic.py +4 -54
- utilities/pydantic_settings.py +240 -0
- utilities/pydantic_settings_sops.py +76 -0
- utilities/pyinstrument.py +8 -10
- utilities/pytest.py +227 -121
- utilities/pytest_plugins/__init__.py +1 -0
- utilities/pytest_plugins/pytest_randomly.py +23 -0
- utilities/pytest_plugins/pytest_regressions.py +56 -0
- utilities/pytest_regressions.py +26 -46
- utilities/random.py +13 -9
- utilities/re.py +58 -28
- utilities/redis.py +401 -550
- utilities/scipy.py +1 -1
- utilities/sentinel.py +10 -0
- utilities/shelve.py +4 -1
- utilities/shutil.py +25 -0
- utilities/slack_sdk.py +36 -106
- utilities/sqlalchemy.py +502 -473
- utilities/sqlalchemy_polars.py +38 -94
- utilities/string.py +2 -3
- utilities/subprocess.py +1572 -0
- utilities/tempfile.py +86 -4
- utilities/testbook.py +50 -0
- utilities/text.py +165 -42
- utilities/timer.py +37 -65
- utilities/traceback.py +158 -929
- utilities/types.py +146 -116
- utilities/typing.py +531 -71
- utilities/tzdata.py +1 -53
- utilities/tzlocal.py +6 -23
- utilities/uuid.py +43 -5
- utilities/version.py +27 -26
- utilities/whenever.py +1776 -386
- utilities/zoneinfo.py +84 -22
- dycw_utilities-0.129.10.dist-info/METADATA +0 -241
- dycw_utilities-0.129.10.dist-info/RECORD +0 -96
- dycw_utilities-0.129.10.dist-info/WHEEL +0 -4
- dycw_utilities-0.129.10.dist-info/licenses/LICENSE +0 -21
- utilities/datetime.py +0 -1409
- utilities/eventkit.py +0 -402
- utilities/loguru.py +0 -144
- utilities/luigi.py +0 -228
- utilities/period.py +0 -324
- utilities/pyrsistent.py +0 -89
- utilities/python_dotenv.py +0 -105
- utilities/streamlit.py +0 -105
- utilities/sys.py +0 -87
- utilities/tenacity.py +0 -145
utilities/dataclasses.py
CHANGED
|
@@ -3,23 +3,10 @@ from __future__ import annotations
|
|
|
3
3
|
from collections.abc import Mapping
|
|
4
4
|
from contextlib import suppress
|
|
5
5
|
from dataclasses import MISSING, dataclass, field, fields, replace
|
|
6
|
-
from typing import
|
|
7
|
-
TYPE_CHECKING,
|
|
8
|
-
Any,
|
|
9
|
-
Generic,
|
|
10
|
-
Literal,
|
|
11
|
-
TypeVar,
|
|
12
|
-
assert_never,
|
|
13
|
-
overload,
|
|
14
|
-
override,
|
|
15
|
-
)
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Literal, assert_never, overload, override
|
|
16
7
|
|
|
17
8
|
from utilities.errors import ImpossibleCaseError
|
|
18
|
-
from utilities.functions import
|
|
19
|
-
get_class_name,
|
|
20
|
-
is_dataclass_class,
|
|
21
|
-
is_dataclass_instance,
|
|
22
|
-
)
|
|
9
|
+
from utilities.functions import get_class_name
|
|
23
10
|
from utilities.iterables import (
|
|
24
11
|
OneStrEmptyError,
|
|
25
12
|
OneStrNonUniqueError,
|
|
@@ -34,7 +21,7 @@ from utilities.parse import (
|
|
|
34
21
|
serialize_object,
|
|
35
22
|
)
|
|
36
23
|
from utilities.re import ExtractGroupError, extract_group
|
|
37
|
-
from utilities.sentinel import Sentinel, sentinel
|
|
24
|
+
from utilities.sentinel import Sentinel, is_sentinel, sentinel
|
|
38
25
|
from utilities.text import (
|
|
39
26
|
BRACKETS,
|
|
40
27
|
LIST_SEPARATOR,
|
|
@@ -43,30 +30,23 @@ from utilities.text import (
|
|
|
43
30
|
_SplitKeyValuePairsSplitError,
|
|
44
31
|
split_key_value_pairs,
|
|
45
32
|
)
|
|
46
|
-
from utilities.types import
|
|
47
|
-
|
|
48
|
-
SerializeObjectExtra,
|
|
49
|
-
StrStrMapping,
|
|
50
|
-
TDataclass,
|
|
51
|
-
TSupportsLT,
|
|
52
|
-
)
|
|
53
|
-
from utilities.typing import get_type_hints
|
|
33
|
+
from utilities.types import MaybeType, SupportsLT
|
|
34
|
+
from utilities.typing import get_type_hints, is_dataclass_class, is_dataclass_instance
|
|
54
35
|
|
|
55
36
|
if TYPE_CHECKING:
|
|
56
37
|
from collections.abc import Callable, Iterable, Iterator
|
|
57
38
|
from collections.abc import Set as AbstractSet
|
|
58
39
|
|
|
59
|
-
from utilities.types import
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
##
|
|
40
|
+
from utilities.types import (
|
|
41
|
+
Dataclass,
|
|
42
|
+
ParseObjectExtra,
|
|
43
|
+
SerializeObjectExtra,
|
|
44
|
+
StrMapping,
|
|
45
|
+
StrStrMapping,
|
|
46
|
+
)
|
|
67
47
|
|
|
68
48
|
|
|
69
|
-
def dataclass_repr(
|
|
49
|
+
def dataclass_repr[T](
|
|
70
50
|
obj: Dataclass,
|
|
71
51
|
/,
|
|
72
52
|
*,
|
|
@@ -77,7 +57,7 @@ def dataclass_repr(
|
|
|
77
57
|
exclude: Iterable[str] | None = None,
|
|
78
58
|
rel_tol: float | None = None,
|
|
79
59
|
abs_tol: float | None = None,
|
|
80
|
-
extra: Mapping[type[
|
|
60
|
+
extra: Mapping[type[T], Callable[[T, T], bool]] | None = None,
|
|
81
61
|
defaults: bool = False,
|
|
82
62
|
recursive: bool = False,
|
|
83
63
|
) -> str:
|
|
@@ -145,7 +125,7 @@ def dataclass_repr(
|
|
|
145
125
|
##
|
|
146
126
|
|
|
147
127
|
|
|
148
|
-
def dataclass_to_dict(
|
|
128
|
+
def dataclass_to_dict[T](
|
|
149
129
|
obj: Dataclass,
|
|
150
130
|
/,
|
|
151
131
|
*,
|
|
@@ -156,7 +136,7 @@ def dataclass_to_dict(
|
|
|
156
136
|
exclude: Iterable[str] | None = None,
|
|
157
137
|
rel_tol: float | None = None,
|
|
158
138
|
abs_tol: float | None = None,
|
|
159
|
-
extra: Mapping[type[
|
|
139
|
+
extra: Mapping[type[T], Callable[[T, T], bool]] | None = None,
|
|
160
140
|
defaults: bool = False,
|
|
161
141
|
final: Callable[[type[Dataclass], StrMapping], StrMapping] | None = None,
|
|
162
142
|
recursive: bool = False,
|
|
@@ -221,7 +201,7 @@ def dataclass_to_dict(
|
|
|
221
201
|
##
|
|
222
202
|
|
|
223
203
|
|
|
224
|
-
def is_nullable_lt(x:
|
|
204
|
+
def is_nullable_lt[T: SupportsLT](x: T | None, y: T | None, /) -> bool | None:
|
|
225
205
|
"""Compare two nullable fields."""
|
|
226
206
|
match cmp_nullable(x, y):
|
|
227
207
|
case 1:
|
|
@@ -230,15 +210,15 @@ def is_nullable_lt(x: TSupportsLT | None, y: TSupportsLT | None, /) -> bool | No
|
|
|
230
210
|
return True
|
|
231
211
|
case 0:
|
|
232
212
|
return None
|
|
233
|
-
case
|
|
213
|
+
case never:
|
|
234
214
|
assert_never(never)
|
|
235
215
|
|
|
236
216
|
|
|
237
217
|
##
|
|
238
218
|
|
|
239
219
|
|
|
240
|
-
def mapping_to_dataclass(
|
|
241
|
-
cls: type[
|
|
220
|
+
def mapping_to_dataclass[T: Dataclass](
|
|
221
|
+
cls: type[T],
|
|
242
222
|
mapping: StrMapping,
|
|
243
223
|
/,
|
|
244
224
|
*,
|
|
@@ -249,7 +229,7 @@ def mapping_to_dataclass(
|
|
|
249
229
|
head: bool = False,
|
|
250
230
|
case_sensitive: bool = False,
|
|
251
231
|
allow_extra: bool = False,
|
|
252
|
-
) ->
|
|
232
|
+
) -> T:
|
|
253
233
|
"""Construct a dataclass from a mapping."""
|
|
254
234
|
if fields is None:
|
|
255
235
|
fields_use = list(
|
|
@@ -291,8 +271,7 @@ def mapping_to_dataclass(
|
|
|
291
271
|
default = {
|
|
292
272
|
f.name
|
|
293
273
|
for f in fields_use
|
|
294
|
-
if (not
|
|
295
|
-
or (not isinstance(f.default_factory, Sentinel))
|
|
274
|
+
if (not is_sentinel(f.default)) or (not is_sentinel(f.default_factory))
|
|
296
275
|
}
|
|
297
276
|
have = set(field_names_to_values) | default
|
|
298
277
|
missing = {f.name for f in fields_use} - have
|
|
@@ -302,12 +281,12 @@ def mapping_to_dataclass(
|
|
|
302
281
|
|
|
303
282
|
|
|
304
283
|
@dataclass(kw_only=True, slots=True)
|
|
305
|
-
class MappingToDataclassError(Exception
|
|
306
|
-
cls: type[
|
|
284
|
+
class MappingToDataclassError[T: Dataclass](Exception):
|
|
285
|
+
cls: type[T]
|
|
307
286
|
|
|
308
287
|
|
|
309
288
|
@dataclass(kw_only=True, slots=True)
|
|
310
|
-
class _MappingToDataClassEmptyError(MappingToDataclassError
|
|
289
|
+
class _MappingToDataClassEmptyError(MappingToDataclassError):
|
|
311
290
|
key: str
|
|
312
291
|
head: bool = False
|
|
313
292
|
case_sensitive: bool = False
|
|
@@ -320,7 +299,7 @@ class _MappingToDataClassEmptyError(MappingToDataclassError[TDataclass]):
|
|
|
320
299
|
|
|
321
300
|
|
|
322
301
|
@dataclass(kw_only=True, slots=True)
|
|
323
|
-
class _MappingToDataClassNonUniqueError(MappingToDataclassError
|
|
302
|
+
class _MappingToDataClassNonUniqueError(MappingToDataclassError):
|
|
324
303
|
key: str
|
|
325
304
|
head: bool = False
|
|
326
305
|
case_sensitive: bool = False
|
|
@@ -340,7 +319,7 @@ class _MappingToDataClassNonUniqueError(MappingToDataclassError[TDataclass]):
|
|
|
340
319
|
|
|
341
320
|
|
|
342
321
|
@dataclass(kw_only=True, slots=True)
|
|
343
|
-
class _MappingToDataClassMissingValuesError(MappingToDataclassError
|
|
322
|
+
class _MappingToDataClassMissingValuesError(MappingToDataclassError):
|
|
344
323
|
fields: AbstractSet[str]
|
|
345
324
|
|
|
346
325
|
@override
|
|
@@ -396,15 +375,15 @@ def one_field(
|
|
|
396
375
|
|
|
397
376
|
|
|
398
377
|
@dataclass(kw_only=True, slots=True)
|
|
399
|
-
class OneFieldError(Exception
|
|
400
|
-
cls: type[
|
|
378
|
+
class OneFieldError[T: Dataclass](Exception):
|
|
379
|
+
cls: type[T]
|
|
401
380
|
key: str
|
|
402
381
|
head: bool = False
|
|
403
382
|
case_sensitive: bool = False
|
|
404
383
|
|
|
405
384
|
|
|
406
385
|
@dataclass(kw_only=True, slots=True)
|
|
407
|
-
class _OneFieldEmptyError(OneFieldError
|
|
386
|
+
class _OneFieldEmptyError(OneFieldError):
|
|
408
387
|
@override
|
|
409
388
|
def __str__(self) -> str:
|
|
410
389
|
return _empty_error_str(
|
|
@@ -413,7 +392,7 @@ class _OneFieldEmptyError(OneFieldError[TDataclass]):
|
|
|
413
392
|
|
|
414
393
|
|
|
415
394
|
@dataclass(kw_only=True, slots=True)
|
|
416
|
-
class _OneFieldNonUniqueError(OneFieldError
|
|
395
|
+
class _OneFieldNonUniqueError(OneFieldError):
|
|
417
396
|
first: str
|
|
418
397
|
second: str
|
|
419
398
|
|
|
@@ -434,34 +413,32 @@ class _OneFieldNonUniqueError(OneFieldError[TDataclass]):
|
|
|
434
413
|
|
|
435
414
|
@overload
|
|
436
415
|
def replace_non_sentinel(
|
|
437
|
-
obj:
|
|
416
|
+
obj: Dataclass, /, *, in_place: Literal[True], **kwargs: Any
|
|
438
417
|
) -> None: ...
|
|
439
418
|
@overload
|
|
440
|
-
def replace_non_sentinel(
|
|
441
|
-
obj:
|
|
442
|
-
) ->
|
|
419
|
+
def replace_non_sentinel[T: Dataclass](
|
|
420
|
+
obj: T, /, *, in_place: Literal[False] = False, **kwargs: Any
|
|
421
|
+
) -> T: ...
|
|
443
422
|
@overload
|
|
444
|
-
def replace_non_sentinel(
|
|
445
|
-
obj:
|
|
446
|
-
) ->
|
|
447
|
-
def replace_non_sentinel(
|
|
448
|
-
obj:
|
|
449
|
-
) ->
|
|
423
|
+
def replace_non_sentinel[T: Dataclass](
|
|
424
|
+
obj: T, /, *, in_place: bool = False, **kwargs: Any
|
|
425
|
+
) -> T | None: ...
|
|
426
|
+
def replace_non_sentinel[T: Dataclass](
|
|
427
|
+
obj: T, /, *, in_place: bool = False, **kwargs: Any
|
|
428
|
+
) -> T | None:
|
|
450
429
|
"""Replace attributes on a dataclass, filtering out sentinel values."""
|
|
451
430
|
if in_place:
|
|
452
431
|
for k, v in kwargs.items():
|
|
453
|
-
if not
|
|
432
|
+
if not is_sentinel(v):
|
|
454
433
|
setattr(obj, k, v)
|
|
455
434
|
return None
|
|
456
|
-
return replace(
|
|
457
|
-
obj, **{k: v for k, v in kwargs.items() if not isinstance(v, Sentinel)}
|
|
458
|
-
)
|
|
435
|
+
return replace(obj, **{k: v for k, v in kwargs.items() if not is_sentinel(v)})
|
|
459
436
|
|
|
460
437
|
|
|
461
438
|
##
|
|
462
439
|
|
|
463
440
|
|
|
464
|
-
def serialize_dataclass(
|
|
441
|
+
def serialize_dataclass[T](
|
|
465
442
|
obj: Dataclass,
|
|
466
443
|
/,
|
|
467
444
|
*,
|
|
@@ -472,7 +449,7 @@ def serialize_dataclass(
|
|
|
472
449
|
exclude: Iterable[str] | None = None,
|
|
473
450
|
rel_tol: float | None = None,
|
|
474
451
|
abs_tol: float | None = None,
|
|
475
|
-
extra_equal: Mapping[type[
|
|
452
|
+
extra_equal: Mapping[type[T], Callable[[T, T], bool]] | None = None,
|
|
476
453
|
defaults: bool = False,
|
|
477
454
|
list_separator: str = LIST_SEPARATOR,
|
|
478
455
|
pair_separator: str = PAIR_SEPARATOR,
|
|
@@ -508,9 +485,9 @@ def serialize_dataclass(
|
|
|
508
485
|
)
|
|
509
486
|
|
|
510
487
|
|
|
511
|
-
def parse_dataclass(
|
|
488
|
+
def parse_dataclass[T: Dataclass](
|
|
512
489
|
text_or_mapping: str | StrStrMapping,
|
|
513
|
-
cls: type[
|
|
490
|
+
cls: type[T],
|
|
514
491
|
/,
|
|
515
492
|
*,
|
|
516
493
|
list_separator: str = LIST_SEPARATOR,
|
|
@@ -523,7 +500,7 @@ def parse_dataclass(
|
|
|
523
500
|
case_sensitive: bool = False,
|
|
524
501
|
allow_extra_keys: bool = False,
|
|
525
502
|
extra_parsers: ParseObjectExtra | None = None,
|
|
526
|
-
) ->
|
|
503
|
+
) -> T:
|
|
527
504
|
"""Construct a dataclass from a string or a mapping or strings."""
|
|
528
505
|
match text_or_mapping:
|
|
529
506
|
case str() as text:
|
|
@@ -536,7 +513,7 @@ def parse_dataclass(
|
|
|
536
513
|
)
|
|
537
514
|
case Mapping() as keys_to_serializes:
|
|
538
515
|
...
|
|
539
|
-
case
|
|
516
|
+
case never:
|
|
540
517
|
assert_never(never)
|
|
541
518
|
fields = list(
|
|
542
519
|
yield_fields(
|
|
@@ -597,9 +574,9 @@ def parse_dataclass(
|
|
|
597
574
|
raise _ParseDataClassMissingValuesError(cls=cls, fields=error.fields) from None
|
|
598
575
|
|
|
599
576
|
|
|
600
|
-
def _parse_dataclass_split_key_value_pairs(
|
|
577
|
+
def _parse_dataclass_split_key_value_pairs[T: Dataclass](
|
|
601
578
|
text: str,
|
|
602
|
-
cls: type[
|
|
579
|
+
cls: type[T],
|
|
603
580
|
/,
|
|
604
581
|
*,
|
|
605
582
|
list_separator: str = LIST_SEPARATOR,
|
|
@@ -657,12 +634,12 @@ def _parse_dataclass_parse_text(
|
|
|
657
634
|
|
|
658
635
|
|
|
659
636
|
@dataclass(kw_only=True, slots=True)
|
|
660
|
-
class ParseDataClassError(Exception
|
|
661
|
-
cls: type[
|
|
637
|
+
class ParseDataClassError[T: Dataclass](Exception):
|
|
638
|
+
cls: type[T]
|
|
662
639
|
|
|
663
640
|
|
|
664
641
|
@dataclass(kw_only=True, slots=True)
|
|
665
|
-
class _ParseDataClassSplitKeyValuePairsSplitError(ParseDataClassError
|
|
642
|
+
class _ParseDataClassSplitKeyValuePairsSplitError(ParseDataClassError):
|
|
666
643
|
text: str
|
|
667
644
|
|
|
668
645
|
@override
|
|
@@ -671,9 +648,7 @@ class _ParseDataClassSplitKeyValuePairsSplitError(ParseDataClassError[TDataclass
|
|
|
671
648
|
|
|
672
649
|
|
|
673
650
|
@dataclass(kw_only=True, slots=True)
|
|
674
|
-
class _ParseDataClassSplitKeyValuePairsDuplicateKeysError(
|
|
675
|
-
ParseDataClassError[TDataclass]
|
|
676
|
-
):
|
|
651
|
+
class _ParseDataClassSplitKeyValuePairsDuplicateKeysError(ParseDataClassError):
|
|
677
652
|
counts: Mapping[str, int]
|
|
678
653
|
|
|
679
654
|
@override
|
|
@@ -682,7 +657,7 @@ class _ParseDataClassSplitKeyValuePairsDuplicateKeysError(
|
|
|
682
657
|
|
|
683
658
|
|
|
684
659
|
@dataclass(kw_only=True, slots=True)
|
|
685
|
-
class _ParseDataClassTextParseError(ParseDataClassError
|
|
660
|
+
class _ParseDataClassTextParseError(ParseDataClassError):
|
|
686
661
|
field: _YieldFieldsClass[Any]
|
|
687
662
|
text: str
|
|
688
663
|
|
|
@@ -692,7 +667,7 @@ class _ParseDataClassTextParseError(ParseDataClassError[TDataclass]):
|
|
|
692
667
|
|
|
693
668
|
|
|
694
669
|
@dataclass(kw_only=True, slots=True)
|
|
695
|
-
class _ParseDataClassTextExtraNonUniqueError(ParseDataClassError
|
|
670
|
+
class _ParseDataClassTextExtraNonUniqueError(ParseDataClassError):
|
|
696
671
|
field: _YieldFieldsClass[Any]
|
|
697
672
|
first: type[Any]
|
|
698
673
|
second: type[Any]
|
|
@@ -703,9 +678,7 @@ class _ParseDataClassTextExtraNonUniqueError(ParseDataClassError[TDataclass]):
|
|
|
703
678
|
|
|
704
679
|
|
|
705
680
|
@dataclass(kw_only=True, slots=True)
|
|
706
|
-
class _ParseDataClassStrMappingToFieldMappingEmptyError(
|
|
707
|
-
ParseDataClassError[TDataclass]
|
|
708
|
-
):
|
|
681
|
+
class _ParseDataClassStrMappingToFieldMappingEmptyError(ParseDataClassError):
|
|
709
682
|
key: str
|
|
710
683
|
head: bool = False
|
|
711
684
|
case_sensitive: bool = False
|
|
@@ -720,9 +693,7 @@ class _ParseDataClassStrMappingToFieldMappingEmptyError(
|
|
|
720
693
|
|
|
721
694
|
|
|
722
695
|
@dataclass(kw_only=True, slots=True)
|
|
723
|
-
class _ParseDataClassStrMappingToFieldMappingNonUniqueError(
|
|
724
|
-
ParseDataClassError[TDataclass]
|
|
725
|
-
):
|
|
696
|
+
class _ParseDataClassStrMappingToFieldMappingNonUniqueError(ParseDataClassError):
|
|
726
697
|
key: str
|
|
727
698
|
head: bool = False
|
|
728
699
|
case_sensitive: bool = False
|
|
@@ -743,7 +714,7 @@ class _ParseDataClassStrMappingToFieldMappingNonUniqueError(
|
|
|
743
714
|
|
|
744
715
|
|
|
745
716
|
@dataclass(kw_only=True, slots=True)
|
|
746
|
-
class _ParseDataClassMissingValuesError(ParseDataClassError
|
|
717
|
+
class _ParseDataClassMissingValuesError(ParseDataClassError):
|
|
747
718
|
fields: AbstractSet[str]
|
|
748
719
|
|
|
749
720
|
@override
|
|
@@ -755,9 +726,9 @@ class _ParseDataClassMissingValuesError(ParseDataClassError[TDataclass]):
|
|
|
755
726
|
##
|
|
756
727
|
|
|
757
728
|
|
|
758
|
-
def str_mapping_to_field_mapping(
|
|
759
|
-
cls: type[
|
|
760
|
-
mapping: Mapping[str,
|
|
729
|
+
def str_mapping_to_field_mapping[T: Dataclass, U](
|
|
730
|
+
cls: type[T],
|
|
731
|
+
mapping: Mapping[str, U],
|
|
761
732
|
/,
|
|
762
733
|
*,
|
|
763
734
|
fields: Iterable[_YieldFieldsClass[Any]] | None = None,
|
|
@@ -767,7 +738,7 @@ def str_mapping_to_field_mapping(
|
|
|
767
738
|
head: bool = False,
|
|
768
739
|
case_sensitive: bool = False,
|
|
769
740
|
allow_extra: bool = False,
|
|
770
|
-
) -> Mapping[_YieldFieldsClass[Any],
|
|
741
|
+
) -> Mapping[_YieldFieldsClass[Any], U]:
|
|
771
742
|
"""Convert a string-mapping into a field-mapping."""
|
|
772
743
|
keys_to_fields: Mapping[str, _YieldFieldsClass[Any]] = {}
|
|
773
744
|
for key in mapping:
|
|
@@ -800,8 +771,8 @@ def str_mapping_to_field_mapping(
|
|
|
800
771
|
|
|
801
772
|
|
|
802
773
|
@dataclass(kw_only=True, slots=True)
|
|
803
|
-
class StrMappingToFieldMappingError(Exception
|
|
804
|
-
cls: type[
|
|
774
|
+
class StrMappingToFieldMappingError[T: Dataclass](Exception):
|
|
775
|
+
cls: type[T]
|
|
805
776
|
key: str
|
|
806
777
|
head: bool = False
|
|
807
778
|
case_sensitive: bool = False
|
|
@@ -855,7 +826,7 @@ def yield_fields(
|
|
|
855
826
|
warn_name_errors: bool = False,
|
|
856
827
|
) -> Iterator[_YieldFieldsClass[Any]]: ...
|
|
857
828
|
def yield_fields(
|
|
858
|
-
obj:
|
|
829
|
+
obj: MaybeType[Dataclass],
|
|
859
830
|
/,
|
|
860
831
|
*,
|
|
861
832
|
globalns: StrMapping | None = None,
|
|
@@ -913,12 +884,12 @@ def yield_fields(
|
|
|
913
884
|
|
|
914
885
|
|
|
915
886
|
@dataclass(order=True, unsafe_hash=True, kw_only=True, slots=True)
|
|
916
|
-
class _YieldFieldsInstance
|
|
887
|
+
class _YieldFieldsInstance[T]:
|
|
917
888
|
name: str
|
|
918
|
-
value:
|
|
889
|
+
value: T = field(hash=False)
|
|
919
890
|
type_: Any = field(hash=False)
|
|
920
|
-
default:
|
|
921
|
-
default_factory: Callable[[],
|
|
891
|
+
default: T | Sentinel = field(default=sentinel, hash=False)
|
|
892
|
+
default_factory: Callable[[], T] | Sentinel = field(default=sentinel, hash=False)
|
|
922
893
|
repr: bool = True
|
|
923
894
|
hash_: bool | None = None
|
|
924
895
|
init: bool = True
|
|
@@ -926,25 +897,19 @@ class _YieldFieldsInstance(Generic[_T]):
|
|
|
926
897
|
metadata: StrMapping = field(default_factory=dict, hash=False)
|
|
927
898
|
kw_only: bool | Sentinel = sentinel
|
|
928
899
|
|
|
929
|
-
def equals_default(
|
|
900
|
+
def equals_default[U](
|
|
930
901
|
self,
|
|
931
902
|
*,
|
|
932
903
|
rel_tol: float | None = None,
|
|
933
904
|
abs_tol: float | None = None,
|
|
934
|
-
extra: Mapping[type[
|
|
905
|
+
extra: Mapping[type[U], Callable[[U, U], bool]] | None = None,
|
|
935
906
|
) -> bool:
|
|
936
907
|
"""Check if the field value equals its default."""
|
|
937
|
-
if
|
|
938
|
-
self.default_factory, Sentinel
|
|
939
|
-
):
|
|
908
|
+
if is_sentinel(self.default) and is_sentinel(self.default_factory):
|
|
940
909
|
return False
|
|
941
|
-
if (not
|
|
942
|
-
self.default_factory, Sentinel
|
|
943
|
-
):
|
|
910
|
+
if (not is_sentinel(self.default)) and is_sentinel(self.default_factory):
|
|
944
911
|
expected = self.default
|
|
945
|
-
elif
|
|
946
|
-
not isinstance(self.default_factory, Sentinel)
|
|
947
|
-
):
|
|
912
|
+
elif is_sentinel(self.default) and (not is_sentinel(self.default_factory)):
|
|
948
913
|
expected = self.default_factory()
|
|
949
914
|
else: # pragma: no cover
|
|
950
915
|
raise ImpossibleCaseError(
|
|
@@ -954,14 +919,14 @@ class _YieldFieldsInstance(Generic[_T]):
|
|
|
954
919
|
self.value, expected, rel_tol=rel_tol, abs_tol=abs_tol, extra=extra
|
|
955
920
|
)
|
|
956
921
|
|
|
957
|
-
def keep(
|
|
922
|
+
def keep[U](
|
|
958
923
|
self,
|
|
959
924
|
*,
|
|
960
925
|
include: Iterable[str] | None = None,
|
|
961
926
|
exclude: Iterable[str] | None = None,
|
|
962
927
|
rel_tol: float | None = None,
|
|
963
928
|
abs_tol: float | None = None,
|
|
964
|
-
extra: Mapping[type[
|
|
929
|
+
extra: Mapping[type[U], Callable[[U, U], bool]] | None = None,
|
|
965
930
|
defaults: bool = False,
|
|
966
931
|
) -> bool:
|
|
967
932
|
"""Whether to include a field."""
|
|
@@ -974,11 +939,11 @@ class _YieldFieldsInstance(Generic[_T]):
|
|
|
974
939
|
|
|
975
940
|
|
|
976
941
|
@dataclass(order=True, unsafe_hash=True, kw_only=True, slots=True)
|
|
977
|
-
class _YieldFieldsClass
|
|
942
|
+
class _YieldFieldsClass[T]:
|
|
978
943
|
name: str
|
|
979
944
|
type_: Any = field(hash=False)
|
|
980
|
-
default:
|
|
981
|
-
default_factory: Callable[[],
|
|
945
|
+
default: T | Sentinel = field(default=sentinel, hash=False)
|
|
946
|
+
default_factory: Callable[[], T] | Sentinel = field(default=sentinel, hash=False)
|
|
982
947
|
repr: bool = True
|
|
983
948
|
hash_: bool | None = None
|
|
984
949
|
init: bool = True
|
|
@@ -1024,7 +989,7 @@ def _empty_error_str_core(
|
|
|
1024
989
|
return f"any field starting with {key!r}"
|
|
1025
990
|
case True, False:
|
|
1026
991
|
return f"any field starting with {key!r} (modulo case)"
|
|
1027
|
-
case
|
|
992
|
+
case never:
|
|
1028
993
|
assert_never(never)
|
|
1029
994
|
|
|
1030
995
|
|
|
@@ -1065,7 +1030,7 @@ def _non_unique_error_str_core(
|
|
|
1065
1030
|
head_msg = f"exactly one field starting with {key!r}"
|
|
1066
1031
|
case True, False:
|
|
1067
1032
|
head_msg = f"exactly one field starting with {key!r} (modulo case)"
|
|
1068
|
-
case
|
|
1033
|
+
case never:
|
|
1069
1034
|
assert_never(never)
|
|
1070
1035
|
return f"{head_msg}; got {first!r}, {second!r} and perhaps more"
|
|
1071
1036
|
|