metaflow 2.15.5__py2.py3-none-any.whl → 2.15.6__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 (51) 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/pypi/utils.py +4 -0
  40. metaflow/runner/click_api.py +7 -2
  41. metaflow/vendor.py +1 -0
  42. metaflow/version.py +1 -1
  43. {metaflow-2.15.5.dist-info → metaflow-2.15.6.dist-info}/METADATA +2 -2
  44. {metaflow-2.15.5.dist-info → metaflow-2.15.6.dist-info}/RECORD +51 -25
  45. {metaflow-2.15.5.data → metaflow-2.15.6.data}/data/share/metaflow/devtools/Makefile +0 -0
  46. {metaflow-2.15.5.data → metaflow-2.15.6.data}/data/share/metaflow/devtools/Tiltfile +0 -0
  47. {metaflow-2.15.5.data → metaflow-2.15.6.data}/data/share/metaflow/devtools/pick_services.sh +0 -0
  48. {metaflow-2.15.5.dist-info → metaflow-2.15.6.dist-info}/LICENSE +0 -0
  49. {metaflow-2.15.5.dist-info → metaflow-2.15.6.dist-info}/WHEEL +0 -0
  50. {metaflow-2.15.5.dist-info → metaflow-2.15.6.dist-info}/entry_points.txt +0 -0
  51. {metaflow-2.15.5.dist-info → metaflow-2.15.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,108 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Collection
4
+ from dataclasses import dataclass
5
+ from enum import Enum, auto
6
+ from typing import TYPE_CHECKING, TypeVar
7
+
8
+ if TYPE_CHECKING:
9
+ from ._functions import TypeCheckFailCallback
10
+
11
+ T = TypeVar("T")
12
+
13
+
14
+ class ForwardRefPolicy(Enum):
15
+ """
16
+ Defines how unresolved forward references are handled.
17
+
18
+ Members:
19
+
20
+ * ``ERROR``: propagate the :exc:`NameError` when the forward reference lookup fails
21
+ * ``WARN``: emit a :class:`~.TypeHintWarning` if the forward reference lookup fails
22
+ * ``IGNORE``: silently skip checks for unresolveable forward references
23
+ """
24
+
25
+ ERROR = auto()
26
+ WARN = auto()
27
+ IGNORE = auto()
28
+
29
+
30
+ class CollectionCheckStrategy(Enum):
31
+ """
32
+ Specifies how thoroughly the contents of collections are type checked.
33
+
34
+ This has an effect on the following built-in checkers:
35
+
36
+ * ``AbstractSet``
37
+ * ``Dict``
38
+ * ``List``
39
+ * ``Mapping``
40
+ * ``Set``
41
+ * ``Tuple[<type>, ...]`` (arbitrarily sized tuples)
42
+
43
+ Members:
44
+
45
+ * ``FIRST_ITEM``: check only the first item
46
+ * ``ALL_ITEMS``: check all items
47
+ """
48
+
49
+ FIRST_ITEM = auto()
50
+ ALL_ITEMS = auto()
51
+
52
+ def iterate_samples(self, collection: Collection[T]) -> Collection[T]:
53
+ if self is CollectionCheckStrategy.FIRST_ITEM:
54
+ if len(collection):
55
+ return [next(iter(collection))]
56
+ else:
57
+ return ()
58
+ else:
59
+ return collection
60
+
61
+
62
+ @dataclass
63
+ class TypeCheckConfiguration:
64
+ """
65
+ You can change Typeguard's behavior with these settings.
66
+
67
+ .. attribute:: typecheck_fail_callback
68
+ :type: Callable[[TypeCheckError, TypeCheckMemo], Any]
69
+
70
+ Callable that is called when type checking fails.
71
+
72
+ Default: ``None`` (the :exc:`~.TypeCheckError` is raised directly)
73
+
74
+ .. attribute:: forward_ref_policy
75
+ :type: ForwardRefPolicy
76
+
77
+ Specifies what to do when a forward reference fails to resolve.
78
+
79
+ Default: ``WARN``
80
+
81
+ .. attribute:: collection_check_strategy
82
+ :type: CollectionCheckStrategy
83
+
84
+ Specifies how thoroughly the contents of collections (list, dict, etc.) are
85
+ type checked.
86
+
87
+ Default: ``FIRST_ITEM``
88
+
89
+ .. attribute:: debug_instrumentation
90
+ :type: bool
91
+
92
+ If set to ``True``, the code of modules or functions instrumented by typeguard
93
+ is printed to ``sys.stderr`` after the instrumentation is done
94
+
95
+ Requires Python 3.9 or newer.
96
+
97
+ Default: ``False``
98
+ """
99
+
100
+ forward_ref_policy: ForwardRefPolicy = ForwardRefPolicy.WARN
101
+ typecheck_fail_callback: TypeCheckFailCallback | None = None
102
+ collection_check_strategy: CollectionCheckStrategy = (
103
+ CollectionCheckStrategy.FIRST_ITEM
104
+ )
105
+ debug_instrumentation: bool = False
106
+
107
+
108
+ global_config = TypeCheckConfiguration()
@@ -0,0 +1,237 @@
1
+ from __future__ import annotations
2
+
3
+ import ast
4
+ import inspect
5
+ import sys
6
+ from collections.abc import Sequence
7
+ from functools import partial
8
+ from inspect import isclass, isfunction
9
+ from types import CodeType, FrameType, FunctionType
10
+ from typing import TYPE_CHECKING, Any, Callable, ForwardRef, TypeVar, cast, overload
11
+ from warnings import warn
12
+
13
+ from ._config import CollectionCheckStrategy, ForwardRefPolicy, global_config
14
+ from ._exceptions import InstrumentationWarning
15
+ from ._functions import TypeCheckFailCallback
16
+ from ._transformer import TypeguardTransformer
17
+ from ._utils import Unset, function_name, get_stacklevel, is_method_of, unset
18
+
19
+ if TYPE_CHECKING:
20
+ from typeshed.stdlib.types import _Cell
21
+
22
+ _F = TypeVar("_F")
23
+
24
+ def typeguard_ignore(f: _F) -> _F:
25
+ """This decorator is a noop during static type-checking."""
26
+ return f
27
+
28
+ else:
29
+ from typing import no_type_check as typeguard_ignore # noqa: F401
30
+
31
+ T_CallableOrType = TypeVar("T_CallableOrType", bound=Callable[..., Any])
32
+
33
+
34
+ def make_cell(value: object) -> _Cell:
35
+ return (lambda: value).__closure__[0] # type: ignore[index]
36
+
37
+
38
+ def find_target_function(
39
+ new_code: CodeType, target_path: Sequence[str], firstlineno: int
40
+ ) -> CodeType | None:
41
+ target_name = target_path[0]
42
+ for const in new_code.co_consts:
43
+ if isinstance(const, CodeType):
44
+ if const.co_name == target_name:
45
+ if const.co_firstlineno == firstlineno:
46
+ return const
47
+ elif len(target_path) > 1:
48
+ target_code = find_target_function(
49
+ const, target_path[1:], firstlineno
50
+ )
51
+ if target_code:
52
+ return target_code
53
+
54
+ return None
55
+
56
+
57
+ def instrument(f: T_CallableOrType) -> FunctionType | str:
58
+ if not getattr(f, "__code__", None):
59
+ return "no code associated"
60
+ elif not getattr(f, "__module__", None):
61
+ return "__module__ attribute is not set"
62
+ elif f.__code__.co_filename == "<stdin>":
63
+ return "cannot instrument functions defined in a REPL"
64
+ elif hasattr(f, "__wrapped__"):
65
+ return (
66
+ "@typechecked only supports instrumenting functions wrapped with "
67
+ "@classmethod, @staticmethod or @property"
68
+ )
69
+
70
+ target_path = [item for item in f.__qualname__.split(".") if item != "<locals>"]
71
+ module_source = inspect.getsource(sys.modules[f.__module__])
72
+ module_ast = ast.parse(module_source)
73
+ instrumentor = TypeguardTransformer(target_path, f.__code__.co_firstlineno)
74
+ instrumentor.visit(module_ast)
75
+
76
+ if not instrumentor.target_node or instrumentor.target_lineno is None:
77
+ return "instrumentor did not find the target function"
78
+
79
+ module_code = compile(module_ast, f.__code__.co_filename, "exec", dont_inherit=True)
80
+ new_code = find_target_function(
81
+ module_code, target_path, instrumentor.target_lineno
82
+ )
83
+ if not new_code:
84
+ return "cannot find the target function in the AST"
85
+
86
+ if global_config.debug_instrumentation and sys.version_info >= (3, 9):
87
+ # Find the matching AST node, then unparse it to source and print to stdout
88
+ print(
89
+ f"Source code of {f.__qualname__}() after instrumentation:"
90
+ "\n----------------------------------------------",
91
+ file=sys.stderr,
92
+ )
93
+ print(ast.unparse(instrumentor.target_node), file=sys.stderr)
94
+ print(
95
+ "----------------------------------------------",
96
+ file=sys.stderr,
97
+ )
98
+
99
+ closure = f.__closure__
100
+ if new_code.co_freevars != f.__code__.co_freevars:
101
+ # Create a new closure and find values for the new free variables
102
+ frame = cast(FrameType, inspect.currentframe())
103
+ frame = cast(FrameType, frame.f_back)
104
+ frame_locals = cast(FrameType, frame.f_back).f_locals
105
+ cells: list[_Cell] = []
106
+ for key in new_code.co_freevars:
107
+ if key in instrumentor.names_used_in_annotations:
108
+ # Find the value and make a new cell from it
109
+ value = frame_locals.get(key) or ForwardRef(key)
110
+ cells.append(make_cell(value))
111
+ else:
112
+ # Reuse the cell from the existing closure
113
+ assert f.__closure__
114
+ cells.append(f.__closure__[f.__code__.co_freevars.index(key)])
115
+
116
+ closure = tuple(cells)
117
+
118
+ new_function = FunctionType(new_code, f.__globals__, f.__name__, closure=closure)
119
+ new_function.__module__ = f.__module__
120
+ new_function.__name__ = f.__name__
121
+ new_function.__qualname__ = f.__qualname__
122
+ new_function.__annotations__ = f.__annotations__
123
+ new_function.__doc__ = f.__doc__
124
+ new_function.__defaults__ = f.__defaults__
125
+ new_function.__kwdefaults__ = f.__kwdefaults__
126
+ return new_function
127
+
128
+
129
+ @overload
130
+ def typechecked(
131
+ *,
132
+ forward_ref_policy: ForwardRefPolicy | Unset = unset,
133
+ typecheck_fail_callback: TypeCheckFailCallback | Unset = unset,
134
+ collection_check_strategy: CollectionCheckStrategy | Unset = unset,
135
+ debug_instrumentation: bool | Unset = unset,
136
+ ) -> Callable[[T_CallableOrType], T_CallableOrType]:
137
+ ...
138
+
139
+
140
+ @overload
141
+ def typechecked(target: T_CallableOrType) -> T_CallableOrType:
142
+ ...
143
+
144
+
145
+ def typechecked(
146
+ target: T_CallableOrType | None = None,
147
+ *,
148
+ forward_ref_policy: ForwardRefPolicy | Unset = unset,
149
+ typecheck_fail_callback: TypeCheckFailCallback | Unset = unset,
150
+ collection_check_strategy: CollectionCheckStrategy | Unset = unset,
151
+ debug_instrumentation: bool | Unset = unset,
152
+ ) -> Any:
153
+ """
154
+ Instrument the target function to perform run-time type checking.
155
+
156
+ This decorator recompiles the target function, injecting code to type check
157
+ arguments, return values, yield values (excluding ``yield from``) and assignments to
158
+ annotated local variables.
159
+
160
+ This can also be used as a class decorator. This will instrument all type annotated
161
+ methods, including :func:`@classmethod <classmethod>`,
162
+ :func:`@staticmethod <staticmethod>`, and :class:`@property <property>` decorated
163
+ methods in the class.
164
+
165
+ .. note:: When Python is run in optimized mode (``-O`` or ``-OO``, this decorator
166
+ is a no-op). This is a feature meant for selectively introducing type checking
167
+ into a code base where the checks aren't meant to be run in production.
168
+
169
+ :param target: the function or class to enable type checking for
170
+ :param forward_ref_policy: override for
171
+ :attr:`.TypeCheckConfiguration.forward_ref_policy`
172
+ :param typecheck_fail_callback: override for
173
+ :attr:`.TypeCheckConfiguration.typecheck_fail_callback`
174
+ :param collection_check_strategy: override for
175
+ :attr:`.TypeCheckConfiguration.collection_check_strategy`
176
+ :param debug_instrumentation: override for
177
+ :attr:`.TypeCheckConfiguration.debug_instrumentation`
178
+
179
+ """
180
+ if target is None:
181
+ return partial(
182
+ typechecked,
183
+ forward_ref_policy=forward_ref_policy,
184
+ typecheck_fail_callback=typecheck_fail_callback,
185
+ collection_check_strategy=collection_check_strategy,
186
+ debug_instrumentation=debug_instrumentation,
187
+ )
188
+
189
+ if not __debug__:
190
+ return target
191
+
192
+ if isclass(target):
193
+ for key, attr in target.__dict__.items():
194
+ if is_method_of(attr, target):
195
+ retval = instrument(attr)
196
+ if isfunction(retval):
197
+ setattr(target, key, retval)
198
+ elif isinstance(attr, (classmethod, staticmethod)):
199
+ if is_method_of(attr.__func__, target):
200
+ retval = instrument(attr.__func__)
201
+ if isfunction(retval):
202
+ wrapper = attr.__class__(retval)
203
+ setattr(target, key, wrapper)
204
+ elif isinstance(attr, property):
205
+ kwargs: dict[str, Any] = dict(doc=attr.__doc__)
206
+ for name in ("fset", "fget", "fdel"):
207
+ property_func = kwargs[name] = getattr(attr, name)
208
+ if is_method_of(property_func, target):
209
+ retval = instrument(property_func)
210
+ if isfunction(retval):
211
+ kwargs[name] = retval
212
+
213
+ setattr(target, key, attr.__class__(**kwargs))
214
+
215
+ return target
216
+
217
+ # Find either the first Python wrapper or the actual function
218
+ wrapper_class: type[classmethod[Any, Any, Any]] | type[
219
+ staticmethod[Any, Any]
220
+ ] | None = None
221
+ if isinstance(target, (classmethod, staticmethod)):
222
+ wrapper_class = target.__class__
223
+ target = target.__func__
224
+
225
+ retval = instrument(target)
226
+ if isinstance(retval, str):
227
+ warn(
228
+ f"{retval} -- not typechecking {function_name(target)}",
229
+ InstrumentationWarning,
230
+ stacklevel=get_stacklevel(),
231
+ )
232
+ return target
233
+
234
+ if wrapper_class is None:
235
+ return retval
236
+ else:
237
+ return wrapper_class(retval)
@@ -0,0 +1,42 @@
1
+ from collections import deque
2
+ from typing import Deque
3
+
4
+
5
+ class TypeHintWarning(UserWarning):
6
+ """
7
+ A warning that is emitted when a type hint in string form could not be resolved to
8
+ an actual type.
9
+ """
10
+
11
+
12
+ class TypeCheckWarning(UserWarning):
13
+ """Emitted by typeguard's type checkers when a type mismatch is detected."""
14
+
15
+ def __init__(self, message: str):
16
+ super().__init__(message)
17
+
18
+
19
+ class InstrumentationWarning(UserWarning):
20
+ """Emitted when there's a problem with instrumenting a function for type checks."""
21
+
22
+ def __init__(self, message: str):
23
+ super().__init__(message)
24
+
25
+
26
+ class TypeCheckError(Exception):
27
+ """
28
+ Raised by typeguard's type checkers when a type mismatch is detected.
29
+ """
30
+
31
+ def __init__(self, message: str):
32
+ super().__init__(message)
33
+ self._path: Deque[str] = deque()
34
+
35
+ def append_path_element(self, element: str) -> None:
36
+ self._path.append(element)
37
+
38
+ def __str__(self) -> str:
39
+ if self._path:
40
+ return " of ".join(self._path) + " " + str(self.args[0])
41
+ else:
42
+ return str(self.args[0])
@@ -0,0 +1,310 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ import warnings
5
+ from typing import Any, Callable, NoReturn, TypeVar, Union, overload
6
+
7
+ from . import _suppression
8
+ from ._checkers import BINARY_MAGIC_METHODS, check_type_internal
9
+ from ._config import (
10
+ CollectionCheckStrategy,
11
+ ForwardRefPolicy,
12
+ TypeCheckConfiguration,
13
+ )
14
+ from ._exceptions import TypeCheckError, TypeCheckWarning
15
+ from ._memo import TypeCheckMemo
16
+ from ._utils import get_stacklevel, qualified_name
17
+
18
+ if sys.version_info >= (3, 11):
19
+ from typing import Literal, Never, TypeAlias
20
+ else:
21
+ from metaflow._vendor.v3_7.typing_extensions import Literal, Never, TypeAlias
22
+
23
+ T = TypeVar("T")
24
+ TypeCheckFailCallback: TypeAlias = Callable[[TypeCheckError, TypeCheckMemo], Any]
25
+
26
+
27
+ @overload
28
+ def check_type(
29
+ value: object,
30
+ expected_type: type[T],
31
+ *,
32
+ forward_ref_policy: ForwardRefPolicy = ...,
33
+ typecheck_fail_callback: TypeCheckFailCallback | None = ...,
34
+ collection_check_strategy: CollectionCheckStrategy = ...,
35
+ ) -> T:
36
+ ...
37
+
38
+
39
+ @overload
40
+ def check_type(
41
+ value: object,
42
+ expected_type: Any,
43
+ *,
44
+ forward_ref_policy: ForwardRefPolicy = ...,
45
+ typecheck_fail_callback: TypeCheckFailCallback | None = ...,
46
+ collection_check_strategy: CollectionCheckStrategy = ...,
47
+ ) -> Any:
48
+ ...
49
+
50
+
51
+ def check_type(
52
+ value: object,
53
+ expected_type: Any,
54
+ *,
55
+ forward_ref_policy: ForwardRefPolicy = TypeCheckConfiguration().forward_ref_policy,
56
+ typecheck_fail_callback: (TypeCheckFailCallback | None) = (
57
+ TypeCheckConfiguration().typecheck_fail_callback
58
+ ),
59
+ collection_check_strategy: CollectionCheckStrategy = (
60
+ TypeCheckConfiguration().collection_check_strategy
61
+ ),
62
+ ) -> Any:
63
+ """
64
+ Ensure that ``value`` matches ``expected_type``.
65
+
66
+ The types from the :mod:`typing` module do not support :func:`isinstance` or
67
+ :func:`issubclass` so a number of type specific checks are required. This function
68
+ knows which checker to call for which type.
69
+
70
+ This function wraps :func:`~.check_type_internal` in the following ways:
71
+
72
+ * Respects type checking suppression (:func:`~.suppress_type_checks`)
73
+ * Forms a :class:`~.TypeCheckMemo` from the current stack frame
74
+ * Calls the configured type check fail callback if the check fails
75
+
76
+ Note that this function is independent of the globally shared configuration in
77
+ :data:`typeguard.config`. This means that usage within libraries is safe from being
78
+ affected configuration changes made by other libraries or by the integrating
79
+ application. Instead, configuration options have the same default values as their
80
+ corresponding fields in :class:`TypeCheckConfiguration`.
81
+
82
+ :param value: value to be checked against ``expected_type``
83
+ :param expected_type: a class or generic type instance, or a tuple of such things
84
+ :param forward_ref_policy: see :attr:`TypeCheckConfiguration.forward_ref_policy`
85
+ :param typecheck_fail_callback:
86
+ see :attr`TypeCheckConfiguration.typecheck_fail_callback`
87
+ :param collection_check_strategy:
88
+ see :attr:`TypeCheckConfiguration.collection_check_strategy`
89
+ :return: ``value``, unmodified
90
+ :raises TypeCheckError: if there is a type mismatch
91
+
92
+ """
93
+ if type(expected_type) is tuple:
94
+ expected_type = Union[expected_type]
95
+
96
+ config = TypeCheckConfiguration(
97
+ forward_ref_policy=forward_ref_policy,
98
+ typecheck_fail_callback=typecheck_fail_callback,
99
+ collection_check_strategy=collection_check_strategy,
100
+ )
101
+
102
+ if _suppression.type_checks_suppressed or expected_type is Any:
103
+ return value
104
+
105
+ frame = sys._getframe(1)
106
+ memo = TypeCheckMemo(frame.f_globals, frame.f_locals, config=config)
107
+ try:
108
+ check_type_internal(value, expected_type, memo)
109
+ except TypeCheckError as exc:
110
+ exc.append_path_element(qualified_name(value, add_class_prefix=True))
111
+ if config.typecheck_fail_callback:
112
+ config.typecheck_fail_callback(exc, memo)
113
+ else:
114
+ raise
115
+
116
+ return value
117
+
118
+
119
+ def check_argument_types(
120
+ func_name: str,
121
+ arguments: dict[str, tuple[Any, Any]],
122
+ memo: TypeCheckMemo,
123
+ ) -> Literal[True]:
124
+ if _suppression.type_checks_suppressed:
125
+ return True
126
+
127
+ for argname, (value, annotation) in arguments.items():
128
+ if annotation is NoReturn or annotation is Never:
129
+ exc = TypeCheckError(
130
+ f"{func_name}() was declared never to be called but it was"
131
+ )
132
+ if memo.config.typecheck_fail_callback:
133
+ memo.config.typecheck_fail_callback(exc, memo)
134
+ else:
135
+ raise exc
136
+
137
+ try:
138
+ check_type_internal(value, annotation, memo)
139
+ except TypeCheckError as exc:
140
+ qualname = qualified_name(value, add_class_prefix=True)
141
+ exc.append_path_element(f'argument "{argname}" ({qualname})')
142
+ if memo.config.typecheck_fail_callback:
143
+ memo.config.typecheck_fail_callback(exc, memo)
144
+ else:
145
+ raise
146
+
147
+ return True
148
+
149
+
150
+ def check_return_type(
151
+ func_name: str,
152
+ retval: T,
153
+ annotation: Any,
154
+ memo: TypeCheckMemo,
155
+ ) -> T:
156
+ if _suppression.type_checks_suppressed:
157
+ return retval
158
+
159
+ if annotation is NoReturn or annotation is Never:
160
+ exc = TypeCheckError(f"{func_name}() was declared never to return but it did")
161
+ if memo.config.typecheck_fail_callback:
162
+ memo.config.typecheck_fail_callback(exc, memo)
163
+ else:
164
+ raise exc
165
+
166
+ try:
167
+ check_type_internal(retval, annotation, memo)
168
+ except TypeCheckError as exc:
169
+ # Allow NotImplemented if this is a binary magic method (__eq__() et al)
170
+ if retval is NotImplemented and annotation is bool:
171
+ # This does (and cannot) not check if it's actually a method
172
+ func_name = func_name.rsplit(".", 1)[-1]
173
+ if func_name in BINARY_MAGIC_METHODS:
174
+ return retval
175
+
176
+ qualname = qualified_name(retval, add_class_prefix=True)
177
+ exc.append_path_element(f"the return value ({qualname})")
178
+ if memo.config.typecheck_fail_callback:
179
+ memo.config.typecheck_fail_callback(exc, memo)
180
+ else:
181
+ raise
182
+
183
+ return retval
184
+
185
+
186
+ def check_send_type(
187
+ func_name: str,
188
+ sendval: T,
189
+ annotation: Any,
190
+ memo: TypeCheckMemo,
191
+ ) -> T:
192
+ if _suppression.type_checks_suppressed:
193
+ return sendval
194
+
195
+ if annotation is NoReturn or annotation is Never:
196
+ exc = TypeCheckError(
197
+ f"{func_name}() was declared never to be sent a value to but it was"
198
+ )
199
+ if memo.config.typecheck_fail_callback:
200
+ memo.config.typecheck_fail_callback(exc, memo)
201
+ else:
202
+ raise exc
203
+
204
+ try:
205
+ check_type_internal(sendval, annotation, memo)
206
+ except TypeCheckError as exc:
207
+ qualname = qualified_name(sendval, add_class_prefix=True)
208
+ exc.append_path_element(f"the value sent to generator ({qualname})")
209
+ if memo.config.typecheck_fail_callback:
210
+ memo.config.typecheck_fail_callback(exc, memo)
211
+ else:
212
+ raise
213
+
214
+ return sendval
215
+
216
+
217
+ def check_yield_type(
218
+ func_name: str,
219
+ yieldval: T,
220
+ annotation: Any,
221
+ memo: TypeCheckMemo,
222
+ ) -> T:
223
+ if _suppression.type_checks_suppressed:
224
+ return yieldval
225
+
226
+ if annotation is NoReturn or annotation is Never:
227
+ exc = TypeCheckError(f"{func_name}() was declared never to yield but it did")
228
+ if memo.config.typecheck_fail_callback:
229
+ memo.config.typecheck_fail_callback(exc, memo)
230
+ else:
231
+ raise exc
232
+
233
+ try:
234
+ check_type_internal(yieldval, annotation, memo)
235
+ except TypeCheckError as exc:
236
+ qualname = qualified_name(yieldval, add_class_prefix=True)
237
+ exc.append_path_element(f"the yielded value ({qualname})")
238
+ if memo.config.typecheck_fail_callback:
239
+ memo.config.typecheck_fail_callback(exc, memo)
240
+ else:
241
+ raise
242
+
243
+ return yieldval
244
+
245
+
246
+ def check_variable_assignment(
247
+ value: object, varname: str, annotation: Any, memo: TypeCheckMemo
248
+ ) -> Any:
249
+ if _suppression.type_checks_suppressed:
250
+ return value
251
+
252
+ try:
253
+ check_type_internal(value, annotation, memo)
254
+ except TypeCheckError as exc:
255
+ qualname = qualified_name(value, add_class_prefix=True)
256
+ exc.append_path_element(f"value assigned to {varname} ({qualname})")
257
+ if memo.config.typecheck_fail_callback:
258
+ memo.config.typecheck_fail_callback(exc, memo)
259
+ else:
260
+ raise
261
+
262
+ return value
263
+
264
+
265
+ def check_multi_variable_assignment(
266
+ value: Any, targets: list[dict[str, Any]], memo: TypeCheckMemo
267
+ ) -> Any:
268
+ if max(len(target) for target in targets) == 1:
269
+ iterated_values = [value]
270
+ else:
271
+ iterated_values = list(value)
272
+
273
+ if not _suppression.type_checks_suppressed:
274
+ for expected_types in targets:
275
+ value_index = 0
276
+ for ann_index, (varname, expected_type) in enumerate(
277
+ expected_types.items()
278
+ ):
279
+ if varname.startswith("*"):
280
+ varname = varname[1:]
281
+ keys_left = len(expected_types) - 1 - ann_index
282
+ next_value_index = len(iterated_values) - keys_left
283
+ obj: object = iterated_values[value_index:next_value_index]
284
+ value_index = next_value_index
285
+ else:
286
+ obj = iterated_values[value_index]
287
+ value_index += 1
288
+
289
+ try:
290
+ check_type_internal(obj, expected_type, memo)
291
+ except TypeCheckError as exc:
292
+ qualname = qualified_name(obj, add_class_prefix=True)
293
+ exc.append_path_element(f"value assigned to {varname} ({qualname})")
294
+ if memo.config.typecheck_fail_callback:
295
+ memo.config.typecheck_fail_callback(exc, memo)
296
+ else:
297
+ raise
298
+
299
+ return iterated_values[0] if len(iterated_values) == 1 else iterated_values
300
+
301
+
302
+ def warn_on_error(exc: TypeCheckError, memo: TypeCheckMemo) -> None:
303
+ """
304
+ Emit a warning on a type mismatch.
305
+
306
+ This is intended to be used as an error handler in
307
+ :attr:`TypeCheckConfiguration.typecheck_fail_callback`.
308
+
309
+ """
310
+ warnings.warn(TypeCheckWarning(str(exc)), stacklevel=get_stacklevel())