|
7 | 7 | import subprocess
|
8 | 8 | import types
|
9 | 9 | from unittest import TestCase, main, skipUnless, skipIf
|
10 |
| -from typing import TypeVar, Optional |
| 10 | +from typing import TypeVar, Optional, Union |
11 | 11 | from typing import T, KT, VT # Not in __all__.
|
12 |
| -from typing import Tuple, List, Dict, Iterator |
| 12 | +from typing import Tuple, List, Dict, Iterator, Callable |
13 | 13 | from typing import Generic
|
14 | 14 | from typing import no_type_check
|
15 | 15 | from typing_extensions import NoReturn, ClassVar, Final, IntVar, Literal, Type, NewType, TypedDict
|
16 |
| -from typing_extensions import TypeAlias, ParamSpec, Concatenate |
| 16 | +from typing_extensions import TypeAlias, ParamSpec, Concatenate, ParamSpecArgs, ParamSpecKwargs |
17 | 17 |
|
18 | 18 | try:
|
19 | 19 | from typing_extensions import Protocol, runtime, runtime_checkable
|
@@ -519,6 +519,80 @@ def test_final_forward_ref(self):
|
519 | 519 | self.assertNotEqual(gth(Loop, globals())['attr'], Final)
|
520 | 520 |
|
521 | 521 |
|
| 522 | +@skipUnless(PEP_560, "Python 3.7+ required") |
| 523 | +class GetUtilitiesTestCase(TestCase): |
| 524 | + def test_get_origin(self): |
| 525 | + from typing_extensions import get_origin |
| 526 | + |
| 527 | + T = TypeVar('T') |
| 528 | + P = ParamSpec('P') |
| 529 | + class C(Generic[T]): pass |
| 530 | + self.assertIs(get_origin(C[int]), C) |
| 531 | + self.assertIs(get_origin(C[T]), C) |
| 532 | + self.assertIs(get_origin(int), None) |
| 533 | + self.assertIs(get_origin(ClassVar[int]), ClassVar) |
| 534 | + self.assertIs(get_origin(Union[int, str]), Union) |
| 535 | + self.assertIs(get_origin(Literal[42, 43]), Literal) |
| 536 | + self.assertIs(get_origin(Final[List[int]]), Final) |
| 537 | + self.assertIs(get_origin(Generic), Generic) |
| 538 | + self.assertIs(get_origin(Generic[T]), Generic) |
| 539 | + self.assertIs(get_origin(List[Tuple[T, T]][int]), list) |
| 540 | + self.assertIs(get_origin(Annotated[T, 'thing']), Annotated) |
| 541 | + self.assertIs(get_origin(List), list) |
| 542 | + self.assertIs(get_origin(Tuple), tuple) |
| 543 | + self.assertIs(get_origin(Callable), collections.abc.Callable) |
| 544 | + if sys.version_info >= (3, 9): |
| 545 | + self.assertIs(get_origin(list[int]), list) |
| 546 | + self.assertIs(get_origin(list), None) |
| 547 | + self.assertIs(get_origin(P.args), P) |
| 548 | + self.assertIs(get_origin(P.kwargs), P) |
| 549 | + |
| 550 | + def test_get_args(self): |
| 551 | + from typing_extensions import get_args |
| 552 | + |
| 553 | + T = TypeVar('T') |
| 554 | + class C(Generic[T]): pass |
| 555 | + self.assertEqual(get_args(C[int]), (int,)) |
| 556 | + self.assertEqual(get_args(C[T]), (T,)) |
| 557 | + self.assertEqual(get_args(int), ()) |
| 558 | + self.assertEqual(get_args(ClassVar[int]), (int,)) |
| 559 | + self.assertEqual(get_args(Union[int, str]), (int, str)) |
| 560 | + self.assertEqual(get_args(Literal[42, 43]), (42, 43)) |
| 561 | + self.assertEqual(get_args(Final[List[int]]), (List[int],)) |
| 562 | + self.assertEqual(get_args(Union[int, Tuple[T, int]][str]), |
| 563 | + (int, Tuple[str, int])) |
| 564 | + self.assertEqual(get_args(typing.Dict[int, Tuple[T, T]][Optional[int]]), |
| 565 | + (int, Tuple[Optional[int], Optional[int]])) |
| 566 | + self.assertEqual(get_args(Callable[[], T][int]), ([], int)) |
| 567 | + self.assertEqual(get_args(Callable[..., int]), (..., int)) |
| 568 | + self.assertEqual(get_args(Union[int, Callable[[Tuple[T, ...]], str]]), |
| 569 | + (int, Callable[[Tuple[T, ...]], str])) |
| 570 | + self.assertEqual(get_args(Tuple[int, ...]), (int, ...)) |
| 571 | + self.assertEqual(get_args(Tuple[()]), ((),)) |
| 572 | + self.assertEqual(get_args(Annotated[T, 'one', 2, ['three']]), (T, 'one', 2, ['three'])) |
| 573 | + self.assertEqual(get_args(List), ()) |
| 574 | + self.assertEqual(get_args(Tuple), ()) |
| 575 | + self.assertEqual(get_args(Callable), ()) |
| 576 | + if sys.version_info >= (3, 9): |
| 577 | + self.assertEqual(get_args(list[int]), (int,)) |
| 578 | + self.assertEqual(get_args(list), ()) |
| 579 | + if sys.version_info >= (3, 9): |
| 580 | + # Support Python versions with and without the fix for |
| 581 | + # https://bugs.python.org/issue42195 |
| 582 | + # The first variant is for 3.9.2+, the second for 3.9.0 and 1 |
| 583 | + self.assertIn(get_args(collections.abc.Callable[[int], str]), |
| 584 | + (([int], str), ([[int]], str))) |
| 585 | + self.assertIn(get_args(collections.abc.Callable[[], str]), |
| 586 | + (([], str), ([[]], str))) |
| 587 | + self.assertEqual(get_args(collections.abc.Callable[..., str]), (..., str)) |
| 588 | + P = ParamSpec('P') |
| 589 | + # In 3.9 and lower we use typing_extensions's hacky implementation |
| 590 | + # of ParamSpec, which gets incorrectly wrapped in a list |
| 591 | + self.assertIn(get_args(Callable[P, int]), [(P, int), ([P], int)]) |
| 592 | + self.assertEqual(get_args(Callable[Concatenate[int, P], int]), |
| 593 | + (Concatenate[int, P], int)) |
| 594 | + |
| 595 | + |
522 | 596 | class CollectionsAbcTests(BaseTestCase):
|
523 | 597 |
|
524 | 598 | def test_isinstance_collections(self):
|
@@ -1952,8 +2026,17 @@ def test_valid_uses(self):
|
1952 | 2026 | # ParamSpec instances should also have args and kwargs attributes.
|
1953 | 2027 | self.assertIn('args', dir(P))
|
1954 | 2028 | self.assertIn('kwargs', dir(P))
|
1955 |
| - P.args |
1956 |
| - P.kwargs |
| 2029 | + |
| 2030 | + def test_args_kwargs(self): |
| 2031 | + P = ParamSpec('P') |
| 2032 | + self.assertIn('args', dir(P)) |
| 2033 | + self.assertIn('kwargs', dir(P)) |
| 2034 | + self.assertIsInstance(P.args, ParamSpecArgs) |
| 2035 | + self.assertIsInstance(P.kwargs, ParamSpecKwargs) |
| 2036 | + self.assertIs(P.args.__origin__, P) |
| 2037 | + self.assertIs(P.kwargs.__origin__, P) |
| 2038 | + self.assertEqual(repr(P.args), "P.args") |
| 2039 | + self.assertEqual(repr(P.kwargs), "P.kwargs") |
1957 | 2040 |
|
1958 | 2041 | # Note: ParamSpec doesn't work for pre-3.10 user-defined Generics due
|
1959 | 2042 | # to type checks inside Generic.
|
@@ -2072,7 +2155,7 @@ def test_typing_extensions_defers_when_possible(self):
|
2072 | 2155 | 'Final',
|
2073 | 2156 | 'get_type_hints'
|
2074 | 2157 | }
|
2075 |
| - if sys.version_info[:2] == (3, 8): |
| 2158 | + if sys.version_info < (3, 10): |
2076 | 2159 | exclude |= {'get_args', 'get_origin'}
|
2077 | 2160 | for item in typing_extensions.__all__:
|
2078 | 2161 | if item not in exclude and hasattr(typing, item):
|
|
0 commit comments