Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/typing_inspect.py: 16%

411 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-25 06:43 +0000

1"""Defines experimental API for runtime inspection of types defined 

2in the standard "typing" module. 

3 

4Example usage:: 

5 from typing_inspect import is_generic_type 

6""" 

7 

8# NOTE: This module must support Python 2.7 in addition to Python 3.x 

9 

10import sys 

11import types 

12import typing 

13import typing_extensions 

14 

15from mypy_extensions import _TypedDictMeta as _TypedDictMeta_Mypy 

16 

17# See comments in typing_extensions source on why the switch is at 3.9.2 

18if (3, 4, 0) <= sys.version_info[:3] < (3, 9, 2): 

19 from typing_extensions import _TypedDictMeta as _TypedDictMeta_TE 

20elif sys.version_info[:3] >= (3, 9, 2): 

21 # Situation with typing_extensions.TypedDict is complicated. 

22 # Use the one defined in typing_extentions, and if there is none, 

23 # fall back to typing. 

24 try: 

25 from typing_extensions import _TypedDictMeta as _TypedDictMeta_TE 

26 except ImportError: 

27 from typing import _TypedDictMeta as _TypedDictMeta_TE 

28else: 

29 # typing_extensions.TypedDict is a re-export from typing. 

30 from typing import TypedDict 

31 _TypedDictMeta_TE = type(TypedDict) 

32 

33NEW_TYPING = sys.version_info[:3] >= (3, 7, 0) # PEP 560 

34if NEW_TYPING: 

35 import collections.abc 

36 

37WITH_FINAL = True 

38WITH_LITERAL = True 

39WITH_CLASSVAR = True 

40WITH_NEWTYPE = True 

41LEGACY_TYPING = False 

42 

43if NEW_TYPING: 

44 from typing import ( 

45 Generic, Callable, Union, TypeVar, ClassVar, Tuple, _GenericAlias, 

46 ForwardRef, NewType, 

47 ) 

48 from typing_extensions import Final, Literal 

49 if sys.version_info[:3] >= (3, 9, 0): 

50 from typing import _SpecialGenericAlias 

51 typingGenericAlias = (_GenericAlias, _SpecialGenericAlias, types.GenericAlias) 

52 else: 

53 typingGenericAlias = (_GenericAlias,) 

54else: 

55 from typing import ( 

56 Callable, CallableMeta, Union, Tuple, TupleMeta, TypeVar, GenericMeta, 

57 _ForwardRef, 

58 ) 

59 try: 

60 from typing import _Union, _ClassVar 

61 except ImportError: 

62 # support for very old typing module <=3.5.3 

63 _Union = type(Union) 

64 WITH_CLASSVAR = False 

65 LEGACY_TYPING = True 

66 

67 try: # python 3.6 

68 from typing_extensions import _Final 

69 except ImportError: # python 2.7 

70 try: 

71 from typing import _Final 

72 except ImportError: 

73 WITH_FINAL = False 

74 

75 try: # python 3.6 

76 from typing_extensions import Literal 

77 except ImportError: # python 2.7 

78 try: 

79 from typing import Literal 

80 except ImportError: 

81 WITH_LITERAL = False 

82 

83 try: # python < 3.5.2 

84 from typing_extensions import NewType 

85 except ImportError: 

86 try: 

87 from typing import NewType 

88 except ImportError: 

89 WITH_NEWTYPE = False 

90 

91 

92def _gorg(cls): 

93 """This function exists for compatibility with old typing versions.""" 

94 assert isinstance(cls, GenericMeta) 

95 if hasattr(cls, '_gorg'): 

96 return cls._gorg 

97 while cls.__origin__ is not None: 

98 cls = cls.__origin__ 

99 return cls 

100 

101 

102def is_generic_type(tp): 

103 """Test if the given type is a generic type. This includes Generic itself, but 

104 excludes special typing constructs such as Union, Tuple, Callable, ClassVar. 

105 Examples:: 

106 

107 is_generic_type(int) == False 

108 is_generic_type(Union[int, str]) == False 

109 is_generic_type(Union[int, T]) == False 

110 is_generic_type(ClassVar[List[int]]) == False 

111 is_generic_type(Callable[..., T]) == False 

112 

113 is_generic_type(Generic) == True 

114 is_generic_type(Generic[T]) == True 

115 is_generic_type(Iterable[int]) == True 

116 is_generic_type(Mapping) == True 

117 is_generic_type(MutableMapping[T, List[int]]) == True 

118 is_generic_type(Sequence[Union[str, bytes]]) == True 

119 """ 

120 if NEW_TYPING: 

121 return (isinstance(tp, type) and issubclass(tp, Generic) or 

122 isinstance(tp, typingGenericAlias) and 

123 tp.__origin__ not in (Union, tuple, ClassVar, collections.abc.Callable)) 

124 return (isinstance(tp, GenericMeta) and not 

125 isinstance(tp, (CallableMeta, TupleMeta))) 

126 

127 

128def is_callable_type(tp): 

129 """Test if the type is a generic callable type, including subclasses 

130 excluding non-generic types and callables. 

131 Examples:: 

132 

133 is_callable_type(int) == False 

134 is_callable_type(type) == False 

135 is_callable_type(Callable) == True 

136 is_callable_type(Callable[..., int]) == True 

137 is_callable_type(Callable[[int, int], Iterable[str]]) == True 

138 class MyClass(Callable[[int], int]): 

139 ... 

140 is_callable_type(MyClass) == True 

141 

142 For more general tests use callable(), for more precise test 

143 (excluding subclasses) use:: 

144 

145 get_origin(tp) is collections.abc.Callable # Callable prior to Python 3.7 

146 """ 

147 if NEW_TYPING: 

148 return (tp is Callable or isinstance(tp, typingGenericAlias) and 

149 tp.__origin__ is collections.abc.Callable or 

150 isinstance(tp, type) and issubclass(tp, Generic) and 

151 issubclass(tp, collections.abc.Callable)) 

152 return type(tp) is CallableMeta 

153 

154 

155def is_tuple_type(tp): 

156 """Test if the type is a generic tuple type, including subclasses excluding 

157 non-generic classes. 

158 Examples:: 

159 

160 is_tuple_type(int) == False 

161 is_tuple_type(tuple) == False 

162 is_tuple_type(Tuple) == True 

163 is_tuple_type(Tuple[str, int]) == True 

164 class MyClass(Tuple[str, int]): 

165 ... 

166 is_tuple_type(MyClass) == True 

167 

168 For more general tests use issubclass(..., tuple), for more precise test 

169 (excluding subclasses) use:: 

170 

171 get_origin(tp) is tuple # Tuple prior to Python 3.7 

172 """ 

173 if NEW_TYPING: 

174 return (tp is Tuple or isinstance(tp, typingGenericAlias) and 

175 tp.__origin__ is tuple or 

176 isinstance(tp, type) and issubclass(tp, Generic) and 

177 issubclass(tp, tuple)) 

178 return type(tp) is TupleMeta 

179 

180 

181def is_optional_type(tp): 

182 """Test if the type is type(None), or is a direct union with it, such as Optional[T]. 

183 

184 NOTE: this method inspects nested `Union` arguments but not `TypeVar` definition 

185 bounds and constraints. So it will return `False` if 

186 - `tp` is a `TypeVar` bound, or constrained to, an optional type 

187 - `tp` is a `Union` to a `TypeVar` bound or constrained to an optional type, 

188 - `tp` refers to a *nested* `Union` containing an optional type or one of the above. 

189 

190 Users wishing to check for optionality in types relying on type variables might wish 

191 to use this method in combination with `get_constraints` and `get_bound` 

192 """ 

193 

194 if tp is type(None): # noqa 

195 return True 

196 elif is_union_type(tp): 

197 return any(is_optional_type(tt) for tt in get_args(tp, evaluate=True)) 

198 else: 

199 return False 

200 

201 

202def is_final_type(tp): 

203 """Test if the type is a final type. Examples:: 

204 

205 is_final_type(int) == False 

206 is_final_type(Final) == True 

207 is_final_type(Final[int]) == True 

208 """ 

209 if NEW_TYPING: 

210 return (tp is Final or 

211 isinstance(tp, typingGenericAlias) and tp.__origin__ is Final) 

212 return WITH_FINAL and type(tp) is _Final 

213 

214 

215try: 

216 MaybeUnionType = types.UnionType 

217except AttributeError: 

218 MaybeUnionType = None 

219 

220 

221def is_union_type(tp): 

222 """Test if the type is a union type. Examples:: 

223 

224 is_union_type(int) == False 

225 is_union_type(Union) == True 

226 is_union_type(Union[int, int]) == False 

227 is_union_type(Union[T, int]) == True 

228 is_union_type(int | int) == False 

229 is_union_type(T | int) == True 

230 """ 

231 if NEW_TYPING: 

232 return (tp is Union or 

233 (isinstance(tp, typingGenericAlias) and tp.__origin__ is Union) or 

234 (MaybeUnionType and isinstance(tp, MaybeUnionType))) 

235 return type(tp) is _Union 

236 

237 

238LITERALS = {Literal} 

239if hasattr(typing, "Literal"): 

240 LITERALS.add(typing.Literal) 

241 

242 

243def is_literal_type(tp): 

244 if NEW_TYPING: 

245 return (tp in LITERALS or 

246 isinstance(tp, typingGenericAlias) and tp.__origin__ in LITERALS) 

247 return WITH_LITERAL and type(tp) is type(Literal) 

248 

249 

250def is_typevar(tp): 

251 """Test if the type represents a type variable. Examples:: 

252 

253 is_typevar(int) == False 

254 is_typevar(T) == True 

255 is_typevar(Union[T, int]) == False 

256 """ 

257 

258 return type(tp) is TypeVar 

259 

260 

261def is_classvar(tp): 

262 """Test if the type represents a class variable. Examples:: 

263 

264 is_classvar(int) == False 

265 is_classvar(ClassVar) == True 

266 is_classvar(ClassVar[int]) == True 

267 is_classvar(ClassVar[List[T]]) == True 

268 """ 

269 if NEW_TYPING: 

270 return (tp is ClassVar or 

271 isinstance(tp, typingGenericAlias) and tp.__origin__ is ClassVar) 

272 elif WITH_CLASSVAR: 

273 return type(tp) is _ClassVar 

274 else: 

275 return False 

276 

277 

278def is_new_type(tp): 

279 """Tests if the type represents a distinct type. Examples:: 

280 

281 is_new_type(int) == False 

282 is_new_type(NewType) == True 

283 is_new_type(NewType('Age', int)) == True 

284 is_new_type(NewType('Scores', List[Dict[str, float]])) == True 

285 """ 

286 if not WITH_NEWTYPE: 

287 return False 

288 elif sys.version_info[:3] >= (3, 10, 0) and sys.version_info.releaselevel != 'beta': 

289 return (tp in (NewType, typing_extensions.NewType) or 

290 isinstance(tp, (NewType, typing_extensions.NewType))) 

291 elif sys.version_info[:3] >= (3, 0, 0): 

292 try: 

293 res = isinstance(tp, typing_extensions.NewType) 

294 except TypeError: 

295 pass 

296 else: 

297 if res: 

298 return res 

299 return (tp in (NewType, typing_extensions.NewType) or 

300 (getattr(tp, '__supertype__', None) is not None and 

301 getattr(tp, '__qualname__', '') == 'NewType.<locals>.new_type' and 

302 tp.__module__ in ('typing', 'typing_extensions'))) 

303 else: # python 2 

304 # __qualname__ is not available in python 2, so we simplify the test here 

305 return (tp is NewType or 

306 (getattr(tp, '__supertype__', None) is not None and 

307 tp.__module__ in ('typing', 'typing_extensions'))) 

308 

309 

310def is_forward_ref(tp): 

311 """Tests if the type is a :class:`typing.ForwardRef`. Examples:: 

312 

313 u = Union["Milk", Way] 

314 args = get_args(u) 

315 is_forward_ref(args[0]) == True 

316 is_forward_ref(args[1]) == False 

317 """ 

318 if not NEW_TYPING: 

319 return isinstance(tp, _ForwardRef) 

320 return isinstance(tp, ForwardRef) 

321 

322 

323def get_last_origin(tp): 

324 """Get the last base of (multiply) subscripted type. Supports generic types, 

325 Union, Callable, and Tuple. Returns None for unsupported types. 

326 Examples:: 

327 

328 get_last_origin(int) == None 

329 get_last_origin(ClassVar[int]) == None 

330 get_last_origin(Generic[T]) == Generic 

331 get_last_origin(Union[T, int][str]) == Union[T, int] 

332 get_last_origin(List[Tuple[T, T]][int]) == List[Tuple[T, T]] 

333 get_last_origin(List) == List 

334 """ 

335 if NEW_TYPING: 

336 raise ValueError('This function is only supported in Python 3.6,' 

337 ' use get_origin instead') 

338 sentinel = object() 

339 origin = getattr(tp, '__origin__', sentinel) 

340 if origin is sentinel: 

341 return None 

342 if origin is None: 

343 return tp 

344 return origin 

345 

346 

347def get_origin(tp): 

348 """Get the unsubscripted version of a type. Supports generic types, Union, 

349 Callable, and Tuple. Returns None for unsupported types. Examples:: 

350 

351 get_origin(int) == None 

352 get_origin(ClassVar[int]) == None 

353 get_origin(Generic) == Generic 

354 get_origin(Generic[T]) == Generic 

355 get_origin(Union[T, int]) == Union 

356 get_origin(List[Tuple[T, T]][int]) == list # List prior to Python 3.7 

357 """ 

358 if NEW_TYPING: 

359 if isinstance(tp, typingGenericAlias): 

360 return tp.__origin__ if tp.__origin__ is not ClassVar else None 

361 if tp is Generic: 

362 return Generic 

363 return None 

364 if isinstance(tp, GenericMeta): 

365 return _gorg(tp) 

366 if is_union_type(tp): 

367 return Union 

368 if is_tuple_type(tp): 

369 return Tuple 

370 if is_literal_type(tp): 

371 if NEW_TYPING: 

372 return tp.__origin__ or tp 

373 return Literal 

374 

375 return None 

376 

377 

378def get_parameters(tp): 

379 """Return type parameters of a parameterizable type as a tuple 

380 in lexicographic order. Parameterizable types are generic types, 

381 unions, tuple types and callable types. Examples:: 

382 

383 get_parameters(int) == () 

384 get_parameters(Generic) == () 

385 get_parameters(Union) == () 

386 get_parameters(List[int]) == () 

387 

388 get_parameters(Generic[T]) == (T,) 

389 get_parameters(Tuple[List[T], List[S_co]]) == (T, S_co) 

390 get_parameters(Union[S_co, Tuple[T, T]][int, U]) == (U,) 

391 get_parameters(Mapping[T, Tuple[S_co, T]]) == (T, S_co) 

392 """ 

393 if LEGACY_TYPING: 

394 # python <= 3.5.2 

395 if is_union_type(tp): 

396 params = [] 

397 for arg in (tp.__union_params__ if tp.__union_params__ is not None else ()): 

398 params += get_parameters(arg) 

399 return tuple(params) 

400 elif is_tuple_type(tp): 

401 params = [] 

402 for arg in (tp.__tuple_params__ if tp.__tuple_params__ is not None else ()): 

403 params += get_parameters(arg) 

404 return tuple(params) 

405 elif is_generic_type(tp): 

406 params = [] 

407 base_params = tp.__parameters__ 

408 if base_params is None: 

409 return () 

410 for bp_ in base_params: 

411 for bp in (get_args(bp_) if is_tuple_type(bp_) else (bp_,)): 

412 if _has_type_var(bp) and not isinstance(bp, TypeVar): 

413 raise TypeError( 

414 "Cannot inherit from a generic class " 

415 "parameterized with " 

416 "non-type-variable %s" % bp) 

417 if params is None: 

418 params = [] 

419 if bp not in params: 

420 params.append(bp) 

421 if params is not None: 

422 return tuple(params) 

423 else: 

424 return () 

425 else: 

426 return () 

427 elif NEW_TYPING: 

428 if ( 

429 ( 

430 isinstance(tp, typingGenericAlias) and 

431 hasattr(tp, '__parameters__') 

432 ) or 

433 isinstance(tp, type) and issubclass(tp, Generic) and 

434 tp is not Generic): 

435 return tp.__parameters__ 

436 else: 

437 return () 

438 elif ( 

439 is_generic_type(tp) or is_union_type(tp) or 

440 is_callable_type(tp) or is_tuple_type(tp) 

441 ): 

442 return tp.__parameters__ if tp.__parameters__ is not None else () 

443 else: 

444 return () 

445 

446 

447def get_last_args(tp): 

448 """Get last arguments of (multiply) subscripted type. 

449 Parameters for Callable are flattened. Examples:: 

450 

451 get_last_args(int) == () 

452 get_last_args(Union) == () 

453 get_last_args(ClassVar[int]) == (int,) 

454 get_last_args(Union[T, int]) == (T, int) 

455 get_last_args(Iterable[Tuple[T, S]][int, T]) == (int, T) 

456 get_last_args(Callable[[T], int]) == (T, int) 

457 get_last_args(Callable[[], int]) == (int,) 

458 """ 

459 if NEW_TYPING: 

460 raise ValueError('This function is only supported in Python 3.6,' 

461 ' use get_args instead') 

462 elif is_classvar(tp): 

463 return (tp.__type__,) if tp.__type__ is not None else () 

464 elif is_generic_type(tp): 

465 try: 

466 if tp.__args__ is not None and len(tp.__args__) > 0: 

467 return tp.__args__ 

468 except AttributeError: 

469 # python 3.5.1 

470 pass 

471 return tp.__parameters__ if tp.__parameters__ is not None else () 

472 elif is_union_type(tp): 

473 try: 

474 return tp.__args__ if tp.__args__ is not None else () 

475 except AttributeError: 

476 # python 3.5.2 

477 return tp.__union_params__ if tp.__union_params__ is not None else () 

478 elif is_callable_type(tp): 

479 return tp.__args__ if tp.__args__ is not None else () 

480 elif is_tuple_type(tp): 

481 try: 

482 return tp.__args__ if tp.__args__ is not None else () 

483 except AttributeError: 

484 # python 3.5.2 

485 return tp.__tuple_params__ if tp.__tuple_params__ is not None else () 

486 else: 

487 return () 

488 

489 

490def _eval_args(args): 

491 """Internal helper for get_args.""" 

492 res = [] 

493 for arg in args: 

494 if not isinstance(arg, tuple): 

495 res.append(arg) 

496 elif is_callable_type(arg[0]): 

497 callable_args = _eval_args(arg[1:]) 

498 if len(arg) == 2: 

499 res.append(Callable[[], callable_args[0]]) 

500 elif arg[1] is Ellipsis: 

501 res.append(Callable[..., callable_args[1]]) 

502 else: 

503 res.append(Callable[list(callable_args[:-1]), callable_args[-1]]) 

504 else: 

505 res.append(type(arg[0]).__getitem__(arg[0], _eval_args(arg[1:]))) 

506 return tuple(res) 

507 

508 

509def get_args(tp, evaluate=None): 

510 """Get type arguments with all substitutions performed. For unions, 

511 basic simplifications used by Union constructor are performed. 

512 On versions prior to 3.7 if `evaluate` is False (default), 

513 report result as nested tuple, this matches 

514 the internal representation of types. If `evaluate` is True 

515 (or if Python version is 3.7 or greater), then all 

516 type parameters are applied (this could be time and memory expensive). 

517 Examples:: 

518 

519 get_args(int) == () 

520 get_args(Union[int, Union[T, int], str][int]) == (int, str) 

521 get_args(Union[int, Tuple[T, int]][str]) == (int, (Tuple, str, int)) 

522 

523 get_args(Union[int, Tuple[T, int]][str], evaluate=True) == \ 

524 (int, Tuple[str, int]) 

525 get_args(Dict[int, Tuple[T, T]][Optional[int]], evaluate=True) == \ 

526 (int, Tuple[Optional[int], Optional[int]]) 

527 get_args(Callable[[], T][int], evaluate=True) == ([], int,) 

528 """ 

529 if NEW_TYPING: 

530 if evaluate is not None and not evaluate: 

531 raise ValueError('evaluate can only be True in Python >= 3.7') 

532 # Note special aliases on Python 3.9 don't have __args__. 

533 if isinstance(tp, typingGenericAlias) and hasattr(tp, '__args__'): 

534 res = tp.__args__ 

535 if get_origin(tp) is collections.abc.Callable and res[0] is not Ellipsis: 

536 res = (list(res[:-1]), res[-1]) 

537 return res 

538 if MaybeUnionType and isinstance(tp, MaybeUnionType): 

539 return tp.__args__ 

540 return () 

541 if is_classvar(tp) or is_final_type(tp): 

542 return (tp.__type__,) if tp.__type__ is not None else () 

543 if is_literal_type(tp): 

544 return tp.__values__ or () 

545 if ( 

546 is_generic_type(tp) or is_union_type(tp) or 

547 is_callable_type(tp) or is_tuple_type(tp) 

548 ): 

549 try: 

550 tree = tp._subs_tree() 

551 except AttributeError: 

552 # Old python typing module <= 3.5.3 

553 if is_union_type(tp): 

554 # backport of union's subs_tree 

555 tree = _union_subs_tree(tp) 

556 elif is_generic_type(tp): 

557 # backport of GenericMeta's subs_tree 

558 tree = _generic_subs_tree(tp) 

559 elif is_tuple_type(tp): 

560 # ad-hoc (inspired by union) 

561 tree = _tuple_subs_tree(tp) 

562 else: 

563 # tree = _subs_tree(tp) 

564 return () 

565 

566 if isinstance(tree, tuple) and len(tree) > 1: 

567 if not evaluate: 

568 return tree[1:] 

569 res = _eval_args(tree[1:]) 

570 if get_origin(tp) is Callable and res[0] is not Ellipsis: 

571 res = (list(res[:-1]), res[-1]) 

572 return res 

573 

574 return () 

575 

576 

577def get_bound(tp): 

578 """Return the type bound to a `TypeVar` if any. 

579 

580 It the type is not a `TypeVar`, a `TypeError` is raised. 

581 Examples:: 

582 

583 get_bound(TypeVar('T')) == None 

584 get_bound(TypeVar('T', bound=int)) == int 

585 """ 

586 

587 if is_typevar(tp): 

588 return getattr(tp, '__bound__', None) 

589 else: 

590 raise TypeError("type is not a `TypeVar`: " + str(tp)) 

591 

592 

593def get_constraints(tp): 

594 """Returns the constraints of a `TypeVar` if any. 

595 

596 It the type is not a `TypeVar`, a `TypeError` is raised 

597 Examples:: 

598 

599 get_constraints(TypeVar('T')) == () 

600 get_constraints(TypeVar('T', int, str)) == (int, str) 

601 """ 

602 

603 if is_typevar(tp): 

604 return getattr(tp, '__constraints__', ()) 

605 else: 

606 raise TypeError("type is not a `TypeVar`: " + str(tp)) 

607 

608 

609def get_generic_type(obj): 

610 """Get the generic type of an object if possible, or runtime class otherwise. 

611 Examples:: 

612 

613 class Node(Generic[T]): 

614 ... 

615 type(Node[int]()) == Node 

616 get_generic_type(Node[int]()) == Node[int] 

617 get_generic_type(Node[T]()) == Node[T] 

618 get_generic_type(1) == int 

619 """ 

620 

621 gen_type = getattr(obj, '__orig_class__', None) 

622 return gen_type if gen_type is not None else type(obj) 

623 

624 

625def get_generic_bases(tp): 

626 """Get generic base types of a type or empty tuple if not possible. 

627 Example:: 

628 

629 class MyClass(List[int], Mapping[str, List[int]]): 

630 ... 

631 MyClass.__bases__ == (List, Mapping) 

632 get_generic_bases(MyClass) == (List[int], Mapping[str, List[int]]) 

633 """ 

634 if LEGACY_TYPING: 

635 return tuple(t for t in tp.__bases__ if isinstance(t, GenericMeta)) 

636 else: 

637 return getattr(tp, '__orig_bases__', ()) 

638 

639 

640def typed_dict_keys(td): 

641 """If td is a TypedDict class, return a dictionary mapping the typed keys to types. 

642 Otherwise, return None. Examples:: 

643 

644 class TD(TypedDict): 

645 x: int 

646 y: int 

647 class Other(dict): 

648 x: int 

649 y: int 

650 

651 typed_dict_keys(TD) == {'x': int, 'y': int} 

652 typed_dict_keys(dict) == None 

653 typed_dict_keys(Other) == None 

654 """ 

655 if isinstance(td, (_TypedDictMeta_Mypy, _TypedDictMeta_TE)): 

656 return td.__annotations__.copy() 

657 return None 

658 

659 

660def get_forward_arg(fr): 

661 """ 

662 If fr is a ForwardRef, return the string representation of the forward reference. 

663 Otherwise return None. Examples:: 

664 

665 tp = List["FRef"] 

666 fr = get_args(tp)[0] 

667 get_forward_arg(fr) == "FRef" 

668 get_forward_arg(tp) == None 

669 """ 

670 return fr.__forward_arg__ if is_forward_ref(fr) else None 

671 

672 

673# A few functions backported and adapted for the LEGACY_TYPING context, and used above 

674 

675def _replace_arg(arg, tvars, args): 

676 """backport of _replace_arg""" 

677 if tvars is None: 

678 tvars = [] 

679 # if hasattr(arg, '_subs_tree') and isinstance(arg, (GenericMeta, _TypingBase)): 

680 # return arg._subs_tree(tvars, args) 

681 if is_union_type(arg): 

682 return _union_subs_tree(arg, tvars, args) 

683 if is_tuple_type(arg): 

684 return _tuple_subs_tree(arg, tvars, args) 

685 if is_generic_type(arg): 

686 return _generic_subs_tree(arg, tvars, args) 

687 if isinstance(arg, TypeVar): 

688 for i, tvar in enumerate(tvars): 

689 if arg == tvar: 

690 return args[i] 

691 return arg 

692 

693 

694def _remove_dups_flatten(parameters): 

695 """backport of _remove_dups_flatten""" 

696 

697 # Flatten out Union[Union[...], ...]. 

698 params = [] 

699 for p in parameters: 

700 if isinstance(p, _Union): # and p.__origin__ is Union: 

701 params.extend(p.__union_params__) # p.__args__) 

702 elif isinstance(p, tuple) and len(p) > 0 and p[0] is Union: 

703 params.extend(p[1:]) 

704 else: 

705 params.append(p) 

706 # Weed out strict duplicates, preserving the first of each occurrence. 

707 all_params = set(params) 

708 if len(all_params) < len(params): 

709 new_params = [] 

710 for t in params: 

711 if t in all_params: 

712 new_params.append(t) 

713 all_params.remove(t) 

714 params = new_params 

715 assert not all_params, all_params 

716 # Weed out subclasses. 

717 # E.g. Union[int, Employee, Manager] == Union[int, Employee]. 

718 # If object is present it will be sole survivor among proper classes. 

719 # Never discard type variables. 

720 # (In particular, Union[str, AnyStr] != AnyStr.) 

721 all_params = set(params) 

722 for t1 in params: 

723 if not isinstance(t1, type): 

724 continue 

725 if any(isinstance(t2, type) and issubclass(t1, t2) 

726 for t2 in all_params - {t1} 

727 if (not (isinstance(t2, GenericMeta) and 

728 get_origin(t2) is not None) and 

729 not isinstance(t2, TypeVar))): 

730 all_params.remove(t1) 

731 return tuple(t for t in params if t in all_params) 

732 

733 

734def _subs_tree(cls, tvars=None, args=None): 

735 """backport of typing._subs_tree, adapted for legacy versions """ 

736 def _get_origin(cls): 

737 try: 

738 return cls.__origin__ 

739 except AttributeError: 

740 return None 

741 

742 current = _get_origin(cls) 

743 if current is None: 

744 if not is_union_type(cls) and not is_tuple_type(cls): 

745 return cls 

746 

747 # Make of chain of origins (i.e. cls -> cls.__origin__) 

748 orig_chain = [] 

749 while _get_origin(current) is not None: 

750 orig_chain.append(current) 

751 current = _get_origin(current) 

752 

753 # Replace type variables in __args__ if asked ... 

754 tree_args = [] 

755 

756 def _get_args(cls): 

757 if is_union_type(cls): 

758 cls_args = cls.__union_params__ 

759 elif is_tuple_type(cls): 

760 cls_args = cls.__tuple_params__ 

761 else: 

762 try: 

763 cls_args = cls.__args__ 

764 except AttributeError: 

765 cls_args = () 

766 return cls_args if cls_args is not None else () 

767 

768 for arg in _get_args(cls): 

769 tree_args.append(_replace_arg(arg, tvars, args)) 

770 # ... then continue replacing down the origin chain. 

771 for ocls in orig_chain: 

772 new_tree_args = [] 

773 for arg in _get_args(ocls): 

774 new_tree_args.append(_replace_arg(arg, get_parameters(ocls), tree_args)) 

775 tree_args = new_tree_args 

776 return tree_args 

777 

778 

779def _union_subs_tree(tp, tvars=None, args=None): 

780 """ backport of Union._subs_tree """ 

781 if tp is Union: 

782 return Union # Nothing to substitute 

783 tree_args = _subs_tree(tp, tvars, args) 

784 # tree_args = tp.__union_params__ if tp.__union_params__ is not None else () 

785 tree_args = _remove_dups_flatten(tree_args) 

786 if len(tree_args) == 1: 

787 return tree_args[0] # Union of a single type is that type 

788 return (Union,) + tree_args 

789 

790 

791def _generic_subs_tree(tp, tvars=None, args=None): 

792 """ backport of GenericMeta._subs_tree """ 

793 if tp.__origin__ is None: 

794 return tp 

795 tree_args = _subs_tree(tp, tvars, args) 

796 return (_gorg(tp),) + tuple(tree_args) 

797 

798 

799def _tuple_subs_tree(tp, tvars=None, args=None): 

800 """ ad-hoc function (inspired by union) for legacy typing """ 

801 if tp is Tuple: 

802 return Tuple # Nothing to substitute 

803 tree_args = _subs_tree(tp, tvars, args) 

804 return (Tuple,) + tuple(tree_args) 

805 

806 

807def _has_type_var(t): 

808 if t is None: 

809 return False 

810 elif is_union_type(t): 

811 return _union_has_type_var(t) 

812 elif is_tuple_type(t): 

813 return _tuple_has_type_var(t) 

814 elif is_generic_type(t): 

815 return _generic_has_type_var(t) 

816 elif is_callable_type(t): 

817 return _callable_has_type_var(t) 

818 else: 

819 return False 

820 

821 

822def _union_has_type_var(tp): 

823 if tp.__union_params__: 

824 for t in tp.__union_params__: 

825 if _has_type_var(t): 

826 return True 

827 return False 

828 

829 

830def _tuple_has_type_var(tp): 

831 if tp.__tuple_params__: 

832 for t in tp.__tuple_params__: 

833 if _has_type_var(t): 

834 return True 

835 return False 

836 

837 

838def _callable_has_type_var(tp): 

839 if tp.__args__: 

840 for t in tp.__args__: 

841 if _has_type_var(t): 

842 return True 

843 return _has_type_var(tp.__result__) 

844 

845 

846def _generic_has_type_var(tp): 

847 if tp.__parameters__: 

848 for t in tp.__parameters__: 

849 if _has_type_var(t): 

850 return True 

851 return False