metaflow 2.15.5__py2.py3-none-any.whl → 2.15.7__py2.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.
Files changed (53) hide show
  1. metaflow/_vendor/typeguard/_checkers.py +259 -95
  2. metaflow/_vendor/typeguard/_config.py +4 -4
  3. metaflow/_vendor/typeguard/_decorators.py +8 -12
  4. metaflow/_vendor/typeguard/_functions.py +33 -32
  5. metaflow/_vendor/typeguard/_pytest_plugin.py +40 -13
  6. metaflow/_vendor/typeguard/_suppression.py +3 -5
  7. metaflow/_vendor/typeguard/_transformer.py +84 -48
  8. metaflow/_vendor/typeguard/_union_transformer.py +1 -0
  9. metaflow/_vendor/typeguard/_utils.py +13 -9
  10. metaflow/_vendor/typing_extensions.py +1088 -500
  11. metaflow/_vendor/v3_7/__init__.py +1 -0
  12. metaflow/_vendor/v3_7/importlib_metadata/__init__.py +1063 -0
  13. metaflow/_vendor/v3_7/importlib_metadata/_adapters.py +68 -0
  14. metaflow/_vendor/v3_7/importlib_metadata/_collections.py +30 -0
  15. metaflow/_vendor/v3_7/importlib_metadata/_compat.py +71 -0
  16. metaflow/_vendor/v3_7/importlib_metadata/_functools.py +104 -0
  17. metaflow/_vendor/v3_7/importlib_metadata/_itertools.py +73 -0
  18. metaflow/_vendor/v3_7/importlib_metadata/_meta.py +48 -0
  19. metaflow/_vendor/v3_7/importlib_metadata/_text.py +99 -0
  20. metaflow/_vendor/v3_7/importlib_metadata/py.typed +0 -0
  21. metaflow/_vendor/v3_7/typeguard/__init__.py +48 -0
  22. metaflow/_vendor/v3_7/typeguard/_checkers.py +906 -0
  23. metaflow/_vendor/v3_7/typeguard/_config.py +108 -0
  24. metaflow/_vendor/v3_7/typeguard/_decorators.py +237 -0
  25. metaflow/_vendor/v3_7/typeguard/_exceptions.py +42 -0
  26. metaflow/_vendor/v3_7/typeguard/_functions.py +310 -0
  27. metaflow/_vendor/v3_7/typeguard/_importhook.py +213 -0
  28. metaflow/_vendor/v3_7/typeguard/_memo.py +48 -0
  29. metaflow/_vendor/v3_7/typeguard/_pytest_plugin.py +100 -0
  30. metaflow/_vendor/v3_7/typeguard/_suppression.py +88 -0
  31. metaflow/_vendor/v3_7/typeguard/_transformer.py +1207 -0
  32. metaflow/_vendor/v3_7/typeguard/_union_transformer.py +54 -0
  33. metaflow/_vendor/v3_7/typeguard/_utils.py +169 -0
  34. metaflow/_vendor/v3_7/typeguard/py.typed +0 -0
  35. metaflow/_vendor/v3_7/typing_extensions.py +3072 -0
  36. metaflow/_vendor/v3_7/zipp.py +329 -0
  37. metaflow/cmd/develop/stubs.py +1 -1
  38. metaflow/extension_support/__init__.py +1 -1
  39. metaflow/plugins/argo/argo_workflows.py +34 -11
  40. metaflow/plugins/argo/argo_workflows_deployer_objects.py +7 -6
  41. metaflow/plugins/pypi/utils.py +4 -0
  42. metaflow/runner/click_api.py +7 -2
  43. metaflow/vendor.py +1 -0
  44. metaflow/version.py +1 -1
  45. {metaflow-2.15.5.data → metaflow-2.15.7.data}/data/share/metaflow/devtools/Makefile +2 -2
  46. {metaflow-2.15.5.dist-info → metaflow-2.15.7.dist-info}/METADATA +4 -3
  47. {metaflow-2.15.5.dist-info → metaflow-2.15.7.dist-info}/RECORD +53 -27
  48. {metaflow-2.15.5.dist-info → metaflow-2.15.7.dist-info}/WHEEL +1 -1
  49. {metaflow-2.15.5.data → metaflow-2.15.7.data}/data/share/metaflow/devtools/Tiltfile +0 -0
  50. {metaflow-2.15.5.data → metaflow-2.15.7.data}/data/share/metaflow/devtools/pick_services.sh +0 -0
  51. {metaflow-2.15.5.dist-info → metaflow-2.15.7.dist-info}/entry_points.txt +0 -0
  52. {metaflow-2.15.5.dist-info → metaflow-2.15.7.dist-info/licenses}/LICENSE +0 -0
  53. {metaflow-2.15.5.dist-info → metaflow-2.15.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,906 @@
1
+ from __future__ import annotations
2
+
3
+ import collections.abc
4
+ import inspect
5
+ import sys
6
+ import types
7
+ import typing
8
+ import warnings
9
+ from enum import Enum
10
+ from inspect import Parameter, isclass, isfunction
11
+ from io import BufferedIOBase, IOBase, RawIOBase, TextIOBase
12
+ from textwrap import indent
13
+ from typing import (
14
+ IO,
15
+ AbstractSet,
16
+ Any,
17
+ BinaryIO,
18
+ Callable,
19
+ Dict,
20
+ ForwardRef,
21
+ List,
22
+ Mapping,
23
+ MutableMapping,
24
+ NewType,
25
+ Optional,
26
+ Sequence,
27
+ Set,
28
+ TextIO,
29
+ Tuple,
30
+ Type,
31
+ TypeVar,
32
+ Union,
33
+ )
34
+ from unittest.mock import Mock
35
+
36
+ try:
37
+ from metaflow._vendor.v3_7 import typing_extensions
38
+ except ImportError:
39
+ typing_extensions = None # type: ignore[assignment]
40
+
41
+ from ._config import ForwardRefPolicy
42
+ from ._exceptions import TypeCheckError, TypeHintWarning
43
+ from ._memo import TypeCheckMemo
44
+ from ._utils import evaluate_forwardref, get_stacklevel, get_type_name, qualified_name
45
+
46
+ if sys.version_info >= (3, 11):
47
+ from typing import (
48
+ Annotated,
49
+ TypeAlias,
50
+ get_args,
51
+ get_origin,
52
+ get_type_hints,
53
+ is_typeddict,
54
+ )
55
+
56
+ SubclassableAny = Any
57
+ else:
58
+ from metaflow._vendor.v3_7.typing_extensions import (
59
+ Annotated,
60
+ TypeAlias,
61
+ get_args,
62
+ get_origin,
63
+ get_type_hints,
64
+ is_typeddict,
65
+ )
66
+ from metaflow._vendor.v3_7.typing_extensions import Any as SubclassableAny
67
+
68
+ if sys.version_info >= (3, 10):
69
+ from importlib.metadata import entry_points
70
+ from typing import ParamSpec
71
+ else:
72
+ from metaflow._vendor.v3_7.importlib_metadata import entry_points
73
+ from metaflow._vendor.v3_7.typing_extensions import ParamSpec
74
+
75
+ TypeCheckerCallable: TypeAlias = Callable[
76
+ [Any, Any, Tuple[Any, ...], TypeCheckMemo], Any
77
+ ]
78
+ TypeCheckLookupCallback: TypeAlias = Callable[
79
+ [Any, Tuple[Any, ...], Tuple[Any, ...]], Optional[TypeCheckerCallable]
80
+ ]
81
+
82
+ checker_lookup_functions: list[TypeCheckLookupCallback] = []
83
+
84
+
85
+ # Sentinel
86
+ _missing = object()
87
+
88
+ # Lifted from mypy.sharedparse
89
+ BINARY_MAGIC_METHODS = {
90
+ "__add__",
91
+ "__and__",
92
+ "__cmp__",
93
+ "__divmod__",
94
+ "__div__",
95
+ "__eq__",
96
+ "__floordiv__",
97
+ "__ge__",
98
+ "__gt__",
99
+ "__iadd__",
100
+ "__iand__",
101
+ "__idiv__",
102
+ "__ifloordiv__",
103
+ "__ilshift__",
104
+ "__imatmul__",
105
+ "__imod__",
106
+ "__imul__",
107
+ "__ior__",
108
+ "__ipow__",
109
+ "__irshift__",
110
+ "__isub__",
111
+ "__itruediv__",
112
+ "__ixor__",
113
+ "__le__",
114
+ "__lshift__",
115
+ "__lt__",
116
+ "__matmul__",
117
+ "__mod__",
118
+ "__mul__",
119
+ "__ne__",
120
+ "__or__",
121
+ "__pow__",
122
+ "__radd__",
123
+ "__rand__",
124
+ "__rdiv__",
125
+ "__rfloordiv__",
126
+ "__rlshift__",
127
+ "__rmatmul__",
128
+ "__rmod__",
129
+ "__rmul__",
130
+ "__ror__",
131
+ "__rpow__",
132
+ "__rrshift__",
133
+ "__rshift__",
134
+ "__rsub__",
135
+ "__rtruediv__",
136
+ "__rxor__",
137
+ "__sub__",
138
+ "__truediv__",
139
+ "__xor__",
140
+ }
141
+
142
+
143
+ def check_callable(
144
+ value: Any,
145
+ origin_type: Any,
146
+ args: tuple[Any, ...],
147
+ memo: TypeCheckMemo,
148
+ ) -> None:
149
+ if not callable(value):
150
+ raise TypeCheckError("is not callable")
151
+
152
+ if args:
153
+ try:
154
+ signature = inspect.signature(value)
155
+ except (TypeError, ValueError):
156
+ return
157
+
158
+ argument_types = args[0]
159
+ if isinstance(argument_types, list) and not any(
160
+ type(item) is ParamSpec for item in argument_types
161
+ ):
162
+ # The callable must not have keyword-only arguments without defaults
163
+ unfulfilled_kwonlyargs = [
164
+ param.name
165
+ for param in signature.parameters.values()
166
+ if param.kind == Parameter.KEYWORD_ONLY
167
+ and param.default == Parameter.empty
168
+ ]
169
+ if unfulfilled_kwonlyargs:
170
+ raise TypeCheckError(
171
+ f"has mandatory keyword-only arguments in its declaration: "
172
+ f'{", ".join(unfulfilled_kwonlyargs)}'
173
+ )
174
+
175
+ num_mandatory_args = len(
176
+ [
177
+ param.name
178
+ for param in signature.parameters.values()
179
+ if param.kind
180
+ in (Parameter.POSITIONAL_ONLY, Parameter.POSITIONAL_OR_KEYWORD)
181
+ and param.default is Parameter.empty
182
+ ]
183
+ )
184
+ has_varargs = any(
185
+ param
186
+ for param in signature.parameters.values()
187
+ if param.kind == Parameter.VAR_POSITIONAL
188
+ )
189
+
190
+ if num_mandatory_args > len(argument_types):
191
+ raise TypeCheckError(
192
+ f"has too many arguments in its declaration; expected "
193
+ f"{len(argument_types)} but {num_mandatory_args} argument(s) "
194
+ f"declared"
195
+ )
196
+ elif not has_varargs and num_mandatory_args < len(argument_types):
197
+ raise TypeCheckError(
198
+ f"has too few arguments in its declaration; expected "
199
+ f"{len(argument_types)} but {num_mandatory_args} argument(s) "
200
+ f"declared"
201
+ )
202
+
203
+
204
+ def check_mapping(
205
+ value: Any,
206
+ origin_type: Any,
207
+ args: tuple[Any, ...],
208
+ memo: TypeCheckMemo,
209
+ ) -> None:
210
+ if origin_type is Dict or origin_type is dict:
211
+ if not isinstance(value, dict):
212
+ raise TypeCheckError("is not a dict")
213
+ if origin_type is MutableMapping or origin_type is collections.abc.MutableMapping:
214
+ if not isinstance(value, collections.abc.MutableMapping):
215
+ raise TypeCheckError("is not a mutable mapping")
216
+ elif not isinstance(value, collections.abc.Mapping):
217
+ raise TypeCheckError("is not a mapping")
218
+
219
+ if args:
220
+ key_type, value_type = args
221
+ if key_type is not Any or value_type is not Any:
222
+ samples = memo.config.collection_check_strategy.iterate_samples(
223
+ value.items()
224
+ )
225
+ for k, v in samples:
226
+ try:
227
+ check_type_internal(k, key_type, memo)
228
+ except TypeCheckError as exc:
229
+ exc.append_path_element(f"key {k!r}")
230
+ raise
231
+
232
+ try:
233
+ check_type_internal(v, value_type, memo)
234
+ except TypeCheckError as exc:
235
+ exc.append_path_element(f"value of key {k!r}")
236
+ raise
237
+
238
+
239
+ def check_typed_dict(
240
+ value: Any,
241
+ origin_type: Any,
242
+ args: tuple[Any, ...],
243
+ memo: TypeCheckMemo,
244
+ ) -> None:
245
+ if not isinstance(value, dict):
246
+ raise TypeCheckError("is not a dict")
247
+
248
+ declared_keys = frozenset(origin_type.__annotations__)
249
+ if hasattr(origin_type, "__required_keys__"):
250
+ required_keys = origin_type.__required_keys__
251
+ else: # py3.8 and lower
252
+ required_keys = declared_keys if origin_type.__total__ else frozenset()
253
+
254
+ existing_keys = frozenset(value)
255
+ extra_keys = existing_keys - declared_keys
256
+ if extra_keys:
257
+ keys_formatted = ", ".join(f'"{key}"' for key in sorted(extra_keys, key=repr))
258
+ raise TypeCheckError(f"has unexpected extra key(s): {keys_formatted}")
259
+
260
+ missing_keys = required_keys - existing_keys
261
+ if missing_keys:
262
+ keys_formatted = ", ".join(f'"{key}"' for key in sorted(missing_keys, key=repr))
263
+ raise TypeCheckError(f"is missing required key(s): {keys_formatted}")
264
+
265
+ for key, argtype in get_type_hints(origin_type).items():
266
+ argvalue = value.get(key, _missing)
267
+ if argvalue is not _missing:
268
+ try:
269
+ check_type_internal(argvalue, argtype, memo)
270
+ except TypeCheckError as exc:
271
+ exc.append_path_element(f"value of key {key!r}")
272
+ raise
273
+
274
+
275
+ def check_list(
276
+ value: Any,
277
+ origin_type: Any,
278
+ args: tuple[Any, ...],
279
+ memo: TypeCheckMemo,
280
+ ) -> None:
281
+ if not isinstance(value, list):
282
+ raise TypeCheckError("is not a list")
283
+
284
+ if args and args != (Any,):
285
+ samples = memo.config.collection_check_strategy.iterate_samples(value)
286
+ for i, v in enumerate(samples):
287
+ try:
288
+ check_type_internal(v, args[0], memo)
289
+ except TypeCheckError as exc:
290
+ exc.append_path_element(f"item {i}")
291
+ raise
292
+
293
+
294
+ def check_sequence(
295
+ value: Any,
296
+ origin_type: Any,
297
+ args: tuple[Any, ...],
298
+ memo: TypeCheckMemo,
299
+ ) -> None:
300
+ if not isinstance(value, collections.abc.Sequence):
301
+ raise TypeCheckError("is not a sequence")
302
+
303
+ if args and args != (Any,):
304
+ samples = memo.config.collection_check_strategy.iterate_samples(value)
305
+ for i, v in enumerate(samples):
306
+ try:
307
+ check_type_internal(v, args[0], memo)
308
+ except TypeCheckError as exc:
309
+ exc.append_path_element(f"item {i}")
310
+ raise
311
+
312
+
313
+ def check_set(
314
+ value: Any,
315
+ origin_type: Any,
316
+ args: tuple[Any, ...],
317
+ memo: TypeCheckMemo,
318
+ ) -> None:
319
+ if origin_type is frozenset:
320
+ if not isinstance(value, frozenset):
321
+ raise TypeCheckError("is not a frozenset")
322
+ elif not isinstance(value, AbstractSet):
323
+ raise TypeCheckError("is not a set")
324
+
325
+ if args and args != (Any,):
326
+ samples = memo.config.collection_check_strategy.iterate_samples(value)
327
+ for v in samples:
328
+ try:
329
+ check_type_internal(v, args[0], memo)
330
+ except TypeCheckError as exc:
331
+ exc.append_path_element(f"[{v}]")
332
+ raise
333
+
334
+
335
+ def check_tuple(
336
+ value: Any,
337
+ origin_type: Any,
338
+ args: tuple[Any, ...],
339
+ memo: TypeCheckMemo,
340
+ ) -> None:
341
+ # Specialized check for NamedTuples
342
+ field_types = getattr(origin_type, "__annotations__", None)
343
+ if field_types is None and sys.version_info < (3, 8):
344
+ field_types = getattr(origin_type, "_field_types", None)
345
+
346
+ if field_types:
347
+ if not isinstance(value, origin_type):
348
+ raise TypeCheckError(
349
+ f"is not a named tuple of type {qualified_name(origin_type)}"
350
+ )
351
+
352
+ for name, field_type in field_types.items():
353
+ try:
354
+ check_type_internal(getattr(value, name), field_type, memo)
355
+ except TypeCheckError as exc:
356
+ exc.append_path_element(f"attribute {name!r}")
357
+ raise
358
+
359
+ return
360
+ elif not isinstance(value, tuple):
361
+ raise TypeCheckError("is not a tuple")
362
+
363
+ if args:
364
+ # Python 3.6+
365
+ use_ellipsis = args[-1] is Ellipsis
366
+ tuple_params = args[: -1 if use_ellipsis else None]
367
+ else:
368
+ # Unparametrized Tuple or plain tuple
369
+ return
370
+
371
+ if use_ellipsis:
372
+ element_type = tuple_params[0]
373
+ samples = memo.config.collection_check_strategy.iterate_samples(value)
374
+ for i, element in enumerate(samples):
375
+ try:
376
+ check_type_internal(element, element_type, memo)
377
+ except TypeCheckError as exc:
378
+ exc.append_path_element(f"item {i}")
379
+ raise
380
+ elif tuple_params == ((),):
381
+ if value != ():
382
+ raise TypeCheckError("is not an empty tuple")
383
+ else:
384
+ if len(value) != len(tuple_params):
385
+ raise TypeCheckError(
386
+ f"has wrong number of elements (expected {len(tuple_params)}, got "
387
+ f"{len(value)} instead)"
388
+ )
389
+
390
+ for i, (element, element_type) in enumerate(zip(value, tuple_params)):
391
+ try:
392
+ check_type_internal(element, element_type, memo)
393
+ except TypeCheckError as exc:
394
+ exc.append_path_element(f"item {i}")
395
+ raise
396
+
397
+
398
+ def check_union(
399
+ value: Any,
400
+ origin_type: Any,
401
+ args: tuple[Any, ...],
402
+ memo: TypeCheckMemo,
403
+ ) -> None:
404
+ errors: dict[str, TypeCheckError] = {}
405
+ for type_ in args:
406
+ try:
407
+ check_type_internal(value, type_, memo)
408
+ return
409
+ except TypeCheckError as exc:
410
+ errors[get_type_name(type_)] = exc
411
+
412
+ formatted_errors = indent(
413
+ "\n".join(f"{key}: {error}" for key, error in errors.items()), " "
414
+ )
415
+ raise TypeCheckError(f"did not match any element in the union:\n{formatted_errors}")
416
+
417
+
418
+ def check_uniontype(
419
+ value: Any,
420
+ origin_type: Any,
421
+ args: tuple[Any, ...],
422
+ memo: TypeCheckMemo,
423
+ ) -> None:
424
+ errors: dict[str, TypeCheckError] = {}
425
+ for type_ in args:
426
+ try:
427
+ check_type_internal(value, type_, memo)
428
+ return
429
+ except TypeCheckError as exc:
430
+ errors[get_type_name(type_)] = exc
431
+
432
+ formatted_errors = indent(
433
+ "\n".join(f"{key}: {error}" for key, error in errors.items()), " "
434
+ )
435
+ raise TypeCheckError(f"did not match any element in the union:\n{formatted_errors}")
436
+
437
+
438
+ def check_class(
439
+ value: Any,
440
+ origin_type: Any,
441
+ args: tuple[Any, ...],
442
+ memo: TypeCheckMemo,
443
+ ) -> None:
444
+ if not isclass(value):
445
+ raise TypeCheckError("is not a class")
446
+
447
+ # Needed on Python 3.7+
448
+ if not args:
449
+ return
450
+
451
+ if isinstance(args[0], ForwardRef):
452
+ expected_class = evaluate_forwardref(args[0], memo)
453
+ else:
454
+ expected_class = args[0]
455
+
456
+ if expected_class is Any:
457
+ return
458
+ elif getattr(expected_class, "_is_protocol", False):
459
+ check_protocol(value, expected_class, (), memo)
460
+ elif isinstance(expected_class, TypeVar):
461
+ check_typevar(value, expected_class, (), memo, subclass_check=True)
462
+ elif get_origin(expected_class) is Union:
463
+ errors: dict[str, TypeCheckError] = {}
464
+ for arg in get_args(expected_class):
465
+ if arg is Any:
466
+ return
467
+
468
+ try:
469
+ check_class(value, type, (arg,), memo)
470
+ return
471
+ except TypeCheckError as exc:
472
+ errors[get_type_name(arg)] = exc
473
+ else:
474
+ formatted_errors = indent(
475
+ "\n".join(f"{key}: {error}" for key, error in errors.items()), " "
476
+ )
477
+ raise TypeCheckError(
478
+ f"did not match any element in the union:\n{formatted_errors}"
479
+ )
480
+ elif not issubclass(value, expected_class):
481
+ raise TypeCheckError(f"is not a subclass of {qualified_name(expected_class)}")
482
+
483
+
484
+ def check_newtype(
485
+ value: Any,
486
+ origin_type: Any,
487
+ args: tuple[Any, ...],
488
+ memo: TypeCheckMemo,
489
+ ) -> None:
490
+ check_type_internal(value, origin_type.__supertype__, memo)
491
+
492
+
493
+ def check_instance(
494
+ value: Any,
495
+ origin_type: Any,
496
+ args: tuple[Any, ...],
497
+ memo: TypeCheckMemo,
498
+ ) -> None:
499
+ if not isinstance(value, origin_type):
500
+ raise TypeCheckError(f"is not an instance of {qualified_name(origin_type)}")
501
+
502
+
503
+ def check_typevar(
504
+ value: Any,
505
+ origin_type: TypeVar,
506
+ args: tuple[Any, ...],
507
+ memo: TypeCheckMemo,
508
+ *,
509
+ subclass_check: bool = False,
510
+ ) -> None:
511
+ if origin_type.__bound__ is not None:
512
+ annotation = (
513
+ Type[origin_type.__bound__] if subclass_check else origin_type.__bound__
514
+ )
515
+ check_type_internal(value, annotation, memo)
516
+ elif origin_type.__constraints__:
517
+ for constraint in origin_type.__constraints__:
518
+ annotation = Type[constraint] if subclass_check else constraint
519
+ try:
520
+ check_type_internal(value, annotation, memo)
521
+ except TypeCheckError:
522
+ pass
523
+ else:
524
+ break
525
+ else:
526
+ formatted_constraints = ", ".join(
527
+ get_type_name(constraint) for constraint in origin_type.__constraints__
528
+ )
529
+ raise TypeCheckError(
530
+ f"does not match any of the constraints " f"({formatted_constraints})"
531
+ )
532
+
533
+
534
+ if sys.version_info >= (3, 8):
535
+ if typing_extensions is None:
536
+
537
+ def _is_literal_type(typ: object) -> bool:
538
+ return typ is typing.Literal
539
+
540
+ else:
541
+
542
+ def _is_literal_type(typ: object) -> bool:
543
+ return typ is typing.Literal or typ is typing_extensions.Literal
544
+
545
+ else:
546
+
547
+ def _is_literal_type(typ: object) -> bool:
548
+ return typ is typing_extensions.Literal
549
+
550
+
551
+ def check_literal(
552
+ value: Any,
553
+ origin_type: Any,
554
+ args: tuple[Any, ...],
555
+ memo: TypeCheckMemo,
556
+ ) -> None:
557
+ def get_literal_args(literal_args: tuple[Any, ...]) -> tuple[Any, ...]:
558
+ retval: list[Any] = []
559
+ for arg in literal_args:
560
+ if _is_literal_type(get_origin(arg)):
561
+ # The first check works on py3.6 and lower, the second one on py3.7+
562
+ retval.extend(get_literal_args(arg.__args__))
563
+ elif arg is None or isinstance(arg, (int, str, bytes, bool, Enum)):
564
+ retval.append(arg)
565
+ else:
566
+ raise TypeError(
567
+ f"Illegal literal value: {arg}"
568
+ ) # TypeError here is deliberate
569
+
570
+ return tuple(retval)
571
+
572
+ final_args = tuple(get_literal_args(args))
573
+ try:
574
+ index = final_args.index(value)
575
+ except ValueError:
576
+ pass
577
+ else:
578
+ if type(final_args[index]) is type(value):
579
+ return
580
+
581
+ formatted_args = ", ".join(repr(arg) for arg in final_args)
582
+ raise TypeCheckError(f"is not any of ({formatted_args})") from None
583
+
584
+
585
+ def check_literal_string(
586
+ value: Any,
587
+ origin_type: Any,
588
+ args: tuple[Any, ...],
589
+ memo: TypeCheckMemo,
590
+ ) -> None:
591
+ check_type_internal(value, str, memo)
592
+
593
+
594
+ def check_typeguard(
595
+ value: Any,
596
+ origin_type: Any,
597
+ args: tuple[Any, ...],
598
+ memo: TypeCheckMemo,
599
+ ) -> None:
600
+ check_type_internal(value, bool, memo)
601
+
602
+
603
+ def check_none(
604
+ value: Any,
605
+ origin_type: Any,
606
+ args: tuple[Any, ...],
607
+ memo: TypeCheckMemo,
608
+ ) -> None:
609
+ if value is not None:
610
+ raise TypeCheckError("is not None")
611
+
612
+
613
+ def check_number(
614
+ value: Any,
615
+ origin_type: Any,
616
+ args: tuple[Any, ...],
617
+ memo: TypeCheckMemo,
618
+ ) -> None:
619
+ if origin_type is complex and not isinstance(value, (complex, float, int)):
620
+ raise TypeCheckError("is neither complex, float or int")
621
+ elif origin_type is float and not isinstance(value, (float, int)):
622
+ raise TypeCheckError("is neither float or int")
623
+
624
+
625
+ def check_io(
626
+ value: Any,
627
+ origin_type: Any,
628
+ args: tuple[Any, ...],
629
+ memo: TypeCheckMemo,
630
+ ) -> None:
631
+ if origin_type is TextIO or (origin_type is IO and args == (str,)):
632
+ if not isinstance(value, TextIOBase):
633
+ raise TypeCheckError("is not a text based I/O object")
634
+ elif origin_type is BinaryIO or (origin_type is IO and args == (bytes,)):
635
+ if not isinstance(value, (RawIOBase, BufferedIOBase)):
636
+ raise TypeCheckError("is not a binary I/O object")
637
+ elif not isinstance(value, IOBase):
638
+ raise TypeCheckError("is not an I/O object")
639
+
640
+
641
+ def check_protocol(
642
+ value: Any,
643
+ origin_type: Any,
644
+ args: tuple[Any, ...],
645
+ memo: TypeCheckMemo,
646
+ ) -> None:
647
+ # TODO: implement proper compatibility checking and support non-runtime protocols
648
+ if getattr(origin_type, "_is_runtime_protocol", False):
649
+ if not isinstance(value, origin_type):
650
+ raise TypeCheckError(
651
+ f"is not compatible with the {origin_type.__qualname__} protocol"
652
+ )
653
+ else:
654
+ warnings.warn(
655
+ f"Typeguard cannot check the {origin_type.__qualname__} protocol because "
656
+ f"it is a non-runtime protocol. If you would like to type check this "
657
+ f"protocol, please use @typing.runtime_checkable",
658
+ stacklevel=get_stacklevel(),
659
+ )
660
+
661
+
662
+ def check_byteslike(
663
+ value: Any,
664
+ origin_type: Any,
665
+ args: tuple[Any, ...],
666
+ memo: TypeCheckMemo,
667
+ ) -> None:
668
+ if not isinstance(value, (bytearray, bytes, memoryview)):
669
+ raise TypeCheckError("is not bytes-like")
670
+
671
+
672
+ def check_self(
673
+ value: Any,
674
+ origin_type: Any,
675
+ args: tuple[Any, ...],
676
+ memo: TypeCheckMemo,
677
+ ) -> None:
678
+ if memo.self_type is None:
679
+ raise TypeCheckError("cannot be checked against Self outside of a method call")
680
+
681
+ if isclass(value):
682
+ if not issubclass(value, memo.self_type):
683
+ raise TypeCheckError(
684
+ f"is not an instance of the self type "
685
+ f"({qualified_name(memo.self_type)})"
686
+ )
687
+ elif not isinstance(value, memo.self_type):
688
+ raise TypeCheckError(
689
+ f"is not an instance of the self type ({qualified_name(memo.self_type)})"
690
+ )
691
+
692
+
693
+ def check_paramspec(
694
+ value: Any,
695
+ origin_type: Any,
696
+ args: tuple[Any, ...],
697
+ memo: TypeCheckMemo,
698
+ ) -> None:
699
+ pass # No-op for now
700
+
701
+
702
+ def check_instanceof(
703
+ value: Any,
704
+ origin_type: Any,
705
+ args: tuple[Any, ...],
706
+ memo: TypeCheckMemo,
707
+ ) -> None:
708
+ if not isinstance(value, origin_type):
709
+ raise TypeCheckError(f"is not an instance of {qualified_name(origin_type)}")
710
+
711
+
712
+ def check_type_internal(
713
+ value: Any,
714
+ annotation: Any,
715
+ memo: TypeCheckMemo,
716
+ ) -> None:
717
+ """
718
+ Check that the given object is compatible with the given type annotation.
719
+
720
+ This function should only be used by type checker callables. Applications should use
721
+ :func:`~.check_type` instead.
722
+
723
+ :param value: the value to check
724
+ :param annotation: the type annotation to check against
725
+ :param memo: a memo object containing configuration and information necessary for
726
+ looking up forward references
727
+ """
728
+
729
+ if isinstance(annotation, ForwardRef):
730
+ try:
731
+ annotation = evaluate_forwardref(annotation, memo)
732
+ except NameError:
733
+ if memo.config.forward_ref_policy is ForwardRefPolicy.ERROR:
734
+ raise
735
+ elif memo.config.forward_ref_policy is ForwardRefPolicy.WARN:
736
+ warnings.warn(
737
+ f"Cannot resolve forward reference {annotation.__forward_arg__!r}",
738
+ TypeHintWarning,
739
+ stacklevel=get_stacklevel(),
740
+ )
741
+
742
+ return
743
+
744
+ if annotation is Any or annotation is SubclassableAny or isinstance(value, Mock):
745
+ return
746
+
747
+ # Skip type checks if value is an instance of a class that inherits from Any
748
+ if not isclass(value) and SubclassableAny in type(value).__bases__:
749
+ return
750
+
751
+ extras: tuple[Any, ...]
752
+ origin_type = get_origin(annotation)
753
+ if origin_type is Annotated:
754
+ annotation, *extras_ = get_args(annotation)
755
+ extras = tuple(extras_)
756
+ origin_type = get_origin(annotation)
757
+ else:
758
+ extras = ()
759
+
760
+ if origin_type is not None:
761
+ args = get_args(annotation)
762
+
763
+ # Compatibility hack to distinguish between unparametrized and empty tuple
764
+ # (tuple[()]), necessary due to https://github.com/python/cpython/issues/91137
765
+ if origin_type in (tuple, Tuple) and annotation is not Tuple and not args:
766
+ args = ((),)
767
+ else:
768
+ origin_type = annotation
769
+ args = ()
770
+
771
+ for lookup_func in checker_lookup_functions:
772
+ checker = lookup_func(origin_type, args, extras)
773
+ if checker:
774
+ checker(value, origin_type, args, memo)
775
+ return
776
+
777
+ if isclass(origin_type):
778
+ if not isinstance(value, origin_type):
779
+ raise TypeCheckError(f"is not an instance of {qualified_name(origin_type)}")
780
+ elif type(origin_type) is str: # noqa: E721
781
+ warnings.warn(
782
+ f"Skipping type check against {origin_type!r}; this looks like a "
783
+ f"string-form forward reference imported from another module",
784
+ TypeHintWarning,
785
+ stacklevel=get_stacklevel(),
786
+ )
787
+
788
+
789
+ # Equality checks are applied to these
790
+ origin_type_checkers = {
791
+ bytes: check_byteslike,
792
+ AbstractSet: check_set,
793
+ BinaryIO: check_io,
794
+ Callable: check_callable,
795
+ collections.abc.Callable: check_callable,
796
+ complex: check_number,
797
+ dict: check_mapping,
798
+ Dict: check_mapping,
799
+ float: check_number,
800
+ frozenset: check_set,
801
+ IO: check_io,
802
+ list: check_list,
803
+ List: check_list,
804
+ Mapping: check_mapping,
805
+ MutableMapping: check_mapping,
806
+ None: check_none,
807
+ collections.abc.Mapping: check_mapping,
808
+ collections.abc.MutableMapping: check_mapping,
809
+ Sequence: check_sequence,
810
+ collections.abc.Sequence: check_sequence,
811
+ collections.abc.Set: check_set,
812
+ set: check_set,
813
+ Set: check_set,
814
+ TextIO: check_io,
815
+ tuple: check_tuple,
816
+ Tuple: check_tuple,
817
+ type: check_class,
818
+ Type: check_class,
819
+ Union: check_union,
820
+ }
821
+ if sys.version_info >= (3, 8):
822
+ origin_type_checkers[typing.Literal] = check_literal
823
+ if sys.version_info >= (3, 10):
824
+ origin_type_checkers[types.UnionType] = check_uniontype
825
+ origin_type_checkers[typing.TypeGuard] = check_typeguard
826
+ if sys.version_info >= (3, 11):
827
+ origin_type_checkers.update(
828
+ {typing.LiteralString: check_literal_string, typing.Self: check_self}
829
+ )
830
+ if typing_extensions is not None:
831
+ # On some Python versions, these may simply be re-exports from typing,
832
+ # but exactly which Python versions is subject to change,
833
+ # so it's best to err on the safe side
834
+ # and update the dictionary on all Python versions
835
+ # if typing_extensions is installed
836
+ origin_type_checkers[typing_extensions.Literal] = check_literal
837
+ origin_type_checkers[typing_extensions.LiteralString] = check_literal_string
838
+ origin_type_checkers[typing_extensions.Self] = check_self
839
+ origin_type_checkers[typing_extensions.TypeGuard] = check_typeguard
840
+
841
+
842
+ def builtin_checker_lookup(
843
+ origin_type: Any, args: tuple[Any, ...], extras: tuple[Any, ...]
844
+ ) -> TypeCheckerCallable | None:
845
+ checker = origin_type_checkers.get(origin_type)
846
+ if checker is not None:
847
+ return checker
848
+ elif is_typeddict(origin_type):
849
+ return check_typed_dict
850
+ elif isclass(origin_type) and issubclass(
851
+ origin_type, Tuple # type: ignore[arg-type]
852
+ ):
853
+ # NamedTuple
854
+ return check_tuple
855
+ elif getattr(origin_type, "_is_protocol", False):
856
+ return check_protocol
857
+ elif isinstance(origin_type, ParamSpec):
858
+ return check_paramspec
859
+ elif isinstance(origin_type, TypeVar):
860
+ return check_typevar
861
+ elif origin_type.__class__ is NewType:
862
+ # typing.NewType on Python 3.10+
863
+ return check_newtype
864
+ elif (
865
+ isfunction(origin_type)
866
+ and getattr(origin_type, "__module__", None) == "typing"
867
+ and getattr(origin_type, "__qualname__", "").startswith("NewType.")
868
+ and hasattr(origin_type, "__supertype__")
869
+ ):
870
+ # typing.NewType on Python 3.9 and below
871
+ return check_newtype
872
+
873
+ return None
874
+
875
+
876
+ checker_lookup_functions.append(builtin_checker_lookup)
877
+
878
+
879
+ def load_plugins() -> None:
880
+ """
881
+ Load all type checker lookup functions from entry points.
882
+
883
+ All entry points from the ``typeguard.checker_lookup`` group are loaded, and the
884
+ returned lookup functions are added to :data:`typeguard.checker_lookup_functions`.
885
+
886
+ .. note:: This function is called implicitly on import, unless the
887
+ ``TYPEGUARD_DISABLE_PLUGIN_AUTOLOAD`` environment variable is present.
888
+ """
889
+
890
+ for ep in entry_points(group="typeguard.checker_lookup"):
891
+ try:
892
+ plugin = ep.load()
893
+ except Exception as exc:
894
+ warnings.warn(
895
+ f"Failed to load plugin {ep.name!r}: " f"{qualified_name(exc)}: {exc}",
896
+ stacklevel=2,
897
+ )
898
+ continue
899
+
900
+ if not callable(plugin):
901
+ warnings.warn(
902
+ f"Plugin {ep} returned a non-callable object: {plugin!r}", stacklevel=2
903
+ )
904
+ continue
905
+
906
+ checker_lookup_functions.insert(0, plugin)