Coverage for pydantic/typing.py: 99.44%
243 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-08-15 13:26 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-08-15 13:26 +0000
1import sys 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
2import typing 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
3from collections.abc import Callable 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
4from os import PathLike 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
5from typing import ( # type: ignore 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
6 TYPE_CHECKING,
7 AbstractSet,
8 Any,
9 Callable as TypingCallable,
10 ClassVar,
11 Dict,
12 ForwardRef,
13 Generator,
14 Iterable,
15 List,
16 Mapping,
17 NewType,
18 Optional,
19 Sequence,
20 Set,
21 Tuple,
22 Type,
23 TypeVar,
24 Union,
25 _eval_type,
26 cast,
27 get_type_hints,
28)
30from typing_extensions import ( 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
31 Annotated,
32 Final,
33 Literal,
34 NotRequired as TypedDictNotRequired,
35 Required as TypedDictRequired,
36)
38try: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
39 from typing import _TypingBase as typing_base # type: ignore 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
40except ImportError: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
41 from typing import _Final as typing_base # type: ignore 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
43try: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
44 from typing import GenericAlias as TypingGenericAlias # type: ignore 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
45except ImportError: 1IJBCKLDEOHMNFG
46 # python < 3.9 does not have GenericAlias (list[int], tuple[str, ...] and so on)
47 TypingGenericAlias = () 1IJBCKLDEOHMNFG
49try: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
50 from types import UnionType as TypesUnionType # type: ignore 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
51except ImportError: 1IJBCstKLDEuvOHAMNFGxy
52 # python < 3.10 does not have UnionType (str | int, byte | bool and so on)
53 TypesUnionType = () 1IJBCstKLDEuvOHAMNFGxy
56if sys.version_info < (3, 9): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
58 def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any: 1IJBCKLDEOHMNFG
59 return type_._evaluate(globalns, localns) 1IJBCKLDEOHMNFG
61else:
63 def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any: 1stabcdefuvghijklAzPQRSTUwxymnopqr
64 # Even though it is the right signature for python 3.9, mypy complains with
65 # `error: Too many arguments for "_evaluate" of "ForwardRef"` hence the cast...
66 # Python 3.13/3.12.4+ made `recursive_guard` a kwarg, so name it explicitly to avoid:
67 # TypeError: ForwardRef._evaluate() missing 1 required keyword-only argument: 'recursive_guard'
68 return cast(Any, type_)._evaluate(globalns, localns, recursive_guard=set()) 1stabcdefuvghijklAzPQRSTUwxymnopqr
71if sys.version_info < (3, 9): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
72 # Ensure we always get all the whole `Annotated` hint, not just the annotated type.
73 # For 3.7 to 3.8, `get_type_hints` doesn't recognize `typing_extensions.Annotated`,
74 # so it already returns the full annotation
75 get_all_type_hints = get_type_hints 1IJBCKLDEOHMNFG
77else:
79 def get_all_type_hints(obj: Any, globalns: Any = None, localns: Any = None) -> Any: 1stabcdefuvghijklAzPQRSTUwxymnopqr
80 return get_type_hints(obj, globalns, localns, include_extras=True) 1stabcdefuvghijklAzPQRSTUwxymnopqr
83_T = TypeVar('_T') 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
85AnyCallable = TypingCallable[..., Any] 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
86NoArgAnyCallable = TypingCallable[[], Any] 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
88# workaround for https://github.com/python/mypy/issues/9496
89AnyArgTCallable = TypingCallable[..., _T] 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
92# Annotated[...] is implemented by returning an instance of one of these classes, depending on
93# python/typing_extensions version.
94AnnotatedTypeNames = {'AnnotatedMeta', '_AnnotatedAlias'} 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
97LITERAL_TYPES: Set[Any] = {Literal} 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
98if hasattr(typing, 'Literal'): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
99 LITERAL_TYPES.add(typing.Literal) 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
102if sys.version_info < (3, 8): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
104 def get_origin(t: Type[Any]) -> Optional[Type[Any]]: 1IJKLOMN
105 if type(t).__name__ in AnnotatedTypeNames: 1IJKLOMN
106 # weirdly this is a runtime requirement, as well as for mypy
107 return cast(Type[Any], Annotated) 1IJKLOMN
108 return getattr(t, '__origin__', None) 1IJKLOMN
110else:
111 from typing import get_origin as _typing_get_origin 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
113 def get_origin(tp: Type[Any]) -> Optional[Type[Any]]: 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
114 """
115 We can't directly use `typing.get_origin` since we need a fallback to support
116 custom generic classes like `ConstrainedList`
117 It should be useless once https://github.com/cython/cython/issues/3537 is
118 solved and https://github.com/pydantic/pydantic/pull/1753 is merged.
119 """
120 if type(tp).__name__ in AnnotatedTypeNames: 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
121 return cast(Type[Any], Annotated) # mypy complains about _SpecialForm 1BCstabcdefDEuvghijklHAzwFGxymnopqr
122 return _typing_get_origin(tp) or getattr(tp, '__origin__', None) 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
125if sys.version_info < (3, 8): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
126 from typing import _GenericAlias 1IJKLOMN
128 def get_args(t: Type[Any]) -> Tuple[Any, ...]: 1IJKLOMN
129 """Compatibility version of get_args for python 3.7.
131 Mostly compatible with the python 3.8 `typing` module version
132 and able to handle almost all use cases.
133 """
134 if type(t).__name__ in AnnotatedTypeNames: 1IJKLOMN
135 return t.__args__ + t.__metadata__ 1IJKLOMN
136 if isinstance(t, _GenericAlias): 1IJKLOMN
137 res = t.__args__ 1IJKLOMN
138 if t.__origin__ is Callable and res and res[0] is not Ellipsis: 1IJKLOMN
139 res = (list(res[:-1]), res[-1]) 1IJKLOMN
140 return res 1IJKLOMN
141 return getattr(t, '__args__', ()) 1IJKLOMN
143else:
144 from typing import get_args as _typing_get_args 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
146 def _generic_get_args(tp: Type[Any]) -> Tuple[Any, ...]: 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
147 """
148 In python 3.9, `typing.Dict`, `typing.List`, ...
149 do have an empty `__args__` by default (instead of the generic ~T for example).
150 In order to still support `Dict` for example and consider it as `Dict[Any, Any]`,
151 we retrieve the `_nparams` value that tells us how many parameters it needs.
152 """
153 if hasattr(tp, '_nparams'): 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
154 return (Any,) * tp._nparams 1stabcdefuvghijklAzwxymnopqr
155 # Special case for `tuple[()]`, which used to return ((),) with `typing.Tuple`
156 # in python 3.10- but now returns () for `tuple` and `Tuple`.
157 # This will probably be clarified in pydantic v2
158 try: 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
159 if tp == Tuple[()] or sys.version_info >= (3, 9) and tp == tuple[()]: # type: ignore[misc] 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
160 return ((),) 1stabcdefuvghijklwxymnopqr
161 # there is a TypeError when compiled with cython
162 except TypeError: # pragma: no cover 1Azw
163 pass
164 return () 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
166 def get_args(tp: Type[Any]) -> Tuple[Any, ...]: 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
167 """Get type arguments with all substitutions performed.
169 For unions, basic simplifications used by Union constructor are performed.
170 Examples::
171 get_args(Dict[str, int]) == (str, int)
172 get_args(int) == ()
173 get_args(Union[int, Union[T, int], str][int]) == (int, str)
174 get_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int])
175 get_args(Callable[[], T][int]) == ([], int)
176 """
177 if type(tp).__name__ in AnnotatedTypeNames: 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
178 return tp.__args__ + tp.__metadata__ 1BCstabcdefDEuvghijklHAzwFGxymnopqr
179 # the fallback is needed for the same reasons as `get_origin` (see above)
180 return _typing_get_args(tp) or getattr(tp, '__args__', ()) or _generic_get_args(tp) 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
183if sys.version_info < (3, 9): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
185 def convert_generics(tp: Type[Any]) -> Type[Any]: 1IJBCKLDEOHMNFG
186 """Python 3.9 and older only supports generics from `typing` module.
187 They convert strings to ForwardRef automatically.
189 Examples::
190 typing.List['Hero'] == typing.List[ForwardRef('Hero')]
191 """
192 return tp 1IJBCKLDEOHMNFG
194else:
195 from typing import _UnionGenericAlias # type: ignore 1stabcdefuvghijklAzPQRSTUwxymnopqr
197 from typing_extensions import _AnnotatedAlias 1stabcdefuvghijklAzPQRSTUwxymnopqr
199 def convert_generics(tp: Type[Any]) -> Type[Any]: 1stabcdefuvghijklAzPQRSTUwxymnopqr
200 """
201 Recursively searches for `str` type hints and replaces them with ForwardRef.
203 Examples::
204 convert_generics(list['Hero']) == list[ForwardRef('Hero')]
205 convert_generics(dict['Hero', 'Team']) == dict[ForwardRef('Hero'), ForwardRef('Team')]
206 convert_generics(typing.Dict['Hero', 'Team']) == typing.Dict[ForwardRef('Hero'), ForwardRef('Team')]
207 convert_generics(list[str | 'Hero'] | int) == list[str | ForwardRef('Hero')] | int
208 """
209 origin = get_origin(tp) 1stabcdefuvghijklAzPQRSTUwxymnopqr
210 if not origin or not hasattr(tp, '__args__'): 1stabcdefuvghijklAzPQRSTUwxymnopqr
211 return tp 1stabcdefuvghijklAzPQRSTUwxymnopqr
213 args = get_args(tp) 1stabcdefuvghijklAzPQRSTUwxymnopqr
215 # typing.Annotated needs special treatment
216 if origin is Annotated: 1stabcdefuvghijklAzPQRSTUwxymnopqr
217 return _AnnotatedAlias(convert_generics(args[0]), args[1:]) 1stabcdefuvghijklAzwxymnopqr
219 # recursively replace `str` instances inside of `GenericAlias` with `ForwardRef(arg)`
220 converted = tuple( 1stabcdefuvghijklAzPQRSTUwxymnopqr
221 ForwardRef(arg) if isinstance(arg, str) and isinstance(tp, TypingGenericAlias) else convert_generics(arg)
222 for arg in args
223 )
225 if converted == args: 1stabcdefuvghijklAzPQRSTUwxymnopqr
226 return tp 1stabcdefuvghijklAzPQRSTUwxymnopqr
227 elif isinstance(tp, TypingGenericAlias): 1stabcdefuvghijklAzwxymnopqr
228 return TypingGenericAlias(origin, converted) 1stabcdefuvghijklAzwxymnopqr
229 elif isinstance(tp, TypesUnionType): 1stabcdefuvghijklAzwxymnopqr
230 # recreate types.UnionType (PEP604, Python >= 3.10)
231 return _UnionGenericAlias(origin, converted) 1abcdefghijklzwmnopqr
232 else:
233 try: 1stabcdefuvghijklAzwxymnopqr
234 setattr(tp, '__args__', converted) 1stabcdefuvghijklAzwxymnopqr
235 except AttributeError: 1abcdefghijklzwmnopqr
236 pass 1abcdefghijklmnopqr
237 return tp 1stabcdefuvghijklAzwxymnopqr
240if sys.version_info < (3, 10): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
242 def is_union(tp: Optional[Type[Any]]) -> bool: 1IJBCstKLDEuvOHAMNFGxy
243 return tp is Union 1IJBCstKLDEuvOHAMNFGxy
245 WithArgsTypes = (TypingGenericAlias,) 1IJBCstKLDEuvOHAMNFGxy
247else:
248 import types 1abcdefghijklzPQRSTUwmnopqr
249 import typing 1abcdefghijklzPQRSTUwmnopqr
251 def is_union(tp: Optional[Type[Any]]) -> bool: 1abcdefghijklzPQRSTUwmnopqr
252 return tp is Union or tp is types.UnionType # noqa: E721 1abcdefghijklzPQRSTUwmnopqr
254 WithArgsTypes = (typing._GenericAlias, types.GenericAlias, types.UnionType) 1abcdefghijklzPQRSTUwmnopqr
257StrPath = Union[str, PathLike] 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
260if TYPE_CHECKING: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
261 from pydantic.fields import ModelField
263 TupleGenerator = Generator[Tuple[str, Any], None, None]
264 DictStrAny = Dict[str, Any]
265 DictAny = Dict[Any, Any]
266 SetStr = Set[str]
267 ListStr = List[str]
268 IntStr = Union[int, str]
269 AbstractSetIntStr = AbstractSet[IntStr]
270 DictIntStrAny = Dict[IntStr, Any]
271 MappingIntStrAny = Mapping[IntStr, Any]
272 CallableGenerator = Generator[AnyCallable, None, None]
273 ReprArgs = Sequence[Tuple[Optional[str], Any]]
275 MYPY = False
276 if MYPY:
277 AnyClassMethod = classmethod[Any]
278 else:
279 # classmethod[TargetType, CallableParamSpecType, CallableReturnType]
280 AnyClassMethod = classmethod[Any, Any, Any]
282__all__ = ( 1BCstabcdefDEuvghijklPQRSTUFGxymnopqr
283 'AnyCallable',
284 'NoArgAnyCallable',
285 'NoneType',
286 'is_none_type',
287 'display_as_type',
288 'resolve_annotations',
289 'is_callable_type',
290 'is_literal_type',
291 'all_literal_values',
292 'is_namedtuple',
293 'is_typeddict',
294 'is_typeddict_special',
295 'is_new_type',
296 'new_type_supertype',
297 'is_classvar',
298 'is_finalvar',
299 'update_field_forward_refs',
300 'update_model_forward_refs',
301 'TupleGenerator',
302 'DictStrAny',
303 'DictAny',
304 'SetStr',
305 'ListStr',
306 'IntStr',
307 'AbstractSetIntStr',
308 'DictIntStrAny',
309 'CallableGenerator',
310 'ReprArgs',
311 'AnyClassMethod',
312 'CallableGenerator',
313 'WithArgsTypes',
314 'get_args',
315 'get_origin',
316 'get_sub_types',
317 'typing_base',
318 'get_all_type_hints',
319 'is_union',
320 'StrPath',
321 'MappingIntStrAny',
322)
325NoneType = None.__class__ 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
328NONE_TYPES: Tuple[Any, Any, Any] = (None, NoneType, Literal[None]) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
331if sys.version_info < (3, 8): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
332 # Even though this implementation is slower, we need it for python 3.7:
333 # In python 3.7 "Literal" is not a builtin type and uses a different
334 # mechanism.
335 # for this reason `Literal[None] is Literal[None]` evaluates to `False`,
336 # breaking the faster implementation used for the other python versions.
338 def is_none_type(type_: Any) -> bool: 1IJKLOMN
339 return type_ in NONE_TYPES 1IJKLOMN
341elif sys.version_info[:2] == (3, 8): 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr
343 def is_none_type(type_: Any) -> bool: 1BCDEHFG
344 for none_type in NONE_TYPES: 1BCDEHFG
345 if type_ is none_type: 1BCDEHFG
346 return True 1BCDEHFG
347 # With python 3.8, specifically 3.8.10, Literal "is" check sare very flakey
348 # can change on very subtle changes like use of types in other modules,
349 # hopefully this check avoids that issue.
350 if is_literal_type(type_): # pragma: no cover 1BCDEHFG
351 return all_literal_values(type_) == (None,) 1BCDEHFG
352 return False 1BCDEHFG
354else:
356 def is_none_type(type_: Any) -> bool: 1stabcdefuvghijklAzPQRSTUwxymnopqr
357 return type_ in NONE_TYPES 1stabcdefuvghijklAzPQRSTUwxymnopqr
360def display_as_type(v: Type[Any]) -> str: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
361 if not isinstance(v, typing_base) and not isinstance(v, WithArgsTypes) and not isinstance(v, type): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
362 v = v.__class__ 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
364 if is_union(get_origin(v)): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
365 return f'Union[{", ".join(map(display_as_type, get_args(v)))}]' 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
367 if isinstance(v, WithArgsTypes): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
368 # Generic alias are constructs like `list[int]`
369 return str(v).replace('typing.', '') 1stabcdefuvghijklAzwxymnopqr
371 try: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
372 return v.__name__ 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
373 except AttributeError: 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
374 # happens with typing objects
375 return str(v).replace('typing.', '') 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
378def resolve_annotations(raw_annotations: Dict[str, Type[Any]], module_name: Optional[str]) -> Dict[str, Type[Any]]: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
379 """
380 Partially taken from typing.get_type_hints.
382 Resolve string or ForwardRef annotations into type objects if possible.
383 """
384 base_globals: Optional[Dict[str, Any]] = None 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
385 if module_name: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
386 try: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
387 module = sys.modules[module_name] 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
388 except KeyError: 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
389 # happens occasionally, see https://github.com/pydantic/pydantic/issues/2363
390 pass 1IJBCstabcdefKLDEuvghijklMNFGxymnopqr
391 else:
392 base_globals = module.__dict__ 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
394 annotations = {} 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
395 for name, value in raw_annotations.items(): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
396 if isinstance(value, str): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
397 if (3, 10) > sys.version_info >= (3, 9, 8) or sys.version_info >= (3, 10, 1): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
398 value = ForwardRef(value, is_argument=False, is_class=True) 1stabcdefuvghijklAzPQRSTUwxymnopqr
399 else:
400 value = ForwardRef(value, is_argument=False) 1IJBCKLDEOHMNFG
401 try: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
402 if sys.version_info >= (3, 13): 402 ↛ 403line 402 didn't jump to line 403 because the condition on line 402 was never true1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
403 value = _eval_type(value, base_globals, None, type_params=())
404 else:
405 value = _eval_type(value, base_globals, None) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
406 except NameError: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
407 # this is ok, it can be fixed with update_forward_refs
408 pass 1IJBCstabcdefKLDEuvghijklPQRSTUMNFGxymnopqr
409 annotations[name] = value 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
410 return annotations 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
413def is_callable_type(type_: Type[Any]) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
414 return type_ is Callable or get_origin(type_) is Callable 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
417def is_literal_type(type_: Type[Any]) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
418 return Literal is not None and get_origin(type_) in LITERAL_TYPES 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
421def literal_values(type_: Type[Any]) -> Tuple[Any, ...]: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
422 return get_args(type_) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
425def all_literal_values(type_: Type[Any]) -> Tuple[Any, ...]: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
426 """
427 This method is used to retrieve all Literal values as
428 Literal can be used recursively (see https://www.python.org/dev/peps/pep-0586)
429 e.g. `Literal[Literal[Literal[1, 2, 3], "foo"], 5, None]`
430 """
431 if not is_literal_type(type_): 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
432 return (type_,) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
434 values = literal_values(type_) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
435 return tuple(x for value in values for x in all_literal_values(value)) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
438def is_namedtuple(type_: Type[Any]) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
439 """
440 Check if a given class is a named tuple.
441 It can be either a `typing.NamedTuple` or `collections.namedtuple`
442 """
443 from pydantic.utils import lenient_issubclass 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
445 return lenient_issubclass(type_, tuple) and hasattr(type_, '_fields') 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
448def is_typeddict(type_: Type[Any]) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
449 """
450 Check if a given class is a typed dict (from `typing` or `typing_extensions`)
451 In 3.10, there will be a public method (https://docs.python.org/3.10/library/typing.html#typing.is_typeddict)
452 """
453 from pydantic.utils import lenient_issubclass 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
455 return lenient_issubclass(type_, dict) and hasattr(type_, '__total__') 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
458def _check_typeddict_special(type_: Any) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
459 return type_ is TypedDictRequired or type_ is TypedDictNotRequired 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
462def is_typeddict_special(type_: Any) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
463 """
464 Check if type is a TypedDict special form (Required or NotRequired).
465 """
466 return _check_typeddict_special(type_) or _check_typeddict_special(get_origin(type_)) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
469test_type = NewType('test_type', str) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
472def is_new_type(type_: Type[Any]) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
473 """
474 Check whether type_ was created using typing.NewType
475 """
476 return isinstance(type_, test_type.__class__) and hasattr(type_, '__supertype__') # type: ignore 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
479def new_type_supertype(type_: Type[Any]) -> Type[Any]: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
480 while hasattr(type_, '__supertype__'): 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
481 type_ = type_.__supertype__ 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
482 return type_ 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
485def _check_classvar(v: Optional[Type[Any]]) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
486 if v is None: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
487 return False 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
489 return v.__class__ == ClassVar.__class__ and getattr(v, '_name', None) == 'ClassVar' 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
492def _check_finalvar(v: Optional[Type[Any]]) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
493 """
494 Check if a given type is a `typing.Final` type.
495 """
496 if v is None: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
497 return False 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
499 return v.__class__ == Final.__class__ and (sys.version_info < (3, 8) or getattr(v, '_name', None) == 'Final') 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
502def is_classvar(ann_type: Type[Any]) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
503 if _check_classvar(ann_type) or _check_classvar(get_origin(ann_type)): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
504 return True 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
506 # this is an ugly workaround for class vars that contain forward references and are therefore themselves
507 # forward references, see #3679
508 if ann_type.__class__ == ForwardRef and ann_type.__forward_arg__.startswith('ClassVar['): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
509 return True 1stabcdefuvghijklAzwxymnopqr
511 return False 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
514def is_finalvar(ann_type: Type[Any]) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
515 return _check_finalvar(ann_type) or _check_finalvar(get_origin(ann_type)) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
518def update_field_forward_refs(field: 'ModelField', globalns: Any, localns: Any) -> None: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
519 """
520 Try to update ForwardRefs on fields based on this ModelField, globalns and localns.
521 """
522 prepare = False 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
523 if field.type_.__class__ == ForwardRef: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
524 prepare = True 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
525 field.type_ = evaluate_forwardref(field.type_, globalns, localns or None) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
526 if field.outer_type_.__class__ == ForwardRef: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
527 prepare = True 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
528 field.outer_type_ = evaluate_forwardref(field.outer_type_, globalns, localns or None) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
529 if prepare: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
530 field.prepare() 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
532 if field.sub_fields: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
533 for sub_f in field.sub_fields: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
534 update_field_forward_refs(sub_f, globalns=globalns, localns=localns) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
536 if field.discriminator_key is not None: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
537 field.prepare_discriminated_union_sub_fields() 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
540def update_model_forward_refs( 1BCstabcdefDEuvghijklOHAzPQRSTUwFGxymnopqr
541 model: Type[Any],
542 fields: Iterable['ModelField'],
543 json_encoders: Dict[Union[Type[Any], str, ForwardRef], AnyCallable],
544 localns: 'DictStrAny',
545 exc_to_suppress: Tuple[Type[BaseException], ...] = (),
546) -> None:
547 """
548 Try to update model fields ForwardRefs based on model and localns.
549 """
550 if model.__module__ in sys.modules: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
551 globalns = sys.modules[model.__module__].__dict__.copy() 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
552 else:
553 globalns = {} 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
555 globalns.setdefault(model.__name__, model) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
557 for f in fields: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
558 try: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
559 update_field_forward_refs(f, globalns=globalns, localns=localns) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
560 except exc_to_suppress: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
561 pass 1IJBCstabcdefKLDEuvghijklPQRSTUMNFGxymnopqr
563 for key in set(json_encoders.keys()): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
564 if isinstance(key, str): 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
565 fr: ForwardRef = ForwardRef(key) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
566 elif isinstance(key, ForwardRef): 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
567 fr = key 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
568 else:
569 continue 1abcdefghijklOHAzwmnopqr
571 try: 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
572 new_key = evaluate_forwardref(fr, globalns, localns or None) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
573 except exc_to_suppress: # pragma: no cover
574 continue
576 json_encoders[new_key] = json_encoders.pop(key) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
579def get_class(type_: Type[Any]) -> Union[None, bool, Type[Any]]: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
580 """
581 Tries to get the class of a Type[T] annotation. Returns True if Type is used
582 without brackets. Otherwise returns None.
583 """
584 if type_ is type: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
585 return True 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
587 if get_origin(type_) is None: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
588 return None 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
590 args = get_args(type_) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
591 if not args or not isinstance(args[0], type): 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
592 return True 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
593 else:
594 return args[0] 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
597def get_sub_types(tp: Any) -> List[Any]: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr
598 """
599 Return all the types that are allowed by type `tp`
600 `tp` can be a `Union` of allowed types or an `Annotated` type
601 """
602 origin = get_origin(tp) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
603 if origin is Annotated: 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
604 return get_sub_types(get_args(tp)[0]) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
605 elif is_union(origin): 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
606 return [x for t in get_args(tp) for x in get_sub_types(t)] 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr
607 else:
608 return [tp] 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr