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/typing.py
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import datetime as dt
|
|
4
|
-
from collections.abc import Mapping, Sequence
|
|
5
|
-
from dataclasses import dataclass
|
|
4
|
+
from collections.abc import Callable, Iterable, Mapping, Sequence
|
|
5
|
+
from dataclasses import dataclass, is_dataclass
|
|
6
|
+
from functools import partial
|
|
6
7
|
from itertools import chain
|
|
7
8
|
from pathlib import Path
|
|
9
|
+
from re import search
|
|
8
10
|
from types import NoneType, UnionType
|
|
9
11
|
from typing import (
|
|
10
12
|
Any,
|
|
13
|
+
ForwardRef,
|
|
11
14
|
Literal,
|
|
12
15
|
NamedTuple,
|
|
16
|
+
NotRequired,
|
|
13
17
|
Optional, # pyright: ignore[reportDeprecated]
|
|
14
|
-
Self,
|
|
15
18
|
TypeAliasType,
|
|
16
19
|
TypeGuard,
|
|
17
|
-
TypeVar,
|
|
18
20
|
Union, # pyright: ignore[reportDeprecated]
|
|
21
|
+
_TypedDictMeta, # pyright: ignore[reportAttributeAccessIssue]
|
|
22
|
+
cast,
|
|
19
23
|
get_origin,
|
|
20
24
|
overload,
|
|
21
25
|
override,
|
|
@@ -25,27 +29,26 @@ from typing import get_type_hints as _get_type_hints
|
|
|
25
29
|
from uuid import UUID
|
|
26
30
|
from warnings import warn
|
|
27
31
|
|
|
32
|
+
import whenever
|
|
33
|
+
from whenever import (
|
|
34
|
+
Date,
|
|
35
|
+
DateDelta,
|
|
36
|
+
DateTimeDelta,
|
|
37
|
+
PlainDateTime,
|
|
38
|
+
Time,
|
|
39
|
+
TimeDelta,
|
|
40
|
+
ZonedDateTime,
|
|
41
|
+
)
|
|
42
|
+
|
|
28
43
|
from utilities.iterables import unique_everseen
|
|
29
44
|
from utilities.sentinel import Sentinel
|
|
30
|
-
from utilities.types import
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
_T5 = TypeVar("_T5")
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
##
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def contains_self(obj: Any, /) -> bool:
|
|
44
|
-
"""Check if an annotation contains `Self`."""
|
|
45
|
-
return (obj is Self) or any(map(contains_self, get_args(obj)))
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
##
|
|
45
|
+
from utilities.types import (
|
|
46
|
+
Dataclass,
|
|
47
|
+
StrMapping,
|
|
48
|
+
StrStrMapping,
|
|
49
|
+
TupleOrStrMapping,
|
|
50
|
+
TypeLike,
|
|
51
|
+
)
|
|
49
52
|
|
|
50
53
|
|
|
51
54
|
def get_args(obj: Any, /, *, optional_drop_none: bool = False) -> tuple[Any, ...]:
|
|
@@ -61,6 +64,18 @@ def get_args(obj: Any, /, *, optional_drop_none: bool = False) -> tuple[Any, ...
|
|
|
61
64
|
##
|
|
62
65
|
|
|
63
66
|
|
|
67
|
+
def get_forward_ref_args(obj: Any, /) -> StrStrMapping:
|
|
68
|
+
"""Get the forward args."""
|
|
69
|
+
return {
|
|
70
|
+
k: v.__forward_arg__
|
|
71
|
+
for k, v in obj.__annotations__.items()
|
|
72
|
+
if isinstance(v, ForwardRef)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
##
|
|
77
|
+
|
|
78
|
+
|
|
64
79
|
def get_literal_elements(obj: Any, /) -> list[Any]:
|
|
65
80
|
"""Get the elements of a literal annotation."""
|
|
66
81
|
return _get_literal_elements_inner(obj)
|
|
@@ -132,21 +147,44 @@ def get_type_hints(
|
|
|
132
147
|
warn_name_errors: bool = False,
|
|
133
148
|
) -> dict[str, Any]:
|
|
134
149
|
"""Get the type hints of an object."""
|
|
135
|
-
|
|
136
|
-
|
|
150
|
+
_ = {
|
|
151
|
+
Date,
|
|
152
|
+
DateDelta,
|
|
153
|
+
DateTimeDelta,
|
|
154
|
+
Literal,
|
|
155
|
+
Path,
|
|
156
|
+
PlainDateTime,
|
|
157
|
+
Sentinel,
|
|
158
|
+
StrMapping,
|
|
159
|
+
Time,
|
|
160
|
+
TimeDelta,
|
|
161
|
+
UUID,
|
|
162
|
+
ZonedDateTime,
|
|
163
|
+
whenever.Date,
|
|
164
|
+
whenever.DateDelta,
|
|
165
|
+
whenever.DateTimeDelta,
|
|
166
|
+
whenever.PlainDateTime,
|
|
167
|
+
whenever.Time,
|
|
168
|
+
whenever.TimeDelta,
|
|
169
|
+
whenever.ZonedDateTime,
|
|
170
|
+
}
|
|
137
171
|
globalns_use = globals() | ({} if globalns is None else dict(globalns))
|
|
138
172
|
localns_use = {} if localns is None else dict(localns)
|
|
173
|
+
result: dict[str, Any] = obj.__annotations__
|
|
174
|
+
result = result | dict(get_forward_ref_args(obj))
|
|
139
175
|
try:
|
|
140
|
-
hints = _get_type_hints(
|
|
176
|
+
hints = _get_type_hints(
|
|
177
|
+
obj, globalns=globalns_use, localns=localns_use, include_extras=True
|
|
178
|
+
)
|
|
141
179
|
except NameError as error:
|
|
142
180
|
if warn_name_errors:
|
|
143
181
|
warn(f"Error getting type hints for {obj!r}; {error}", stacklevel=2)
|
|
144
182
|
else:
|
|
145
|
-
result
|
|
183
|
+
result = result | {
|
|
146
184
|
key: value
|
|
147
185
|
for key, value in hints.items()
|
|
148
186
|
if (key not in result) or isinstance(result[key], str)
|
|
149
|
-
}
|
|
187
|
+
}
|
|
150
188
|
return result
|
|
151
189
|
|
|
152
190
|
|
|
@@ -159,12 +197,9 @@ def get_union_type_classes(obj: Any, /) -> tuple[type[Any], ...]:
|
|
|
159
197
|
raise _GetUnionTypeClassesUnionTypeError(obj=obj)
|
|
160
198
|
types_: Sequence[type[Any]] = []
|
|
161
199
|
for arg in get_args(obj):
|
|
162
|
-
if isinstance(arg, type):
|
|
163
|
-
types_.append(arg)
|
|
164
|
-
elif is_union_type(arg):
|
|
165
|
-
types_.extend(get_union_type_classes(arg))
|
|
166
|
-
else:
|
|
200
|
+
if not isinstance(arg, type):
|
|
167
201
|
raise _GetUnionTypeClassesInternalTypeError(obj=obj, inner=arg)
|
|
202
|
+
types_.append(arg)
|
|
168
203
|
return tuple(types_)
|
|
169
204
|
|
|
170
205
|
|
|
@@ -194,6 +229,22 @@ class _GetUnionTypeClassesInternalTypeError(GetUnionTypeClassesError):
|
|
|
194
229
|
##
|
|
195
230
|
|
|
196
231
|
|
|
232
|
+
def is_dataclass_class(obj: Any, /) -> TypeGuard[type[Dataclass]]:
|
|
233
|
+
"""Check if an object is a dataclass."""
|
|
234
|
+
return isinstance(obj, type) and is_dataclass(obj)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
##
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def is_dataclass_instance(obj: Any, /) -> TypeGuard[Dataclass]:
|
|
241
|
+
"""Check if an object is an instance of a dataclass."""
|
|
242
|
+
return (not isinstance(obj, type)) and is_dataclass(obj)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
##
|
|
246
|
+
|
|
247
|
+
|
|
197
248
|
def is_dict_type(obj: Any, /) -> bool:
|
|
198
249
|
"""Check if an object is a dict type annotation."""
|
|
199
250
|
return _is_annotation_of_type(obj, dict)
|
|
@@ -211,49 +262,175 @@ def is_frozenset_type(obj: Any, /) -> bool:
|
|
|
211
262
|
|
|
212
263
|
|
|
213
264
|
@overload
|
|
214
|
-
def is_instance_gen
|
|
265
|
+
def is_instance_gen[T](
|
|
266
|
+
obj: Any,
|
|
267
|
+
type_: type[T],
|
|
268
|
+
/,
|
|
269
|
+
*,
|
|
270
|
+
globalns: StrMapping | None = None,
|
|
271
|
+
localns: StrMapping | None = None,
|
|
272
|
+
warn_name_errors: bool = False,
|
|
273
|
+
) -> TypeGuard[T]: ...
|
|
215
274
|
@overload
|
|
216
|
-
def is_instance_gen
|
|
275
|
+
def is_instance_gen[T1](
|
|
276
|
+
obj: Any,
|
|
277
|
+
type_: tuple[T1],
|
|
278
|
+
/,
|
|
279
|
+
*,
|
|
280
|
+
globalns: StrMapping | None = None,
|
|
281
|
+
localns: StrMapping | None = None,
|
|
282
|
+
warn_name_errors: bool = False,
|
|
283
|
+
) -> TypeGuard[T1]: ...
|
|
217
284
|
@overload
|
|
218
|
-
def is_instance_gen
|
|
285
|
+
def is_instance_gen[T1, T2](
|
|
286
|
+
obj: Any,
|
|
287
|
+
type_: tuple[T1, T2],
|
|
288
|
+
/,
|
|
289
|
+
*,
|
|
290
|
+
globalns: StrMapping | None = None,
|
|
291
|
+
localns: StrMapping | None = None,
|
|
292
|
+
warn_name_errors: bool = False,
|
|
293
|
+
) -> TypeGuard[T1 | T2]: ...
|
|
219
294
|
@overload
|
|
220
|
-
def is_instance_gen(
|
|
221
|
-
obj: Any,
|
|
222
|
-
|
|
295
|
+
def is_instance_gen[T1, T2, T3](
|
|
296
|
+
obj: Any,
|
|
297
|
+
type_: tuple[T1, T2, T3],
|
|
298
|
+
/,
|
|
299
|
+
*,
|
|
300
|
+
globalns: StrMapping | None = None,
|
|
301
|
+
localns: StrMapping | None = None,
|
|
302
|
+
warn_name_errors: bool = False,
|
|
303
|
+
) -> TypeGuard[T1 | T2 | T3]: ...
|
|
223
304
|
@overload
|
|
224
|
-
def is_instance_gen(
|
|
225
|
-
obj: Any,
|
|
226
|
-
|
|
305
|
+
def is_instance_gen[T1, T2, T3, T4](
|
|
306
|
+
obj: Any,
|
|
307
|
+
type_: tuple[T1, T2, T3, T4],
|
|
308
|
+
/,
|
|
309
|
+
*,
|
|
310
|
+
globalns: StrMapping | None = None,
|
|
311
|
+
localns: StrMapping | None = None,
|
|
312
|
+
warn_name_errors: bool = False,
|
|
313
|
+
) -> TypeGuard[T1 | T2 | T3 | T4]: ...
|
|
227
314
|
@overload
|
|
228
|
-
def is_instance_gen(
|
|
229
|
-
obj: Any,
|
|
230
|
-
|
|
315
|
+
def is_instance_gen[T1, T2, T3, T4, T5](
|
|
316
|
+
obj: Any,
|
|
317
|
+
type_: tuple[T1, T2, T3, T4, T5],
|
|
318
|
+
/,
|
|
319
|
+
*,
|
|
320
|
+
globalns: StrMapping | None = None,
|
|
321
|
+
localns: StrMapping | None = None,
|
|
322
|
+
warn_name_errors: bool = False,
|
|
323
|
+
) -> TypeGuard[T1 | T2 | T3 | T4 | T5]: ...
|
|
231
324
|
@overload
|
|
232
|
-
def is_instance_gen(
|
|
233
|
-
|
|
325
|
+
def is_instance_gen(
|
|
326
|
+
obj: Any,
|
|
327
|
+
type_: Any,
|
|
328
|
+
/,
|
|
329
|
+
*,
|
|
330
|
+
globalns: StrMapping | None = None,
|
|
331
|
+
localns: StrMapping | None = None,
|
|
332
|
+
warn_name_errors: bool = False,
|
|
333
|
+
) -> bool: ...
|
|
334
|
+
def is_instance_gen(
|
|
335
|
+
obj: Any,
|
|
336
|
+
type_: Any,
|
|
337
|
+
/,
|
|
338
|
+
*,
|
|
339
|
+
globalns: StrMapping | None = None,
|
|
340
|
+
localns: StrMapping | None = None,
|
|
341
|
+
warn_name_errors: bool = False,
|
|
342
|
+
) -> bool:
|
|
234
343
|
"""Check if an instance relationship holds, except bool<int."""
|
|
235
344
|
# parent
|
|
236
345
|
if isinstance(type_, tuple):
|
|
237
|
-
return any(
|
|
346
|
+
return any(
|
|
347
|
+
is_instance_gen(
|
|
348
|
+
obj,
|
|
349
|
+
t,
|
|
350
|
+
globalns=globalns,
|
|
351
|
+
localns=localns,
|
|
352
|
+
warn_name_errors=warn_name_errors,
|
|
353
|
+
)
|
|
354
|
+
for t in type_
|
|
355
|
+
)
|
|
238
356
|
if is_literal_type(type_):
|
|
239
357
|
return obj in get_args(type_)
|
|
240
358
|
if is_union_type(type_):
|
|
241
|
-
return any(
|
|
359
|
+
return any(
|
|
360
|
+
is_instance_gen(
|
|
361
|
+
obj,
|
|
362
|
+
t,
|
|
363
|
+
globalns=globalns,
|
|
364
|
+
localns=localns,
|
|
365
|
+
warn_name_errors=warn_name_errors,
|
|
366
|
+
)
|
|
367
|
+
for t in get_args(type_)
|
|
368
|
+
)
|
|
242
369
|
# tuple vs tuple
|
|
243
370
|
if isinstance(obj, tuple) and is_tuple_type(type_):
|
|
244
371
|
type_args = get_args(type_)
|
|
245
372
|
return (len(obj) == len(type_args)) and all(
|
|
246
|
-
is_instance_gen(
|
|
373
|
+
is_instance_gen(
|
|
374
|
+
o,
|
|
375
|
+
t,
|
|
376
|
+
globalns=globalns,
|
|
377
|
+
localns=localns,
|
|
378
|
+
warn_name_errors=warn_name_errors,
|
|
379
|
+
)
|
|
380
|
+
for o, t in zip(obj, type_args, strict=True)
|
|
247
381
|
)
|
|
248
382
|
if isinstance(obj, tuple) is not is_tuple_type(type_):
|
|
249
383
|
return False
|
|
250
384
|
# basic
|
|
385
|
+
if isinstance(type_, _TypedDictMeta):
|
|
386
|
+
return _is_instance_typed_dict(
|
|
387
|
+
obj,
|
|
388
|
+
type_,
|
|
389
|
+
globalns=globalns,
|
|
390
|
+
localns=localns,
|
|
391
|
+
warn_name_errors=warn_name_errors,
|
|
392
|
+
)
|
|
251
393
|
if isinstance(type_, type):
|
|
252
394
|
return any(_is_instance_gen_type(obj, t) for t in get_type_classes(type_))
|
|
253
395
|
raise IsInstanceGenError(obj=obj, type_=type_)
|
|
254
396
|
|
|
255
397
|
|
|
256
|
-
def
|
|
398
|
+
def _is_instance_typed_dict[T: _TypedDictMeta](
|
|
399
|
+
obj: Any,
|
|
400
|
+
type_: type[T],
|
|
401
|
+
/,
|
|
402
|
+
*,
|
|
403
|
+
globalns: StrMapping | None = None,
|
|
404
|
+
localns: StrMapping | None = None,
|
|
405
|
+
warn_name_errors: bool = False,
|
|
406
|
+
) -> TypeGuard[T]:
|
|
407
|
+
if not isinstance(obj, dict):
|
|
408
|
+
return False
|
|
409
|
+
if not all(isinstance(k, str) for k in obj):
|
|
410
|
+
return False
|
|
411
|
+
obj = cast("dict[str, Any]", obj)
|
|
412
|
+
hints = get_type_hints(
|
|
413
|
+
type_, globalns=globalns, localns=localns, warn_name_errors=warn_name_errors
|
|
414
|
+
)
|
|
415
|
+
optional = {
|
|
416
|
+
k for k, v in type_.__annotations__.items() if is_not_required_annotation(v)
|
|
417
|
+
}
|
|
418
|
+
required = {k: v for k, v in hints.items() if k not in optional}
|
|
419
|
+
if not set(obj).issuperset(required):
|
|
420
|
+
return False
|
|
421
|
+
return all(
|
|
422
|
+
is_instance_gen(
|
|
423
|
+
obj[k],
|
|
424
|
+
required[k],
|
|
425
|
+
globalns=globalns,
|
|
426
|
+
localns=localns,
|
|
427
|
+
warn_name_errors=warn_name_errors,
|
|
428
|
+
)
|
|
429
|
+
for k in required
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
def _is_instance_gen_type[T](obj: Any, type_: type[T], /) -> TypeGuard[T]:
|
|
257
434
|
return (
|
|
258
435
|
isinstance(obj, type_)
|
|
259
436
|
and not (
|
|
@@ -282,6 +459,101 @@ class IsInstanceGenError(Exception):
|
|
|
282
459
|
##
|
|
283
460
|
|
|
284
461
|
|
|
462
|
+
@overload
|
|
463
|
+
def is_iterable_of[T](
|
|
464
|
+
obj: Any,
|
|
465
|
+
cls: type[T],
|
|
466
|
+
/,
|
|
467
|
+
*,
|
|
468
|
+
globalns: StrMapping | None = None,
|
|
469
|
+
localns: StrMapping | None = None,
|
|
470
|
+
warn_name_errors: bool = False,
|
|
471
|
+
) -> TypeGuard[Iterable[T]]: ...
|
|
472
|
+
@overload
|
|
473
|
+
def is_iterable_of[T1](
|
|
474
|
+
obj: Any,
|
|
475
|
+
cls: tuple[type[T1]],
|
|
476
|
+
/,
|
|
477
|
+
*,
|
|
478
|
+
globalns: StrMapping | None = None,
|
|
479
|
+
localns: StrMapping | None = None,
|
|
480
|
+
warn_name_errors: bool = False,
|
|
481
|
+
) -> TypeGuard[Iterable[T1]]: ...
|
|
482
|
+
@overload
|
|
483
|
+
def is_iterable_of[T1, T2](
|
|
484
|
+
obj: Any,
|
|
485
|
+
cls: tuple[type[T1], type[T2]],
|
|
486
|
+
/,
|
|
487
|
+
*,
|
|
488
|
+
globalns: StrMapping | None = None,
|
|
489
|
+
localns: StrMapping | None = None,
|
|
490
|
+
warn_name_errors: bool = False,
|
|
491
|
+
) -> TypeGuard[Iterable[T1 | T2]]: ...
|
|
492
|
+
@overload
|
|
493
|
+
def is_iterable_of[T1, T2, T3](
|
|
494
|
+
obj: Any,
|
|
495
|
+
cls: tuple[type[T1], type[T2], type[T3]],
|
|
496
|
+
/,
|
|
497
|
+
*,
|
|
498
|
+
globalns: StrMapping | None = None,
|
|
499
|
+
localns: StrMapping | None = None,
|
|
500
|
+
warn_name_errors: bool = False,
|
|
501
|
+
) -> TypeGuard[Iterable[T1 | T2 | T3]]: ...
|
|
502
|
+
@overload
|
|
503
|
+
def is_iterable_of[T1, T2, T3, T4](
|
|
504
|
+
obj: Any,
|
|
505
|
+
cls: tuple[type[T1], type[T2], type[T3], type[T4]],
|
|
506
|
+
/,
|
|
507
|
+
*,
|
|
508
|
+
globalns: StrMapping | None = None,
|
|
509
|
+
localns: StrMapping | None = None,
|
|
510
|
+
warn_name_errors: bool = False,
|
|
511
|
+
) -> TypeGuard[Iterable[T1 | T2 | T3 | T4]]: ...
|
|
512
|
+
@overload
|
|
513
|
+
def is_iterable_of[T1, T2, T3, T4, T5](
|
|
514
|
+
obj: Any,
|
|
515
|
+
cls: tuple[type[T1], type[T2], type[T3], type[T4], type[T5]],
|
|
516
|
+
/,
|
|
517
|
+
*,
|
|
518
|
+
globalns: StrMapping | None = None,
|
|
519
|
+
localns: StrMapping | None = None,
|
|
520
|
+
warn_name_errors: bool = False,
|
|
521
|
+
) -> TypeGuard[Iterable[T1 | T2 | T3 | T4 | T5]]: ...
|
|
522
|
+
@overload
|
|
523
|
+
def is_iterable_of[T](
|
|
524
|
+
obj: Any,
|
|
525
|
+
cls: TypeLike[T],
|
|
526
|
+
/,
|
|
527
|
+
*,
|
|
528
|
+
globalns: StrMapping | None = None,
|
|
529
|
+
localns: StrMapping | None = None,
|
|
530
|
+
warn_name_errors: bool = False,
|
|
531
|
+
) -> TypeGuard[Iterable[T]]: ...
|
|
532
|
+
def is_iterable_of[T](
|
|
533
|
+
obj: Any,
|
|
534
|
+
cls: TypeLike[T],
|
|
535
|
+
/,
|
|
536
|
+
*,
|
|
537
|
+
globalns: StrMapping | None = None,
|
|
538
|
+
localns: StrMapping | None = None,
|
|
539
|
+
warn_name_errors: bool = False,
|
|
540
|
+
) -> TypeGuard[Iterable[T]]:
|
|
541
|
+
"""Check if an object is a iterable of tuple or string mappings."""
|
|
542
|
+
return isinstance(obj, Iterable) and all(
|
|
543
|
+
is_instance_gen(
|
|
544
|
+
o,
|
|
545
|
+
cls,
|
|
546
|
+
globalns=globalns,
|
|
547
|
+
localns=localns,
|
|
548
|
+
warn_name_errors=warn_name_errors,
|
|
549
|
+
)
|
|
550
|
+
for o in obj
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
##
|
|
555
|
+
|
|
556
|
+
|
|
285
557
|
def is_list_type(obj: Any, /) -> bool:
|
|
286
558
|
"""Check if an object is a list type annotation."""
|
|
287
559
|
return _is_annotation_of_type(obj, list)
|
|
@@ -328,6 +600,30 @@ def _is_namedtuple_core(obj: Any, /) -> bool:
|
|
|
328
600
|
##
|
|
329
601
|
|
|
330
602
|
|
|
603
|
+
def is_not_required_annotation(obj: Any) -> bool:
|
|
604
|
+
"""Check if an annotation is not required."""
|
|
605
|
+
if is_not_required_type(obj):
|
|
606
|
+
return True
|
|
607
|
+
match obj:
|
|
608
|
+
case str() as text:
|
|
609
|
+
return bool(search("NotRequired", text))
|
|
610
|
+
case ForwardRef() as fr:
|
|
611
|
+
return is_not_required_annotation(fr.__forward_arg__)
|
|
612
|
+
case _:
|
|
613
|
+
return False
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
##
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
def is_not_required_type(obj: Any, /) -> bool:
|
|
620
|
+
"""Check if an object is a not-required type annotation."""
|
|
621
|
+
return (obj is NotRequired) or _is_annotation_of_type(obj, NotRequired)
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
##
|
|
625
|
+
|
|
626
|
+
|
|
331
627
|
def is_optional_type(obj: Any, /) -> bool:
|
|
332
628
|
"""Check if an object is an optional type annotation."""
|
|
333
629
|
is_optional = _is_annotation_of_type(obj, Optional) # pyright: ignore[reportDeprecated]
|
|
@@ -339,6 +635,104 @@ def is_optional_type(obj: Any, /) -> bool:
|
|
|
339
635
|
##
|
|
340
636
|
|
|
341
637
|
|
|
638
|
+
@overload
|
|
639
|
+
def is_sequence_of[T](
|
|
640
|
+
obj: Any,
|
|
641
|
+
cls: type[T],
|
|
642
|
+
/,
|
|
643
|
+
*,
|
|
644
|
+
globalns: StrMapping | None = None,
|
|
645
|
+
localns: StrMapping | None = None,
|
|
646
|
+
warn_name_errors: bool = False,
|
|
647
|
+
) -> TypeGuard[Sequence[T]]: ...
|
|
648
|
+
@overload
|
|
649
|
+
def is_sequence_of[T1](
|
|
650
|
+
obj: Any,
|
|
651
|
+
cls: tuple[type[T1]],
|
|
652
|
+
/,
|
|
653
|
+
*,
|
|
654
|
+
globalns: StrMapping | None = None,
|
|
655
|
+
localns: StrMapping | None = None,
|
|
656
|
+
warn_name_errors: bool = False,
|
|
657
|
+
) -> TypeGuard[Sequence[T1]]: ...
|
|
658
|
+
@overload
|
|
659
|
+
def is_sequence_of[T1, T2](
|
|
660
|
+
obj: Any,
|
|
661
|
+
cls: tuple[type[T1], type[T2]],
|
|
662
|
+
/,
|
|
663
|
+
*,
|
|
664
|
+
globalns: StrMapping | None = None,
|
|
665
|
+
localns: StrMapping | None = None,
|
|
666
|
+
warn_name_errors: bool = False,
|
|
667
|
+
) -> TypeGuard[Sequence[T1 | T2]]: ...
|
|
668
|
+
@overload
|
|
669
|
+
def is_sequence_of[T1, T2, T3](
|
|
670
|
+
obj: Any,
|
|
671
|
+
cls: tuple[type[T1], type[T2], type[T3]],
|
|
672
|
+
/,
|
|
673
|
+
*,
|
|
674
|
+
globalns: StrMapping | None = None,
|
|
675
|
+
localns: StrMapping | None = None,
|
|
676
|
+
warn_name_errors: bool = False,
|
|
677
|
+
) -> TypeGuard[Sequence[T1 | T2 | T3]]: ...
|
|
678
|
+
@overload
|
|
679
|
+
def is_sequence_of[T1, T2, T3, T4](
|
|
680
|
+
obj: Any,
|
|
681
|
+
cls: tuple[type[T1], type[T2], type[T3], type[T4]],
|
|
682
|
+
/,
|
|
683
|
+
*,
|
|
684
|
+
globalns: StrMapping | None = None,
|
|
685
|
+
localns: StrMapping | None = None,
|
|
686
|
+
warn_name_errors: bool = False,
|
|
687
|
+
) -> TypeGuard[Sequence[T1 | T2 | T3 | T4]]: ...
|
|
688
|
+
@overload
|
|
689
|
+
def is_sequence_of[T1, T2, T3, T4, T5](
|
|
690
|
+
obj: Any,
|
|
691
|
+
cls: tuple[type[T1], type[T2], type[T3], type[T4], type[T5]],
|
|
692
|
+
/,
|
|
693
|
+
*,
|
|
694
|
+
globalns: StrMapping | None = None,
|
|
695
|
+
localns: StrMapping | None = None,
|
|
696
|
+
warn_name_errors: bool = False,
|
|
697
|
+
) -> TypeGuard[Sequence[T1 | T2 | T3 | T4 | T5]]: ...
|
|
698
|
+
@overload
|
|
699
|
+
def is_sequence_of[T](
|
|
700
|
+
obj: Any,
|
|
701
|
+
cls: TypeLike[T],
|
|
702
|
+
/,
|
|
703
|
+
*,
|
|
704
|
+
globalns: StrMapping | None = None,
|
|
705
|
+
localns: StrMapping | None = None,
|
|
706
|
+
warn_name_errors: bool = False,
|
|
707
|
+
) -> TypeGuard[Sequence[T]]: ...
|
|
708
|
+
def is_sequence_of[T](
|
|
709
|
+
obj: Any,
|
|
710
|
+
cls: TypeLike[T],
|
|
711
|
+
/,
|
|
712
|
+
*,
|
|
713
|
+
globalns: StrMapping | None = None,
|
|
714
|
+
localns: StrMapping | None = None,
|
|
715
|
+
warn_name_errors: bool = False,
|
|
716
|
+
) -> TypeGuard[Sequence[T]]:
|
|
717
|
+
"""Check if an object is a sequence of tuple or string mappings."""
|
|
718
|
+
return isinstance(obj, Sequence) and is_iterable_of(
|
|
719
|
+
obj, cls, globalns=globalns, localns=localns, warn_name_errors=warn_name_errors
|
|
720
|
+
)
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
##
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
def is_sequence_of_tuple_or_str_mapping(
|
|
727
|
+
obj: Any, /
|
|
728
|
+
) -> TypeGuard[Sequence[TupleOrStrMapping]]:
|
|
729
|
+
"""Check if an object is a sequence of tuple or string mappings."""
|
|
730
|
+
return isinstance(obj, Sequence) and all(map(is_tuple_or_str_mapping, obj))
|
|
731
|
+
|
|
732
|
+
|
|
733
|
+
##
|
|
734
|
+
|
|
735
|
+
|
|
342
736
|
def is_sequence_type(obj: Any, /) -> bool:
|
|
343
737
|
"""Check if an object is a sequence type annotation."""
|
|
344
738
|
return _is_annotation_of_type(obj, Sequence)
|
|
@@ -355,30 +749,36 @@ def is_set_type(obj: Any, /) -> bool:
|
|
|
355
749
|
##
|
|
356
750
|
|
|
357
751
|
|
|
752
|
+
def is_string_mapping(obj: Any, /) -> TypeGuard[StrMapping]:
|
|
753
|
+
"""Check if an object is a string mapping."""
|
|
754
|
+
return isinstance(obj, Mapping) and is_iterable_of(obj, str)
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
##
|
|
758
|
+
|
|
759
|
+
|
|
358
760
|
@overload
|
|
359
|
-
def is_subclass_gen(cls: type[Any], parent: type[
|
|
761
|
+
def is_subclass_gen[T](cls: type[Any], parent: type[T], /) -> TypeGuard[type[T]]: ...
|
|
360
762
|
@overload
|
|
361
|
-
def is_subclass_gen(
|
|
362
|
-
cls: type[Any], parent: tuple[type[
|
|
363
|
-
) -> TypeGuard[type[
|
|
763
|
+
def is_subclass_gen[T1](
|
|
764
|
+
cls: type[Any], parent: tuple[type[T1]], /
|
|
765
|
+
) -> TypeGuard[type[T1]]: ...
|
|
364
766
|
@overload
|
|
365
|
-
def is_subclass_gen(
|
|
366
|
-
cls: type[Any], parent: tuple[type[
|
|
367
|
-
) -> TypeGuard[type[
|
|
767
|
+
def is_subclass_gen[T1, T2](
|
|
768
|
+
cls: type[Any], parent: tuple[type[T1], type[T2]], /
|
|
769
|
+
) -> TypeGuard[type[T1 | T2]]: ...
|
|
368
770
|
@overload
|
|
369
|
-
def is_subclass_gen(
|
|
370
|
-
cls: type[Any], parent: tuple[type[
|
|
371
|
-
) -> TypeGuard[type[
|
|
771
|
+
def is_subclass_gen[T1, T2, T3](
|
|
772
|
+
cls: type[Any], parent: tuple[type[T1], type[T2], type[T3]], /
|
|
773
|
+
) -> TypeGuard[type[T1 | T2 | T3]]: ...
|
|
372
774
|
@overload
|
|
373
|
-
def is_subclass_gen(
|
|
374
|
-
cls: type[Any], parent: tuple[type[
|
|
375
|
-
) -> TypeGuard[type[
|
|
775
|
+
def is_subclass_gen[T1, T2, T3, T4](
|
|
776
|
+
cls: type[Any], parent: tuple[type[T1], type[T2], type[T3], type[T4]], /
|
|
777
|
+
) -> TypeGuard[type[T1 | T2 | T3 | T4]]: ...
|
|
376
778
|
@overload
|
|
377
|
-
def is_subclass_gen(
|
|
378
|
-
cls: type[Any],
|
|
379
|
-
|
|
380
|
-
/,
|
|
381
|
-
) -> TypeGuard[type[_T1 | _T2 | _T3 | _T4 | _T5]]: ...
|
|
779
|
+
def is_subclass_gen[T1, T2, T3, T4, T5](
|
|
780
|
+
cls: type[Any], parent: tuple[type[T1], type[T2], type[T3], type[T4], type[T5]], /
|
|
781
|
+
) -> TypeGuard[type[T1 | T2 | T3 | T4 | T5]]: ...
|
|
382
782
|
@overload
|
|
383
783
|
def is_subclass_gen(cls: Any, parent: Any, /) -> bool: ...
|
|
384
784
|
def is_subclass_gen(cls: Any, parent: Any, /) -> bool:
|
|
@@ -414,7 +814,7 @@ def is_subclass_gen(cls: Any, parent: Any, /) -> bool:
|
|
|
414
814
|
raise IsSubclassGenError(cls=cls)
|
|
415
815
|
|
|
416
816
|
|
|
417
|
-
def _is_subclass_gen_type(cls: type[Any], parent: type[
|
|
817
|
+
def _is_subclass_gen_type[T](cls: type[Any], parent: type[T], /) -> TypeGuard[type[T]]:
|
|
418
818
|
return (
|
|
419
819
|
issubclass(cls, parent)
|
|
420
820
|
and not (
|
|
@@ -442,6 +842,22 @@ class IsSubclassGenError(Exception):
|
|
|
442
842
|
##
|
|
443
843
|
|
|
444
844
|
|
|
845
|
+
def is_tuple(obj: Any, /) -> TypeGuard[tuple[Any, ...]]:
|
|
846
|
+
"""Check if an object is a tuple."""
|
|
847
|
+
return isinstance(obj, tuple)
|
|
848
|
+
|
|
849
|
+
|
|
850
|
+
##
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
def is_tuple_or_str_mapping(obj: Any, /) -> TypeGuard[TupleOrStrMapping]:
|
|
854
|
+
"""Check if an object is a tuple or string mapping."""
|
|
855
|
+
return is_tuple(obj) or is_string_mapping(obj)
|
|
856
|
+
|
|
857
|
+
|
|
858
|
+
##
|
|
859
|
+
|
|
860
|
+
|
|
445
861
|
def is_tuple_type(obj: Any, /) -> bool:
|
|
446
862
|
"""Check if an object is a tuple type annotation."""
|
|
447
863
|
return _is_annotation_of_type(obj, tuple)
|
|
@@ -466,28 +882,72 @@ def _is_annotation_of_type(obj: Any, origin: Any, /) -> bool:
|
|
|
466
882
|
)
|
|
467
883
|
|
|
468
884
|
|
|
885
|
+
##
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
@overload
|
|
889
|
+
def make_isinstance[T](cls: type[T], /) -> Callable[[Any], TypeGuard[T]]: ...
|
|
890
|
+
@overload
|
|
891
|
+
def make_isinstance[T1](cls: tuple[type[T1]], /) -> Callable[[Any], TypeGuard[T1]]: ...
|
|
892
|
+
@overload
|
|
893
|
+
def make_isinstance[T1, T2](
|
|
894
|
+
cls: tuple[type[T1], type[T2]], /
|
|
895
|
+
) -> Callable[[Any], TypeGuard[T1 | T2]]: ...
|
|
896
|
+
@overload
|
|
897
|
+
def make_isinstance[T1, T2, T3](
|
|
898
|
+
cls: tuple[type[T1], type[T2], type[T3]], /
|
|
899
|
+
) -> Callable[[Any], TypeGuard[T1 | T2 | T3]]: ...
|
|
900
|
+
@overload
|
|
901
|
+
def make_isinstance[T1, T2, T3, T4](
|
|
902
|
+
cls: tuple[type[T1], type[T2], type[T3], type[T4]], /
|
|
903
|
+
) -> Callable[[Any], TypeGuard[T1 | T2 | T3 | T4]]: ...
|
|
904
|
+
@overload
|
|
905
|
+
def make_isinstance[T1, T2, T3, T4, T5](
|
|
906
|
+
cls: tuple[type[T1], type[T2], type[T3], type[T4], type[T5]], /
|
|
907
|
+
) -> Callable[[Any], TypeGuard[T1 | T2 | T3 | T4 | T5]]: ...
|
|
908
|
+
@overload
|
|
909
|
+
def make_isinstance[T](cls: TypeLike[T], /) -> Callable[[Any], TypeGuard[T]]: ...
|
|
910
|
+
def make_isinstance[T](cls: TypeLike[T], /) -> Callable[[Any], TypeGuard[T]]:
|
|
911
|
+
"""Make a curried `isinstance` function."""
|
|
912
|
+
return partial(_make_instance_core, cls=cls)
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
def _make_instance_core[T](obj: Any, /, *, cls: TypeLike[T]) -> TypeGuard[T]:
|
|
916
|
+
return is_instance_gen(obj, cls)
|
|
917
|
+
|
|
918
|
+
|
|
469
919
|
__all__ = [
|
|
470
920
|
"GetTypeClassesError",
|
|
471
921
|
"GetUnionTypeClassesError",
|
|
472
922
|
"IsInstanceGenError",
|
|
473
923
|
"IsSubclassGenError",
|
|
474
|
-
"contains_self",
|
|
475
924
|
"get_literal_elements",
|
|
476
925
|
"get_type_classes",
|
|
477
926
|
"get_type_hints",
|
|
478
927
|
"get_union_type_classes",
|
|
928
|
+
"is_dataclass_class",
|
|
929
|
+
"is_dataclass_instance",
|
|
479
930
|
"is_dict_type",
|
|
480
931
|
"is_frozenset_type",
|
|
481
932
|
"is_instance_gen",
|
|
933
|
+
"is_iterable_of",
|
|
482
934
|
"is_list_type",
|
|
483
935
|
"is_literal_type",
|
|
484
936
|
"is_mapping_type",
|
|
485
937
|
"is_namedtuple_class",
|
|
486
938
|
"is_namedtuple_instance",
|
|
939
|
+
"is_not_required_annotation",
|
|
940
|
+
"is_not_required_type",
|
|
487
941
|
"is_optional_type",
|
|
942
|
+
"is_sequence_of",
|
|
943
|
+
"is_sequence_of_tuple_or_str_mapping",
|
|
488
944
|
"is_sequence_type",
|
|
489
945
|
"is_set_type",
|
|
946
|
+
"is_string_mapping",
|
|
490
947
|
"is_subclass_gen",
|
|
948
|
+
"is_tuple",
|
|
949
|
+
"is_tuple_or_str_mapping",
|
|
491
950
|
"is_tuple_type",
|
|
492
951
|
"is_union_type",
|
|
952
|
+
"make_isinstance",
|
|
493
953
|
]
|