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

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) 

29 

30from typing_extensions import ( 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

31 Annotated, 

32 Final, 

33 Literal, 

34 NotRequired as TypedDictNotRequired, 

35 Required as TypedDictRequired, 

36) 

37 

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

42 

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

48 

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

54 

55 

56if sys.version_info < (3, 9): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

57 

58 def evaluate_forwardref(type_: ForwardRef, globalns: Any, localns: Any) -> Any: 1IJBCKLDEOHMNFG

59 return type_._evaluate(globalns, localns) 1IJBCKLDEOHMNFG

60 

61else: 

62 

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

69 

70 

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

76 

77else: 

78 

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

81 

82 

83_T = TypeVar('_T') 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

84 

85AnyCallable = TypingCallable[..., Any] 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

86NoArgAnyCallable = TypingCallable[[], Any] 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

87 

88# workaround for https://github.com/python/mypy/issues/9496 

89AnyArgTCallable = TypingCallable[..., _T] 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

90 

91 

92# Annotated[...] is implemented by returning an instance of one of these classes, depending on 

93# python/typing_extensions version. 

94AnnotatedTypeNames = {'AnnotatedMeta', '_AnnotatedAlias'} 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

95 

96 

97LITERAL_TYPES: Set[Any] = {Literal} 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

98if hasattr(typing, 'Literal'): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

99 LITERAL_TYPES.add(typing.Literal) 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr

100 

101 

102if sys.version_info < (3, 8): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

103 

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

109 

110else: 

111 from typing import get_origin as _typing_get_origin 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr

112 

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

123 

124 

125if sys.version_info < (3, 8): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

126 from typing import _GenericAlias 1IJKLOMN

127 

128 def get_args(t: Type[Any]) -> Tuple[Any, ...]: 1IJKLOMN

129 """Compatibility version of get_args for python 3.7. 

130 

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

142 

143else: 

144 from typing import get_args as _typing_get_args 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr

145 

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

165 

166 def get_args(tp: Type[Any]) -> Tuple[Any, ...]: 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr

167 """Get type arguments with all substitutions performed. 

168 

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

181 

182 

183if sys.version_info < (3, 9): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

184 

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. 

188 

189 Examples:: 

190 typing.List['Hero'] == typing.List[ForwardRef('Hero')] 

191 """ 

192 return tp 1IJBCKLDEOHMNFG

193 

194else: 

195 from typing import _UnionGenericAlias # type: ignore 1stabcdefuvghijklAzPQRSTUwxymnopqr

196 

197 from typing_extensions import _AnnotatedAlias 1stabcdefuvghijklAzPQRSTUwxymnopqr

198 

199 def convert_generics(tp: Type[Any]) -> Type[Any]: 1stabcdefuvghijklAzPQRSTUwxymnopqr

200 """ 

201 Recursively searches for `str` type hints and replaces them with ForwardRef. 

202 

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

212 

213 args = get_args(tp) 1stabcdefuvghijklAzPQRSTUwxymnopqr

214 

215 # typing.Annotated needs special treatment 

216 if origin is Annotated: 1stabcdefuvghijklAzPQRSTUwxymnopqr

217 return _AnnotatedAlias(convert_generics(args[0]), args[1:]) 1stabcdefuvghijklAzwxymnopqr

218 

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 ) 

224 

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

238 

239 

240if sys.version_info < (3, 10): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

241 

242 def is_union(tp: Optional[Type[Any]]) -> bool: 1IJBCstKLDEuvOHAMNFGxy

243 return tp is Union 1IJBCstKLDEuvOHAMNFGxy

244 

245 WithArgsTypes = (TypingGenericAlias,) 1IJBCstKLDEuvOHAMNFGxy

246 

247else: 

248 import types 1abcdefghijklzPQRSTUwmnopqr

249 import typing 1abcdefghijklzPQRSTUwmnopqr

250 

251 def is_union(tp: Optional[Type[Any]]) -> bool: 1abcdefghijklzPQRSTUwmnopqr

252 return tp is Union or tp is types.UnionType # noqa: E721 1abcdefghijklzPQRSTUwmnopqr

253 

254 WithArgsTypes = (typing._GenericAlias, types.GenericAlias, types.UnionType) 1abcdefghijklzPQRSTUwmnopqr

255 

256 

257StrPath = Union[str, PathLike] 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

258 

259 

260if TYPE_CHECKING: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

261 from pydantic.fields import ModelField 

262 

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]] 

274 

275 MYPY = False 

276 if MYPY: 

277 AnyClassMethod = classmethod[Any] 

278 else: 

279 # classmethod[TargetType, CallableParamSpecType, CallableReturnType] 

280 AnyClassMethod = classmethod[Any, Any, Any] 

281 

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) 

323 

324 

325NoneType = None.__class__ 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

326 

327 

328NONE_TYPES: Tuple[Any, Any, Any] = (None, NoneType, Literal[None]) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

329 

330 

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. 

337 

338 def is_none_type(type_: Any) -> bool: 1IJKLOMN

339 return type_ in NONE_TYPES 1IJKLOMN

340 

341elif sys.version_info[:2] == (3, 8): 1BCstabcdefDEuvghijklHAzPQRSTUwFGxymnopqr

342 

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

353 

354else: 

355 

356 def is_none_type(type_: Any) -> bool: 1stabcdefuvghijklAzPQRSTUwxymnopqr

357 return type_ in NONE_TYPES 1stabcdefuvghijklAzPQRSTUwxymnopqr

358 

359 

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

363 

364 if is_union(get_origin(v)): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

365 return f'Union[{", ".join(map(display_as_type, get_args(v)))}]' 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr

366 

367 if isinstance(v, WithArgsTypes): 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

368 # Generic alias are constructs like `list[int]` 

369 return str(v).replace('typing.', '') 1stabcdefuvghijklAzwxymnopqr

370 

371 try: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

372 return v.__name__ 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

373 except AttributeError: 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr

374 # happens with typing objects 

375 return str(v).replace('typing.', '') 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr

376 

377 

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. 

381 

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

393 

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

411 

412 

413def is_callable_type(type_: Type[Any]) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

414 return type_ is Callable or get_origin(type_) is Callable 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

415 

416 

417def is_literal_type(type_: Type[Any]) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

418 return Literal is not None and get_origin(type_) in LITERAL_TYPES 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

419 

420 

421def literal_values(type_: Type[Any]) -> Tuple[Any, ...]: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

422 return get_args(type_) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr

423 

424 

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

433 

434 values = literal_values(type_) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr

435 return tuple(x for value in values for x in all_literal_values(value)) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr

436 

437 

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

444 

445 return lenient_issubclass(type_, tuple) and hasattr(type_, '_fields') 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

446 

447 

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

454 

455 return lenient_issubclass(type_, dict) and hasattr(type_, '__total__') 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

456 

457 

458def _check_typeddict_special(type_: Any) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

459 return type_ is TypedDictRequired or type_ is TypedDictNotRequired 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

460 

461 

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

467 

468 

469test_type = NewType('test_type', str) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

470 

471 

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

477 

478 

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

483 

484 

485def _check_classvar(v: Optional[Type[Any]]) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

486 if v is None: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

487 return False 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

488 

489 return v.__class__ == ClassVar.__class__ and getattr(v, '_name', None) == 'ClassVar' 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

490 

491 

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

498 

499 return v.__class__ == Final.__class__ and (sys.version_info < (3, 8) or getattr(v, '_name', None) == 'Final') 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

500 

501 

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

505 

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

510 

511 return False 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

512 

513 

514def is_finalvar(ann_type: Type[Any]) -> bool: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

515 return _check_finalvar(ann_type) or _check_finalvar(get_origin(ann_type)) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

516 

517 

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

531 

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

535 

536 if field.discriminator_key is not None: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

537 field.prepare_discriminated_union_sub_fields() 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr

538 

539 

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

554 

555 globalns.setdefault(model.__name__, model) 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

556 

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

562 

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

570 

571 try: 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr

572 new_key = evaluate_forwardref(fr, globalns, localns or None) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr

573 except exc_to_suppress: # pragma: no cover 

574 continue 

575 

576 json_encoders[new_key] = json_encoders.pop(key) 1IJBCstabcdefKLDEuvghijklOHAzwMNFGxymnopqr

577 

578 

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

586 

587 if get_origin(type_) is None: 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

588 return None 1IJBCstabcdefKLDEuvghijklOHAzPQRSTUwMNFGxymnopqr

589 

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

595 

596 

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