1import contextlib 2import collections 3from collections import defaultdict 4from functools import lru_cache, wraps 5import inspect 6import itertools 7import pickle 8import re 9import sys 10import warnings 11from unittest import TestCase, main, skipUnless, skip 12from unittest.mock import patch 13from copy import copy, deepcopy 14 15from typing import Any, NoReturn, Never, assert_never 16from typing import overload, get_overloads, clear_overloads 17from typing import TypeVar, TypeVarTuple, Unpack, AnyStr 18from typing import T, KT, VT # Not in __all__. 19from typing import Union, Optional, Literal 20from typing import Tuple, List, Dict, MutableMapping 21from typing import Callable 22from typing import Generic, ClassVar, Final, final, Protocol 23from typing import assert_type, cast, runtime_checkable 24from typing import get_type_hints 25from typing import get_origin, get_args 26from typing import is_typeddict 27from typing import reveal_type 28from typing import dataclass_transform 29from typing import no_type_check, no_type_check_decorator 30from typing import Type 31from typing import NamedTuple, NotRequired, Required, TypedDict 32from typing import IO, TextIO, BinaryIO 33from typing import Pattern, Match 34from typing import Annotated, ForwardRef 35from typing import Self, LiteralString 36from typing import TypeAlias 37from typing import ParamSpec, Concatenate, ParamSpecArgs, ParamSpecKwargs 38from typing import TypeGuard 39import abc 40import textwrap 41import typing 42import weakref 43import types 44 45from test.support import import_helper, captured_stderr, cpython_only 46from test import mod_generics_cache 47from test import _typed_dict_helper 48 49 50py_typing = import_helper.import_fresh_module('typing', blocked=['_typing']) 51c_typing = import_helper.import_fresh_module('typing', fresh=['_typing']) 52 53CANNOT_SUBCLASS_TYPE = 'Cannot subclass special typing classes' 54 55 56class BaseTestCase(TestCase): 57 58 def assertIsSubclass(self, cls, class_or_tuple, msg=None): 59 if not issubclass(cls, class_or_tuple): 60 message = '%r is not a subclass of %r' % (cls, class_or_tuple) 61 if msg is not None: 62 message += ' : %s' % msg 63 raise self.failureException(message) 64 65 def assertNotIsSubclass(self, cls, class_or_tuple, msg=None): 66 if issubclass(cls, class_or_tuple): 67 message = '%r is a subclass of %r' % (cls, class_or_tuple) 68 if msg is not None: 69 message += ' : %s' % msg 70 raise self.failureException(message) 71 72 def clear_caches(self): 73 for f in typing._cleanups: 74 f() 75 76 77def all_pickle_protocols(test_func): 78 """Runs `test_func` with various values for `proto` argument.""" 79 80 @wraps(test_func) 81 def wrapper(self): 82 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 83 with self.subTest(pickle_proto=proto): 84 test_func(self, proto=proto) 85 86 return wrapper 87 88 89class Employee: 90 pass 91 92 93class Manager(Employee): 94 pass 95 96 97class Founder(Employee): 98 pass 99 100 101class ManagingFounder(Manager, Founder): 102 pass 103 104 105class AnyTests(BaseTestCase): 106 107 def test_any_instance_type_error(self): 108 with self.assertRaises(TypeError): 109 isinstance(42, Any) 110 111 def test_repr(self): 112 self.assertEqual(repr(Any), 'typing.Any') 113 114 class Sub(Any): pass 115 self.assertEqual( 116 repr(Sub), 117 f"<class '{__name__}.AnyTests.test_repr.<locals>.Sub'>", 118 ) 119 120 def test_errors(self): 121 with self.assertRaises(TypeError): 122 issubclass(42, Any) 123 with self.assertRaises(TypeError): 124 Any[int] # Any is not a generic type. 125 126 def test_can_subclass(self): 127 class Mock(Any): pass 128 self.assertTrue(issubclass(Mock, Any)) 129 self.assertIsInstance(Mock(), Mock) 130 131 class Something: pass 132 self.assertFalse(issubclass(Something, Any)) 133 self.assertNotIsInstance(Something(), Mock) 134 135 class MockSomething(Something, Mock): pass 136 self.assertTrue(issubclass(MockSomething, Any)) 137 ms = MockSomething() 138 self.assertIsInstance(ms, MockSomething) 139 self.assertIsInstance(ms, Something) 140 self.assertIsInstance(ms, Mock) 141 142 def test_cannot_instantiate(self): 143 with self.assertRaises(TypeError): 144 Any() 145 with self.assertRaises(TypeError): 146 type(Any)() 147 148 def test_any_works_with_alias(self): 149 # These expressions must simply not fail. 150 typing.Match[Any] 151 typing.Pattern[Any] 152 typing.IO[Any] 153 154 155class BottomTypeTestsMixin: 156 bottom_type: ClassVar[Any] 157 158 def test_equality(self): 159 self.assertEqual(self.bottom_type, self.bottom_type) 160 self.assertIs(self.bottom_type, self.bottom_type) 161 self.assertNotEqual(self.bottom_type, None) 162 163 def test_get_origin(self): 164 self.assertIs(get_origin(self.bottom_type), None) 165 166 def test_instance_type_error(self): 167 with self.assertRaises(TypeError): 168 isinstance(42, self.bottom_type) 169 170 def test_subclass_type_error(self): 171 with self.assertRaises(TypeError): 172 issubclass(Employee, self.bottom_type) 173 with self.assertRaises(TypeError): 174 issubclass(NoReturn, self.bottom_type) 175 176 def test_not_generic(self): 177 with self.assertRaises(TypeError): 178 self.bottom_type[int] 179 180 def test_cannot_subclass(self): 181 with self.assertRaises(TypeError): 182 class A(self.bottom_type): 183 pass 184 with self.assertRaises(TypeError): 185 class A(type(self.bottom_type)): 186 pass 187 188 def test_cannot_instantiate(self): 189 with self.assertRaises(TypeError): 190 self.bottom_type() 191 with self.assertRaises(TypeError): 192 type(self.bottom_type)() 193 194 195class NoReturnTests(BottomTypeTestsMixin, BaseTestCase): 196 bottom_type = NoReturn 197 198 def test_repr(self): 199 self.assertEqual(repr(NoReturn), 'typing.NoReturn') 200 201 def test_get_type_hints(self): 202 def some(arg: NoReturn) -> NoReturn: ... 203 def some_str(arg: 'NoReturn') -> 'typing.NoReturn': ... 204 205 expected = {'arg': NoReturn, 'return': NoReturn} 206 for target in [some, some_str]: 207 with self.subTest(target=target): 208 self.assertEqual(gth(target), expected) 209 210 def test_not_equality(self): 211 self.assertNotEqual(NoReturn, Never) 212 self.assertNotEqual(Never, NoReturn) 213 214 215class NeverTests(BottomTypeTestsMixin, BaseTestCase): 216 bottom_type = Never 217 218 def test_repr(self): 219 self.assertEqual(repr(Never), 'typing.Never') 220 221 def test_get_type_hints(self): 222 def some(arg: Never) -> Never: ... 223 def some_str(arg: 'Never') -> 'typing.Never': ... 224 225 expected = {'arg': Never, 'return': Never} 226 for target in [some, some_str]: 227 with self.subTest(target=target): 228 self.assertEqual(gth(target), expected) 229 230 231class AssertNeverTests(BaseTestCase): 232 def test_exception(self): 233 with self.assertRaises(AssertionError): 234 assert_never(None) 235 236 value = "some value" 237 with self.assertRaisesRegex(AssertionError, value): 238 assert_never(value) 239 240 # Make sure a huge value doesn't get printed in its entirety 241 huge_value = "a" * 10000 242 with self.assertRaises(AssertionError) as cm: 243 assert_never(huge_value) 244 self.assertLess( 245 len(cm.exception.args[0]), 246 typing._ASSERT_NEVER_REPR_MAX_LENGTH * 2, 247 ) 248 249 250class SelfTests(BaseTestCase): 251 def test_equality(self): 252 self.assertEqual(Self, Self) 253 self.assertIs(Self, Self) 254 self.assertNotEqual(Self, None) 255 256 def test_basics(self): 257 class Foo: 258 def bar(self) -> Self: ... 259 class FooStr: 260 def bar(self) -> 'Self': ... 261 class FooStrTyping: 262 def bar(self) -> 'typing.Self': ... 263 264 for target in [Foo, FooStr, FooStrTyping]: 265 with self.subTest(target=target): 266 self.assertEqual(gth(target.bar), {'return': Self}) 267 self.assertIs(get_origin(Self), None) 268 269 def test_repr(self): 270 self.assertEqual(repr(Self), 'typing.Self') 271 272 def test_cannot_subscript(self): 273 with self.assertRaises(TypeError): 274 Self[int] 275 276 def test_cannot_subclass(self): 277 with self.assertRaises(TypeError): 278 class C(type(Self)): 279 pass 280 with self.assertRaises(TypeError): 281 class C(Self): 282 pass 283 284 def test_cannot_init(self): 285 with self.assertRaises(TypeError): 286 Self() 287 with self.assertRaises(TypeError): 288 type(Self)() 289 290 def test_no_isinstance(self): 291 with self.assertRaises(TypeError): 292 isinstance(1, Self) 293 with self.assertRaises(TypeError): 294 issubclass(int, Self) 295 296 def test_alias(self): 297 # TypeAliases are not actually part of the spec 298 alias_1 = Tuple[Self, Self] 299 alias_2 = List[Self] 300 alias_3 = ClassVar[Self] 301 self.assertEqual(get_args(alias_1), (Self, Self)) 302 self.assertEqual(get_args(alias_2), (Self,)) 303 self.assertEqual(get_args(alias_3), (Self,)) 304 305 306class LiteralStringTests(BaseTestCase): 307 def test_equality(self): 308 self.assertEqual(LiteralString, LiteralString) 309 self.assertIs(LiteralString, LiteralString) 310 self.assertNotEqual(LiteralString, None) 311 312 def test_basics(self): 313 class Foo: 314 def bar(self) -> LiteralString: ... 315 class FooStr: 316 def bar(self) -> 'LiteralString': ... 317 class FooStrTyping: 318 def bar(self) -> 'typing.LiteralString': ... 319 320 for target in [Foo, FooStr, FooStrTyping]: 321 with self.subTest(target=target): 322 self.assertEqual(gth(target.bar), {'return': LiteralString}) 323 self.assertIs(get_origin(LiteralString), None) 324 325 def test_repr(self): 326 self.assertEqual(repr(LiteralString), 'typing.LiteralString') 327 328 def test_cannot_subscript(self): 329 with self.assertRaises(TypeError): 330 LiteralString[int] 331 332 def test_cannot_subclass(self): 333 with self.assertRaises(TypeError): 334 class C(type(LiteralString)): 335 pass 336 with self.assertRaises(TypeError): 337 class C(LiteralString): 338 pass 339 340 def test_cannot_init(self): 341 with self.assertRaises(TypeError): 342 LiteralString() 343 with self.assertRaises(TypeError): 344 type(LiteralString)() 345 346 def test_no_isinstance(self): 347 with self.assertRaises(TypeError): 348 isinstance(1, LiteralString) 349 with self.assertRaises(TypeError): 350 issubclass(int, LiteralString) 351 352 def test_alias(self): 353 alias_1 = Tuple[LiteralString, LiteralString] 354 alias_2 = List[LiteralString] 355 alias_3 = ClassVar[LiteralString] 356 self.assertEqual(get_args(alias_1), (LiteralString, LiteralString)) 357 self.assertEqual(get_args(alias_2), (LiteralString,)) 358 self.assertEqual(get_args(alias_3), (LiteralString,)) 359 360class TypeVarTests(BaseTestCase): 361 def test_basic_plain(self): 362 T = TypeVar('T') 363 # T equals itself. 364 self.assertEqual(T, T) 365 # T is an instance of TypeVar 366 self.assertIsInstance(T, TypeVar) 367 self.assertEqual(T.__name__, 'T') 368 self.assertEqual(T.__constraints__, ()) 369 self.assertIs(T.__bound__, None) 370 self.assertIs(T.__covariant__, False) 371 self.assertIs(T.__contravariant__, False) 372 373 def test_attributes(self): 374 T_bound = TypeVar('T_bound', bound=int) 375 self.assertEqual(T_bound.__name__, 'T_bound') 376 self.assertEqual(T_bound.__constraints__, ()) 377 self.assertIs(T_bound.__bound__, int) 378 379 T_constraints = TypeVar('T_constraints', int, str) 380 self.assertEqual(T_constraints.__name__, 'T_constraints') 381 self.assertEqual(T_constraints.__constraints__, (int, str)) 382 self.assertIs(T_constraints.__bound__, None) 383 384 T_co = TypeVar('T_co', covariant=True) 385 self.assertEqual(T_co.__name__, 'T_co') 386 self.assertIs(T_co.__covariant__, True) 387 self.assertIs(T_co.__contravariant__, False) 388 389 T_contra = TypeVar('T_contra', contravariant=True) 390 self.assertEqual(T_contra.__name__, 'T_contra') 391 self.assertIs(T_contra.__covariant__, False) 392 self.assertIs(T_contra.__contravariant__, True) 393 394 def test_typevar_instance_type_error(self): 395 T = TypeVar('T') 396 with self.assertRaises(TypeError): 397 isinstance(42, T) 398 399 def test_typevar_subclass_type_error(self): 400 T = TypeVar('T') 401 with self.assertRaises(TypeError): 402 issubclass(int, T) 403 with self.assertRaises(TypeError): 404 issubclass(T, int) 405 406 def test_constrained_error(self): 407 with self.assertRaises(TypeError): 408 X = TypeVar('X', int) 409 X 410 411 def test_union_unique(self): 412 X = TypeVar('X') 413 Y = TypeVar('Y') 414 self.assertNotEqual(X, Y) 415 self.assertEqual(Union[X], X) 416 self.assertNotEqual(Union[X], Union[X, Y]) 417 self.assertEqual(Union[X, X], X) 418 self.assertNotEqual(Union[X, int], Union[X]) 419 self.assertNotEqual(Union[X, int], Union[int]) 420 self.assertEqual(Union[X, int].__args__, (X, int)) 421 self.assertEqual(Union[X, int].__parameters__, (X,)) 422 self.assertIs(Union[X, int].__origin__, Union) 423 424 def test_or(self): 425 X = TypeVar('X') 426 # use a string because str doesn't implement 427 # __or__/__ror__ itself 428 self.assertEqual(X | "x", Union[X, "x"]) 429 self.assertEqual("x" | X, Union["x", X]) 430 # make sure the order is correct 431 self.assertEqual(get_args(X | "x"), (X, ForwardRef("x"))) 432 self.assertEqual(get_args("x" | X), (ForwardRef("x"), X)) 433 434 def test_union_constrained(self): 435 A = TypeVar('A', str, bytes) 436 self.assertNotEqual(Union[A, str], Union[A]) 437 438 def test_repr(self): 439 self.assertEqual(repr(T), '~T') 440 self.assertEqual(repr(KT), '~KT') 441 self.assertEqual(repr(VT), '~VT') 442 self.assertEqual(repr(AnyStr), '~AnyStr') 443 T_co = TypeVar('T_co', covariant=True) 444 self.assertEqual(repr(T_co), '+T_co') 445 T_contra = TypeVar('T_contra', contravariant=True) 446 self.assertEqual(repr(T_contra), '-T_contra') 447 448 def test_no_redefinition(self): 449 self.assertNotEqual(TypeVar('T'), TypeVar('T')) 450 self.assertNotEqual(TypeVar('T', int, str), TypeVar('T', int, str)) 451 452 def test_cannot_subclass_vars(self): 453 with self.assertRaises(TypeError): 454 class V(TypeVar('T')): 455 pass 456 457 def test_cannot_subclass_var_itself(self): 458 with self.assertRaises(TypeError): 459 class V(TypeVar): 460 pass 461 462 def test_cannot_instantiate_vars(self): 463 with self.assertRaises(TypeError): 464 TypeVar('A')() 465 466 def test_bound_errors(self): 467 with self.assertRaises(TypeError): 468 TypeVar('X', bound=Union) 469 with self.assertRaises(TypeError): 470 TypeVar('X', str, float, bound=Employee) 471 472 def test_missing__name__(self): 473 # See bpo-39942 474 code = ("import typing\n" 475 "T = typing.TypeVar('T')\n" 476 ) 477 exec(code, {}) 478 479 def test_no_bivariant(self): 480 with self.assertRaises(ValueError): 481 TypeVar('T', covariant=True, contravariant=True) 482 483 def test_var_substitution(self): 484 T = TypeVar('T') 485 subst = T.__typing_subst__ 486 self.assertIs(subst(int), int) 487 self.assertEqual(subst(list[int]), list[int]) 488 self.assertEqual(subst(List[int]), List[int]) 489 self.assertEqual(subst(List), List) 490 self.assertIs(subst(Any), Any) 491 self.assertIs(subst(None), type(None)) 492 self.assertIs(subst(T), T) 493 self.assertEqual(subst(int|str), int|str) 494 self.assertEqual(subst(Union[int, str]), Union[int, str]) 495 496 def test_bad_var_substitution(self): 497 T = TypeVar('T') 498 bad_args = ( 499 (), (int, str), Union, 500 Generic, Generic[T], Protocol, Protocol[T], 501 Final, Final[int], ClassVar, ClassVar[int], 502 ) 503 for arg in bad_args: 504 with self.subTest(arg=arg): 505 with self.assertRaises(TypeError): 506 T.__typing_subst__(arg) 507 with self.assertRaises(TypeError): 508 List[T][arg] 509 with self.assertRaises(TypeError): 510 list[T][arg] 511 512 513def template_replace(templates: list[str], replacements: dict[str, list[str]]) -> list[tuple[str]]: 514 """Renders templates with possible combinations of replacements. 515 516 Example 1: Suppose that: 517 templates = ["dog_breed are awesome", "dog_breed are cool"] 518 replacements = ["dog_breed": ["Huskies", "Beagles"]] 519 Then we would return: 520 [ 521 ("Huskies are awesome", "Huskies are cool"), 522 ("Beagles are awesome", "Beagles are cool") 523 ] 524 525 Example 2: Suppose that: 526 templates = ["Huskies are word1 but also word2"] 527 replacements = {"word1": ["playful", "cute"], 528 "word2": ["feisty", "tiring"]} 529 Then we would return: 530 [ 531 ("Huskies are playful but also feisty"), 532 ("Huskies are playful but also tiring"), 533 ("Huskies are cute but also feisty"), 534 ("Huskies are cute but also tiring") 535 ] 536 537 Note that if any of the replacements do not occur in any template: 538 templates = ["Huskies are word1", "Beagles!"] 539 replacements = {"word1": ["playful", "cute"], 540 "word2": ["feisty", "tiring"]} 541 Then we do not generate duplicates, returning: 542 [ 543 ("Huskies are playful", "Beagles!"), 544 ("Huskies are cute", "Beagles!") 545 ] 546 """ 547 # First, build a structure like: 548 # [ 549 # [("word1", "playful"), ("word1", "cute")], 550 # [("word2", "feisty"), ("word2", "tiring")] 551 # ] 552 replacement_combos = [] 553 for original, possible_replacements in replacements.items(): 554 original_replacement_tuples = [] 555 for replacement in possible_replacements: 556 original_replacement_tuples.append((original, replacement)) 557 replacement_combos.append(original_replacement_tuples) 558 559 # Second, generate rendered templates, including possible duplicates. 560 rendered_templates = [] 561 for replacement_combo in itertools.product(*replacement_combos): 562 # replacement_combo would be e.g. 563 # [("word1", "playful"), ("word2", "feisty")] 564 templates_with_replacements = [] 565 for template in templates: 566 for original, replacement in replacement_combo: 567 template = template.replace(original, replacement) 568 templates_with_replacements.append(template) 569 rendered_templates.append(tuple(templates_with_replacements)) 570 571 # Finally, remove the duplicates (but keep the order). 572 rendered_templates_no_duplicates = [] 573 for x in rendered_templates: 574 # Inefficient, but should be fine for our purposes. 575 if x not in rendered_templates_no_duplicates: 576 rendered_templates_no_duplicates.append(x) 577 578 return rendered_templates_no_duplicates 579 580 581class TemplateReplacementTests(BaseTestCase): 582 583 def test_two_templates_two_replacements_yields_correct_renders(self): 584 actual = template_replace( 585 templates=["Cats are word1", "Dogs are word2"], 586 replacements={ 587 "word1": ["small", "cute"], 588 "word2": ["big", "fluffy"], 589 }, 590 ) 591 expected = [ 592 ("Cats are small", "Dogs are big"), 593 ("Cats are small", "Dogs are fluffy"), 594 ("Cats are cute", "Dogs are big"), 595 ("Cats are cute", "Dogs are fluffy"), 596 ] 597 self.assertEqual(actual, expected) 598 599 def test_no_duplicates_if_replacement_not_in_templates(self): 600 actual = template_replace( 601 templates=["Cats are word1", "Dogs!"], 602 replacements={ 603 "word1": ["small", "cute"], 604 "word2": ["big", "fluffy"], 605 }, 606 ) 607 expected = [ 608 ("Cats are small", "Dogs!"), 609 ("Cats are cute", "Dogs!"), 610 ] 611 self.assertEqual(actual, expected) 612 613 614class GenericAliasSubstitutionTests(BaseTestCase): 615 """Tests for type variable substitution in generic aliases. 616 617 For variadic cases, these tests should be regarded as the source of truth, 618 since we hadn't realised the full complexity of variadic substitution 619 at the time of finalizing PEP 646. For full discussion, see 620 https://github.com/python/cpython/issues/91162. 621 """ 622 623 def test_one_parameter(self): 624 T = TypeVar('T') 625 Ts = TypeVarTuple('Ts') 626 Ts2 = TypeVarTuple('Ts2') 627 628 class C(Generic[T]): pass 629 630 generics = ['C', 'list', 'List'] 631 tuple_types = ['tuple', 'Tuple'] 632 633 tests = [ 634 # Alias # Args # Expected result 635 ('generic[T]', '[()]', 'TypeError'), 636 ('generic[T]', '[int]', 'generic[int]'), 637 ('generic[T]', '[int, str]', 'TypeError'), 638 ('generic[T]', '[tuple_type[int, ...]]', 'generic[tuple_type[int, ...]]'), 639 ('generic[T]', '[*tuple_type[int]]', 'generic[int]'), 640 ('generic[T]', '[*tuple_type[()]]', 'TypeError'), 641 ('generic[T]', '[*tuple_type[int, str]]', 'TypeError'), 642 ('generic[T]', '[*tuple_type[int, ...]]', 'TypeError'), 643 ('generic[T]', '[*Ts]', 'TypeError'), 644 ('generic[T]', '[T, *Ts]', 'TypeError'), 645 ('generic[T]', '[*Ts, T]', 'TypeError'), 646 # Raises TypeError because C is not variadic. 647 # (If C _were_ variadic, it'd be fine.) 648 ('C[T, *tuple_type[int, ...]]', '[int]', 'TypeError'), 649 # Should definitely raise TypeError: list only takes one argument. 650 ('list[T, *tuple_type[int, ...]]', '[int]', 'list[int, *tuple_type[int, ...]]'), 651 ('List[T, *tuple_type[int, ...]]', '[int]', 'TypeError'), 652 # Should raise, because more than one `TypeVarTuple` is not supported. 653 ('generic[*Ts, *Ts2]', '[int]', 'TypeError'), 654 ] 655 656 for alias_template, args_template, expected_template in tests: 657 rendered_templates = template_replace( 658 templates=[alias_template, args_template, expected_template], 659 replacements={'generic': generics, 'tuple_type': tuple_types} 660 ) 661 for alias_str, args_str, expected_str in rendered_templates: 662 with self.subTest(alias=alias_str, args=args_str, expected=expected_str): 663 if expected_str == 'TypeError': 664 with self.assertRaises(TypeError): 665 eval(alias_str + args_str) 666 else: 667 self.assertEqual( 668 eval(alias_str + args_str), 669 eval(expected_str) 670 ) 671 672 673 def test_two_parameters(self): 674 T1 = TypeVar('T1') 675 T2 = TypeVar('T2') 676 Ts = TypeVarTuple('Ts') 677 678 class C(Generic[T1, T2]): pass 679 680 generics = ['C', 'dict', 'Dict'] 681 tuple_types = ['tuple', 'Tuple'] 682 683 tests = [ 684 # Alias # Args # Expected result 685 ('generic[T1, T2]', '[()]', 'TypeError'), 686 ('generic[T1, T2]', '[int]', 'TypeError'), 687 ('generic[T1, T2]', '[int, str]', 'generic[int, str]'), 688 ('generic[T1, T2]', '[int, str, bool]', 'TypeError'), 689 ('generic[T1, T2]', '[*tuple_type[int]]', 'TypeError'), 690 ('generic[T1, T2]', '[*tuple_type[int, str]]', 'generic[int, str]'), 691 ('generic[T1, T2]', '[*tuple_type[int, str, bool]]', 'TypeError'), 692 693 ('generic[T1, T2]', '[int, *tuple_type[str]]', 'generic[int, str]'), 694 ('generic[T1, T2]', '[*tuple_type[int], str]', 'generic[int, str]'), 695 ('generic[T1, T2]', '[*tuple_type[int], *tuple_type[str]]', 'generic[int, str]'), 696 ('generic[T1, T2]', '[*tuple_type[int, str], *tuple_type[()]]', 'generic[int, str]'), 697 ('generic[T1, T2]', '[*tuple_type[()], *tuple_type[int, str]]', 'generic[int, str]'), 698 ('generic[T1, T2]', '[*tuple_type[int], *tuple_type[()]]', 'TypeError'), 699 ('generic[T1, T2]', '[*tuple_type[()], *tuple_type[int]]', 'TypeError'), 700 ('generic[T1, T2]', '[*tuple_type[int, str], *tuple_type[float]]', 'TypeError'), 701 ('generic[T1, T2]', '[*tuple_type[int], *tuple_type[str, float]]', 'TypeError'), 702 ('generic[T1, T2]', '[*tuple_type[int, str], *tuple_type[float, bool]]', 'TypeError'), 703 704 ('generic[T1, T2]', '[tuple_type[int, ...]]', 'TypeError'), 705 ('generic[T1, T2]', '[tuple_type[int, ...], tuple_type[str, ...]]', 'generic[tuple_type[int, ...], tuple_type[str, ...]]'), 706 ('generic[T1, T2]', '[*tuple_type[int, ...]]', 'TypeError'), 707 ('generic[T1, T2]', '[int, *tuple_type[str, ...]]', 'TypeError'), 708 ('generic[T1, T2]', '[*tuple_type[int, ...], str]', 'TypeError'), 709 ('generic[T1, T2]', '[*tuple_type[int, ...], *tuple_type[str, ...]]', 'TypeError'), 710 ('generic[T1, T2]', '[*Ts]', 'TypeError'), 711 ('generic[T1, T2]', '[T, *Ts]', 'TypeError'), 712 ('generic[T1, T2]', '[*Ts, T]', 'TypeError'), 713 # This one isn't technically valid - none of the things that 714 # `generic` can be (defined in `generics` above) are variadic, so we 715 # shouldn't really be able to do `generic[T1, *tuple_type[int, ...]]`. 716 # So even if type checkers shouldn't allow it, we allow it at 717 # runtime, in accordance with a general philosophy of "Keep the 718 # runtime lenient so people can experiment with typing constructs". 719 ('generic[T1, *tuple_type[int, ...]]', '[str]', 'generic[str, *tuple_type[int, ...]]'), 720 ] 721 722 for alias_template, args_template, expected_template in tests: 723 rendered_templates = template_replace( 724 templates=[alias_template, args_template, expected_template], 725 replacements={'generic': generics, 'tuple_type': tuple_types} 726 ) 727 for alias_str, args_str, expected_str in rendered_templates: 728 with self.subTest(alias=alias_str, args=args_str, expected=expected_str): 729 if expected_str == 'TypeError': 730 with self.assertRaises(TypeError): 731 eval(alias_str + args_str) 732 else: 733 self.assertEqual( 734 eval(alias_str + args_str), 735 eval(expected_str) 736 ) 737 738 def test_three_parameters(self): 739 T1 = TypeVar('T1') 740 T2 = TypeVar('T2') 741 T3 = TypeVar('T3') 742 743 class C(Generic[T1, T2, T3]): pass 744 745 generics = ['C'] 746 tuple_types = ['tuple', 'Tuple'] 747 748 tests = [ 749 # Alias # Args # Expected result 750 ('generic[T1, bool, T2]', '[int, str]', 'generic[int, bool, str]'), 751 ('generic[T1, bool, T2]', '[*tuple_type[int, str]]', 'generic[int, bool, str]'), 752 ] 753 754 for alias_template, args_template, expected_template in tests: 755 rendered_templates = template_replace( 756 templates=[alias_template, args_template, expected_template], 757 replacements={'generic': generics, 'tuple_type': tuple_types} 758 ) 759 for alias_str, args_str, expected_str in rendered_templates: 760 with self.subTest(alias=alias_str, args=args_str, expected=expected_str): 761 if expected_str == 'TypeError': 762 with self.assertRaises(TypeError): 763 eval(alias_str + args_str) 764 else: 765 self.assertEqual( 766 eval(alias_str + args_str), 767 eval(expected_str) 768 ) 769 770 def test_variadic_parameters(self): 771 T1 = TypeVar('T1') 772 T2 = TypeVar('T2') 773 Ts = TypeVarTuple('Ts') 774 775 class C(Generic[*Ts]): pass 776 777 generics = ['C', 'tuple', 'Tuple'] 778 tuple_types = ['tuple', 'Tuple'] 779 780 tests = [ 781 # Alias # Args # Expected result 782 ('generic[*Ts]', '[()]', 'generic[()]'), 783 ('generic[*Ts]', '[int]', 'generic[int]'), 784 ('generic[*Ts]', '[int, str]', 'generic[int, str]'), 785 ('generic[*Ts]', '[*tuple_type[int]]', 'generic[int]'), 786 ('generic[*Ts]', '[*tuple_type[*Ts]]', 'generic[*Ts]'), 787 ('generic[*Ts]', '[*tuple_type[int, str]]', 'generic[int, str]'), 788 ('generic[*Ts]', '[str, *tuple_type[int, ...], bool]', 'generic[str, *tuple_type[int, ...], bool]'), 789 ('generic[*Ts]', '[tuple_type[int, ...]]', 'generic[tuple_type[int, ...]]'), 790 ('generic[*Ts]', '[tuple_type[int, ...], tuple_type[str, ...]]', 'generic[tuple_type[int, ...], tuple_type[str, ...]]'), 791 ('generic[*Ts]', '[*tuple_type[int, ...]]', 'generic[*tuple_type[int, ...]]'), 792 ('generic[*Ts]', '[*tuple_type[int, ...], *tuple_type[str, ...]]', 'TypeError'), 793 794 ('generic[*Ts]', '[*Ts]', 'generic[*Ts]'), 795 ('generic[*Ts]', '[T, *Ts]', 'generic[T, *Ts]'), 796 ('generic[*Ts]', '[*Ts, T]', 'generic[*Ts, T]'), 797 ('generic[T, *Ts]', '[()]', 'TypeError'), 798 ('generic[T, *Ts]', '[int]', 'generic[int]'), 799 ('generic[T, *Ts]', '[int, str]', 'generic[int, str]'), 800 ('generic[T, *Ts]', '[int, str, bool]', 'generic[int, str, bool]'), 801 ('generic[list[T], *Ts]', '[()]', 'TypeError'), 802 ('generic[list[T], *Ts]', '[int]', 'generic[list[int]]'), 803 ('generic[list[T], *Ts]', '[int, str]', 'generic[list[int], str]'), 804 ('generic[list[T], *Ts]', '[int, str, bool]', 'generic[list[int], str, bool]'), 805 806 ('generic[*Ts, T]', '[()]', 'TypeError'), 807 ('generic[*Ts, T]', '[int]', 'generic[int]'), 808 ('generic[*Ts, T]', '[int, str]', 'generic[int, str]'), 809 ('generic[*Ts, T]', '[int, str, bool]', 'generic[int, str, bool]'), 810 ('generic[*Ts, list[T]]', '[()]', 'TypeError'), 811 ('generic[*Ts, list[T]]', '[int]', 'generic[list[int]]'), 812 ('generic[*Ts, list[T]]', '[int, str]', 'generic[int, list[str]]'), 813 ('generic[*Ts, list[T]]', '[int, str, bool]', 'generic[int, str, list[bool]]'), 814 815 ('generic[T1, T2, *Ts]', '[()]', 'TypeError'), 816 ('generic[T1, T2, *Ts]', '[int]', 'TypeError'), 817 ('generic[T1, T2, *Ts]', '[int, str]', 'generic[int, str]'), 818 ('generic[T1, T2, *Ts]', '[int, str, bool]', 'generic[int, str, bool]'), 819 ('generic[T1, T2, *Ts]', '[int, str, bool, bytes]', 'generic[int, str, bool, bytes]'), 820 821 ('generic[*Ts, T1, T2]', '[()]', 'TypeError'), 822 ('generic[*Ts, T1, T2]', '[int]', 'TypeError'), 823 ('generic[*Ts, T1, T2]', '[int, str]', 'generic[int, str]'), 824 ('generic[*Ts, T1, T2]', '[int, str, bool]', 'generic[int, str, bool]'), 825 ('generic[*Ts, T1, T2]', '[int, str, bool, bytes]', 'generic[int, str, bool, bytes]'), 826 827 ('generic[T1, *Ts, T2]', '[()]', 'TypeError'), 828 ('generic[T1, *Ts, T2]', '[int]', 'TypeError'), 829 ('generic[T1, *Ts, T2]', '[int, str]', 'generic[int, str]'), 830 ('generic[T1, *Ts, T2]', '[int, str, bool]', 'generic[int, str, bool]'), 831 ('generic[T1, *Ts, T2]', '[int, str, bool, bytes]', 'generic[int, str, bool, bytes]'), 832 833 ('generic[T, *Ts]', '[*tuple_type[int, ...]]', 'generic[int, *tuple_type[int, ...]]'), 834 ('generic[T, *Ts]', '[str, *tuple_type[int, ...]]', 'generic[str, *tuple_type[int, ...]]'), 835 ('generic[T, *Ts]', '[*tuple_type[int, ...], str]', 'generic[int, *tuple_type[int, ...], str]'), 836 ('generic[*Ts, T]', '[*tuple_type[int, ...]]', 'generic[*tuple_type[int, ...], int]'), 837 ('generic[*Ts, T]', '[str, *tuple_type[int, ...]]', 'generic[str, *tuple_type[int, ...], int]'), 838 ('generic[*Ts, T]', '[*tuple_type[int, ...], str]', 'generic[*tuple_type[int, ...], str]'), 839 ('generic[T1, *Ts, T2]', '[*tuple_type[int, ...]]', 'generic[int, *tuple_type[int, ...], int]'), 840 ('generic[T, str, *Ts]', '[*tuple_type[int, ...]]', 'generic[int, str, *tuple_type[int, ...]]'), 841 ('generic[*Ts, str, T]', '[*tuple_type[int, ...]]', 'generic[*tuple_type[int, ...], str, int]'), 842 ('generic[list[T], *Ts]', '[*tuple_type[int, ...]]', 'generic[list[int], *tuple_type[int, ...]]'), 843 ('generic[*Ts, list[T]]', '[*tuple_type[int, ...]]', 'generic[*tuple_type[int, ...], list[int]]'), 844 845 ('generic[T, *tuple_type[int, ...]]', '[str]', 'generic[str, *tuple_type[int, ...]]'), 846 ('generic[T1, T2, *tuple_type[int, ...]]', '[str, bool]', 'generic[str, bool, *tuple_type[int, ...]]'), 847 ('generic[T1, *tuple_type[int, ...], T2]', '[str, bool]', 'generic[str, *tuple_type[int, ...], bool]'), 848 ('generic[T1, *tuple_type[int, ...], T2]', '[str, bool, float]', 'TypeError'), 849 850 ('generic[T1, *tuple_type[T2, ...]]', '[int, str]', 'generic[int, *tuple_type[str, ...]]'), 851 ('generic[*tuple_type[T1, ...], T2]', '[int, str]', 'generic[*tuple_type[int, ...], str]'), 852 ('generic[T1, *tuple_type[generic[*Ts], ...]]', '[int, str, bool]', 'generic[int, *tuple_type[generic[str, bool], ...]]'), 853 ('generic[*tuple_type[generic[*Ts], ...], T1]', '[int, str, bool]', 'generic[*tuple_type[generic[int, str], ...], bool]'), 854 ] 855 856 for alias_template, args_template, expected_template in tests: 857 rendered_templates = template_replace( 858 templates=[alias_template, args_template, expected_template], 859 replacements={'generic': generics, 'tuple_type': tuple_types} 860 ) 861 for alias_str, args_str, expected_str in rendered_templates: 862 with self.subTest(alias=alias_str, args=args_str, expected=expected_str): 863 if expected_str == 'TypeError': 864 with self.assertRaises(TypeError): 865 eval(alias_str + args_str) 866 else: 867 self.assertEqual( 868 eval(alias_str + args_str), 869 eval(expected_str) 870 ) 871 872 873 874class UnpackTests(BaseTestCase): 875 876 def test_accepts_single_type(self): 877 (*tuple[int],) 878 Unpack[Tuple[int]] 879 880 def test_dir(self): 881 dir_items = set(dir(Unpack[Tuple[int]])) 882 for required_item in [ 883 '__args__', '__parameters__', '__origin__', 884 ]: 885 with self.subTest(required_item=required_item): 886 self.assertIn(required_item, dir_items) 887 888 def test_rejects_multiple_types(self): 889 with self.assertRaises(TypeError): 890 Unpack[Tuple[int], Tuple[str]] 891 # We can't do the equivalent for `*` here - 892 # *(Tuple[int], Tuple[str]) is just plain tuple unpacking, 893 # which is valid. 894 895 def test_rejects_multiple_parameterization(self): 896 with self.assertRaises(TypeError): 897 (*tuple[int],)[0][tuple[int]] 898 with self.assertRaises(TypeError): 899 Unpack[Tuple[int]][Tuple[int]] 900 901 def test_cannot_be_called(self): 902 with self.assertRaises(TypeError): 903 Unpack() 904 905 906class TypeVarTupleTests(BaseTestCase): 907 908 def assertEndsWith(self, string, tail): 909 if not string.endswith(tail): 910 self.fail(f"String {string!r} does not end with {tail!r}") 911 912 def test_name(self): 913 Ts = TypeVarTuple('Ts') 914 self.assertEqual(Ts.__name__, 'Ts') 915 Ts2 = TypeVarTuple('Ts2') 916 self.assertEqual(Ts2.__name__, 'Ts2') 917 918 def test_instance_is_equal_to_itself(self): 919 Ts = TypeVarTuple('Ts') 920 self.assertEqual(Ts, Ts) 921 922 def test_different_instances_are_different(self): 923 self.assertNotEqual(TypeVarTuple('Ts'), TypeVarTuple('Ts')) 924 925 def test_instance_isinstance_of_typevartuple(self): 926 Ts = TypeVarTuple('Ts') 927 self.assertIsInstance(Ts, TypeVarTuple) 928 929 def test_cannot_call_instance(self): 930 Ts = TypeVarTuple('Ts') 931 with self.assertRaises(TypeError): 932 Ts() 933 934 def test_unpacked_typevartuple_is_equal_to_itself(self): 935 Ts = TypeVarTuple('Ts') 936 self.assertEqual((*Ts,)[0], (*Ts,)[0]) 937 self.assertEqual(Unpack[Ts], Unpack[Ts]) 938 939 def test_parameterised_tuple_is_equal_to_itself(self): 940 Ts = TypeVarTuple('Ts') 941 self.assertEqual(tuple[*Ts], tuple[*Ts]) 942 self.assertEqual(Tuple[Unpack[Ts]], Tuple[Unpack[Ts]]) 943 944 def tests_tuple_arg_ordering_matters(self): 945 Ts1 = TypeVarTuple('Ts1') 946 Ts2 = TypeVarTuple('Ts2') 947 self.assertNotEqual( 948 tuple[*Ts1, *Ts2], 949 tuple[*Ts2, *Ts1], 950 ) 951 self.assertNotEqual( 952 Tuple[Unpack[Ts1], Unpack[Ts2]], 953 Tuple[Unpack[Ts2], Unpack[Ts1]], 954 ) 955 956 def test_tuple_args_and_parameters_are_correct(self): 957 Ts = TypeVarTuple('Ts') 958 t1 = tuple[*Ts] 959 self.assertEqual(t1.__args__, (*Ts,)) 960 self.assertEqual(t1.__parameters__, (Ts,)) 961 t2 = Tuple[Unpack[Ts]] 962 self.assertEqual(t2.__args__, (Unpack[Ts],)) 963 self.assertEqual(t2.__parameters__, (Ts,)) 964 965 def test_var_substitution(self): 966 Ts = TypeVarTuple('Ts') 967 T = TypeVar('T') 968 T2 = TypeVar('T2') 969 class G1(Generic[*Ts]): pass 970 class G2(Generic[Unpack[Ts]]): pass 971 972 for A in G1, G2, Tuple, tuple: 973 B = A[*Ts] 974 self.assertEqual(B[()], A[()]) 975 self.assertEqual(B[float], A[float]) 976 self.assertEqual(B[float, str], A[float, str]) 977 978 C = A[Unpack[Ts]] 979 self.assertEqual(C[()], A[()]) 980 self.assertEqual(C[float], A[float]) 981 self.assertEqual(C[float, str], A[float, str]) 982 983 D = list[A[*Ts]] 984 self.assertEqual(D[()], list[A[()]]) 985 self.assertEqual(D[float], list[A[float]]) 986 self.assertEqual(D[float, str], list[A[float, str]]) 987 988 E = List[A[Unpack[Ts]]] 989 self.assertEqual(E[()], List[A[()]]) 990 self.assertEqual(E[float], List[A[float]]) 991 self.assertEqual(E[float, str], List[A[float, str]]) 992 993 F = A[T, *Ts, T2] 994 with self.assertRaises(TypeError): 995 F[()] 996 with self.assertRaises(TypeError): 997 F[float] 998 self.assertEqual(F[float, str], A[float, str]) 999 self.assertEqual(F[float, str, int], A[float, str, int]) 1000 self.assertEqual(F[float, str, int, bytes], A[float, str, int, bytes]) 1001 1002 G = A[T, Unpack[Ts], T2] 1003 with self.assertRaises(TypeError): 1004 G[()] 1005 with self.assertRaises(TypeError): 1006 G[float] 1007 self.assertEqual(G[float, str], A[float, str]) 1008 self.assertEqual(G[float, str, int], A[float, str, int]) 1009 self.assertEqual(G[float, str, int, bytes], A[float, str, int, bytes]) 1010 1011 H = tuple[list[T], A[*Ts], list[T2]] 1012 with self.assertRaises(TypeError): 1013 H[()] 1014 with self.assertRaises(TypeError): 1015 H[float] 1016 if A != Tuple: 1017 self.assertEqual(H[float, str], 1018 tuple[list[float], A[()], list[str]]) 1019 self.assertEqual(H[float, str, int], 1020 tuple[list[float], A[str], list[int]]) 1021 self.assertEqual(H[float, str, int, bytes], 1022 tuple[list[float], A[str, int], list[bytes]]) 1023 1024 I = Tuple[List[T], A[Unpack[Ts]], List[T2]] 1025 with self.assertRaises(TypeError): 1026 I[()] 1027 with self.assertRaises(TypeError): 1028 I[float] 1029 if A != Tuple: 1030 self.assertEqual(I[float, str], 1031 Tuple[List[float], A[()], List[str]]) 1032 self.assertEqual(I[float, str, int], 1033 Tuple[List[float], A[str], List[int]]) 1034 self.assertEqual(I[float, str, int, bytes], 1035 Tuple[List[float], A[str, int], List[bytes]]) 1036 1037 def test_bad_var_substitution(self): 1038 Ts = TypeVarTuple('Ts') 1039 T = TypeVar('T') 1040 T2 = TypeVar('T2') 1041 class G1(Generic[*Ts]): pass 1042 class G2(Generic[Unpack[Ts]]): pass 1043 1044 for A in G1, G2, Tuple, tuple: 1045 B = A[Ts] 1046 with self.assertRaises(TypeError): 1047 B[int, str] 1048 1049 C = A[T, T2] 1050 with self.assertRaises(TypeError): 1051 C[*Ts] 1052 with self.assertRaises(TypeError): 1053 C[Unpack[Ts]] 1054 1055 B = A[T, *Ts, str, T2] 1056 with self.assertRaises(TypeError): 1057 B[int, *Ts] 1058 with self.assertRaises(TypeError): 1059 B[int, *Ts, *Ts] 1060 1061 C = A[T, Unpack[Ts], str, T2] 1062 with self.assertRaises(TypeError): 1063 C[int, Unpack[Ts]] 1064 with self.assertRaises(TypeError): 1065 C[int, Unpack[Ts], Unpack[Ts]] 1066 1067 def test_repr_is_correct(self): 1068 Ts = TypeVarTuple('Ts') 1069 1070 class G1(Generic[*Ts]): pass 1071 class G2(Generic[Unpack[Ts]]): pass 1072 1073 self.assertEqual(repr(Ts), 'Ts') 1074 1075 self.assertEqual(repr((*Ts,)[0]), '*Ts') 1076 self.assertEqual(repr(Unpack[Ts]), '*Ts') 1077 1078 self.assertEqual(repr(tuple[*Ts]), 'tuple[*Ts]') 1079 self.assertEqual(repr(Tuple[Unpack[Ts]]), 'typing.Tuple[*Ts]') 1080 1081 self.assertEqual(repr(*tuple[*Ts]), '*tuple[*Ts]') 1082 self.assertEqual(repr(Unpack[Tuple[Unpack[Ts]]]), '*typing.Tuple[*Ts]') 1083 1084 def test_variadic_class_repr_is_correct(self): 1085 Ts = TypeVarTuple('Ts') 1086 class A(Generic[*Ts]): pass 1087 class B(Generic[Unpack[Ts]]): pass 1088 1089 self.assertEndsWith(repr(A[()]), 'A[()]') 1090 self.assertEndsWith(repr(B[()]), 'B[()]') 1091 self.assertEndsWith(repr(A[float]), 'A[float]') 1092 self.assertEndsWith(repr(B[float]), 'B[float]') 1093 self.assertEndsWith(repr(A[float, str]), 'A[float, str]') 1094 self.assertEndsWith(repr(B[float, str]), 'B[float, str]') 1095 1096 self.assertEndsWith(repr(A[*tuple[int, ...]]), 1097 'A[*tuple[int, ...]]') 1098 self.assertEndsWith(repr(B[Unpack[Tuple[int, ...]]]), 1099 'B[*typing.Tuple[int, ...]]') 1100 1101 self.assertEndsWith(repr(A[float, *tuple[int, ...]]), 1102 'A[float, *tuple[int, ...]]') 1103 self.assertEndsWith(repr(A[float, Unpack[Tuple[int, ...]]]), 1104 'A[float, *typing.Tuple[int, ...]]') 1105 1106 self.assertEndsWith(repr(A[*tuple[int, ...], str]), 1107 'A[*tuple[int, ...], str]') 1108 self.assertEndsWith(repr(B[Unpack[Tuple[int, ...]], str]), 1109 'B[*typing.Tuple[int, ...], str]') 1110 1111 self.assertEndsWith(repr(A[float, *tuple[int, ...], str]), 1112 'A[float, *tuple[int, ...], str]') 1113 self.assertEndsWith(repr(B[float, Unpack[Tuple[int, ...]], str]), 1114 'B[float, *typing.Tuple[int, ...], str]') 1115 1116 def test_variadic_class_alias_repr_is_correct(self): 1117 Ts = TypeVarTuple('Ts') 1118 class A(Generic[Unpack[Ts]]): pass 1119 1120 B = A[*Ts] 1121 self.assertEndsWith(repr(B), 'A[*Ts]') 1122 self.assertEndsWith(repr(B[()]), 'A[()]') 1123 self.assertEndsWith(repr(B[float]), 'A[float]') 1124 self.assertEndsWith(repr(B[float, str]), 'A[float, str]') 1125 1126 C = A[Unpack[Ts]] 1127 self.assertEndsWith(repr(C), 'A[*Ts]') 1128 self.assertEndsWith(repr(C[()]), 'A[()]') 1129 self.assertEndsWith(repr(C[float]), 'A[float]') 1130 self.assertEndsWith(repr(C[float, str]), 'A[float, str]') 1131 1132 D = A[*Ts, int] 1133 self.assertEndsWith(repr(D), 'A[*Ts, int]') 1134 self.assertEndsWith(repr(D[()]), 'A[int]') 1135 self.assertEndsWith(repr(D[float]), 'A[float, int]') 1136 self.assertEndsWith(repr(D[float, str]), 'A[float, str, int]') 1137 1138 E = A[Unpack[Ts], int] 1139 self.assertEndsWith(repr(E), 'A[*Ts, int]') 1140 self.assertEndsWith(repr(E[()]), 'A[int]') 1141 self.assertEndsWith(repr(E[float]), 'A[float, int]') 1142 self.assertEndsWith(repr(E[float, str]), 'A[float, str, int]') 1143 1144 F = A[int, *Ts] 1145 self.assertEndsWith(repr(F), 'A[int, *Ts]') 1146 self.assertEndsWith(repr(F[()]), 'A[int]') 1147 self.assertEndsWith(repr(F[float]), 'A[int, float]') 1148 self.assertEndsWith(repr(F[float, str]), 'A[int, float, str]') 1149 1150 G = A[int, Unpack[Ts]] 1151 self.assertEndsWith(repr(G), 'A[int, *Ts]') 1152 self.assertEndsWith(repr(G[()]), 'A[int]') 1153 self.assertEndsWith(repr(G[float]), 'A[int, float]') 1154 self.assertEndsWith(repr(G[float, str]), 'A[int, float, str]') 1155 1156 H = A[int, *Ts, str] 1157 self.assertEndsWith(repr(H), 'A[int, *Ts, str]') 1158 self.assertEndsWith(repr(H[()]), 'A[int, str]') 1159 self.assertEndsWith(repr(H[float]), 'A[int, float, str]') 1160 self.assertEndsWith(repr(H[float, str]), 'A[int, float, str, str]') 1161 1162 I = A[int, Unpack[Ts], str] 1163 self.assertEndsWith(repr(I), 'A[int, *Ts, str]') 1164 self.assertEndsWith(repr(I[()]), 'A[int, str]') 1165 self.assertEndsWith(repr(I[float]), 'A[int, float, str]') 1166 self.assertEndsWith(repr(I[float, str]), 'A[int, float, str, str]') 1167 1168 J = A[*Ts, *tuple[str, ...]] 1169 self.assertEndsWith(repr(J), 'A[*Ts, *tuple[str, ...]]') 1170 self.assertEndsWith(repr(J[()]), 'A[*tuple[str, ...]]') 1171 self.assertEndsWith(repr(J[float]), 'A[float, *tuple[str, ...]]') 1172 self.assertEndsWith(repr(J[float, str]), 'A[float, str, *tuple[str, ...]]') 1173 1174 K = A[Unpack[Ts], Unpack[Tuple[str, ...]]] 1175 self.assertEndsWith(repr(K), 'A[*Ts, *typing.Tuple[str, ...]]') 1176 self.assertEndsWith(repr(K[()]), 'A[*typing.Tuple[str, ...]]') 1177 self.assertEndsWith(repr(K[float]), 'A[float, *typing.Tuple[str, ...]]') 1178 self.assertEndsWith(repr(K[float, str]), 'A[float, str, *typing.Tuple[str, ...]]') 1179 1180 def test_cannot_subclass_class(self): 1181 with self.assertRaises(TypeError): 1182 class C(TypeVarTuple): pass 1183 1184 def test_cannot_subclass_instance(self): 1185 Ts = TypeVarTuple('Ts') 1186 with self.assertRaises(TypeError): 1187 class C(Ts): pass 1188 with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): 1189 class C(type(Unpack)): pass 1190 with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): 1191 class C(type(*Ts)): pass 1192 with self.assertRaisesRegex(TypeError, CANNOT_SUBCLASS_TYPE): 1193 class C(type(Unpack[Ts])): pass 1194 with self.assertRaisesRegex(TypeError, 1195 r'Cannot subclass typing\.Unpack'): 1196 class C(Unpack): pass 1197 with self.assertRaisesRegex(TypeError, r'Cannot subclass \*Ts'): 1198 class C(*Ts): pass 1199 with self.assertRaisesRegex(TypeError, r'Cannot subclass \*Ts'): 1200 class C(Unpack[Ts]): pass 1201 1202 def test_variadic_class_args_are_correct(self): 1203 T = TypeVar('T') 1204 Ts = TypeVarTuple('Ts') 1205 class A(Generic[*Ts]): pass 1206 class B(Generic[Unpack[Ts]]): pass 1207 1208 C = A[()] 1209 D = B[()] 1210 self.assertEqual(C.__args__, ()) 1211 self.assertEqual(D.__args__, ()) 1212 1213 E = A[int] 1214 F = B[int] 1215 self.assertEqual(E.__args__, (int,)) 1216 self.assertEqual(F.__args__, (int,)) 1217 1218 G = A[int, str] 1219 H = B[int, str] 1220 self.assertEqual(G.__args__, (int, str)) 1221 self.assertEqual(H.__args__, (int, str)) 1222 1223 I = A[T] 1224 J = B[T] 1225 self.assertEqual(I.__args__, (T,)) 1226 self.assertEqual(J.__args__, (T,)) 1227 1228 K = A[*Ts] 1229 L = B[Unpack[Ts]] 1230 self.assertEqual(K.__args__, (*Ts,)) 1231 self.assertEqual(L.__args__, (Unpack[Ts],)) 1232 1233 M = A[T, *Ts] 1234 N = B[T, Unpack[Ts]] 1235 self.assertEqual(M.__args__, (T, *Ts)) 1236 self.assertEqual(N.__args__, (T, Unpack[Ts])) 1237 1238 O = A[*Ts, T] 1239 P = B[Unpack[Ts], T] 1240 self.assertEqual(O.__args__, (*Ts, T)) 1241 self.assertEqual(P.__args__, (Unpack[Ts], T)) 1242 1243 def test_variadic_class_origin_is_correct(self): 1244 Ts = TypeVarTuple('Ts') 1245 1246 class C(Generic[*Ts]): pass 1247 self.assertIs(C[int].__origin__, C) 1248 self.assertIs(C[T].__origin__, C) 1249 self.assertIs(C[Unpack[Ts]].__origin__, C) 1250 1251 class D(Generic[Unpack[Ts]]): pass 1252 self.assertIs(D[int].__origin__, D) 1253 self.assertIs(D[T].__origin__, D) 1254 self.assertIs(D[Unpack[Ts]].__origin__, D) 1255 1256 def test_get_type_hints_on_unpack_args(self): 1257 Ts = TypeVarTuple('Ts') 1258 1259 def func1(*args: *Ts): pass 1260 self.assertEqual(gth(func1), {'args': Unpack[Ts]}) 1261 1262 def func2(*args: *tuple[int, str]): pass 1263 self.assertEqual(gth(func2), {'args': Unpack[tuple[int, str]]}) 1264 1265 class CustomVariadic(Generic[*Ts]): pass 1266 1267 def func3(*args: *CustomVariadic[int, str]): pass 1268 self.assertEqual(gth(func3), {'args': Unpack[CustomVariadic[int, str]]}) 1269 1270 def test_get_type_hints_on_unpack_args_string(self): 1271 Ts = TypeVarTuple('Ts') 1272 1273 def func1(*args: '*Ts'): pass 1274 self.assertEqual(gth(func1, localns={'Ts': Ts}), 1275 {'args': Unpack[Ts]}) 1276 1277 def func2(*args: '*tuple[int, str]'): pass 1278 self.assertEqual(gth(func2), {'args': Unpack[tuple[int, str]]}) 1279 1280 class CustomVariadic(Generic[*Ts]): pass 1281 1282 def func3(*args: '*CustomVariadic[int, str]'): pass 1283 self.assertEqual(gth(func3, localns={'CustomVariadic': CustomVariadic}), 1284 {'args': Unpack[CustomVariadic[int, str]]}) 1285 1286 def test_tuple_args_are_correct(self): 1287 Ts = TypeVarTuple('Ts') 1288 1289 self.assertEqual(tuple[*Ts].__args__, (*Ts,)) 1290 self.assertEqual(Tuple[Unpack[Ts]].__args__, (Unpack[Ts],)) 1291 1292 self.assertEqual(tuple[*Ts, int].__args__, (*Ts, int)) 1293 self.assertEqual(Tuple[Unpack[Ts], int].__args__, (Unpack[Ts], int)) 1294 1295 self.assertEqual(tuple[int, *Ts].__args__, (int, *Ts)) 1296 self.assertEqual(Tuple[int, Unpack[Ts]].__args__, (int, Unpack[Ts])) 1297 1298 self.assertEqual(tuple[int, *Ts, str].__args__, 1299 (int, *Ts, str)) 1300 self.assertEqual(Tuple[int, Unpack[Ts], str].__args__, 1301 (int, Unpack[Ts], str)) 1302 1303 self.assertEqual(tuple[*Ts, int].__args__, (*Ts, int)) 1304 self.assertEqual(Tuple[Unpack[Ts]].__args__, (Unpack[Ts],)) 1305 1306 def test_callable_args_are_correct(self): 1307 Ts = TypeVarTuple('Ts') 1308 Ts1 = TypeVarTuple('Ts1') 1309 Ts2 = TypeVarTuple('Ts2') 1310 1311 # TypeVarTuple in the arguments 1312 1313 a = Callable[[*Ts], None] 1314 b = Callable[[Unpack[Ts]], None] 1315 self.assertEqual(a.__args__, (*Ts, type(None))) 1316 self.assertEqual(b.__args__, (Unpack[Ts], type(None))) 1317 1318 c = Callable[[int, *Ts], None] 1319 d = Callable[[int, Unpack[Ts]], None] 1320 self.assertEqual(c.__args__, (int, *Ts, type(None))) 1321 self.assertEqual(d.__args__, (int, Unpack[Ts], type(None))) 1322 1323 e = Callable[[*Ts, int], None] 1324 f = Callable[[Unpack[Ts], int], None] 1325 self.assertEqual(e.__args__, (*Ts, int, type(None))) 1326 self.assertEqual(f.__args__, (Unpack[Ts], int, type(None))) 1327 1328 g = Callable[[str, *Ts, int], None] 1329 h = Callable[[str, Unpack[Ts], int], None] 1330 self.assertEqual(g.__args__, (str, *Ts, int, type(None))) 1331 self.assertEqual(h.__args__, (str, Unpack[Ts], int, type(None))) 1332 1333 # TypeVarTuple as the return 1334 1335 i = Callable[[None], *Ts] 1336 j = Callable[[None], Unpack[Ts]] 1337 self.assertEqual(i.__args__, (type(None), *Ts)) 1338 self.assertEqual(j.__args__, (type(None), Unpack[Ts])) 1339 1340 k = Callable[[None], tuple[int, *Ts]] 1341 l = Callable[[None], Tuple[int, Unpack[Ts]]] 1342 self.assertEqual(k.__args__, (type(None), tuple[int, *Ts])) 1343 self.assertEqual(l.__args__, (type(None), Tuple[int, Unpack[Ts]])) 1344 1345 m = Callable[[None], tuple[*Ts, int]] 1346 n = Callable[[None], Tuple[Unpack[Ts], int]] 1347 self.assertEqual(m.__args__, (type(None), tuple[*Ts, int])) 1348 self.assertEqual(n.__args__, (type(None), Tuple[Unpack[Ts], int])) 1349 1350 o = Callable[[None], tuple[str, *Ts, int]] 1351 p = Callable[[None], Tuple[str, Unpack[Ts], int]] 1352 self.assertEqual(o.__args__, (type(None), tuple[str, *Ts, int])) 1353 self.assertEqual(p.__args__, (type(None), Tuple[str, Unpack[Ts], int])) 1354 1355 # TypeVarTuple in both 1356 1357 q = Callable[[*Ts], *Ts] 1358 r = Callable[[Unpack[Ts]], Unpack[Ts]] 1359 self.assertEqual(q.__args__, (*Ts, *Ts)) 1360 self.assertEqual(r.__args__, (Unpack[Ts], Unpack[Ts])) 1361 1362 s = Callable[[*Ts1], *Ts2] 1363 u = Callable[[Unpack[Ts1]], Unpack[Ts2]] 1364 self.assertEqual(s.__args__, (*Ts1, *Ts2)) 1365 self.assertEqual(u.__args__, (Unpack[Ts1], Unpack[Ts2])) 1366 1367 def test_variadic_class_with_duplicate_typevartuples_fails(self): 1368 Ts1 = TypeVarTuple('Ts1') 1369 Ts2 = TypeVarTuple('Ts2') 1370 1371 with self.assertRaises(TypeError): 1372 class C(Generic[*Ts1, *Ts1]): pass 1373 with self.assertRaises(TypeError): 1374 class C(Generic[Unpack[Ts1], Unpack[Ts1]]): pass 1375 1376 with self.assertRaises(TypeError): 1377 class C(Generic[*Ts1, *Ts2, *Ts1]): pass 1378 with self.assertRaises(TypeError): 1379 class C(Generic[Unpack[Ts1], Unpack[Ts2], Unpack[Ts1]]): pass 1380 1381 def test_type_concatenation_in_variadic_class_argument_list_succeeds(self): 1382 Ts = TypeVarTuple('Ts') 1383 class C(Generic[Unpack[Ts]]): pass 1384 1385 C[int, *Ts] 1386 C[int, Unpack[Ts]] 1387 1388 C[*Ts, int] 1389 C[Unpack[Ts], int] 1390 1391 C[int, *Ts, str] 1392 C[int, Unpack[Ts], str] 1393 1394 C[int, bool, *Ts, float, str] 1395 C[int, bool, Unpack[Ts], float, str] 1396 1397 def test_type_concatenation_in_tuple_argument_list_succeeds(self): 1398 Ts = TypeVarTuple('Ts') 1399 1400 tuple[int, *Ts] 1401 tuple[*Ts, int] 1402 tuple[int, *Ts, str] 1403 tuple[int, bool, *Ts, float, str] 1404 1405 Tuple[int, Unpack[Ts]] 1406 Tuple[Unpack[Ts], int] 1407 Tuple[int, Unpack[Ts], str] 1408 Tuple[int, bool, Unpack[Ts], float, str] 1409 1410 def test_variadic_class_definition_using_packed_typevartuple_fails(self): 1411 Ts = TypeVarTuple('Ts') 1412 with self.assertRaises(TypeError): 1413 class C(Generic[Ts]): pass 1414 1415 def test_variadic_class_definition_using_concrete_types_fails(self): 1416 Ts = TypeVarTuple('Ts') 1417 with self.assertRaises(TypeError): 1418 class F(Generic[*Ts, int]): pass 1419 with self.assertRaises(TypeError): 1420 class E(Generic[Unpack[Ts], int]): pass 1421 1422 def test_variadic_class_with_2_typevars_accepts_2_or_more_args(self): 1423 Ts = TypeVarTuple('Ts') 1424 T1 = TypeVar('T1') 1425 T2 = TypeVar('T2') 1426 1427 class A(Generic[T1, T2, *Ts]): pass 1428 A[int, str] 1429 A[int, str, float] 1430 A[int, str, float, bool] 1431 1432 class B(Generic[T1, T2, Unpack[Ts]]): pass 1433 B[int, str] 1434 B[int, str, float] 1435 B[int, str, float, bool] 1436 1437 class C(Generic[T1, *Ts, T2]): pass 1438 C[int, str] 1439 C[int, str, float] 1440 C[int, str, float, bool] 1441 1442 class D(Generic[T1, Unpack[Ts], T2]): pass 1443 D[int, str] 1444 D[int, str, float] 1445 D[int, str, float, bool] 1446 1447 class E(Generic[*Ts, T1, T2]): pass 1448 E[int, str] 1449 E[int, str, float] 1450 E[int, str, float, bool] 1451 1452 class F(Generic[Unpack[Ts], T1, T2]): pass 1453 F[int, str] 1454 F[int, str, float] 1455 F[int, str, float, bool] 1456 1457 def test_variadic_args_annotations_are_correct(self): 1458 Ts = TypeVarTuple('Ts') 1459 1460 def f(*args: Unpack[Ts]): pass 1461 def g(*args: *Ts): pass 1462 self.assertEqual(f.__annotations__, {'args': Unpack[Ts]}) 1463 self.assertEqual(g.__annotations__, {'args': (*Ts,)[0]}) 1464 1465 def test_variadic_args_with_ellipsis_annotations_are_correct(self): 1466 def a(*args: *tuple[int, ...]): pass 1467 self.assertEqual(a.__annotations__, 1468 {'args': (*tuple[int, ...],)[0]}) 1469 1470 def b(*args: Unpack[Tuple[int, ...]]): pass 1471 self.assertEqual(b.__annotations__, 1472 {'args': Unpack[Tuple[int, ...]]}) 1473 1474 def test_concatenation_in_variadic_args_annotations_are_correct(self): 1475 Ts = TypeVarTuple('Ts') 1476 1477 # Unpacking using `*`, native `tuple` type 1478 1479 def a(*args: *tuple[int, *Ts]): pass 1480 self.assertEqual( 1481 a.__annotations__, 1482 {'args': (*tuple[int, *Ts],)[0]}, 1483 ) 1484 1485 def b(*args: *tuple[*Ts, int]): pass 1486 self.assertEqual( 1487 b.__annotations__, 1488 {'args': (*tuple[*Ts, int],)[0]}, 1489 ) 1490 1491 def c(*args: *tuple[str, *Ts, int]): pass 1492 self.assertEqual( 1493 c.__annotations__, 1494 {'args': (*tuple[str, *Ts, int],)[0]}, 1495 ) 1496 1497 def d(*args: *tuple[int, bool, *Ts, float, str]): pass 1498 self.assertEqual( 1499 d.__annotations__, 1500 {'args': (*tuple[int, bool, *Ts, float, str],)[0]}, 1501 ) 1502 1503 # Unpacking using `Unpack`, `Tuple` type from typing.py 1504 1505 def e(*args: Unpack[Tuple[int, Unpack[Ts]]]): pass 1506 self.assertEqual( 1507 e.__annotations__, 1508 {'args': Unpack[Tuple[int, Unpack[Ts]]]}, 1509 ) 1510 1511 def f(*args: Unpack[Tuple[Unpack[Ts], int]]): pass 1512 self.assertEqual( 1513 f.__annotations__, 1514 {'args': Unpack[Tuple[Unpack[Ts], int]]}, 1515 ) 1516 1517 def g(*args: Unpack[Tuple[str, Unpack[Ts], int]]): pass 1518 self.assertEqual( 1519 g.__annotations__, 1520 {'args': Unpack[Tuple[str, Unpack[Ts], int]]}, 1521 ) 1522 1523 def h(*args: Unpack[Tuple[int, bool, Unpack[Ts], float, str]]): pass 1524 self.assertEqual( 1525 h.__annotations__, 1526 {'args': Unpack[Tuple[int, bool, Unpack[Ts], float, str]]}, 1527 ) 1528 1529 def test_variadic_class_same_args_results_in_equalty(self): 1530 Ts = TypeVarTuple('Ts') 1531 class C(Generic[*Ts]): pass 1532 class D(Generic[Unpack[Ts]]): pass 1533 1534 self.assertEqual(C[int], C[int]) 1535 self.assertEqual(D[int], D[int]) 1536 1537 Ts1 = TypeVarTuple('Ts1') 1538 Ts2 = TypeVarTuple('Ts2') 1539 1540 self.assertEqual( 1541 C[*Ts1], 1542 C[*Ts1], 1543 ) 1544 self.assertEqual( 1545 D[Unpack[Ts1]], 1546 D[Unpack[Ts1]], 1547 ) 1548 1549 self.assertEqual( 1550 C[*Ts1, *Ts2], 1551 C[*Ts1, *Ts2], 1552 ) 1553 self.assertEqual( 1554 D[Unpack[Ts1], Unpack[Ts2]], 1555 D[Unpack[Ts1], Unpack[Ts2]], 1556 ) 1557 1558 self.assertEqual( 1559 C[int, *Ts1, *Ts2], 1560 C[int, *Ts1, *Ts2], 1561 ) 1562 self.assertEqual( 1563 D[int, Unpack[Ts1], Unpack[Ts2]], 1564 D[int, Unpack[Ts1], Unpack[Ts2]], 1565 ) 1566 1567 def test_variadic_class_arg_ordering_matters(self): 1568 Ts = TypeVarTuple('Ts') 1569 class C(Generic[*Ts]): pass 1570 class D(Generic[Unpack[Ts]]): pass 1571 1572 self.assertNotEqual( 1573 C[int, str], 1574 C[str, int], 1575 ) 1576 self.assertNotEqual( 1577 D[int, str], 1578 D[str, int], 1579 ) 1580 1581 Ts1 = TypeVarTuple('Ts1') 1582 Ts2 = TypeVarTuple('Ts2') 1583 1584 self.assertNotEqual( 1585 C[*Ts1, *Ts2], 1586 C[*Ts2, *Ts1], 1587 ) 1588 self.assertNotEqual( 1589 D[Unpack[Ts1], Unpack[Ts2]], 1590 D[Unpack[Ts2], Unpack[Ts1]], 1591 ) 1592 1593 def test_variadic_class_arg_typevartuple_identity_matters(self): 1594 Ts = TypeVarTuple('Ts') 1595 Ts1 = TypeVarTuple('Ts1') 1596 Ts2 = TypeVarTuple('Ts2') 1597 1598 class C(Generic[*Ts]): pass 1599 class D(Generic[Unpack[Ts]]): pass 1600 1601 self.assertNotEqual(C[*Ts1], C[*Ts2]) 1602 self.assertNotEqual(D[Unpack[Ts1]], D[Unpack[Ts2]]) 1603 1604 1605class TypeVarTuplePicklingTests(BaseTestCase): 1606 # These are slightly awkward tests to run, because TypeVarTuples are only 1607 # picklable if defined in the global scope. We therefore need to push 1608 # various things defined in these tests into the global scope with `global` 1609 # statements at the start of each test. 1610 1611 @all_pickle_protocols 1612 def test_pickling_then_unpickling_results_in_same_identity(self, proto): 1613 global global_Ts1 # See explanation at start of class. 1614 global_Ts1 = TypeVarTuple('global_Ts1') 1615 global_Ts2 = pickle.loads(pickle.dumps(global_Ts1, proto)) 1616 self.assertIs(global_Ts1, global_Ts2) 1617 1618 @all_pickle_protocols 1619 def test_pickling_then_unpickling_unpacked_results_in_same_identity(self, proto): 1620 global global_Ts # See explanation at start of class. 1621 global_Ts = TypeVarTuple('global_Ts') 1622 1623 unpacked1 = (*global_Ts,)[0] 1624 unpacked2 = pickle.loads(pickle.dumps(unpacked1, proto)) 1625 self.assertIs(unpacked1, unpacked2) 1626 1627 unpacked3 = Unpack[global_Ts] 1628 unpacked4 = pickle.loads(pickle.dumps(unpacked3, proto)) 1629 self.assertIs(unpacked3, unpacked4) 1630 1631 @all_pickle_protocols 1632 def test_pickling_then_unpickling_tuple_with_typevartuple_equality( 1633 self, proto 1634 ): 1635 global global_T, global_Ts # See explanation at start of class. 1636 global_T = TypeVar('global_T') 1637 global_Ts = TypeVarTuple('global_Ts') 1638 1639 tuples = [ 1640 tuple[*global_Ts], 1641 Tuple[Unpack[global_Ts]], 1642 1643 tuple[T, *global_Ts], 1644 Tuple[T, Unpack[global_Ts]], 1645 1646 tuple[int, *global_Ts], 1647 Tuple[int, Unpack[global_Ts]], 1648 ] 1649 for t in tuples: 1650 t2 = pickle.loads(pickle.dumps(t, proto)) 1651 self.assertEqual(t, t2) 1652 1653 1654class UnionTests(BaseTestCase): 1655 1656 def test_basics(self): 1657 u = Union[int, float] 1658 self.assertNotEqual(u, Union) 1659 1660 def test_subclass_error(self): 1661 with self.assertRaises(TypeError): 1662 issubclass(int, Union) 1663 with self.assertRaises(TypeError): 1664 issubclass(Union, int) 1665 with self.assertRaises(TypeError): 1666 issubclass(Union[int, str], int) 1667 1668 def test_union_any(self): 1669 u = Union[Any] 1670 self.assertEqual(u, Any) 1671 u1 = Union[int, Any] 1672 u2 = Union[Any, int] 1673 u3 = Union[Any, object] 1674 self.assertEqual(u1, u2) 1675 self.assertNotEqual(u1, Any) 1676 self.assertNotEqual(u2, Any) 1677 self.assertNotEqual(u3, Any) 1678 1679 def test_union_object(self): 1680 u = Union[object] 1681 self.assertEqual(u, object) 1682 u1 = Union[int, object] 1683 u2 = Union[object, int] 1684 self.assertEqual(u1, u2) 1685 self.assertNotEqual(u1, object) 1686 self.assertNotEqual(u2, object) 1687 1688 def test_unordered(self): 1689 u1 = Union[int, float] 1690 u2 = Union[float, int] 1691 self.assertEqual(u1, u2) 1692 1693 def test_single_class_disappears(self): 1694 t = Union[Employee] 1695 self.assertIs(t, Employee) 1696 1697 def test_base_class_kept(self): 1698 u = Union[Employee, Manager] 1699 self.assertNotEqual(u, Employee) 1700 self.assertIn(Employee, u.__args__) 1701 self.assertIn(Manager, u.__args__) 1702 1703 def test_union_union(self): 1704 u = Union[int, float] 1705 v = Union[u, Employee] 1706 self.assertEqual(v, Union[int, float, Employee]) 1707 1708 def test_repr(self): 1709 self.assertEqual(repr(Union), 'typing.Union') 1710 u = Union[Employee, int] 1711 self.assertEqual(repr(u), 'typing.Union[%s.Employee, int]' % __name__) 1712 u = Union[int, Employee] 1713 self.assertEqual(repr(u), 'typing.Union[int, %s.Employee]' % __name__) 1714 T = TypeVar('T') 1715 u = Union[T, int][int] 1716 self.assertEqual(repr(u), repr(int)) 1717 u = Union[List[int], int] 1718 self.assertEqual(repr(u), 'typing.Union[typing.List[int], int]') 1719 u = Union[list[int], dict[str, float]] 1720 self.assertEqual(repr(u), 'typing.Union[list[int], dict[str, float]]') 1721 u = Union[int | float] 1722 self.assertEqual(repr(u), 'typing.Union[int, float]') 1723 1724 u = Union[None, str] 1725 self.assertEqual(repr(u), 'typing.Optional[str]') 1726 u = Union[str, None] 1727 self.assertEqual(repr(u), 'typing.Optional[str]') 1728 u = Union[None, str, int] 1729 self.assertEqual(repr(u), 'typing.Union[NoneType, str, int]') 1730 u = Optional[str] 1731 self.assertEqual(repr(u), 'typing.Optional[str]') 1732 1733 def test_dir(self): 1734 dir_items = set(dir(Union[str, int])) 1735 for required_item in [ 1736 '__args__', '__parameters__', '__origin__', 1737 ]: 1738 with self.subTest(required_item=required_item): 1739 self.assertIn(required_item, dir_items) 1740 1741 def test_cannot_subclass(self): 1742 with self.assertRaises(TypeError): 1743 class C(Union): 1744 pass 1745 with self.assertRaises(TypeError): 1746 class C(type(Union)): 1747 pass 1748 with self.assertRaises(TypeError): 1749 class C(Union[int, str]): 1750 pass 1751 1752 def test_cannot_instantiate(self): 1753 with self.assertRaises(TypeError): 1754 Union() 1755 with self.assertRaises(TypeError): 1756 type(Union)() 1757 u = Union[int, float] 1758 with self.assertRaises(TypeError): 1759 u() 1760 with self.assertRaises(TypeError): 1761 type(u)() 1762 1763 def test_union_generalization(self): 1764 self.assertFalse(Union[str, typing.Iterable[int]] == str) 1765 self.assertFalse(Union[str, typing.Iterable[int]] == typing.Iterable[int]) 1766 self.assertIn(str, Union[str, typing.Iterable[int]].__args__) 1767 self.assertIn(typing.Iterable[int], Union[str, typing.Iterable[int]].__args__) 1768 1769 def test_union_compare_other(self): 1770 self.assertNotEqual(Union, object) 1771 self.assertNotEqual(Union, Any) 1772 self.assertNotEqual(ClassVar, Union) 1773 self.assertNotEqual(Optional, Union) 1774 self.assertNotEqual([None], Optional) 1775 self.assertNotEqual(Optional, typing.Mapping) 1776 self.assertNotEqual(Optional[typing.MutableMapping], Union) 1777 1778 def test_optional(self): 1779 o = Optional[int] 1780 u = Union[int, None] 1781 self.assertEqual(o, u) 1782 1783 def test_empty(self): 1784 with self.assertRaises(TypeError): 1785 Union[()] 1786 1787 def test_no_eval_union(self): 1788 u = Union[int, str] 1789 def f(x: u): ... 1790 self.assertIs(get_type_hints(f)['x'], u) 1791 1792 def test_function_repr_union(self): 1793 def fun() -> int: ... 1794 self.assertEqual(repr(Union[fun, int]), 'typing.Union[fun, int]') 1795 1796 def test_union_str_pattern(self): 1797 # Shouldn't crash; see http://bugs.python.org/issue25390 1798 A = Union[str, Pattern] 1799 A 1800 1801 def test_etree(self): 1802 # See https://github.com/python/typing/issues/229 1803 # (Only relevant for Python 2.) 1804 from xml.etree.ElementTree import Element 1805 1806 Union[Element, str] # Shouldn't crash 1807 1808 def Elem(*args): 1809 return Element(*args) 1810 1811 Union[Elem, str] # Nor should this 1812 1813 def test_union_of_literals(self): 1814 self.assertEqual(Union[Literal[1], Literal[2]].__args__, 1815 (Literal[1], Literal[2])) 1816 self.assertEqual(Union[Literal[1], Literal[1]], 1817 Literal[1]) 1818 1819 self.assertEqual(Union[Literal[False], Literal[0]].__args__, 1820 (Literal[False], Literal[0])) 1821 self.assertEqual(Union[Literal[True], Literal[1]].__args__, 1822 (Literal[True], Literal[1])) 1823 1824 import enum 1825 class Ints(enum.IntEnum): 1826 A = 0 1827 B = 1 1828 1829 self.assertEqual(Union[Literal[Ints.A], Literal[Ints.A]], 1830 Literal[Ints.A]) 1831 self.assertEqual(Union[Literal[Ints.B], Literal[Ints.B]], 1832 Literal[Ints.B]) 1833 1834 self.assertEqual(Union[Literal[Ints.A], Literal[Ints.B]].__args__, 1835 (Literal[Ints.A], Literal[Ints.B])) 1836 1837 self.assertEqual(Union[Literal[0], Literal[Ints.A], Literal[False]].__args__, 1838 (Literal[0], Literal[Ints.A], Literal[False])) 1839 self.assertEqual(Union[Literal[1], Literal[Ints.B], Literal[True]].__args__, 1840 (Literal[1], Literal[Ints.B], Literal[True])) 1841 1842 1843class TupleTests(BaseTestCase): 1844 1845 def test_basics(self): 1846 with self.assertRaises(TypeError): 1847 issubclass(Tuple, Tuple[int, str]) 1848 with self.assertRaises(TypeError): 1849 issubclass(tuple, Tuple[int, str]) 1850 1851 class TP(tuple): ... 1852 self.assertIsSubclass(tuple, Tuple) 1853 self.assertIsSubclass(TP, Tuple) 1854 1855 def test_equality(self): 1856 self.assertEqual(Tuple[int], Tuple[int]) 1857 self.assertEqual(Tuple[int, ...], Tuple[int, ...]) 1858 self.assertNotEqual(Tuple[int], Tuple[int, int]) 1859 self.assertNotEqual(Tuple[int], Tuple[int, ...]) 1860 1861 def test_tuple_subclass(self): 1862 class MyTuple(tuple): 1863 pass 1864 self.assertIsSubclass(MyTuple, Tuple) 1865 self.assertIsSubclass(Tuple, Tuple) 1866 self.assertIsSubclass(tuple, Tuple) 1867 1868 def test_tuple_instance_type_error(self): 1869 with self.assertRaises(TypeError): 1870 isinstance((0, 0), Tuple[int, int]) 1871 self.assertIsInstance((0, 0), Tuple) 1872 1873 def test_repr(self): 1874 self.assertEqual(repr(Tuple), 'typing.Tuple') 1875 self.assertEqual(repr(Tuple[()]), 'typing.Tuple[()]') 1876 self.assertEqual(repr(Tuple[int, float]), 'typing.Tuple[int, float]') 1877 self.assertEqual(repr(Tuple[int, ...]), 'typing.Tuple[int, ...]') 1878 self.assertEqual(repr(Tuple[list[int]]), 'typing.Tuple[list[int]]') 1879 1880 def test_errors(self): 1881 with self.assertRaises(TypeError): 1882 issubclass(42, Tuple) 1883 with self.assertRaises(TypeError): 1884 issubclass(42, Tuple[int]) 1885 1886 1887class BaseCallableTests: 1888 1889 def test_self_subclass(self): 1890 Callable = self.Callable 1891 with self.assertRaises(TypeError): 1892 issubclass(types.FunctionType, Callable[[int], int]) 1893 self.assertIsSubclass(types.FunctionType, Callable) 1894 self.assertIsSubclass(Callable, Callable) 1895 1896 def test_eq_hash(self): 1897 Callable = self.Callable 1898 C = Callable[[int], int] 1899 self.assertEqual(C, Callable[[int], int]) 1900 self.assertEqual(len({C, Callable[[int], int]}), 1) 1901 self.assertNotEqual(C, Callable[[int], str]) 1902 self.assertNotEqual(C, Callable[[str], int]) 1903 self.assertNotEqual(C, Callable[[int, int], int]) 1904 self.assertNotEqual(C, Callable[[], int]) 1905 self.assertNotEqual(C, Callable[..., int]) 1906 self.assertNotEqual(C, Callable) 1907 1908 def test_dir(self): 1909 Callable = self.Callable 1910 dir_items = set(dir(Callable[..., int])) 1911 for required_item in [ 1912 '__args__', '__parameters__', '__origin__', 1913 ]: 1914 with self.subTest(required_item=required_item): 1915 self.assertIn(required_item, dir_items) 1916 1917 def test_cannot_instantiate(self): 1918 Callable = self.Callable 1919 with self.assertRaises(TypeError): 1920 Callable() 1921 with self.assertRaises(TypeError): 1922 type(Callable)() 1923 c = Callable[[int], str] 1924 with self.assertRaises(TypeError): 1925 c() 1926 with self.assertRaises(TypeError): 1927 type(c)() 1928 1929 def test_callable_wrong_forms(self): 1930 Callable = self.Callable 1931 with self.assertRaises(TypeError): 1932 Callable[int] 1933 1934 def test_callable_instance_works(self): 1935 Callable = self.Callable 1936 def f(): 1937 pass 1938 self.assertIsInstance(f, Callable) 1939 self.assertNotIsInstance(None, Callable) 1940 1941 def test_callable_instance_type_error(self): 1942 Callable = self.Callable 1943 def f(): 1944 pass 1945 with self.assertRaises(TypeError): 1946 self.assertIsInstance(f, Callable[[], None]) 1947 with self.assertRaises(TypeError): 1948 self.assertIsInstance(f, Callable[[], Any]) 1949 with self.assertRaises(TypeError): 1950 self.assertNotIsInstance(None, Callable[[], None]) 1951 with self.assertRaises(TypeError): 1952 self.assertNotIsInstance(None, Callable[[], Any]) 1953 1954 def test_repr(self): 1955 Callable = self.Callable 1956 fullname = f'{Callable.__module__}.Callable' 1957 ct0 = Callable[[], bool] 1958 self.assertEqual(repr(ct0), f'{fullname}[[], bool]') 1959 ct2 = Callable[[str, float], int] 1960 self.assertEqual(repr(ct2), f'{fullname}[[str, float], int]') 1961 ctv = Callable[..., str] 1962 self.assertEqual(repr(ctv), f'{fullname}[..., str]') 1963 ct3 = Callable[[str, float], list[int]] 1964 self.assertEqual(repr(ct3), f'{fullname}[[str, float], list[int]]') 1965 1966 def test_callable_with_ellipsis(self): 1967 Callable = self.Callable 1968 def foo(a: Callable[..., T]): 1969 pass 1970 1971 self.assertEqual(get_type_hints(foo, globals(), locals()), 1972 {'a': Callable[..., T]}) 1973 1974 def test_ellipsis_in_generic(self): 1975 Callable = self.Callable 1976 # Shouldn't crash; see https://github.com/python/typing/issues/259 1977 typing.List[Callable[..., str]] 1978 1979 def test_or_and_ror(self): 1980 Callable = self.Callable 1981 self.assertEqual(Callable | Tuple, Union[Callable, Tuple]) 1982 self.assertEqual(Tuple | Callable, Union[Tuple, Callable]) 1983 1984 def test_basic(self): 1985 Callable = self.Callable 1986 alias = Callable[[int, str], float] 1987 if Callable is collections.abc.Callable: 1988 self.assertIsInstance(alias, types.GenericAlias) 1989 self.assertIs(alias.__origin__, collections.abc.Callable) 1990 self.assertEqual(alias.__args__, (int, str, float)) 1991 self.assertEqual(alias.__parameters__, ()) 1992 1993 def test_weakref(self): 1994 Callable = self.Callable 1995 alias = Callable[[int, str], float] 1996 self.assertEqual(weakref.ref(alias)(), alias) 1997 1998 def test_pickle(self): 1999 global T_pickle, P_pickle, TS_pickle # needed for pickling 2000 Callable = self.Callable 2001 T_pickle = TypeVar('T_pickle') 2002 P_pickle = ParamSpec('P_pickle') 2003 TS_pickle = TypeVarTuple('TS_pickle') 2004 2005 samples = [ 2006 Callable[[int, str], float], 2007 Callable[P_pickle, int], 2008 Callable[P_pickle, T_pickle], 2009 Callable[Concatenate[int, P_pickle], int], 2010 Callable[Concatenate[*TS_pickle, P_pickle], int], 2011 ] 2012 for alias in samples: 2013 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 2014 with self.subTest(alias=alias, proto=proto): 2015 s = pickle.dumps(alias, proto) 2016 loaded = pickle.loads(s) 2017 self.assertEqual(alias.__origin__, loaded.__origin__) 2018 self.assertEqual(alias.__args__, loaded.__args__) 2019 self.assertEqual(alias.__parameters__, loaded.__parameters__) 2020 2021 del T_pickle, P_pickle, TS_pickle # cleaning up global state 2022 2023 def test_var_substitution(self): 2024 Callable = self.Callable 2025 fullname = f"{Callable.__module__}.Callable" 2026 C1 = Callable[[int, T], T] 2027 C2 = Callable[[KT, T], VT] 2028 C3 = Callable[..., T] 2029 self.assertEqual(C1[str], Callable[[int, str], str]) 2030 self.assertEqual(C1[None], Callable[[int, type(None)], type(None)]) 2031 self.assertEqual(C2[int, float, str], Callable[[int, float], str]) 2032 self.assertEqual(C3[int], Callable[..., int]) 2033 self.assertEqual(C3[NoReturn], Callable[..., NoReturn]) 2034 2035 # multi chaining 2036 C4 = C2[int, VT, str] 2037 self.assertEqual(repr(C4), f"{fullname}[[int, ~VT], str]") 2038 self.assertEqual(repr(C4[dict]), f"{fullname}[[int, dict], str]") 2039 self.assertEqual(C4[dict], Callable[[int, dict], str]) 2040 2041 # substitute a nested GenericAlias (both typing and the builtin 2042 # version) 2043 C5 = Callable[[typing.List[T], tuple[KT, T], VT], int] 2044 self.assertEqual(C5[int, str, float], 2045 Callable[[typing.List[int], tuple[str, int], float], int]) 2046 2047 def test_type_subst_error(self): 2048 Callable = self.Callable 2049 P = ParamSpec('P') 2050 T = TypeVar('T') 2051 2052 pat = "Expected a list of types, an ellipsis, ParamSpec, or Concatenate." 2053 2054 with self.assertRaisesRegex(TypeError, pat): 2055 Callable[P, T][0, int] 2056 2057 def test_type_erasure(self): 2058 Callable = self.Callable 2059 class C1(Callable): 2060 def __call__(self): 2061 return None 2062 a = C1[[int], T] 2063 self.assertIs(a().__class__, C1) 2064 self.assertEqual(a().__orig_class__, C1[[int], T]) 2065 2066 def test_paramspec(self): 2067 Callable = self.Callable 2068 fullname = f"{Callable.__module__}.Callable" 2069 P = ParamSpec('P') 2070 P2 = ParamSpec('P2') 2071 C1 = Callable[P, T] 2072 # substitution 2073 self.assertEqual(C1[[int], str], Callable[[int], str]) 2074 self.assertEqual(C1[[int, str], str], Callable[[int, str], str]) 2075 self.assertEqual(C1[[], str], Callable[[], str]) 2076 self.assertEqual(C1[..., str], Callable[..., str]) 2077 self.assertEqual(C1[P2, str], Callable[P2, str]) 2078 self.assertEqual(C1[Concatenate[int, P2], str], 2079 Callable[Concatenate[int, P2], str]) 2080 self.assertEqual(repr(C1), f"{fullname}[~P, ~T]") 2081 self.assertEqual(repr(C1[[int, str], str]), f"{fullname}[[int, str], str]") 2082 with self.assertRaises(TypeError): 2083 C1[int, str] 2084 2085 C2 = Callable[P, int] 2086 self.assertEqual(C2[[int]], Callable[[int], int]) 2087 self.assertEqual(C2[[int, str]], Callable[[int, str], int]) 2088 self.assertEqual(C2[[]], Callable[[], int]) 2089 self.assertEqual(C2[...], Callable[..., int]) 2090 self.assertEqual(C2[P2], Callable[P2, int]) 2091 self.assertEqual(C2[Concatenate[int, P2]], 2092 Callable[Concatenate[int, P2], int]) 2093 # special case in PEP 612 where 2094 # X[int, str, float] == X[[int, str, float]] 2095 self.assertEqual(C2[int], Callable[[int], int]) 2096 self.assertEqual(C2[int, str], Callable[[int, str], int]) 2097 self.assertEqual(repr(C2), f"{fullname}[~P, int]") 2098 self.assertEqual(repr(C2[int, str]), f"{fullname}[[int, str], int]") 2099 2100 def test_concatenate(self): 2101 Callable = self.Callable 2102 fullname = f"{Callable.__module__}.Callable" 2103 T = TypeVar('T') 2104 P = ParamSpec('P') 2105 P2 = ParamSpec('P2') 2106 C = Callable[Concatenate[int, P], T] 2107 self.assertEqual(repr(C), 2108 f"{fullname}[typing.Concatenate[int, ~P], ~T]") 2109 self.assertEqual(C[P2, int], Callable[Concatenate[int, P2], int]) 2110 self.assertEqual(C[[str, float], int], Callable[[int, str, float], int]) 2111 self.assertEqual(C[[], int], Callable[[int], int]) 2112 self.assertEqual(C[Concatenate[str, P2], int], 2113 Callable[Concatenate[int, str, P2], int]) 2114 self.assertEqual(C[..., int], Callable[Concatenate[int, ...], int]) 2115 2116 C = Callable[Concatenate[int, P], int] 2117 self.assertEqual(repr(C), 2118 f"{fullname}[typing.Concatenate[int, ~P], int]") 2119 self.assertEqual(C[P2], Callable[Concatenate[int, P2], int]) 2120 self.assertEqual(C[[str, float]], Callable[[int, str, float], int]) 2121 self.assertEqual(C[str, float], Callable[[int, str, float], int]) 2122 self.assertEqual(C[[]], Callable[[int], int]) 2123 self.assertEqual(C[Concatenate[str, P2]], 2124 Callable[Concatenate[int, str, P2], int]) 2125 self.assertEqual(C[...], Callable[Concatenate[int, ...], int]) 2126 2127 def test_nested_paramspec(self): 2128 # Since Callable has some special treatment, we want to be sure 2129 # that substituion works correctly, see gh-103054 2130 Callable = self.Callable 2131 P = ParamSpec('P') 2132 P2 = ParamSpec('P2') 2133 T = TypeVar('T') 2134 T2 = TypeVar('T2') 2135 Ts = TypeVarTuple('Ts') 2136 class My(Generic[P, T]): 2137 pass 2138 2139 self.assertEqual(My.__parameters__, (P, T)) 2140 2141 C1 = My[[int, T2], Callable[P2, T2]] 2142 self.assertEqual(C1.__args__, ((int, T2), Callable[P2, T2])) 2143 self.assertEqual(C1.__parameters__, (T2, P2)) 2144 self.assertEqual(C1[str, [list[int], bytes]], 2145 My[[int, str], Callable[[list[int], bytes], str]]) 2146 2147 C2 = My[[Callable[[T2], int], list[T2]], str] 2148 self.assertEqual(C2.__args__, ((Callable[[T2], int], list[T2]), str)) 2149 self.assertEqual(C2.__parameters__, (T2,)) 2150 self.assertEqual(C2[list[str]], 2151 My[[Callable[[list[str]], int], list[list[str]]], str]) 2152 2153 C3 = My[[Callable[P2, T2], T2], T2] 2154 self.assertEqual(C3.__args__, ((Callable[P2, T2], T2), T2)) 2155 self.assertEqual(C3.__parameters__, (P2, T2)) 2156 self.assertEqual(C3[[], int], 2157 My[[Callable[[], int], int], int]) 2158 self.assertEqual(C3[[str, bool], int], 2159 My[[Callable[[str, bool], int], int], int]) 2160 self.assertEqual(C3[[str, bool], T][int], 2161 My[[Callable[[str, bool], int], int], int]) 2162 2163 C4 = My[[Callable[[int, *Ts, str], T2], T2], T2] 2164 self.assertEqual(C4.__args__, ((Callable[[int, *Ts, str], T2], T2), T2)) 2165 self.assertEqual(C4.__parameters__, (Ts, T2)) 2166 self.assertEqual(C4[bool, bytes, float], 2167 My[[Callable[[int, bool, bytes, str], float], float], float]) 2168 2169 def test_errors(self): 2170 Callable = self.Callable 2171 alias = Callable[[int, str], float] 2172 with self.assertRaisesRegex(TypeError, "is not a generic class"): 2173 alias[int] 2174 P = ParamSpec('P') 2175 C1 = Callable[P, T] 2176 with self.assertRaisesRegex(TypeError, "many arguments for"): 2177 C1[int, str, str] 2178 with self.assertRaisesRegex(TypeError, "few arguments for"): 2179 C1[int] 2180 2181class TypingCallableTests(BaseCallableTests, BaseTestCase): 2182 Callable = typing.Callable 2183 2184 def test_consistency(self): 2185 # bpo-42195 2186 # Testing collections.abc.Callable's consistency with typing.Callable 2187 c1 = typing.Callable[[int, str], dict] 2188 c2 = collections.abc.Callable[[int, str], dict] 2189 self.assertEqual(c1.__args__, c2.__args__) 2190 self.assertEqual(hash(c1.__args__), hash(c2.__args__)) 2191 2192 2193class CollectionsCallableTests(BaseCallableTests, BaseTestCase): 2194 Callable = collections.abc.Callable 2195 2196 2197class LiteralTests(BaseTestCase): 2198 def test_basics(self): 2199 # All of these are allowed. 2200 Literal[1] 2201 Literal[1, 2, 3] 2202 Literal["x", "y", "z"] 2203 Literal[None] 2204 Literal[True] 2205 Literal[1, "2", False] 2206 Literal[Literal[1, 2], Literal[4, 5]] 2207 Literal[b"foo", u"bar"] 2208 2209 def test_enum(self): 2210 import enum 2211 class My(enum.Enum): 2212 A = 'A' 2213 2214 self.assertEqual(Literal[My.A].__args__, (My.A,)) 2215 2216 def test_illegal_parameters_do_not_raise_runtime_errors(self): 2217 # Type checkers should reject these types, but we do not 2218 # raise errors at runtime to maintain maximum flexibility. 2219 Literal[int] 2220 Literal[3j + 2, ..., ()] 2221 Literal[{"foo": 3, "bar": 4}] 2222 Literal[T] 2223 2224 def test_literals_inside_other_types(self): 2225 List[Literal[1, 2, 3]] 2226 List[Literal[("foo", "bar", "baz")]] 2227 2228 def test_repr(self): 2229 self.assertEqual(repr(Literal[1]), "typing.Literal[1]") 2230 self.assertEqual(repr(Literal[1, True, "foo"]), "typing.Literal[1, True, 'foo']") 2231 self.assertEqual(repr(Literal[int]), "typing.Literal[int]") 2232 self.assertEqual(repr(Literal), "typing.Literal") 2233 self.assertEqual(repr(Literal[None]), "typing.Literal[None]") 2234 self.assertEqual(repr(Literal[1, 2, 3, 3]), "typing.Literal[1, 2, 3]") 2235 2236 def test_dir(self): 2237 dir_items = set(dir(Literal[1, 2, 3])) 2238 for required_item in [ 2239 '__args__', '__parameters__', '__origin__', 2240 ]: 2241 with self.subTest(required_item=required_item): 2242 self.assertIn(required_item, dir_items) 2243 2244 def test_cannot_init(self): 2245 with self.assertRaises(TypeError): 2246 Literal() 2247 with self.assertRaises(TypeError): 2248 Literal[1]() 2249 with self.assertRaises(TypeError): 2250 type(Literal)() 2251 with self.assertRaises(TypeError): 2252 type(Literal[1])() 2253 2254 def test_no_isinstance_or_issubclass(self): 2255 with self.assertRaises(TypeError): 2256 isinstance(1, Literal[1]) 2257 with self.assertRaises(TypeError): 2258 isinstance(int, Literal[1]) 2259 with self.assertRaises(TypeError): 2260 issubclass(1, Literal[1]) 2261 with self.assertRaises(TypeError): 2262 issubclass(int, Literal[1]) 2263 2264 def test_no_subclassing(self): 2265 with self.assertRaises(TypeError): 2266 class Foo(Literal[1]): pass 2267 with self.assertRaises(TypeError): 2268 class Bar(Literal): pass 2269 2270 def test_no_multiple_subscripts(self): 2271 with self.assertRaises(TypeError): 2272 Literal[1][1] 2273 2274 def test_equal(self): 2275 self.assertNotEqual(Literal[0], Literal[False]) 2276 self.assertNotEqual(Literal[True], Literal[1]) 2277 self.assertNotEqual(Literal[1], Literal[2]) 2278 self.assertNotEqual(Literal[1, True], Literal[1]) 2279 self.assertNotEqual(Literal[1, True], Literal[1, 1]) 2280 self.assertNotEqual(Literal[1, 2], Literal[True, 2]) 2281 self.assertEqual(Literal[1], Literal[1]) 2282 self.assertEqual(Literal[1, 2], Literal[2, 1]) 2283 self.assertEqual(Literal[1, 2, 3], Literal[1, 2, 3, 3]) 2284 2285 def test_hash(self): 2286 self.assertEqual(hash(Literal[1]), hash(Literal[1])) 2287 self.assertEqual(hash(Literal[1, 2]), hash(Literal[2, 1])) 2288 self.assertEqual(hash(Literal[1, 2, 3]), hash(Literal[1, 2, 3, 3])) 2289 2290 def test_args(self): 2291 self.assertEqual(Literal[1, 2, 3].__args__, (1, 2, 3)) 2292 self.assertEqual(Literal[1, 2, 3, 3].__args__, (1, 2, 3)) 2293 self.assertEqual(Literal[1, Literal[2], Literal[3, 4]].__args__, (1, 2, 3, 4)) 2294 # Mutable arguments will not be deduplicated 2295 self.assertEqual(Literal[[], []].__args__, ([], [])) 2296 2297 def test_flatten(self): 2298 l1 = Literal[Literal[1], Literal[2], Literal[3]] 2299 l2 = Literal[Literal[1, 2], 3] 2300 l3 = Literal[Literal[1, 2, 3]] 2301 for l in l1, l2, l3: 2302 self.assertEqual(l, Literal[1, 2, 3]) 2303 self.assertEqual(l.__args__, (1, 2, 3)) 2304 2305 def test_does_not_flatten_enum(self): 2306 import enum 2307 class Ints(enum.IntEnum): 2308 A = 1 2309 B = 2 2310 2311 l = Literal[ 2312 Literal[Ints.A], 2313 Literal[Ints.B], 2314 Literal[1], 2315 Literal[2], 2316 ] 2317 self.assertEqual(l.__args__, (Ints.A, Ints.B, 1, 2)) 2318 2319 2320XK = TypeVar('XK', str, bytes) 2321XV = TypeVar('XV') 2322 2323 2324class SimpleMapping(Generic[XK, XV]): 2325 2326 def __getitem__(self, key: XK) -> XV: 2327 ... 2328 2329 def __setitem__(self, key: XK, value: XV): 2330 ... 2331 2332 def get(self, key: XK, default: XV = None) -> XV: 2333 ... 2334 2335 2336class MySimpleMapping(SimpleMapping[XK, XV]): 2337 2338 def __init__(self): 2339 self.store = {} 2340 2341 def __getitem__(self, key: str): 2342 return self.store[key] 2343 2344 def __setitem__(self, key: str, value): 2345 self.store[key] = value 2346 2347 def get(self, key: str, default=None): 2348 try: 2349 return self.store[key] 2350 except KeyError: 2351 return default 2352 2353 2354class Coordinate(Protocol): 2355 x: int 2356 y: int 2357 2358@runtime_checkable 2359class Point(Coordinate, Protocol): 2360 label: str 2361 2362class MyPoint: 2363 x: int 2364 y: int 2365 label: str 2366 2367class XAxis(Protocol): 2368 x: int 2369 2370class YAxis(Protocol): 2371 y: int 2372 2373@runtime_checkable 2374class Position(XAxis, YAxis, Protocol): 2375 pass 2376 2377@runtime_checkable 2378class Proto(Protocol): 2379 attr: int 2380 def meth(self, arg: str) -> int: 2381 ... 2382 2383class Concrete(Proto): 2384 pass 2385 2386class Other: 2387 attr: int = 1 2388 def meth(self, arg: str) -> int: 2389 if arg == 'this': 2390 return 1 2391 return 0 2392 2393class NT(NamedTuple): 2394 x: int 2395 y: int 2396 2397@runtime_checkable 2398class HasCallProtocol(Protocol): 2399 __call__: typing.Callable 2400 2401 2402class ProtocolTests(BaseTestCase): 2403 def test_basic_protocol(self): 2404 @runtime_checkable 2405 class P(Protocol): 2406 def meth(self): 2407 pass 2408 2409 class C: pass 2410 2411 class D: 2412 def meth(self): 2413 pass 2414 2415 def f(): 2416 pass 2417 2418 self.assertIsSubclass(D, P) 2419 self.assertIsInstance(D(), P) 2420 self.assertNotIsSubclass(C, P) 2421 self.assertNotIsInstance(C(), P) 2422 self.assertNotIsSubclass(types.FunctionType, P) 2423 self.assertNotIsInstance(f, P) 2424 2425 def test_everything_implements_empty_protocol(self): 2426 @runtime_checkable 2427 class Empty(Protocol): 2428 pass 2429 2430 class C: 2431 pass 2432 2433 def f(): 2434 pass 2435 2436 for thing in (object, type, tuple, C, types.FunctionType): 2437 self.assertIsSubclass(thing, Empty) 2438 for thing in (object(), 1, (), typing, f): 2439 self.assertIsInstance(thing, Empty) 2440 2441 def test_function_implements_protocol(self): 2442 def f(): 2443 pass 2444 2445 self.assertIsInstance(f, HasCallProtocol) 2446 2447 def test_no_inheritance_from_nominal(self): 2448 class C: pass 2449 2450 class BP(Protocol): pass 2451 2452 with self.assertRaises(TypeError): 2453 class P(C, Protocol): 2454 pass 2455 with self.assertRaises(TypeError): 2456 class P(Protocol, C): 2457 pass 2458 with self.assertRaises(TypeError): 2459 class P(BP, C, Protocol): 2460 pass 2461 2462 class D(BP, C): pass 2463 2464 class E(C, BP): pass 2465 2466 self.assertNotIsInstance(D(), E) 2467 self.assertNotIsInstance(E(), D) 2468 2469 def test_no_instantiation(self): 2470 class P(Protocol): pass 2471 2472 with self.assertRaises(TypeError): 2473 P() 2474 2475 class C(P): pass 2476 2477 self.assertIsInstance(C(), C) 2478 with self.assertRaises(TypeError): 2479 C(42) 2480 2481 T = TypeVar('T') 2482 2483 class PG(Protocol[T]): pass 2484 2485 with self.assertRaises(TypeError): 2486 PG() 2487 with self.assertRaises(TypeError): 2488 PG[int]() 2489 with self.assertRaises(TypeError): 2490 PG[T]() 2491 2492 class CG(PG[T]): pass 2493 2494 self.assertIsInstance(CG[int](), CG) 2495 with self.assertRaises(TypeError): 2496 CG[int](42) 2497 2498 def test_protocol_defining_init_does_not_get_overridden(self): 2499 # check that P.__init__ doesn't get clobbered 2500 # see https://bugs.python.org/issue44807 2501 2502 class P(Protocol): 2503 x: int 2504 def __init__(self, x: int) -> None: 2505 self.x = x 2506 class C: pass 2507 2508 c = C() 2509 P.__init__(c, 1) 2510 self.assertEqual(c.x, 1) 2511 2512 def test_concrete_class_inheriting_init_from_protocol(self): 2513 class P(Protocol): 2514 x: int 2515 def __init__(self, x: int) -> None: 2516 self.x = x 2517 2518 class C(P): pass 2519 2520 c = C(1) 2521 self.assertIsInstance(c, C) 2522 self.assertEqual(c.x, 1) 2523 2524 def test_cannot_instantiate_abstract(self): 2525 @runtime_checkable 2526 class P(Protocol): 2527 @abc.abstractmethod 2528 def ameth(self) -> int: 2529 raise NotImplementedError 2530 2531 class B(P): 2532 pass 2533 2534 class C(B): 2535 def ameth(self) -> int: 2536 return 26 2537 2538 with self.assertRaises(TypeError): 2539 B() 2540 self.assertIsInstance(C(), P) 2541 2542 def test_subprotocols_extending(self): 2543 class P1(Protocol): 2544 def meth1(self): 2545 pass 2546 2547 @runtime_checkable 2548 class P2(P1, Protocol): 2549 def meth2(self): 2550 pass 2551 2552 class C: 2553 def meth1(self): 2554 pass 2555 2556 def meth2(self): 2557 pass 2558 2559 class C1: 2560 def meth1(self): 2561 pass 2562 2563 class C2: 2564 def meth2(self): 2565 pass 2566 2567 self.assertNotIsInstance(C1(), P2) 2568 self.assertNotIsInstance(C2(), P2) 2569 self.assertNotIsSubclass(C1, P2) 2570 self.assertNotIsSubclass(C2, P2) 2571 self.assertIsInstance(C(), P2) 2572 self.assertIsSubclass(C, P2) 2573 2574 def test_subprotocols_merging(self): 2575 class P1(Protocol): 2576 def meth1(self): 2577 pass 2578 2579 class P2(Protocol): 2580 def meth2(self): 2581 pass 2582 2583 @runtime_checkable 2584 class P(P1, P2, Protocol): 2585 pass 2586 2587 class C: 2588 def meth1(self): 2589 pass 2590 2591 def meth2(self): 2592 pass 2593 2594 class C1: 2595 def meth1(self): 2596 pass 2597 2598 class C2: 2599 def meth2(self): 2600 pass 2601 2602 self.assertNotIsInstance(C1(), P) 2603 self.assertNotIsInstance(C2(), P) 2604 self.assertNotIsSubclass(C1, P) 2605 self.assertNotIsSubclass(C2, P) 2606 self.assertIsInstance(C(), P) 2607 self.assertIsSubclass(C, P) 2608 2609 def test_protocols_issubclass(self): 2610 T = TypeVar('T') 2611 2612 @runtime_checkable 2613 class P(Protocol): 2614 def x(self): ... 2615 2616 @runtime_checkable 2617 class PG(Protocol[T]): 2618 def x(self): ... 2619 2620 class BadP(Protocol): 2621 def x(self): ... 2622 2623 class BadPG(Protocol[T]): 2624 def x(self): ... 2625 2626 class C: 2627 def x(self): ... 2628 2629 self.assertIsSubclass(C, P) 2630 self.assertIsSubclass(C, PG) 2631 self.assertIsSubclass(BadP, PG) 2632 2633 with self.assertRaises(TypeError): 2634 issubclass(C, PG[T]) 2635 with self.assertRaises(TypeError): 2636 issubclass(C, PG[C]) 2637 with self.assertRaises(TypeError): 2638 issubclass(C, BadP) 2639 with self.assertRaises(TypeError): 2640 issubclass(C, BadPG) 2641 with self.assertRaises(TypeError): 2642 issubclass(P, PG[T]) 2643 with self.assertRaises(TypeError): 2644 issubclass(PG, PG[int]) 2645 2646 def test_protocols_issubclass_non_callable(self): 2647 class C: 2648 x = 1 2649 2650 @runtime_checkable 2651 class PNonCall(Protocol): 2652 x = 1 2653 2654 with self.assertRaises(TypeError): 2655 issubclass(C, PNonCall) 2656 self.assertIsInstance(C(), PNonCall) 2657 PNonCall.register(C) 2658 with self.assertRaises(TypeError): 2659 issubclass(C, PNonCall) 2660 self.assertIsInstance(C(), PNonCall) 2661 2662 # check that non-protocol subclasses are not affected 2663 class D(PNonCall): ... 2664 2665 self.assertNotIsSubclass(C, D) 2666 self.assertNotIsInstance(C(), D) 2667 D.register(C) 2668 self.assertIsSubclass(C, D) 2669 self.assertIsInstance(C(), D) 2670 with self.assertRaises(TypeError): 2671 issubclass(D, PNonCall) 2672 2673 def test_protocols_isinstance(self): 2674 T = TypeVar('T') 2675 2676 @runtime_checkable 2677 class P(Protocol): 2678 def meth(x): ... 2679 2680 @runtime_checkable 2681 class PG(Protocol[T]): 2682 def meth(x): ... 2683 2684 @runtime_checkable 2685 class WeirdProto(Protocol): 2686 meth = str.maketrans 2687 2688 @runtime_checkable 2689 class WeirdProto2(Protocol): 2690 meth = lambda *args, **kwargs: None 2691 2692 class CustomCallable: 2693 def __call__(self, *args, **kwargs): 2694 pass 2695 2696 @runtime_checkable 2697 class WeirderProto(Protocol): 2698 meth = CustomCallable() 2699 2700 class BadP(Protocol): 2701 def meth(x): ... 2702 2703 class BadPG(Protocol[T]): 2704 def meth(x): ... 2705 2706 class C: 2707 def meth(x): ... 2708 2709 class C2: 2710 def __init__(self): 2711 self.meth = lambda: None 2712 2713 for klass in C, C2: 2714 for proto in P, PG, WeirdProto, WeirdProto2, WeirderProto: 2715 with self.subTest(klass=klass.__name__, proto=proto.__name__): 2716 self.assertIsInstance(klass(), proto) 2717 2718 with self.assertRaises(TypeError): 2719 isinstance(C(), PG[T]) 2720 with self.assertRaises(TypeError): 2721 isinstance(C(), PG[C]) 2722 with self.assertRaises(TypeError): 2723 isinstance(C(), BadP) 2724 with self.assertRaises(TypeError): 2725 isinstance(C(), BadPG) 2726 2727 def test_protocols_isinstance_properties_and_descriptors(self): 2728 class C: 2729 @property 2730 def attr(self): 2731 return 42 2732 2733 class CustomDescriptor: 2734 def __get__(self, obj, objtype=None): 2735 return 42 2736 2737 class D: 2738 attr = CustomDescriptor() 2739 2740 # Check that properties set on superclasses 2741 # are still found by the isinstance() logic 2742 class E(C): ... 2743 class F(D): ... 2744 2745 class Empty: ... 2746 2747 T = TypeVar('T') 2748 2749 @runtime_checkable 2750 class P(Protocol): 2751 @property 2752 def attr(self): ... 2753 2754 @runtime_checkable 2755 class P1(Protocol): 2756 attr: int 2757 2758 @runtime_checkable 2759 class PG(Protocol[T]): 2760 @property 2761 def attr(self): ... 2762 2763 @runtime_checkable 2764 class PG1(Protocol[T]): 2765 attr: T 2766 2767 for protocol_class in P, P1, PG, PG1: 2768 for klass in C, D, E, F: 2769 with self.subTest( 2770 klass=klass.__name__, 2771 protocol_class=protocol_class.__name__ 2772 ): 2773 self.assertIsInstance(klass(), protocol_class) 2774 2775 with self.subTest(klass="Empty", protocol_class=protocol_class.__name__): 2776 self.assertNotIsInstance(Empty(), protocol_class) 2777 2778 class BadP(Protocol): 2779 @property 2780 def attr(self): ... 2781 2782 class BadP1(Protocol): 2783 attr: int 2784 2785 class BadPG(Protocol[T]): 2786 @property 2787 def attr(self): ... 2788 2789 class BadPG1(Protocol[T]): 2790 attr: T 2791 2792 for obj in PG[T], PG[C], PG1[T], PG1[C], BadP, BadP1, BadPG, BadPG1: 2793 for klass in C, D, E, F, Empty: 2794 with self.subTest(klass=klass.__name__, obj=obj): 2795 with self.assertRaises(TypeError): 2796 isinstance(klass(), obj) 2797 2798 def test_protocols_isinstance_not_fooled_by_custom_dir(self): 2799 @runtime_checkable 2800 class HasX(Protocol): 2801 x: int 2802 2803 class CustomDirWithX: 2804 x = 10 2805 def __dir__(self): 2806 return [] 2807 2808 class CustomDirWithoutX: 2809 def __dir__(self): 2810 return ["x"] 2811 2812 self.assertIsInstance(CustomDirWithX(), HasX) 2813 self.assertNotIsInstance(CustomDirWithoutX(), HasX) 2814 2815 def test_protocols_isinstance_py36(self): 2816 class APoint: 2817 def __init__(self, x, y, label): 2818 self.x = x 2819 self.y = y 2820 self.label = label 2821 2822 class BPoint: 2823 label = 'B' 2824 2825 def __init__(self, x, y): 2826 self.x = x 2827 self.y = y 2828 2829 class C: 2830 def __init__(self, attr): 2831 self.attr = attr 2832 2833 def meth(self, arg): 2834 return 0 2835 2836 class Bad: pass 2837 2838 self.assertIsInstance(APoint(1, 2, 'A'), Point) 2839 self.assertIsInstance(BPoint(1, 2), Point) 2840 self.assertNotIsInstance(MyPoint(), Point) 2841 self.assertIsInstance(BPoint(1, 2), Position) 2842 self.assertIsInstance(Other(), Proto) 2843 self.assertIsInstance(Concrete(), Proto) 2844 self.assertIsInstance(C(42), Proto) 2845 self.assertNotIsInstance(Bad(), Proto) 2846 self.assertNotIsInstance(Bad(), Point) 2847 self.assertNotIsInstance(Bad(), Position) 2848 self.assertNotIsInstance(Bad(), Concrete) 2849 self.assertNotIsInstance(Other(), Concrete) 2850 self.assertIsInstance(NT(1, 2), Position) 2851 2852 def test_protocols_isinstance_init(self): 2853 T = TypeVar('T') 2854 2855 @runtime_checkable 2856 class P(Protocol): 2857 x = 1 2858 2859 @runtime_checkable 2860 class PG(Protocol[T]): 2861 x = 1 2862 2863 class C: 2864 def __init__(self, x): 2865 self.x = x 2866 2867 self.assertIsInstance(C(1), P) 2868 self.assertIsInstance(C(1), PG) 2869 2870 def test_protocols_isinstance_monkeypatching(self): 2871 @runtime_checkable 2872 class HasX(Protocol): 2873 x: int 2874 2875 class Foo: ... 2876 2877 f = Foo() 2878 self.assertNotIsInstance(f, HasX) 2879 f.x = 42 2880 self.assertIsInstance(f, HasX) 2881 del f.x 2882 self.assertNotIsInstance(f, HasX) 2883 2884 def test_protocol_checks_after_subscript(self): 2885 class P(Protocol[T]): pass 2886 class C(P[T]): pass 2887 class Other1: pass 2888 class Other2: pass 2889 CA = C[Any] 2890 2891 self.assertNotIsInstance(Other1(), C) 2892 self.assertNotIsSubclass(Other2, C) 2893 2894 class D1(C[Any]): pass 2895 class D2(C[Any]): pass 2896 CI = C[int] 2897 2898 self.assertIsInstance(D1(), C) 2899 self.assertIsSubclass(D2, C) 2900 2901 def test_protocols_support_register(self): 2902 @runtime_checkable 2903 class P(Protocol): 2904 x = 1 2905 2906 class PM(Protocol): 2907 def meth(self): pass 2908 2909 class D(PM): pass 2910 2911 class C: pass 2912 2913 D.register(C) 2914 P.register(C) 2915 self.assertIsInstance(C(), P) 2916 self.assertIsInstance(C(), D) 2917 2918 def test_none_on_non_callable_doesnt_block_implementation(self): 2919 @runtime_checkable 2920 class P(Protocol): 2921 x = 1 2922 2923 class A: 2924 x = 1 2925 2926 class B(A): 2927 x = None 2928 2929 class C: 2930 def __init__(self): 2931 self.x = None 2932 2933 self.assertIsInstance(B(), P) 2934 self.assertIsInstance(C(), P) 2935 2936 def test_none_on_callable_blocks_implementation(self): 2937 @runtime_checkable 2938 class P(Protocol): 2939 def x(self): ... 2940 2941 class A: 2942 def x(self): ... 2943 2944 class B(A): 2945 x = None 2946 2947 class C: 2948 def __init__(self): 2949 self.x = None 2950 2951 self.assertNotIsInstance(B(), P) 2952 self.assertNotIsInstance(C(), P) 2953 2954 def test_non_protocol_subclasses(self): 2955 class P(Protocol): 2956 x = 1 2957 2958 @runtime_checkable 2959 class PR(Protocol): 2960 def meth(self): pass 2961 2962 class NonP(P): 2963 x = 1 2964 2965 class NonPR(PR): pass 2966 2967 class C: 2968 x = 1 2969 2970 class D: 2971 def meth(self): pass 2972 2973 self.assertNotIsInstance(C(), NonP) 2974 self.assertNotIsInstance(D(), NonPR) 2975 self.assertNotIsSubclass(C, NonP) 2976 self.assertNotIsSubclass(D, NonPR) 2977 self.assertIsInstance(NonPR(), PR) 2978 self.assertIsSubclass(NonPR, PR) 2979 2980 def test_custom_subclasshook(self): 2981 class P(Protocol): 2982 x = 1 2983 2984 class OKClass: pass 2985 2986 class BadClass: 2987 x = 1 2988 2989 class C(P): 2990 @classmethod 2991 def __subclasshook__(cls, other): 2992 return other.__name__.startswith("OK") 2993 2994 self.assertIsInstance(OKClass(), C) 2995 self.assertNotIsInstance(BadClass(), C) 2996 self.assertIsSubclass(OKClass, C) 2997 self.assertNotIsSubclass(BadClass, C) 2998 2999 def test_issubclass_fails_correctly(self): 3000 @runtime_checkable 3001 class P(Protocol): 3002 x = 1 3003 3004 class C: pass 3005 3006 with self.assertRaises(TypeError): 3007 issubclass(C(), P) 3008 3009 def test_defining_generic_protocols(self): 3010 T = TypeVar('T') 3011 S = TypeVar('S') 3012 3013 @runtime_checkable 3014 class PR(Protocol[T, S]): 3015 def meth(self): pass 3016 3017 class P(PR[int, T], Protocol[T]): 3018 y = 1 3019 3020 with self.assertRaises(TypeError): 3021 PR[int] 3022 with self.assertRaises(TypeError): 3023 P[int, str] 3024 3025 class C(PR[int, T]): pass 3026 3027 self.assertIsInstance(C[str](), C) 3028 3029 def test_defining_generic_protocols_old_style(self): 3030 T = TypeVar('T') 3031 S = TypeVar('S') 3032 3033 @runtime_checkable 3034 class PR(Protocol, Generic[T, S]): 3035 def meth(self): pass 3036 3037 class P(PR[int, str], Protocol): 3038 y = 1 3039 3040 with self.assertRaises(TypeError): 3041 issubclass(PR[int, str], PR) 3042 self.assertIsSubclass(P, PR) 3043 with self.assertRaises(TypeError): 3044 PR[int] 3045 3046 class P1(Protocol, Generic[T]): 3047 def bar(self, x: T) -> str: ... 3048 3049 class P2(Generic[T], Protocol): 3050 def bar(self, x: T) -> str: ... 3051 3052 @runtime_checkable 3053 class PSub(P1[str], Protocol): 3054 x = 1 3055 3056 class Test: 3057 x = 1 3058 3059 def bar(self, x: str) -> str: 3060 return x 3061 3062 self.assertIsInstance(Test(), PSub) 3063 3064 def test_init_called(self): 3065 T = TypeVar('T') 3066 3067 class P(Protocol[T]): pass 3068 3069 class C(P[T]): 3070 def __init__(self): 3071 self.test = 'OK' 3072 3073 self.assertEqual(C[int]().test, 'OK') 3074 3075 class B: 3076 def __init__(self): 3077 self.test = 'OK' 3078 3079 class D1(B, P[T]): 3080 pass 3081 3082 self.assertEqual(D1[int]().test, 'OK') 3083 3084 class D2(P[T], B): 3085 pass 3086 3087 self.assertEqual(D2[int]().test, 'OK') 3088 3089 def test_new_called(self): 3090 T = TypeVar('T') 3091 3092 class P(Protocol[T]): pass 3093 3094 class C(P[T]): 3095 def __new__(cls, *args): 3096 self = super().__new__(cls, *args) 3097 self.test = 'OK' 3098 return self 3099 3100 self.assertEqual(C[int]().test, 'OK') 3101 with self.assertRaises(TypeError): 3102 C[int](42) 3103 with self.assertRaises(TypeError): 3104 C[int](a=42) 3105 3106 def test_protocols_bad_subscripts(self): 3107 T = TypeVar('T') 3108 S = TypeVar('S') 3109 with self.assertRaises(TypeError): 3110 class P(Protocol[T, T]): pass 3111 with self.assertRaises(TypeError): 3112 class P(Protocol[int]): pass 3113 with self.assertRaises(TypeError): 3114 class P(Protocol[T], Protocol[S]): pass 3115 with self.assertRaises(TypeError): 3116 class P(typing.Mapping[T, S], Protocol[T]): pass 3117 3118 def test_generic_protocols_repr(self): 3119 T = TypeVar('T') 3120 S = TypeVar('S') 3121 3122 class P(Protocol[T, S]): pass 3123 3124 self.assertTrue(repr(P[T, S]).endswith('P[~T, ~S]')) 3125 self.assertTrue(repr(P[int, str]).endswith('P[int, str]')) 3126 3127 def test_generic_protocols_eq(self): 3128 T = TypeVar('T') 3129 S = TypeVar('S') 3130 3131 class P(Protocol[T, S]): pass 3132 3133 self.assertEqual(P, P) 3134 self.assertEqual(P[int, T], P[int, T]) 3135 self.assertEqual(P[T, T][Tuple[T, S]][int, str], 3136 P[Tuple[int, str], Tuple[int, str]]) 3137 3138 def test_generic_protocols_special_from_generic(self): 3139 T = TypeVar('T') 3140 3141 class P(Protocol[T]): pass 3142 3143 self.assertEqual(P.__parameters__, (T,)) 3144 self.assertEqual(P[int].__parameters__, ()) 3145 self.assertEqual(P[int].__args__, (int,)) 3146 self.assertIs(P[int].__origin__, P) 3147 3148 def test_generic_protocols_special_from_protocol(self): 3149 @runtime_checkable 3150 class PR(Protocol): 3151 x = 1 3152 3153 class P(Protocol): 3154 def meth(self): 3155 pass 3156 3157 T = TypeVar('T') 3158 3159 class PG(Protocol[T]): 3160 x = 1 3161 3162 def meth(self): 3163 pass 3164 3165 self.assertTrue(P._is_protocol) 3166 self.assertTrue(PR._is_protocol) 3167 self.assertTrue(PG._is_protocol) 3168 self.assertFalse(P._is_runtime_protocol) 3169 self.assertTrue(PR._is_runtime_protocol) 3170 self.assertTrue(PG[int]._is_protocol) 3171 self.assertEqual(typing._get_protocol_attrs(P), {'meth'}) 3172 self.assertEqual(typing._get_protocol_attrs(PR), {'x'}) 3173 self.assertEqual(frozenset(typing._get_protocol_attrs(PG)), 3174 frozenset({'x', 'meth'})) 3175 3176 def test_no_runtime_deco_on_nominal(self): 3177 with self.assertRaises(TypeError): 3178 @runtime_checkable 3179 class C: pass 3180 3181 class Proto(Protocol): 3182 x = 1 3183 3184 with self.assertRaises(TypeError): 3185 @runtime_checkable 3186 class Concrete(Proto): 3187 pass 3188 3189 def test_none_treated_correctly(self): 3190 @runtime_checkable 3191 class P(Protocol): 3192 x = None # type: int 3193 3194 class B(object): pass 3195 3196 self.assertNotIsInstance(B(), P) 3197 3198 class C: 3199 x = 1 3200 3201 class D: 3202 x = None 3203 3204 self.assertIsInstance(C(), P) 3205 self.assertIsInstance(D(), P) 3206 3207 class CI: 3208 def __init__(self): 3209 self.x = 1 3210 3211 class DI: 3212 def __init__(self): 3213 self.x = None 3214 3215 self.assertIsInstance(CI(), P) 3216 self.assertIsInstance(DI(), P) 3217 3218 def test_protocols_in_unions(self): 3219 class P(Protocol): 3220 x = None # type: int 3221 3222 Alias = typing.Union[typing.Iterable, P] 3223 Alias2 = typing.Union[P, typing.Iterable] 3224 self.assertEqual(Alias, Alias2) 3225 3226 def test_protocols_pickleable(self): 3227 global P, CP # pickle wants to reference the class by name 3228 T = TypeVar('T') 3229 3230 @runtime_checkable 3231 class P(Protocol[T]): 3232 x = 1 3233 3234 class CP(P[int]): 3235 pass 3236 3237 c = CP() 3238 c.foo = 42 3239 c.bar = 'abc' 3240 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 3241 z = pickle.dumps(c, proto) 3242 x = pickle.loads(z) 3243 self.assertEqual(x.foo, 42) 3244 self.assertEqual(x.bar, 'abc') 3245 self.assertEqual(x.x, 1) 3246 self.assertEqual(x.__dict__, {'foo': 42, 'bar': 'abc'}) 3247 s = pickle.dumps(P, proto) 3248 D = pickle.loads(s) 3249 3250 class E: 3251 x = 1 3252 3253 self.assertIsInstance(E(), D) 3254 3255 def test_supports_int(self): 3256 self.assertIsSubclass(int, typing.SupportsInt) 3257 self.assertNotIsSubclass(str, typing.SupportsInt) 3258 3259 def test_supports_float(self): 3260 self.assertIsSubclass(float, typing.SupportsFloat) 3261 self.assertNotIsSubclass(str, typing.SupportsFloat) 3262 3263 def test_supports_complex(self): 3264 3265 class C: 3266 def __complex__(self): 3267 return 0j 3268 3269 self.assertIsSubclass(complex, typing.SupportsComplex) 3270 self.assertIsSubclass(C, typing.SupportsComplex) 3271 self.assertNotIsSubclass(str, typing.SupportsComplex) 3272 3273 def test_supports_bytes(self): 3274 3275 class B: 3276 def __bytes__(self): 3277 return b'' 3278 3279 self.assertIsSubclass(bytes, typing.SupportsBytes) 3280 self.assertIsSubclass(B, typing.SupportsBytes) 3281 self.assertNotIsSubclass(str, typing.SupportsBytes) 3282 3283 def test_supports_abs(self): 3284 self.assertIsSubclass(float, typing.SupportsAbs) 3285 self.assertIsSubclass(int, typing.SupportsAbs) 3286 self.assertNotIsSubclass(str, typing.SupportsAbs) 3287 3288 def test_supports_round(self): 3289 issubclass(float, typing.SupportsRound) 3290 self.assertIsSubclass(float, typing.SupportsRound) 3291 self.assertIsSubclass(int, typing.SupportsRound) 3292 self.assertNotIsSubclass(str, typing.SupportsRound) 3293 3294 def test_reversible(self): 3295 self.assertIsSubclass(list, typing.Reversible) 3296 self.assertNotIsSubclass(int, typing.Reversible) 3297 3298 def test_supports_index(self): 3299 self.assertIsSubclass(int, typing.SupportsIndex) 3300 self.assertNotIsSubclass(str, typing.SupportsIndex) 3301 3302 def test_bundled_protocol_instance_works(self): 3303 self.assertIsInstance(0, typing.SupportsAbs) 3304 class C1(typing.SupportsInt): 3305 def __int__(self) -> int: 3306 return 42 3307 class C2(C1): 3308 pass 3309 c = C2() 3310 self.assertIsInstance(c, C1) 3311 3312 def test_collections_protocols_allowed(self): 3313 @runtime_checkable 3314 class Custom(collections.abc.Iterable, Protocol): 3315 def close(self): ... 3316 3317 class A: pass 3318 class B: 3319 def __iter__(self): 3320 return [] 3321 def close(self): 3322 return 0 3323 3324 self.assertIsSubclass(B, Custom) 3325 self.assertNotIsSubclass(A, Custom) 3326 3327 def test_builtin_protocol_allowlist(self): 3328 with self.assertRaises(TypeError): 3329 class CustomProtocol(TestCase, Protocol): 3330 pass 3331 3332 class CustomContextManager(typing.ContextManager, Protocol): 3333 pass 3334 3335 def test_non_runtime_protocol_isinstance_check(self): 3336 class P(Protocol): 3337 x: int 3338 3339 with self.assertRaisesRegex(TypeError, "@runtime_checkable"): 3340 isinstance(1, P) 3341 3342 def test_super_call_init(self): 3343 class P(Protocol): 3344 x: int 3345 3346 class Foo(P): 3347 def __init__(self): 3348 super().__init__() 3349 3350 Foo() # Previously triggered RecursionError 3351 3352 3353class GenericTests(BaseTestCase): 3354 3355 def test_basics(self): 3356 X = SimpleMapping[str, Any] 3357 self.assertEqual(X.__parameters__, ()) 3358 with self.assertRaises(TypeError): 3359 X[str] 3360 with self.assertRaises(TypeError): 3361 X[str, str] 3362 Y = SimpleMapping[XK, str] 3363 self.assertEqual(Y.__parameters__, (XK,)) 3364 Y[str] 3365 with self.assertRaises(TypeError): 3366 Y[str, str] 3367 SM1 = SimpleMapping[str, int] 3368 with self.assertRaises(TypeError): 3369 issubclass(SM1, SimpleMapping) 3370 self.assertIsInstance(SM1(), SimpleMapping) 3371 T = TypeVar("T") 3372 self.assertEqual(List[list[T] | float].__parameters__, (T,)) 3373 3374 def test_generic_errors(self): 3375 T = TypeVar('T') 3376 S = TypeVar('S') 3377 with self.assertRaises(TypeError): 3378 Generic[T][T] 3379 with self.assertRaises(TypeError): 3380 Generic[T][S] 3381 with self.assertRaises(TypeError): 3382 class C(Generic[T], Generic[T]): ... 3383 with self.assertRaises(TypeError): 3384 isinstance([], List[int]) 3385 with self.assertRaises(TypeError): 3386 issubclass(list, List[int]) 3387 with self.assertRaises(TypeError): 3388 class NewGeneric(Generic): ... 3389 with self.assertRaises(TypeError): 3390 class MyGeneric(Generic[T], Generic[S]): ... 3391 with self.assertRaises(TypeError): 3392 class MyGeneric(List[T], Generic[S]): ... 3393 with self.assertRaises(TypeError): 3394 Generic[()] 3395 class C(Generic[T]): pass 3396 with self.assertRaises(TypeError): 3397 C[()] 3398 3399 def test_init(self): 3400 T = TypeVar('T') 3401 S = TypeVar('S') 3402 with self.assertRaises(TypeError): 3403 Generic[T, T] 3404 with self.assertRaises(TypeError): 3405 Generic[T, S, T] 3406 3407 def test_init_subclass(self): 3408 class X(typing.Generic[T]): 3409 def __init_subclass__(cls, **kwargs): 3410 super().__init_subclass__(**kwargs) 3411 cls.attr = 42 3412 class Y(X): 3413 pass 3414 self.assertEqual(Y.attr, 42) 3415 with self.assertRaises(AttributeError): 3416 X.attr 3417 X.attr = 1 3418 Y.attr = 2 3419 class Z(Y): 3420 pass 3421 class W(X[int]): 3422 pass 3423 self.assertEqual(Y.attr, 2) 3424 self.assertEqual(Z.attr, 42) 3425 self.assertEqual(W.attr, 42) 3426 3427 def test_repr(self): 3428 self.assertEqual(repr(SimpleMapping), 3429 f"<class '{__name__}.SimpleMapping'>") 3430 self.assertEqual(repr(MySimpleMapping), 3431 f"<class '{__name__}.MySimpleMapping'>") 3432 3433 def test_chain_repr(self): 3434 T = TypeVar('T') 3435 S = TypeVar('S') 3436 3437 class C(Generic[T]): 3438 pass 3439 3440 X = C[Tuple[S, T]] 3441 self.assertEqual(X, C[Tuple[S, T]]) 3442 self.assertNotEqual(X, C[Tuple[T, S]]) 3443 3444 Y = X[T, int] 3445 self.assertEqual(Y, X[T, int]) 3446 self.assertNotEqual(Y, X[S, int]) 3447 self.assertNotEqual(Y, X[T, str]) 3448 3449 Z = Y[str] 3450 self.assertEqual(Z, Y[str]) 3451 self.assertNotEqual(Z, Y[int]) 3452 self.assertNotEqual(Z, Y[T]) 3453 3454 self.assertTrue(str(Z).endswith( 3455 '.C[typing.Tuple[str, int]]')) 3456 3457 def test_new_repr(self): 3458 T = TypeVar('T') 3459 U = TypeVar('U', covariant=True) 3460 S = TypeVar('S') 3461 3462 self.assertEqual(repr(List), 'typing.List') 3463 self.assertEqual(repr(List[T]), 'typing.List[~T]') 3464 self.assertEqual(repr(List[U]), 'typing.List[+U]') 3465 self.assertEqual(repr(List[S][T][int]), 'typing.List[int]') 3466 self.assertEqual(repr(List[int]), 'typing.List[int]') 3467 3468 def test_new_repr_complex(self): 3469 T = TypeVar('T') 3470 TS = TypeVar('TS') 3471 3472 self.assertEqual(repr(typing.Mapping[T, TS][TS, T]), 'typing.Mapping[~TS, ~T]') 3473 self.assertEqual(repr(List[Tuple[T, TS]][int, T]), 3474 'typing.List[typing.Tuple[int, ~T]]') 3475 self.assertEqual( 3476 repr(List[Tuple[T, T]][List[int]]), 3477 'typing.List[typing.Tuple[typing.List[int], typing.List[int]]]' 3478 ) 3479 3480 def test_new_repr_bare(self): 3481 T = TypeVar('T') 3482 self.assertEqual(repr(Generic[T]), 'typing.Generic[~T]') 3483 self.assertEqual(repr(typing.Protocol[T]), 'typing.Protocol[~T]') 3484 class C(typing.Dict[Any, Any]): ... 3485 # this line should just work 3486 repr(C.__mro__) 3487 3488 def test_dict(self): 3489 T = TypeVar('T') 3490 3491 class B(Generic[T]): 3492 pass 3493 3494 b = B() 3495 b.foo = 42 3496 self.assertEqual(b.__dict__, {'foo': 42}) 3497 3498 class C(B[int]): 3499 pass 3500 3501 c = C() 3502 c.bar = 'abc' 3503 self.assertEqual(c.__dict__, {'bar': 'abc'}) 3504 3505 def test_subscripted_generics_as_proxies(self): 3506 T = TypeVar('T') 3507 class C(Generic[T]): 3508 x = 'def' 3509 self.assertEqual(C[int].x, 'def') 3510 self.assertEqual(C[C[int]].x, 'def') 3511 C[C[int]].x = 'changed' 3512 self.assertEqual(C.x, 'changed') 3513 self.assertEqual(C[str].x, 'changed') 3514 C[List[str]].z = 'new' 3515 self.assertEqual(C.z, 'new') 3516 self.assertEqual(C[Tuple[int]].z, 'new') 3517 3518 self.assertEqual(C().x, 'changed') 3519 self.assertEqual(C[Tuple[str]]().z, 'new') 3520 3521 class D(C[T]): 3522 pass 3523 self.assertEqual(D[int].x, 'changed') 3524 self.assertEqual(D.z, 'new') 3525 D.z = 'from derived z' 3526 D[int].x = 'from derived x' 3527 self.assertEqual(C.x, 'changed') 3528 self.assertEqual(C[int].z, 'new') 3529 self.assertEqual(D.x, 'from derived x') 3530 self.assertEqual(D[str].z, 'from derived z') 3531 3532 def test_abc_registry_kept(self): 3533 T = TypeVar('T') 3534 class C(collections.abc.Mapping, Generic[T]): ... 3535 C.register(int) 3536 self.assertIsInstance(1, C) 3537 C[int] 3538 self.assertIsInstance(1, C) 3539 C._abc_registry_clear() 3540 C._abc_caches_clear() # To keep refleak hunting mode clean 3541 3542 def test_false_subclasses(self): 3543 class MyMapping(MutableMapping[str, str]): pass 3544 self.assertNotIsInstance({}, MyMapping) 3545 self.assertNotIsSubclass(dict, MyMapping) 3546 3547 def test_abc_bases(self): 3548 class MM(MutableMapping[str, str]): 3549 def __getitem__(self, k): 3550 return None 3551 def __setitem__(self, k, v): 3552 pass 3553 def __delitem__(self, k): 3554 pass 3555 def __iter__(self): 3556 return iter(()) 3557 def __len__(self): 3558 return 0 3559 # this should just work 3560 MM().update() 3561 self.assertIsInstance(MM(), collections.abc.MutableMapping) 3562 self.assertIsInstance(MM(), MutableMapping) 3563 self.assertNotIsInstance(MM(), List) 3564 self.assertNotIsInstance({}, MM) 3565 3566 def test_multiple_bases(self): 3567 class MM1(MutableMapping[str, str], collections.abc.MutableMapping): 3568 pass 3569 class MM2(collections.abc.MutableMapping, MutableMapping[str, str]): 3570 pass 3571 self.assertEqual(MM2.__bases__, (collections.abc.MutableMapping, Generic)) 3572 3573 def test_orig_bases(self): 3574 T = TypeVar('T') 3575 class C(typing.Dict[str, T]): ... 3576 self.assertEqual(C.__orig_bases__, (typing.Dict[str, T],)) 3577 3578 def test_naive_runtime_checks(self): 3579 def naive_dict_check(obj, tp): 3580 # Check if a dictionary conforms to Dict type 3581 if len(tp.__parameters__) > 0: 3582 raise NotImplementedError 3583 if tp.__args__: 3584 KT, VT = tp.__args__ 3585 return all( 3586 isinstance(k, KT) and isinstance(v, VT) 3587 for k, v in obj.items() 3588 ) 3589 self.assertTrue(naive_dict_check({'x': 1}, typing.Dict[str, int])) 3590 self.assertFalse(naive_dict_check({1: 'x'}, typing.Dict[str, int])) 3591 with self.assertRaises(NotImplementedError): 3592 naive_dict_check({1: 'x'}, typing.Dict[str, T]) 3593 3594 def naive_generic_check(obj, tp): 3595 # Check if an instance conforms to the generic class 3596 if not hasattr(obj, '__orig_class__'): 3597 raise NotImplementedError 3598 return obj.__orig_class__ == tp 3599 class Node(Generic[T]): ... 3600 self.assertTrue(naive_generic_check(Node[int](), Node[int])) 3601 self.assertFalse(naive_generic_check(Node[str](), Node[int])) 3602 self.assertFalse(naive_generic_check(Node[str](), List)) 3603 with self.assertRaises(NotImplementedError): 3604 naive_generic_check([1, 2, 3], Node[int]) 3605 3606 def naive_list_base_check(obj, tp): 3607 # Check if list conforms to a List subclass 3608 return all(isinstance(x, tp.__orig_bases__[0].__args__[0]) 3609 for x in obj) 3610 class C(List[int]): ... 3611 self.assertTrue(naive_list_base_check([1, 2, 3], C)) 3612 self.assertFalse(naive_list_base_check(['a', 'b'], C)) 3613 3614 def test_multi_subscr_base(self): 3615 T = TypeVar('T') 3616 U = TypeVar('U') 3617 V = TypeVar('V') 3618 class C(List[T][U][V]): ... 3619 class D(C, List[T][U][V]): ... 3620 self.assertEqual(C.__parameters__, (V,)) 3621 self.assertEqual(D.__parameters__, (V,)) 3622 self.assertEqual(C[int].__parameters__, ()) 3623 self.assertEqual(D[int].__parameters__, ()) 3624 self.assertEqual(C[int].__args__, (int,)) 3625 self.assertEqual(D[int].__args__, (int,)) 3626 self.assertEqual(C.__bases__, (list, Generic)) 3627 self.assertEqual(D.__bases__, (C, list, Generic)) 3628 self.assertEqual(C.__orig_bases__, (List[T][U][V],)) 3629 self.assertEqual(D.__orig_bases__, (C, List[T][U][V])) 3630 3631 def test_subscript_meta(self): 3632 T = TypeVar('T') 3633 class Meta(type): ... 3634 self.assertEqual(Type[Meta], Type[Meta]) 3635 self.assertEqual(Union[T, int][Meta], Union[Meta, int]) 3636 self.assertEqual(Callable[..., Meta].__args__, (Ellipsis, Meta)) 3637 3638 def test_generic_hashes(self): 3639 class A(Generic[T]): 3640 ... 3641 3642 class B(Generic[T]): 3643 class A(Generic[T]): 3644 ... 3645 3646 self.assertEqual(A, A) 3647 self.assertEqual(mod_generics_cache.A[str], mod_generics_cache.A[str]) 3648 self.assertEqual(B.A, B.A) 3649 self.assertEqual(mod_generics_cache.B.A[B.A[str]], 3650 mod_generics_cache.B.A[B.A[str]]) 3651 3652 self.assertNotEqual(A, B.A) 3653 self.assertNotEqual(A, mod_generics_cache.A) 3654 self.assertNotEqual(A, mod_generics_cache.B.A) 3655 self.assertNotEqual(B.A, mod_generics_cache.A) 3656 self.assertNotEqual(B.A, mod_generics_cache.B.A) 3657 3658 self.assertNotEqual(A[str], B.A[str]) 3659 self.assertNotEqual(A[List[Any]], B.A[List[Any]]) 3660 self.assertNotEqual(A[str], mod_generics_cache.A[str]) 3661 self.assertNotEqual(A[str], mod_generics_cache.B.A[str]) 3662 self.assertNotEqual(B.A[int], mod_generics_cache.A[int]) 3663 self.assertNotEqual(B.A[List[Any]], mod_generics_cache.B.A[List[Any]]) 3664 3665 self.assertNotEqual(Tuple[A[str]], Tuple[B.A[str]]) 3666 self.assertNotEqual(Tuple[A[List[Any]]], Tuple[B.A[List[Any]]]) 3667 self.assertNotEqual(Union[str, A[str]], Union[str, mod_generics_cache.A[str]]) 3668 self.assertNotEqual(Union[A[str], A[str]], 3669 Union[A[str], mod_generics_cache.A[str]]) 3670 self.assertNotEqual(typing.FrozenSet[A[str]], 3671 typing.FrozenSet[mod_generics_cache.B.A[str]]) 3672 3673 self.assertTrue(repr(Tuple[A[str]]).endswith('<locals>.A[str]]')) 3674 self.assertTrue(repr(Tuple[B.A[str]]).endswith('<locals>.B.A[str]]')) 3675 self.assertTrue(repr(Tuple[mod_generics_cache.A[str]]) 3676 .endswith('mod_generics_cache.A[str]]')) 3677 self.assertTrue(repr(Tuple[mod_generics_cache.B.A[str]]) 3678 .endswith('mod_generics_cache.B.A[str]]')) 3679 3680 def test_extended_generic_rules_eq(self): 3681 T = TypeVar('T') 3682 U = TypeVar('U') 3683 self.assertEqual(Tuple[T, T][int], Tuple[int, int]) 3684 self.assertEqual(typing.Iterable[Tuple[T, T]][T], typing.Iterable[Tuple[T, T]]) 3685 with self.assertRaises(TypeError): 3686 Tuple[T, int][()] 3687 3688 self.assertEqual(Union[T, int][int], int) 3689 self.assertEqual(Union[T, U][int, Union[int, str]], Union[int, str]) 3690 class Base: ... 3691 class Derived(Base): ... 3692 self.assertEqual(Union[T, Base][Union[Base, Derived]], Union[Base, Derived]) 3693 self.assertEqual(Callable[[T], T][KT], Callable[[KT], KT]) 3694 self.assertEqual(Callable[..., List[T]][int], Callable[..., List[int]]) 3695 3696 def test_extended_generic_rules_repr(self): 3697 T = TypeVar('T') 3698 self.assertEqual(repr(Union[Tuple, Callable]).replace('typing.', ''), 3699 'Union[Tuple, Callable]') 3700 self.assertEqual(repr(Union[Tuple, Tuple[int]]).replace('typing.', ''), 3701 'Union[Tuple, Tuple[int]]') 3702 self.assertEqual(repr(Callable[..., Optional[T]][int]).replace('typing.', ''), 3703 'Callable[..., Optional[int]]') 3704 self.assertEqual(repr(Callable[[], List[T]][int]).replace('typing.', ''), 3705 'Callable[[], List[int]]') 3706 3707 def test_generic_forward_ref(self): 3708 def foobar(x: List[List['CC']]): ... 3709 def foobar2(x: list[list[ForwardRef('CC')]]): ... 3710 def foobar3(x: list[ForwardRef('CC | int')] | int): ... 3711 class CC: ... 3712 self.assertEqual( 3713 get_type_hints(foobar, globals(), locals()), 3714 {'x': List[List[CC]]} 3715 ) 3716 self.assertEqual( 3717 get_type_hints(foobar2, globals(), locals()), 3718 {'x': list[list[CC]]} 3719 ) 3720 self.assertEqual( 3721 get_type_hints(foobar3, globals(), locals()), 3722 {'x': list[CC | int] | int} 3723 ) 3724 3725 T = TypeVar('T') 3726 AT = Tuple[T, ...] 3727 def barfoo(x: AT): ... 3728 self.assertIs(get_type_hints(barfoo, globals(), locals())['x'], AT) 3729 CT = Callable[..., List[T]] 3730 def barfoo2(x: CT): ... 3731 self.assertIs(get_type_hints(barfoo2, globals(), locals())['x'], CT) 3732 3733 def test_generic_pep585_forward_ref(self): 3734 # See https://bugs.python.org/issue41370 3735 3736 class C1: 3737 a: list['C1'] 3738 self.assertEqual( 3739 get_type_hints(C1, globals(), locals()), 3740 {'a': list[C1]} 3741 ) 3742 3743 class C2: 3744 a: dict['C1', list[List[list['C2']]]] 3745 self.assertEqual( 3746 get_type_hints(C2, globals(), locals()), 3747 {'a': dict[C1, list[List[list[C2]]]]} 3748 ) 3749 3750 # Test stringified annotations 3751 scope = {} 3752 exec(textwrap.dedent(''' 3753 from __future__ import annotations 3754 class C3: 3755 a: List[list["C2"]] 3756 '''), scope) 3757 C3 = scope['C3'] 3758 self.assertEqual(C3.__annotations__['a'], "List[list['C2']]") 3759 self.assertEqual( 3760 get_type_hints(C3, globals(), locals()), 3761 {'a': List[list[C2]]} 3762 ) 3763 3764 # Test recursive types 3765 X = list["X"] 3766 def f(x: X): ... 3767 self.assertEqual( 3768 get_type_hints(f, globals(), locals()), 3769 {'x': list[list[ForwardRef('X')]]} 3770 ) 3771 3772 def test_extended_generic_rules_subclassing(self): 3773 class T1(Tuple[T, KT]): ... 3774 class T2(Tuple[T, ...]): ... 3775 class C1(typing.Container[T]): 3776 def __contains__(self, item): 3777 return False 3778 3779 self.assertEqual(T1.__parameters__, (T, KT)) 3780 self.assertEqual(T1[int, str].__args__, (int, str)) 3781 self.assertEqual(T1[int, T].__origin__, T1) 3782 3783 self.assertEqual(T2.__parameters__, (T,)) 3784 # These don't work because of tuple.__class_item__ 3785 ## with self.assertRaises(TypeError): 3786 ## T1[int] 3787 ## with self.assertRaises(TypeError): 3788 ## T2[int, str] 3789 3790 self.assertEqual(repr(C1[int]).split('.')[-1], 'C1[int]') 3791 self.assertEqual(C1.__parameters__, (T,)) 3792 self.assertIsInstance(C1(), collections.abc.Container) 3793 self.assertIsSubclass(C1, collections.abc.Container) 3794 self.assertIsInstance(T1(), tuple) 3795 self.assertIsSubclass(T2, tuple) 3796 with self.assertRaises(TypeError): 3797 issubclass(Tuple[int, ...], typing.Sequence) 3798 with self.assertRaises(TypeError): 3799 issubclass(Tuple[int, ...], typing.Iterable) 3800 3801 def test_fail_with_bare_union(self): 3802 with self.assertRaises(TypeError): 3803 List[Union] 3804 with self.assertRaises(TypeError): 3805 Tuple[Optional] 3806 with self.assertRaises(TypeError): 3807 ClassVar[ClassVar[int]] 3808 with self.assertRaises(TypeError): 3809 List[ClassVar[int]] 3810 3811 def test_fail_with_bare_generic(self): 3812 T = TypeVar('T') 3813 with self.assertRaises(TypeError): 3814 List[Generic] 3815 with self.assertRaises(TypeError): 3816 Tuple[Generic[T]] 3817 with self.assertRaises(TypeError): 3818 List[typing.Protocol] 3819 3820 def test_type_erasure_special(self): 3821 T = TypeVar('T') 3822 # this is the only test that checks type caching 3823 self.clear_caches() 3824 class MyTup(Tuple[T, T]): ... 3825 self.assertIs(MyTup[int]().__class__, MyTup) 3826 self.assertEqual(MyTup[int]().__orig_class__, MyTup[int]) 3827 class MyDict(typing.Dict[T, T]): ... 3828 self.assertIs(MyDict[int]().__class__, MyDict) 3829 self.assertEqual(MyDict[int]().__orig_class__, MyDict[int]) 3830 class MyDef(typing.DefaultDict[str, T]): ... 3831 self.assertIs(MyDef[int]().__class__, MyDef) 3832 self.assertEqual(MyDef[int]().__orig_class__, MyDef[int]) 3833 class MyChain(typing.ChainMap[str, T]): ... 3834 self.assertIs(MyChain[int]().__class__, MyChain) 3835 self.assertEqual(MyChain[int]().__orig_class__, MyChain[int]) 3836 3837 def test_all_repr_eq_any(self): 3838 objs = (getattr(typing, el) for el in typing.__all__) 3839 for obj in objs: 3840 self.assertNotEqual(repr(obj), '') 3841 self.assertEqual(obj, obj) 3842 if (getattr(obj, '__parameters__', None) 3843 and not isinstance(obj, typing.TypeVar) 3844 and isinstance(obj.__parameters__, tuple) 3845 and len(obj.__parameters__) == 1): 3846 self.assertEqual(obj[Any].__args__, (Any,)) 3847 if isinstance(obj, type): 3848 for base in obj.__mro__: 3849 self.assertNotEqual(repr(base), '') 3850 self.assertEqual(base, base) 3851 3852 def test_pickle(self): 3853 global C # pickle wants to reference the class by name 3854 T = TypeVar('T') 3855 3856 class B(Generic[T]): 3857 pass 3858 3859 class C(B[int]): 3860 pass 3861 3862 c = C() 3863 c.foo = 42 3864 c.bar = 'abc' 3865 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 3866 z = pickle.dumps(c, proto) 3867 x = pickle.loads(z) 3868 self.assertEqual(x.foo, 42) 3869 self.assertEqual(x.bar, 'abc') 3870 self.assertEqual(x.__dict__, {'foo': 42, 'bar': 'abc'}) 3871 samples = [Any, Union, Tuple, Callable, ClassVar, 3872 Union[int, str], ClassVar[List], Tuple[int, ...], Tuple[()], 3873 Callable[[str], bytes], 3874 typing.DefaultDict, typing.FrozenSet[int]] 3875 for s in samples: 3876 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 3877 z = pickle.dumps(s, proto) 3878 x = pickle.loads(z) 3879 self.assertEqual(s, x) 3880 more_samples = [List, typing.Iterable, typing.Type, List[int], 3881 typing.Type[typing.Mapping], typing.AbstractSet[Tuple[int, str]]] 3882 for s in more_samples: 3883 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 3884 z = pickle.dumps(s, proto) 3885 x = pickle.loads(z) 3886 self.assertEqual(s, x) 3887 3888 def test_copy_and_deepcopy(self): 3889 T = TypeVar('T') 3890 class Node(Generic[T]): ... 3891 things = [Union[T, int], Tuple[T, int], Tuple[()], 3892 Callable[..., T], Callable[[int], int], 3893 Tuple[Any, Any], Node[T], Node[int], Node[Any], typing.Iterable[T], 3894 typing.Iterable[Any], typing.Iterable[int], typing.Dict[int, str], 3895 typing.Dict[T, Any], ClassVar[int], ClassVar[List[T]], Tuple['T', 'T'], 3896 Union['T', int], List['T'], typing.Mapping['T', int]] 3897 for t in things + [Any]: 3898 self.assertEqual(t, copy(t)) 3899 self.assertEqual(t, deepcopy(t)) 3900 3901 def test_immutability_by_copy_and_pickle(self): 3902 # Special forms like Union, Any, etc., generic aliases to containers like List, 3903 # Mapping, etc., and type variabcles are considered immutable by copy and pickle. 3904 global TP, TPB, TPV, PP # for pickle 3905 TP = TypeVar('TP') 3906 TPB = TypeVar('TPB', bound=int) 3907 TPV = TypeVar('TPV', bytes, str) 3908 PP = ParamSpec('PP') 3909 for X in [TP, TPB, TPV, PP, 3910 List, typing.Mapping, ClassVar, typing.Iterable, 3911 Union, Any, Tuple, Callable]: 3912 with self.subTest(thing=X): 3913 self.assertIs(copy(X), X) 3914 self.assertIs(deepcopy(X), X) 3915 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 3916 self.assertIs(pickle.loads(pickle.dumps(X, proto)), X) 3917 del TP, TPB, TPV, PP 3918 3919 # Check that local type variables are copyable. 3920 TL = TypeVar('TL') 3921 TLB = TypeVar('TLB', bound=int) 3922 TLV = TypeVar('TLV', bytes, str) 3923 PL = ParamSpec('PL') 3924 for X in [TL, TLB, TLV, PL]: 3925 with self.subTest(thing=X): 3926 self.assertIs(copy(X), X) 3927 self.assertIs(deepcopy(X), X) 3928 3929 def test_copy_generic_instances(self): 3930 T = TypeVar('T') 3931 class C(Generic[T]): 3932 def __init__(self, attr: T) -> None: 3933 self.attr = attr 3934 3935 c = C(42) 3936 self.assertEqual(copy(c).attr, 42) 3937 self.assertEqual(deepcopy(c).attr, 42) 3938 self.assertIsNot(copy(c), c) 3939 self.assertIsNot(deepcopy(c), c) 3940 c.attr = 1 3941 self.assertEqual(copy(c).attr, 1) 3942 self.assertEqual(deepcopy(c).attr, 1) 3943 ci = C[int](42) 3944 self.assertEqual(copy(ci).attr, 42) 3945 self.assertEqual(deepcopy(ci).attr, 42) 3946 self.assertIsNot(copy(ci), ci) 3947 self.assertIsNot(deepcopy(ci), ci) 3948 ci.attr = 1 3949 self.assertEqual(copy(ci).attr, 1) 3950 self.assertEqual(deepcopy(ci).attr, 1) 3951 self.assertEqual(ci.__orig_class__, C[int]) 3952 3953 def test_weakref_all(self): 3954 T = TypeVar('T') 3955 things = [Any, Union[T, int], Callable[..., T], Tuple[Any, Any], 3956 Optional[List[int]], typing.Mapping[int, str], 3957 typing.Match[bytes], typing.Iterable['whatever']] 3958 for t in things: 3959 self.assertEqual(weakref.ref(t)(), t) 3960 3961 def test_parameterized_slots(self): 3962 T = TypeVar('T') 3963 class C(Generic[T]): 3964 __slots__ = ('potato',) 3965 3966 c = C() 3967 c_int = C[int]() 3968 3969 c.potato = 0 3970 c_int.potato = 0 3971 with self.assertRaises(AttributeError): 3972 c.tomato = 0 3973 with self.assertRaises(AttributeError): 3974 c_int.tomato = 0 3975 3976 def foo(x: C['C']): ... 3977 self.assertEqual(get_type_hints(foo, globals(), locals())['x'], C[C]) 3978 self.assertEqual(copy(C[int]), deepcopy(C[int])) 3979 3980 def test_parameterized_slots_dict(self): 3981 T = TypeVar('T') 3982 class D(Generic[T]): 3983 __slots__ = {'banana': 42} 3984 3985 d = D() 3986 d_int = D[int]() 3987 3988 d.banana = 'yes' 3989 d_int.banana = 'yes' 3990 with self.assertRaises(AttributeError): 3991 d.foobar = 'no' 3992 with self.assertRaises(AttributeError): 3993 d_int.foobar = 'no' 3994 3995 def test_errors(self): 3996 with self.assertRaises(TypeError): 3997 B = SimpleMapping[XK, Any] 3998 3999 class C(Generic[B]): 4000 pass 4001 4002 def test_repr_2(self): 4003 class C(Generic[T]): 4004 pass 4005 4006 self.assertEqual(C.__module__, __name__) 4007 self.assertEqual(C.__qualname__, 4008 'GenericTests.test_repr_2.<locals>.C') 4009 X = C[int] 4010 self.assertEqual(X.__module__, __name__) 4011 self.assertEqual(repr(X).split('.')[-1], 'C[int]') 4012 4013 class Y(C[int]): 4014 pass 4015 4016 self.assertEqual(Y.__module__, __name__) 4017 self.assertEqual(Y.__qualname__, 4018 'GenericTests.test_repr_2.<locals>.Y') 4019 4020 def test_eq_1(self): 4021 self.assertEqual(Generic, Generic) 4022 self.assertEqual(Generic[T], Generic[T]) 4023 self.assertNotEqual(Generic[KT], Generic[VT]) 4024 4025 def test_eq_2(self): 4026 4027 class A(Generic[T]): 4028 pass 4029 4030 class B(Generic[T]): 4031 pass 4032 4033 self.assertEqual(A, A) 4034 self.assertNotEqual(A, B) 4035 self.assertEqual(A[T], A[T]) 4036 self.assertNotEqual(A[T], B[T]) 4037 4038 def test_multiple_inheritance(self): 4039 4040 class A(Generic[T, VT]): 4041 pass 4042 4043 class B(Generic[KT, T]): 4044 pass 4045 4046 class C(A[T, VT], Generic[VT, T, KT], B[KT, T]): 4047 pass 4048 4049 self.assertEqual(C.__parameters__, (VT, T, KT)) 4050 4051 def test_multiple_inheritance_special(self): 4052 S = TypeVar('S') 4053 class B(Generic[S]): ... 4054 class C(List[int], B): ... 4055 self.assertEqual(C.__mro__, (C, list, B, Generic, object)) 4056 4057 def test_init_subclass_super_called(self): 4058 class FinalException(Exception): 4059 pass 4060 4061 class Final: 4062 def __init_subclass__(cls, **kwargs) -> None: 4063 for base in cls.__bases__: 4064 if base is not Final and issubclass(base, Final): 4065 raise FinalException(base) 4066 super().__init_subclass__(**kwargs) 4067 class Test(Generic[T], Final): 4068 pass 4069 with self.assertRaises(FinalException): 4070 class Subclass(Test): 4071 pass 4072 with self.assertRaises(FinalException): 4073 class Subclass(Test[int]): 4074 pass 4075 4076 def test_nested(self): 4077 4078 G = Generic 4079 4080 class Visitor(G[T]): 4081 4082 a = None 4083 4084 def set(self, a: T): 4085 self.a = a 4086 4087 def get(self): 4088 return self.a 4089 4090 def visit(self) -> T: 4091 return self.a 4092 4093 V = Visitor[typing.List[int]] 4094 4095 class IntListVisitor(V): 4096 4097 def append(self, x: int): 4098 self.a.append(x) 4099 4100 a = IntListVisitor() 4101 a.set([]) 4102 a.append(1) 4103 a.append(42) 4104 self.assertEqual(a.get(), [1, 42]) 4105 4106 def test_type_erasure(self): 4107 T = TypeVar('T') 4108 4109 class Node(Generic[T]): 4110 def __init__(self, label: T, 4111 left: 'Node[T]' = None, 4112 right: 'Node[T]' = None): 4113 self.label = label # type: T 4114 self.left = left # type: Optional[Node[T]] 4115 self.right = right # type: Optional[Node[T]] 4116 4117 def foo(x: T): 4118 a = Node(x) 4119 b = Node[T](x) 4120 c = Node[Any](x) 4121 self.assertIs(type(a), Node) 4122 self.assertIs(type(b), Node) 4123 self.assertIs(type(c), Node) 4124 self.assertEqual(a.label, x) 4125 self.assertEqual(b.label, x) 4126 self.assertEqual(c.label, x) 4127 4128 foo(42) 4129 4130 def test_implicit_any(self): 4131 T = TypeVar('T') 4132 4133 class C(Generic[T]): 4134 pass 4135 4136 class D(C): 4137 pass 4138 4139 self.assertEqual(D.__parameters__, ()) 4140 4141 with self.assertRaises(TypeError): 4142 D[int] 4143 with self.assertRaises(TypeError): 4144 D[Any] 4145 with self.assertRaises(TypeError): 4146 D[T] 4147 4148 def test_new_with_args(self): 4149 4150 class A(Generic[T]): 4151 pass 4152 4153 class B: 4154 def __new__(cls, arg): 4155 # call object 4156 obj = super().__new__(cls) 4157 obj.arg = arg 4158 return obj 4159 4160 # mro: C, A, Generic, B, object 4161 class C(A, B): 4162 pass 4163 4164 c = C('foo') 4165 self.assertEqual(c.arg, 'foo') 4166 4167 def test_new_with_args2(self): 4168 4169 class A: 4170 def __init__(self, arg): 4171 self.from_a = arg 4172 # call object 4173 super().__init__() 4174 4175 # mro: C, Generic, A, object 4176 class C(Generic[T], A): 4177 def __init__(self, arg): 4178 self.from_c = arg 4179 # call Generic 4180 super().__init__(arg) 4181 4182 c = C('foo') 4183 self.assertEqual(c.from_a, 'foo') 4184 self.assertEqual(c.from_c, 'foo') 4185 4186 def test_new_no_args(self): 4187 4188 class A(Generic[T]): 4189 pass 4190 4191 with self.assertRaises(TypeError): 4192 A('foo') 4193 4194 class B: 4195 def __new__(cls): 4196 # call object 4197 obj = super().__new__(cls) 4198 obj.from_b = 'b' 4199 return obj 4200 4201 # mro: C, A, Generic, B, object 4202 class C(A, B): 4203 def __init__(self, arg): 4204 self.arg = arg 4205 4206 def __new__(cls, arg): 4207 # call A 4208 obj = super().__new__(cls) 4209 obj.from_c = 'c' 4210 return obj 4211 4212 c = C('foo') 4213 self.assertEqual(c.arg, 'foo') 4214 self.assertEqual(c.from_b, 'b') 4215 self.assertEqual(c.from_c, 'c') 4216 4217 def test_subclass_special_form(self): 4218 for obj in ( 4219 ClassVar[int], 4220 Final[int], 4221 Union[int, float], 4222 Optional[int], 4223 Literal[1, 2], 4224 Concatenate[int, ParamSpec("P")], 4225 TypeGuard[int], 4226 ): 4227 with self.subTest(msg=obj): 4228 with self.assertRaisesRegex( 4229 TypeError, f'^{re.escape(f"Cannot subclass {obj!r}")}$' 4230 ): 4231 class Foo(obj): 4232 pass 4233 4234 def test_complex_subclasses(self): 4235 T_co = TypeVar("T_co", covariant=True) 4236 4237 class Base(Generic[T_co]): 4238 ... 4239 4240 T = TypeVar("T") 4241 4242 # see gh-94607: this fails in that bug 4243 class Sub(Base, Generic[T]): 4244 ... 4245 4246 def test_parameter_detection(self): 4247 self.assertEqual(List[T].__parameters__, (T,)) 4248 self.assertEqual(List[List[T]].__parameters__, (T,)) 4249 class A: 4250 __parameters__ = (T,) 4251 # Bare classes should be skipped 4252 for a in (List, list): 4253 for b in (A, int, TypeVar, TypeVarTuple, ParamSpec, types.GenericAlias, types.UnionType): 4254 with self.subTest(generic=a, sub=b): 4255 with self.assertRaisesRegex(TypeError, '.* is not a generic class'): 4256 a[b][str] 4257 # Duck-typing anything that looks like it has __parameters__. 4258 # These tests are optional and failure is okay. 4259 self.assertEqual(List[A()].__parameters__, (T,)) 4260 # C version of GenericAlias 4261 self.assertEqual(list[A()].__parameters__, (T,)) 4262 4263 def test_non_generic_subscript(self): 4264 T = TypeVar('T') 4265 class G(Generic[T]): 4266 pass 4267 class A: 4268 __parameters__ = (T,) 4269 4270 for s in (int, G, A, List, list, 4271 TypeVar, TypeVarTuple, ParamSpec, 4272 types.GenericAlias, types.UnionType): 4273 4274 for t in Tuple, tuple: 4275 with self.subTest(tuple=t, sub=s): 4276 self.assertEqual(t[s, T][int], t[s, int]) 4277 self.assertEqual(t[T, s][int], t[int, s]) 4278 a = t[s] 4279 with self.assertRaises(TypeError): 4280 a[int] 4281 4282 for c in Callable, collections.abc.Callable: 4283 with self.subTest(callable=c, sub=s): 4284 self.assertEqual(c[[s], T][int], c[[s], int]) 4285 self.assertEqual(c[[T], s][int], c[[int], s]) 4286 a = c[[s], s] 4287 with self.assertRaises(TypeError): 4288 a[int] 4289 4290 4291class ClassVarTests(BaseTestCase): 4292 4293 def test_basics(self): 4294 with self.assertRaises(TypeError): 4295 ClassVar[int, str] 4296 with self.assertRaises(TypeError): 4297 ClassVar[int][str] 4298 4299 def test_repr(self): 4300 self.assertEqual(repr(ClassVar), 'typing.ClassVar') 4301 cv = ClassVar[int] 4302 self.assertEqual(repr(cv), 'typing.ClassVar[int]') 4303 cv = ClassVar[Employee] 4304 self.assertEqual(repr(cv), 'typing.ClassVar[%s.Employee]' % __name__) 4305 4306 def test_cannot_subclass(self): 4307 with self.assertRaises(TypeError): 4308 class C(type(ClassVar)): 4309 pass 4310 with self.assertRaises(TypeError): 4311 class C(type(ClassVar[int])): 4312 pass 4313 4314 def test_cannot_init(self): 4315 with self.assertRaises(TypeError): 4316 ClassVar() 4317 with self.assertRaises(TypeError): 4318 type(ClassVar)() 4319 with self.assertRaises(TypeError): 4320 type(ClassVar[Optional[int]])() 4321 4322 def test_no_isinstance(self): 4323 with self.assertRaises(TypeError): 4324 isinstance(1, ClassVar[int]) 4325 with self.assertRaises(TypeError): 4326 issubclass(int, ClassVar) 4327 4328class FinalTests(BaseTestCase): 4329 4330 def test_basics(self): 4331 Final[int] # OK 4332 with self.assertRaises(TypeError): 4333 Final[int, str] 4334 with self.assertRaises(TypeError): 4335 Final[int][str] 4336 with self.assertRaises(TypeError): 4337 Optional[Final[int]] 4338 4339 def test_repr(self): 4340 self.assertEqual(repr(Final), 'typing.Final') 4341 cv = Final[int] 4342 self.assertEqual(repr(cv), 'typing.Final[int]') 4343 cv = Final[Employee] 4344 self.assertEqual(repr(cv), 'typing.Final[%s.Employee]' % __name__) 4345 cv = Final[tuple[int]] 4346 self.assertEqual(repr(cv), 'typing.Final[tuple[int]]') 4347 4348 def test_cannot_subclass(self): 4349 with self.assertRaises(TypeError): 4350 class C(type(Final)): 4351 pass 4352 with self.assertRaises(TypeError): 4353 class C(type(Final[int])): 4354 pass 4355 4356 def test_cannot_init(self): 4357 with self.assertRaises(TypeError): 4358 Final() 4359 with self.assertRaises(TypeError): 4360 type(Final)() 4361 with self.assertRaises(TypeError): 4362 type(Final[Optional[int]])() 4363 4364 def test_no_isinstance(self): 4365 with self.assertRaises(TypeError): 4366 isinstance(1, Final[int]) 4367 with self.assertRaises(TypeError): 4368 issubclass(int, Final) 4369 4370 4371class FinalDecoratorTests(BaseTestCase): 4372 def test_final_unmodified(self): 4373 def func(x): ... 4374 self.assertIs(func, final(func)) 4375 4376 def test_dunder_final(self): 4377 @final 4378 def func(): ... 4379 @final 4380 class Cls: ... 4381 self.assertIs(True, func.__final__) 4382 self.assertIs(True, Cls.__final__) 4383 4384 class Wrapper: 4385 __slots__ = ("func",) 4386 def __init__(self, func): 4387 self.func = func 4388 def __call__(self, *args, **kwargs): 4389 return self.func(*args, **kwargs) 4390 4391 # Check that no error is thrown if the attribute 4392 # is not writable. 4393 @final 4394 @Wrapper 4395 def wrapped(): ... 4396 self.assertIsInstance(wrapped, Wrapper) 4397 self.assertIs(False, hasattr(wrapped, "__final__")) 4398 4399 class Meta(type): 4400 @property 4401 def __final__(self): return "can't set me" 4402 @final 4403 class WithMeta(metaclass=Meta): ... 4404 self.assertEqual(WithMeta.__final__, "can't set me") 4405 4406 # Builtin classes throw TypeError if you try to set an 4407 # attribute. 4408 final(int) 4409 self.assertIs(False, hasattr(int, "__final__")) 4410 4411 # Make sure it works with common builtin decorators 4412 class Methods: 4413 @final 4414 @classmethod 4415 def clsmethod(cls): ... 4416 4417 @final 4418 @staticmethod 4419 def stmethod(): ... 4420 4421 # The other order doesn't work because property objects 4422 # don't allow attribute assignment. 4423 @property 4424 @final 4425 def prop(self): ... 4426 4427 @final 4428 @lru_cache() 4429 def cached(self): ... 4430 4431 # Use getattr_static because the descriptor returns the 4432 # underlying function, which doesn't have __final__. 4433 self.assertIs( 4434 True, 4435 inspect.getattr_static(Methods, "clsmethod").__final__ 4436 ) 4437 self.assertIs( 4438 True, 4439 inspect.getattr_static(Methods, "stmethod").__final__ 4440 ) 4441 self.assertIs(True, Methods.prop.fget.__final__) 4442 self.assertIs(True, Methods.cached.__final__) 4443 4444 4445class CastTests(BaseTestCase): 4446 4447 def test_basics(self): 4448 self.assertEqual(cast(int, 42), 42) 4449 self.assertEqual(cast(float, 42), 42) 4450 self.assertIs(type(cast(float, 42)), int) 4451 self.assertEqual(cast(Any, 42), 42) 4452 self.assertEqual(cast(list, 42), 42) 4453 self.assertEqual(cast(Union[str, float], 42), 42) 4454 self.assertEqual(cast(AnyStr, 42), 42) 4455 self.assertEqual(cast(None, 42), 42) 4456 4457 def test_errors(self): 4458 # Bogus calls are not expected to fail. 4459 cast(42, 42) 4460 cast('hello', 42) 4461 4462 4463class AssertTypeTests(BaseTestCase): 4464 4465 def test_basics(self): 4466 arg = 42 4467 self.assertIs(assert_type(arg, int), arg) 4468 self.assertIs(assert_type(arg, str | float), arg) 4469 self.assertIs(assert_type(arg, AnyStr), arg) 4470 self.assertIs(assert_type(arg, None), arg) 4471 4472 def test_errors(self): 4473 # Bogus calls are not expected to fail. 4474 arg = 42 4475 self.assertIs(assert_type(arg, 42), arg) 4476 self.assertIs(assert_type(arg, 'hello'), arg) 4477 4478 4479# We need this to make sure that `@no_type_check` respects `__module__` attr: 4480from test import ann_module8 4481 4482@no_type_check 4483class NoTypeCheck_Outer: 4484 Inner = ann_module8.NoTypeCheck_Outer.Inner 4485 4486@no_type_check 4487class NoTypeCheck_WithFunction: 4488 NoTypeCheck_function = ann_module8.NoTypeCheck_function 4489 4490 4491class ForwardRefTests(BaseTestCase): 4492 4493 def test_basics(self): 4494 4495 class Node(Generic[T]): 4496 4497 def __init__(self, label: T): 4498 self.label = label 4499 self.left = self.right = None 4500 4501 def add_both(self, 4502 left: 'Optional[Node[T]]', 4503 right: 'Node[T]' = None, 4504 stuff: int = None, 4505 blah=None): 4506 self.left = left 4507 self.right = right 4508 4509 def add_left(self, node: Optional['Node[T]']): 4510 self.add_both(node, None) 4511 4512 def add_right(self, node: 'Node[T]' = None): 4513 self.add_both(None, node) 4514 4515 t = Node[int] 4516 both_hints = get_type_hints(t.add_both, globals(), locals()) 4517 self.assertEqual(both_hints['left'], Optional[Node[T]]) 4518 self.assertEqual(both_hints['right'], Node[T]) 4519 self.assertEqual(both_hints['stuff'], int) 4520 self.assertNotIn('blah', both_hints) 4521 4522 left_hints = get_type_hints(t.add_left, globals(), locals()) 4523 self.assertEqual(left_hints['node'], Optional[Node[T]]) 4524 4525 right_hints = get_type_hints(t.add_right, globals(), locals()) 4526 self.assertEqual(right_hints['node'], Node[T]) 4527 4528 def test_forwardref_instance_type_error(self): 4529 fr = typing.ForwardRef('int') 4530 with self.assertRaises(TypeError): 4531 isinstance(42, fr) 4532 4533 def test_forwardref_subclass_type_error(self): 4534 fr = typing.ForwardRef('int') 4535 with self.assertRaises(TypeError): 4536 issubclass(int, fr) 4537 4538 def test_forwardref_only_str_arg(self): 4539 with self.assertRaises(TypeError): 4540 typing.ForwardRef(1) # only `str` type is allowed 4541 4542 def test_forward_equality(self): 4543 fr = typing.ForwardRef('int') 4544 self.assertEqual(fr, typing.ForwardRef('int')) 4545 self.assertNotEqual(List['int'], List[int]) 4546 self.assertNotEqual(fr, typing.ForwardRef('int', module=__name__)) 4547 frm = typing.ForwardRef('int', module=__name__) 4548 self.assertEqual(frm, typing.ForwardRef('int', module=__name__)) 4549 self.assertNotEqual(frm, typing.ForwardRef('int', module='__other_name__')) 4550 4551 def test_forward_equality_gth(self): 4552 c1 = typing.ForwardRef('C') 4553 c1_gth = typing.ForwardRef('C') 4554 c2 = typing.ForwardRef('C') 4555 c2_gth = typing.ForwardRef('C') 4556 4557 class C: 4558 pass 4559 def foo(a: c1_gth, b: c2_gth): 4560 pass 4561 4562 self.assertEqual(get_type_hints(foo, globals(), locals()), {'a': C, 'b': C}) 4563 self.assertEqual(c1, c2) 4564 self.assertEqual(c1, c1_gth) 4565 self.assertEqual(c1_gth, c2_gth) 4566 self.assertEqual(List[c1], List[c1_gth]) 4567 self.assertNotEqual(List[c1], List[C]) 4568 self.assertNotEqual(List[c1_gth], List[C]) 4569 self.assertEqual(Union[c1, c1_gth], Union[c1]) 4570 self.assertEqual(Union[c1, c1_gth, int], Union[c1, int]) 4571 4572 def test_forward_equality_hash(self): 4573 c1 = typing.ForwardRef('int') 4574 c1_gth = typing.ForwardRef('int') 4575 c2 = typing.ForwardRef('int') 4576 c2_gth = typing.ForwardRef('int') 4577 4578 def foo(a: c1_gth, b: c2_gth): 4579 pass 4580 get_type_hints(foo, globals(), locals()) 4581 4582 self.assertEqual(hash(c1), hash(c2)) 4583 self.assertEqual(hash(c1_gth), hash(c2_gth)) 4584 self.assertEqual(hash(c1), hash(c1_gth)) 4585 4586 c3 = typing.ForwardRef('int', module=__name__) 4587 c4 = typing.ForwardRef('int', module='__other_name__') 4588 4589 self.assertNotEqual(hash(c3), hash(c1)) 4590 self.assertNotEqual(hash(c3), hash(c1_gth)) 4591 self.assertNotEqual(hash(c3), hash(c4)) 4592 self.assertEqual(hash(c3), hash(typing.ForwardRef('int', module=__name__))) 4593 4594 def test_forward_equality_namespace(self): 4595 class A: 4596 pass 4597 def namespace1(): 4598 a = typing.ForwardRef('A') 4599 def fun(x: a): 4600 pass 4601 get_type_hints(fun, globals(), locals()) 4602 return a 4603 4604 def namespace2(): 4605 a = typing.ForwardRef('A') 4606 4607 class A: 4608 pass 4609 def fun(x: a): 4610 pass 4611 4612 get_type_hints(fun, globals(), locals()) 4613 return a 4614 4615 self.assertEqual(namespace1(), namespace1()) 4616 self.assertNotEqual(namespace1(), namespace2()) 4617 4618 def test_forward_repr(self): 4619 self.assertEqual(repr(List['int']), "typing.List[ForwardRef('int')]") 4620 self.assertEqual(repr(List[ForwardRef('int', module='mod')]), 4621 "typing.List[ForwardRef('int', module='mod')]") 4622 4623 def test_union_forward(self): 4624 4625 def foo(a: Union['T']): 4626 pass 4627 4628 self.assertEqual(get_type_hints(foo, globals(), locals()), 4629 {'a': Union[T]}) 4630 4631 def foo(a: tuple[ForwardRef('T')] | int): 4632 pass 4633 4634 self.assertEqual(get_type_hints(foo, globals(), locals()), 4635 {'a': tuple[T] | int}) 4636 4637 def test_tuple_forward(self): 4638 4639 def foo(a: Tuple['T']): 4640 pass 4641 4642 self.assertEqual(get_type_hints(foo, globals(), locals()), 4643 {'a': Tuple[T]}) 4644 4645 def foo(a: tuple[ForwardRef('T')]): 4646 pass 4647 4648 self.assertEqual(get_type_hints(foo, globals(), locals()), 4649 {'a': tuple[T]}) 4650 4651 def test_double_forward(self): 4652 def foo(a: 'List[\'int\']'): 4653 pass 4654 self.assertEqual(get_type_hints(foo, globals(), locals()), 4655 {'a': List[int]}) 4656 4657 def test_forward_recursion_actually(self): 4658 def namespace1(): 4659 a = typing.ForwardRef('A') 4660 A = a 4661 def fun(x: a): pass 4662 4663 ret = get_type_hints(fun, globals(), locals()) 4664 return a 4665 4666 def namespace2(): 4667 a = typing.ForwardRef('A') 4668 A = a 4669 def fun(x: a): pass 4670 4671 ret = get_type_hints(fun, globals(), locals()) 4672 return a 4673 4674 def cmp(o1, o2): 4675 return o1 == o2 4676 4677 r1 = namespace1() 4678 r2 = namespace2() 4679 self.assertIsNot(r1, r2) 4680 self.assertRaises(RecursionError, cmp, r1, r2) 4681 4682 def test_union_forward_recursion(self): 4683 ValueList = List['Value'] 4684 Value = Union[str, ValueList] 4685 4686 class C: 4687 foo: List[Value] 4688 class D: 4689 foo: Union[Value, ValueList] 4690 class E: 4691 foo: Union[List[Value], ValueList] 4692 class F: 4693 foo: Union[Value, List[Value], ValueList] 4694 4695 self.assertEqual(get_type_hints(C, globals(), locals()), get_type_hints(C, globals(), locals())) 4696 self.assertEqual(get_type_hints(C, globals(), locals()), 4697 {'foo': List[Union[str, List[Union[str, List['Value']]]]]}) 4698 self.assertEqual(get_type_hints(D, globals(), locals()), 4699 {'foo': Union[str, List[Union[str, List['Value']]]]}) 4700 self.assertEqual(get_type_hints(E, globals(), locals()), 4701 {'foo': Union[ 4702 List[Union[str, List[Union[str, List['Value']]]]], 4703 List[Union[str, List['Value']]] 4704 ] 4705 }) 4706 self.assertEqual(get_type_hints(F, globals(), locals()), 4707 {'foo': Union[ 4708 str, 4709 List[Union[str, List['Value']]], 4710 List[Union[str, List[Union[str, List['Value']]]]] 4711 ] 4712 }) 4713 4714 def test_callable_forward(self): 4715 4716 def foo(a: Callable[['T'], 'T']): 4717 pass 4718 4719 self.assertEqual(get_type_hints(foo, globals(), locals()), 4720 {'a': Callable[[T], T]}) 4721 4722 def test_callable_with_ellipsis_forward(self): 4723 4724 def foo(a: 'Callable[..., T]'): 4725 pass 4726 4727 self.assertEqual(get_type_hints(foo, globals(), locals()), 4728 {'a': Callable[..., T]}) 4729 4730 def test_special_forms_forward(self): 4731 4732 class C: 4733 a: Annotated['ClassVar[int]', (3, 5)] = 4 4734 b: Annotated['Final[int]', "const"] = 4 4735 x: 'ClassVar' = 4 4736 y: 'Final' = 4 4737 4738 class CF: 4739 b: List['Final[int]'] = 4 4740 4741 self.assertEqual(get_type_hints(C, globals())['a'], ClassVar[int]) 4742 self.assertEqual(get_type_hints(C, globals())['b'], Final[int]) 4743 self.assertEqual(get_type_hints(C, globals())['x'], ClassVar) 4744 self.assertEqual(get_type_hints(C, globals())['y'], Final) 4745 with self.assertRaises(TypeError): 4746 get_type_hints(CF, globals()), 4747 4748 def test_syntax_error(self): 4749 4750 with self.assertRaises(SyntaxError): 4751 Generic['/T'] 4752 4753 def test_delayed_syntax_error(self): 4754 4755 def foo(a: 'Node[T'): 4756 pass 4757 4758 with self.assertRaises(SyntaxError): 4759 get_type_hints(foo) 4760 4761 def test_name_error(self): 4762 4763 def foo(a: 'Noode[T]'): 4764 pass 4765 4766 with self.assertRaises(NameError): 4767 get_type_hints(foo, locals()) 4768 4769 def test_no_type_check(self): 4770 4771 @no_type_check 4772 def foo(a: 'whatevers') -> {}: 4773 pass 4774 4775 th = get_type_hints(foo) 4776 self.assertEqual(th, {}) 4777 4778 def test_no_type_check_class(self): 4779 4780 @no_type_check 4781 class C: 4782 def foo(a: 'whatevers') -> {}: 4783 pass 4784 4785 cth = get_type_hints(C.foo) 4786 self.assertEqual(cth, {}) 4787 ith = get_type_hints(C().foo) 4788 self.assertEqual(ith, {}) 4789 4790 def test_no_type_check_no_bases(self): 4791 class C: 4792 def meth(self, x: int): ... 4793 @no_type_check 4794 class D(C): 4795 c = C 4796 4797 # verify that @no_type_check never affects bases 4798 self.assertEqual(get_type_hints(C.meth), {'x': int}) 4799 4800 # and never child classes: 4801 class Child(D): 4802 def foo(self, x: int): ... 4803 4804 self.assertEqual(get_type_hints(Child.foo), {'x': int}) 4805 4806 def test_no_type_check_nested_types(self): 4807 # See https://bugs.python.org/issue46571 4808 class Other: 4809 o: int 4810 class B: # Has the same `__name__`` as `A.B` and different `__qualname__` 4811 o: int 4812 @no_type_check 4813 class A: 4814 a: int 4815 class B: 4816 b: int 4817 class C: 4818 c: int 4819 class D: 4820 d: int 4821 4822 Other = Other 4823 4824 for klass in [A, A.B, A.B.C, A.D]: 4825 with self.subTest(klass=klass): 4826 self.assertTrue(klass.__no_type_check__) 4827 self.assertEqual(get_type_hints(klass), {}) 4828 4829 for not_modified in [Other, B]: 4830 with self.subTest(not_modified=not_modified): 4831 with self.assertRaises(AttributeError): 4832 not_modified.__no_type_check__ 4833 self.assertNotEqual(get_type_hints(not_modified), {}) 4834 4835 def test_no_type_check_class_and_static_methods(self): 4836 @no_type_check 4837 class Some: 4838 @staticmethod 4839 def st(x: int) -> int: ... 4840 @classmethod 4841 def cl(cls, y: int) -> int: ... 4842 4843 self.assertTrue(Some.st.__no_type_check__) 4844 self.assertEqual(get_type_hints(Some.st), {}) 4845 self.assertTrue(Some.cl.__no_type_check__) 4846 self.assertEqual(get_type_hints(Some.cl), {}) 4847 4848 def test_no_type_check_other_module(self): 4849 self.assertTrue(NoTypeCheck_Outer.__no_type_check__) 4850 with self.assertRaises(AttributeError): 4851 ann_module8.NoTypeCheck_Outer.__no_type_check__ 4852 with self.assertRaises(AttributeError): 4853 ann_module8.NoTypeCheck_Outer.Inner.__no_type_check__ 4854 4855 self.assertTrue(NoTypeCheck_WithFunction.__no_type_check__) 4856 with self.assertRaises(AttributeError): 4857 ann_module8.NoTypeCheck_function.__no_type_check__ 4858 4859 def test_no_type_check_foreign_functions(self): 4860 # We should not modify this function: 4861 def some(*args: int) -> int: 4862 ... 4863 4864 @no_type_check 4865 class A: 4866 some_alias = some 4867 some_class = classmethod(some) 4868 some_static = staticmethod(some) 4869 4870 with self.assertRaises(AttributeError): 4871 some.__no_type_check__ 4872 self.assertEqual(get_type_hints(some), {'args': int, 'return': int}) 4873 4874 def test_no_type_check_lambda(self): 4875 @no_type_check 4876 class A: 4877 # Corner case: `lambda` is both an assignment and a function: 4878 bar: Callable[[int], int] = lambda arg: arg 4879 4880 self.assertTrue(A.bar.__no_type_check__) 4881 self.assertEqual(get_type_hints(A.bar), {}) 4882 4883 def test_no_type_check_TypeError(self): 4884 # This simply should not fail with 4885 # `TypeError: can't set attributes of built-in/extension type 'dict'` 4886 no_type_check(dict) 4887 4888 def test_no_type_check_forward_ref_as_string(self): 4889 class C: 4890 foo: typing.ClassVar[int] = 7 4891 class D: 4892 foo: ClassVar[int] = 7 4893 class E: 4894 foo: 'typing.ClassVar[int]' = 7 4895 class F: 4896 foo: 'ClassVar[int]' = 7 4897 4898 expected_result = {'foo': typing.ClassVar[int]} 4899 for clazz in [C, D, E, F]: 4900 self.assertEqual(get_type_hints(clazz), expected_result) 4901 4902 def test_nested_classvar_fails_forward_ref_check(self): 4903 class E: 4904 foo: 'typing.ClassVar[typing.ClassVar[int]]' = 7 4905 class F: 4906 foo: ClassVar['ClassVar[int]'] = 7 4907 4908 for clazz in [E, F]: 4909 with self.assertRaises(TypeError): 4910 get_type_hints(clazz) 4911 4912 def test_meta_no_type_check(self): 4913 4914 @no_type_check_decorator 4915 def magic_decorator(func): 4916 return func 4917 4918 self.assertEqual(magic_decorator.__name__, 'magic_decorator') 4919 4920 @magic_decorator 4921 def foo(a: 'whatevers') -> {}: 4922 pass 4923 4924 @magic_decorator 4925 class C: 4926 def foo(a: 'whatevers') -> {}: 4927 pass 4928 4929 self.assertEqual(foo.__name__, 'foo') 4930 th = get_type_hints(foo) 4931 self.assertEqual(th, {}) 4932 cth = get_type_hints(C.foo) 4933 self.assertEqual(cth, {}) 4934 ith = get_type_hints(C().foo) 4935 self.assertEqual(ith, {}) 4936 4937 def test_default_globals(self): 4938 code = ("class C:\n" 4939 " def foo(self, a: 'C') -> 'D': pass\n" 4940 "class D:\n" 4941 " def bar(self, b: 'D') -> C: pass\n" 4942 ) 4943 ns = {} 4944 exec(code, ns) 4945 hints = get_type_hints(ns['C'].foo) 4946 self.assertEqual(hints, {'a': ns['C'], 'return': ns['D']}) 4947 4948 def test_final_forward_ref(self): 4949 self.assertEqual(gth(Loop, globals())['attr'], Final[Loop]) 4950 self.assertNotEqual(gth(Loop, globals())['attr'], Final[int]) 4951 self.assertNotEqual(gth(Loop, globals())['attr'], Final) 4952 4953 def test_or(self): 4954 X = ForwardRef('X') 4955 # __or__/__ror__ itself 4956 self.assertEqual(X | "x", Union[X, "x"]) 4957 self.assertEqual("x" | X, Union["x", X]) 4958 4959 4960@lru_cache() 4961def cached_func(x, y): 4962 return 3 * x + y 4963 4964 4965class MethodHolder: 4966 @classmethod 4967 def clsmethod(cls): ... 4968 @staticmethod 4969 def stmethod(): ... 4970 def method(self): ... 4971 4972 4973class OverloadTests(BaseTestCase): 4974 4975 def test_overload_fails(self): 4976 with self.assertRaises(NotImplementedError): 4977 4978 @overload 4979 def blah(): 4980 pass 4981 4982 blah() 4983 4984 def test_overload_succeeds(self): 4985 @overload 4986 def blah(): 4987 pass 4988 4989 def blah(): 4990 pass 4991 4992 blah() 4993 4994 @cpython_only # gh-98713 4995 def test_overload_on_compiled_functions(self): 4996 with patch("typing._overload_registry", 4997 defaultdict(lambda: defaultdict(dict))): 4998 # The registry starts out empty: 4999 self.assertEqual(typing._overload_registry, {}) 5000 5001 # This should just not fail: 5002 overload(sum) 5003 overload(print) 5004 5005 # No overloads are recorded (but, it still has a side-effect): 5006 self.assertEqual(typing.get_overloads(sum), []) 5007 self.assertEqual(typing.get_overloads(print), []) 5008 5009 def set_up_overloads(self): 5010 def blah(): 5011 pass 5012 5013 overload1 = blah 5014 overload(blah) 5015 5016 def blah(): 5017 pass 5018 5019 overload2 = blah 5020 overload(blah) 5021 5022 def blah(): 5023 pass 5024 5025 return blah, [overload1, overload2] 5026 5027 # Make sure we don't clear the global overload registry 5028 @patch("typing._overload_registry", 5029 defaultdict(lambda: defaultdict(dict))) 5030 def test_overload_registry(self): 5031 # The registry starts out empty 5032 self.assertEqual(typing._overload_registry, {}) 5033 5034 impl, overloads = self.set_up_overloads() 5035 self.assertNotEqual(typing._overload_registry, {}) 5036 self.assertEqual(list(get_overloads(impl)), overloads) 5037 5038 def some_other_func(): pass 5039 overload(some_other_func) 5040 other_overload = some_other_func 5041 def some_other_func(): pass 5042 self.assertEqual(list(get_overloads(some_other_func)), [other_overload]) 5043 # Unrelated function still has no overloads: 5044 def not_overloaded(): pass 5045 self.assertEqual(list(get_overloads(not_overloaded)), []) 5046 5047 # Make sure that after we clear all overloads, the registry is 5048 # completely empty. 5049 clear_overloads() 5050 self.assertEqual(typing._overload_registry, {}) 5051 self.assertEqual(get_overloads(impl), []) 5052 5053 # Querying a function with no overloads shouldn't change the registry. 5054 def the_only_one(): pass 5055 self.assertEqual(get_overloads(the_only_one), []) 5056 self.assertEqual(typing._overload_registry, {}) 5057 5058 def test_overload_registry_repeated(self): 5059 for _ in range(2): 5060 impl, overloads = self.set_up_overloads() 5061 5062 self.assertEqual(list(get_overloads(impl)), overloads) 5063 5064 5065# Definitions needed for features introduced in Python 3.6 5066 5067from test import ann_module, ann_module2, ann_module3, ann_module5, ann_module6 5068 5069T_a = TypeVar('T_a') 5070 5071class AwaitableWrapper(typing.Awaitable[T_a]): 5072 5073 def __init__(self, value): 5074 self.value = value 5075 5076 def __await__(self) -> typing.Iterator[T_a]: 5077 yield 5078 return self.value 5079 5080class AsyncIteratorWrapper(typing.AsyncIterator[T_a]): 5081 5082 def __init__(self, value: typing.Iterable[T_a]): 5083 self.value = value 5084 5085 def __aiter__(self) -> typing.AsyncIterator[T_a]: 5086 return self 5087 5088 async def __anext__(self) -> T_a: 5089 data = await self.value 5090 if data: 5091 return data 5092 else: 5093 raise StopAsyncIteration 5094 5095class ACM: 5096 async def __aenter__(self) -> int: 5097 return 42 5098 async def __aexit__(self, etype, eval, tb): 5099 return None 5100 5101class A: 5102 y: float 5103class B(A): 5104 x: ClassVar[Optional['B']] = None 5105 y: int 5106 b: int 5107class CSub(B): 5108 z: ClassVar['CSub'] = B() 5109class G(Generic[T]): 5110 lst: ClassVar[List[T]] = [] 5111 5112class Loop: 5113 attr: Final['Loop'] 5114 5115class NoneAndForward: 5116 parent: 'NoneAndForward' 5117 meaning: None 5118 5119class CoolEmployee(NamedTuple): 5120 name: str 5121 cool: int 5122 5123class CoolEmployeeWithDefault(NamedTuple): 5124 name: str 5125 cool: int = 0 5126 5127class XMeth(NamedTuple): 5128 x: int 5129 def double(self): 5130 return 2 * self.x 5131 5132class XRepr(NamedTuple): 5133 x: int 5134 y: int = 1 5135 def __str__(self): 5136 return f'{self.x} -> {self.y}' 5137 def __add__(self, other): 5138 return 0 5139 5140Label = TypedDict('Label', [('label', str)]) 5141 5142class Point2D(TypedDict): 5143 x: int 5144 y: int 5145 5146class Point2DGeneric(Generic[T], TypedDict): 5147 a: T 5148 b: T 5149 5150class Bar(_typed_dict_helper.Foo, total=False): 5151 b: int 5152 5153class BarGeneric(_typed_dict_helper.FooGeneric[T], total=False): 5154 b: int 5155 5156class LabelPoint2D(Point2D, Label): ... 5157 5158class Options(TypedDict, total=False): 5159 log_level: int 5160 log_path: str 5161 5162class TotalMovie(TypedDict): 5163 title: str 5164 year: NotRequired[int] 5165 5166class NontotalMovie(TypedDict, total=False): 5167 title: Required[str] 5168 year: int 5169 5170class ParentNontotalMovie(TypedDict, total=False): 5171 title: Required[str] 5172 5173class ChildTotalMovie(ParentNontotalMovie): 5174 year: NotRequired[int] 5175 5176class ParentDeeplyAnnotatedMovie(TypedDict): 5177 title: Annotated[Annotated[Required[str], "foobar"], "another level"] 5178 5179class ChildDeeplyAnnotatedMovie(ParentDeeplyAnnotatedMovie): 5180 year: NotRequired[Annotated[int, 2000]] 5181 5182class AnnotatedMovie(TypedDict): 5183 title: Annotated[Required[str], "foobar"] 5184 year: NotRequired[Annotated[int, 2000]] 5185 5186class DeeplyAnnotatedMovie(TypedDict): 5187 title: Annotated[Annotated[Required[str], "foobar"], "another level"] 5188 year: NotRequired[Annotated[int, 2000]] 5189 5190class WeirdlyQuotedMovie(TypedDict): 5191 title: Annotated['Annotated[Required[str], "foobar"]', "another level"] 5192 year: NotRequired['Annotated[int, 2000]'] 5193 5194class HasForeignBaseClass(mod_generics_cache.A): 5195 some_xrepr: 'XRepr' 5196 other_a: 'mod_generics_cache.A' 5197 5198async def g_with(am: typing.AsyncContextManager[int]): 5199 x: int 5200 async with am as x: 5201 return x 5202 5203try: 5204 g_with(ACM()).send(None) 5205except StopIteration as e: 5206 assert e.args[0] == 42 5207 5208gth = get_type_hints 5209 5210class ForRefExample: 5211 @ann_module.dec 5212 def func(self: 'ForRefExample'): 5213 pass 5214 5215 @ann_module.dec 5216 @ann_module.dec 5217 def nested(self: 'ForRefExample'): 5218 pass 5219 5220 5221class GetTypeHintTests(BaseTestCase): 5222 def test_get_type_hints_from_various_objects(self): 5223 # For invalid objects should fail with TypeError (not AttributeError etc). 5224 with self.assertRaises(TypeError): 5225 gth(123) 5226 with self.assertRaises(TypeError): 5227 gth('abc') 5228 with self.assertRaises(TypeError): 5229 gth(None) 5230 5231 def test_get_type_hints_modules(self): 5232 ann_module_type_hints = {1: 2, 'f': Tuple[int, int], 'x': int, 'y': str, 'u': int | float} 5233 self.assertEqual(gth(ann_module), ann_module_type_hints) 5234 self.assertEqual(gth(ann_module2), {}) 5235 self.assertEqual(gth(ann_module3), {}) 5236 5237 @skip("known bug") 5238 def test_get_type_hints_modules_forwardref(self): 5239 # FIXME: This currently exposes a bug in typing. Cached forward references 5240 # don't account for the case where there are multiple types of the same 5241 # name coming from different modules in the same program. 5242 mgc_hints = {'default_a': Optional[mod_generics_cache.A], 5243 'default_b': Optional[mod_generics_cache.B]} 5244 self.assertEqual(gth(mod_generics_cache), mgc_hints) 5245 5246 def test_get_type_hints_classes(self): 5247 self.assertEqual(gth(ann_module.C), # gth will find the right globalns 5248 {'y': Optional[ann_module.C]}) 5249 self.assertIsInstance(gth(ann_module.j_class), dict) 5250 self.assertEqual(gth(ann_module.M), {'123': 123, 'o': type}) 5251 self.assertEqual(gth(ann_module.D), 5252 {'j': str, 'k': str, 'y': Optional[ann_module.C]}) 5253 self.assertEqual(gth(ann_module.Y), {'z': int}) 5254 self.assertEqual(gth(ann_module.h_class), 5255 {'y': Optional[ann_module.C]}) 5256 self.assertEqual(gth(ann_module.S), {'x': str, 'y': str}) 5257 self.assertEqual(gth(ann_module.foo), {'x': int}) 5258 self.assertEqual(gth(NoneAndForward), 5259 {'parent': NoneAndForward, 'meaning': type(None)}) 5260 self.assertEqual(gth(HasForeignBaseClass), 5261 {'some_xrepr': XRepr, 'other_a': mod_generics_cache.A, 5262 'some_b': mod_generics_cache.B}) 5263 self.assertEqual(gth(XRepr.__new__), 5264 {'x': int, 'y': int}) 5265 self.assertEqual(gth(mod_generics_cache.B), 5266 {'my_inner_a1': mod_generics_cache.B.A, 5267 'my_inner_a2': mod_generics_cache.B.A, 5268 'my_outer_a': mod_generics_cache.A}) 5269 5270 def test_get_type_hints_classes_no_implicit_optional(self): 5271 class WithNoneDefault: 5272 field: int = None # most type-checkers won't be happy with it 5273 5274 self.assertEqual(gth(WithNoneDefault), {'field': int}) 5275 5276 def test_respect_no_type_check(self): 5277 @no_type_check 5278 class NoTpCheck: 5279 class Inn: 5280 def __init__(self, x: 'not a type'): ... 5281 self.assertTrue(NoTpCheck.__no_type_check__) 5282 self.assertTrue(NoTpCheck.Inn.__init__.__no_type_check__) 5283 self.assertEqual(gth(ann_module2.NTC.meth), {}) 5284 class ABase(Generic[T]): 5285 def meth(x: int): ... 5286 @no_type_check 5287 class Der(ABase): ... 5288 self.assertEqual(gth(ABase.meth), {'x': int}) 5289 5290 def test_get_type_hints_for_builtins(self): 5291 # Should not fail for built-in classes and functions. 5292 self.assertEqual(gth(int), {}) 5293 self.assertEqual(gth(type), {}) 5294 self.assertEqual(gth(dir), {}) 5295 self.assertEqual(gth(len), {}) 5296 self.assertEqual(gth(object.__str__), {}) 5297 self.assertEqual(gth(object().__str__), {}) 5298 self.assertEqual(gth(str.join), {}) 5299 5300 def test_previous_behavior(self): 5301 def testf(x, y): ... 5302 testf.__annotations__['x'] = 'int' 5303 self.assertEqual(gth(testf), {'x': int}) 5304 def testg(x: None): ... 5305 self.assertEqual(gth(testg), {'x': type(None)}) 5306 5307 def test_get_type_hints_for_object_with_annotations(self): 5308 class A: ... 5309 class B: ... 5310 b = B() 5311 b.__annotations__ = {'x': 'A'} 5312 self.assertEqual(gth(b, locals()), {'x': A}) 5313 5314 def test_get_type_hints_ClassVar(self): 5315 self.assertEqual(gth(ann_module2.CV, ann_module2.__dict__), 5316 {'var': typing.ClassVar[ann_module2.CV]}) 5317 self.assertEqual(gth(B, globals()), 5318 {'y': int, 'x': ClassVar[Optional[B]], 'b': int}) 5319 self.assertEqual(gth(CSub, globals()), 5320 {'z': ClassVar[CSub], 'y': int, 'b': int, 5321 'x': ClassVar[Optional[B]]}) 5322 self.assertEqual(gth(G), {'lst': ClassVar[List[T]]}) 5323 5324 def test_get_type_hints_wrapped_decoratored_func(self): 5325 expects = {'self': ForRefExample} 5326 self.assertEqual(gth(ForRefExample.func), expects) 5327 self.assertEqual(gth(ForRefExample.nested), expects) 5328 5329 def test_get_type_hints_annotated(self): 5330 def foobar(x: List['X']): ... 5331 X = Annotated[int, (1, 10)] 5332 self.assertEqual( 5333 get_type_hints(foobar, globals(), locals()), 5334 {'x': List[int]} 5335 ) 5336 self.assertEqual( 5337 get_type_hints(foobar, globals(), locals(), include_extras=True), 5338 {'x': List[Annotated[int, (1, 10)]]} 5339 ) 5340 5341 def foobar(x: list[ForwardRef('X')]): ... 5342 X = Annotated[int, (1, 10)] 5343 self.assertEqual( 5344 get_type_hints(foobar, globals(), locals()), 5345 {'x': list[int]} 5346 ) 5347 self.assertEqual( 5348 get_type_hints(foobar, globals(), locals(), include_extras=True), 5349 {'x': list[Annotated[int, (1, 10)]]} 5350 ) 5351 5352 BA = Tuple[Annotated[T, (1, 0)], ...] 5353 def barfoo(x: BA): ... 5354 self.assertEqual(get_type_hints(barfoo, globals(), locals())['x'], Tuple[T, ...]) 5355 self.assertEqual( 5356 get_type_hints(barfoo, globals(), locals(), include_extras=True)['x'], 5357 BA 5358 ) 5359 5360 BA = tuple[Annotated[T, (1, 0)], ...] 5361 def barfoo(x: BA): ... 5362 self.assertEqual(get_type_hints(barfoo, globals(), locals())['x'], tuple[T, ...]) 5363 self.assertEqual( 5364 get_type_hints(barfoo, globals(), locals(), include_extras=True)['x'], 5365 BA 5366 ) 5367 5368 def barfoo2(x: typing.Callable[..., Annotated[List[T], "const"]], 5369 y: typing.Union[int, Annotated[T, "mutable"]]): ... 5370 self.assertEqual( 5371 get_type_hints(barfoo2, globals(), locals()), 5372 {'x': typing.Callable[..., List[T]], 'y': typing.Union[int, T]} 5373 ) 5374 5375 BA2 = typing.Callable[..., List[T]] 5376 def barfoo3(x: BA2): ... 5377 self.assertIs( 5378 get_type_hints(barfoo3, globals(), locals(), include_extras=True)["x"], 5379 BA2 5380 ) 5381 BA3 = typing.Annotated[int | float, "const"] 5382 def barfoo4(x: BA3): ... 5383 self.assertEqual( 5384 get_type_hints(barfoo4, globals(), locals()), 5385 {"x": int | float} 5386 ) 5387 self.assertEqual( 5388 get_type_hints(barfoo4, globals(), locals(), include_extras=True), 5389 {"x": typing.Annotated[int | float, "const"]} 5390 ) 5391 5392 def test_get_type_hints_annotated_in_union(self): # bpo-46603 5393 def with_union(x: int | list[Annotated[str, 'meta']]): ... 5394 5395 self.assertEqual(get_type_hints(with_union), {'x': int | list[str]}) 5396 self.assertEqual( 5397 get_type_hints(with_union, include_extras=True), 5398 {'x': int | list[Annotated[str, 'meta']]}, 5399 ) 5400 5401 def test_get_type_hints_annotated_refs(self): 5402 5403 Const = Annotated[T, "Const"] 5404 5405 class MySet(Generic[T]): 5406 5407 def __ior__(self, other: "Const[MySet[T]]") -> "MySet[T]": 5408 ... 5409 5410 def __iand__(self, other: Const["MySet[T]"]) -> "MySet[T]": 5411 ... 5412 5413 self.assertEqual( 5414 get_type_hints(MySet.__iand__, globals(), locals()), 5415 {'other': MySet[T], 'return': MySet[T]} 5416 ) 5417 5418 self.assertEqual( 5419 get_type_hints(MySet.__iand__, globals(), locals(), include_extras=True), 5420 {'other': Const[MySet[T]], 'return': MySet[T]} 5421 ) 5422 5423 self.assertEqual( 5424 get_type_hints(MySet.__ior__, globals(), locals()), 5425 {'other': MySet[T], 'return': MySet[T]} 5426 ) 5427 5428 def test_get_type_hints_annotated_with_none_default(self): 5429 # See: https://bugs.python.org/issue46195 5430 def annotated_with_none_default(x: Annotated[int, 'data'] = None): ... 5431 self.assertEqual( 5432 get_type_hints(annotated_with_none_default), 5433 {'x': int}, 5434 ) 5435 self.assertEqual( 5436 get_type_hints(annotated_with_none_default, include_extras=True), 5437 {'x': Annotated[int, 'data']}, 5438 ) 5439 5440 def test_get_type_hints_classes_str_annotations(self): 5441 class Foo: 5442 y = str 5443 x: 'y' 5444 # This previously raised an error under PEP 563. 5445 self.assertEqual(get_type_hints(Foo), {'x': str}) 5446 5447 def test_get_type_hints_bad_module(self): 5448 # bpo-41515 5449 class BadModule: 5450 pass 5451 BadModule.__module__ = 'bad' # Something not in sys.modules 5452 self.assertNotIn('bad', sys.modules) 5453 self.assertEqual(get_type_hints(BadModule), {}) 5454 5455 def test_get_type_hints_annotated_bad_module(self): 5456 # See https://bugs.python.org/issue44468 5457 class BadBase: 5458 foo: tuple 5459 class BadType(BadBase): 5460 bar: list 5461 BadType.__module__ = BadBase.__module__ = 'bad' 5462 self.assertNotIn('bad', sys.modules) 5463 self.assertEqual(get_type_hints(BadType), {'foo': tuple, 'bar': list}) 5464 5465 def test_forward_ref_and_final(self): 5466 # https://bugs.python.org/issue45166 5467 hints = get_type_hints(ann_module5) 5468 self.assertEqual(hints, {'name': Final[str]}) 5469 5470 hints = get_type_hints(ann_module5.MyClass) 5471 self.assertEqual(hints, {'value': Final}) 5472 5473 def test_top_level_class_var(self): 5474 # https://bugs.python.org/issue45166 5475 with self.assertRaisesRegex( 5476 TypeError, 5477 r'typing.ClassVar\[int\] is not valid as type argument', 5478 ): 5479 get_type_hints(ann_module6) 5480 5481 def test_get_type_hints_typeddict(self): 5482 self.assertEqual(get_type_hints(TotalMovie), {'title': str, 'year': int}) 5483 self.assertEqual(get_type_hints(TotalMovie, include_extras=True), { 5484 'title': str, 5485 'year': NotRequired[int], 5486 }) 5487 5488 self.assertEqual(get_type_hints(AnnotatedMovie), {'title': str, 'year': int}) 5489 self.assertEqual(get_type_hints(AnnotatedMovie, include_extras=True), { 5490 'title': Annotated[Required[str], "foobar"], 5491 'year': NotRequired[Annotated[int, 2000]], 5492 }) 5493 5494 self.assertEqual(get_type_hints(DeeplyAnnotatedMovie), {'title': str, 'year': int}) 5495 self.assertEqual(get_type_hints(DeeplyAnnotatedMovie, include_extras=True), { 5496 'title': Annotated[Required[str], "foobar", "another level"], 5497 'year': NotRequired[Annotated[int, 2000]], 5498 }) 5499 5500 self.assertEqual(get_type_hints(WeirdlyQuotedMovie), {'title': str, 'year': int}) 5501 self.assertEqual(get_type_hints(WeirdlyQuotedMovie, include_extras=True), { 5502 'title': Annotated[Required[str], "foobar", "another level"], 5503 'year': NotRequired[Annotated[int, 2000]], 5504 }) 5505 5506 self.assertEqual(get_type_hints(_typed_dict_helper.VeryAnnotated), {'a': int}) 5507 self.assertEqual(get_type_hints(_typed_dict_helper.VeryAnnotated, include_extras=True), { 5508 'a': Annotated[Required[int], "a", "b", "c"] 5509 }) 5510 5511 self.assertEqual(get_type_hints(ChildTotalMovie), {"title": str, "year": int}) 5512 self.assertEqual(get_type_hints(ChildTotalMovie, include_extras=True), { 5513 "title": Required[str], "year": NotRequired[int] 5514 }) 5515 5516 self.assertEqual(get_type_hints(ChildDeeplyAnnotatedMovie), {"title": str, "year": int}) 5517 self.assertEqual(get_type_hints(ChildDeeplyAnnotatedMovie, include_extras=True), { 5518 "title": Annotated[Required[str], "foobar", "another level"], 5519 "year": NotRequired[Annotated[int, 2000]] 5520 }) 5521 5522 def test_get_type_hints_collections_abc_callable(self): 5523 # https://github.com/python/cpython/issues/91621 5524 P = ParamSpec('P') 5525 def f(x: collections.abc.Callable[[int], int]): ... 5526 def g(x: collections.abc.Callable[..., int]): ... 5527 def h(x: collections.abc.Callable[P, int]): ... 5528 5529 self.assertEqual(get_type_hints(f), {'x': collections.abc.Callable[[int], int]}) 5530 self.assertEqual(get_type_hints(g), {'x': collections.abc.Callable[..., int]}) 5531 self.assertEqual(get_type_hints(h), {'x': collections.abc.Callable[P, int]}) 5532 5533 5534class GetUtilitiesTestCase(TestCase): 5535 def test_get_origin(self): 5536 T = TypeVar('T') 5537 Ts = TypeVarTuple('Ts') 5538 P = ParamSpec('P') 5539 class C(Generic[T]): pass 5540 self.assertIs(get_origin(C[int]), C) 5541 self.assertIs(get_origin(C[T]), C) 5542 self.assertIs(get_origin(int), None) 5543 self.assertIs(get_origin(ClassVar[int]), ClassVar) 5544 self.assertIs(get_origin(Union[int, str]), Union) 5545 self.assertIs(get_origin(Literal[42, 43]), Literal) 5546 self.assertIs(get_origin(Final[List[int]]), Final) 5547 self.assertIs(get_origin(Generic), Generic) 5548 self.assertIs(get_origin(Generic[T]), Generic) 5549 self.assertIs(get_origin(List[Tuple[T, T]][int]), list) 5550 self.assertIs(get_origin(Annotated[T, 'thing']), Annotated) 5551 self.assertIs(get_origin(List), list) 5552 self.assertIs(get_origin(Tuple), tuple) 5553 self.assertIs(get_origin(Callable), collections.abc.Callable) 5554 self.assertIs(get_origin(list[int]), list) 5555 self.assertIs(get_origin(list), None) 5556 self.assertIs(get_origin(list | str), types.UnionType) 5557 self.assertIs(get_origin(P.args), P) 5558 self.assertIs(get_origin(P.kwargs), P) 5559 self.assertIs(get_origin(Required[int]), Required) 5560 self.assertIs(get_origin(NotRequired[int]), NotRequired) 5561 self.assertIs(get_origin((*Ts,)[0]), Unpack) 5562 self.assertIs(get_origin(Unpack[Ts]), Unpack) 5563 self.assertIs(get_origin((*tuple[*Ts],)[0]), tuple) 5564 self.assertIs(get_origin(Unpack[Tuple[Unpack[Ts]]]), Unpack) 5565 5566 def test_get_args(self): 5567 T = TypeVar('T') 5568 class C(Generic[T]): pass 5569 self.assertEqual(get_args(C[int]), (int,)) 5570 self.assertEqual(get_args(C[T]), (T,)) 5571 self.assertEqual(get_args(int), ()) 5572 self.assertEqual(get_args(ClassVar[int]), (int,)) 5573 self.assertEqual(get_args(Union[int, str]), (int, str)) 5574 self.assertEqual(get_args(Literal[42, 43]), (42, 43)) 5575 self.assertEqual(get_args(Final[List[int]]), (List[int],)) 5576 self.assertEqual(get_args(Union[int, Tuple[T, int]][str]), 5577 (int, Tuple[str, int])) 5578 self.assertEqual(get_args(typing.Dict[int, Tuple[T, T]][Optional[int]]), 5579 (int, Tuple[Optional[int], Optional[int]])) 5580 self.assertEqual(get_args(Callable[[], T][int]), ([], int)) 5581 self.assertEqual(get_args(Callable[..., int]), (..., int)) 5582 self.assertEqual(get_args(Union[int, Callable[[Tuple[T, ...]], str]]), 5583 (int, Callable[[Tuple[T, ...]], str])) 5584 self.assertEqual(get_args(Tuple[int, ...]), (int, ...)) 5585 self.assertEqual(get_args(Tuple[()]), ()) 5586 self.assertEqual(get_args(Annotated[T, 'one', 2, ['three']]), (T, 'one', 2, ['three'])) 5587 self.assertEqual(get_args(List), ()) 5588 self.assertEqual(get_args(Tuple), ()) 5589 self.assertEqual(get_args(Callable), ()) 5590 self.assertEqual(get_args(list[int]), (int,)) 5591 self.assertEqual(get_args(list), ()) 5592 self.assertEqual(get_args(collections.abc.Callable[[int], str]), ([int], str)) 5593 self.assertEqual(get_args(collections.abc.Callable[..., str]), (..., str)) 5594 self.assertEqual(get_args(collections.abc.Callable[[], str]), ([], str)) 5595 self.assertEqual(get_args(collections.abc.Callable[[int], str]), 5596 get_args(Callable[[int], str])) 5597 P = ParamSpec('P') 5598 self.assertEqual(get_args(Callable[P, int]), (P, int)) 5599 self.assertEqual(get_args(Callable[Concatenate[int, P], int]), 5600 (Concatenate[int, P], int)) 5601 self.assertEqual(get_args(list | str), (list, str)) 5602 self.assertEqual(get_args(Required[int]), (int,)) 5603 self.assertEqual(get_args(NotRequired[int]), (int,)) 5604 self.assertEqual(get_args(TypeAlias), ()) 5605 self.assertEqual(get_args(TypeGuard[int]), (int,)) 5606 Ts = TypeVarTuple('Ts') 5607 self.assertEqual(get_args(Ts), ()) 5608 self.assertEqual(get_args((*Ts,)[0]), (Ts,)) 5609 self.assertEqual(get_args(Unpack[Ts]), (Ts,)) 5610 self.assertEqual(get_args(tuple[*Ts]), (*Ts,)) 5611 self.assertEqual(get_args(tuple[Unpack[Ts]]), (Unpack[Ts],)) 5612 self.assertEqual(get_args((*tuple[*Ts],)[0]), (*Ts,)) 5613 self.assertEqual(get_args(Unpack[tuple[Unpack[Ts]]]), (tuple[Unpack[Ts]],)) 5614 5615 5616class CollectionsAbcTests(BaseTestCase): 5617 5618 def test_hashable(self): 5619 self.assertIsInstance(42, typing.Hashable) 5620 self.assertNotIsInstance([], typing.Hashable) 5621 5622 def test_iterable(self): 5623 self.assertIsInstance([], typing.Iterable) 5624 # Due to ABC caching, the second time takes a separate code 5625 # path and could fail. So call this a few times. 5626 self.assertIsInstance([], typing.Iterable) 5627 self.assertIsInstance([], typing.Iterable) 5628 self.assertNotIsInstance(42, typing.Iterable) 5629 # Just in case, also test issubclass() a few times. 5630 self.assertIsSubclass(list, typing.Iterable) 5631 self.assertIsSubclass(list, typing.Iterable) 5632 5633 def test_iterator(self): 5634 it = iter([]) 5635 self.assertIsInstance(it, typing.Iterator) 5636 self.assertNotIsInstance(42, typing.Iterator) 5637 5638 def test_awaitable(self): 5639 ns = {} 5640 exec( 5641 "async def foo() -> typing.Awaitable[int]:\n" 5642 " return await AwaitableWrapper(42)\n", 5643 globals(), ns) 5644 foo = ns['foo'] 5645 g = foo() 5646 self.assertIsInstance(g, typing.Awaitable) 5647 self.assertNotIsInstance(foo, typing.Awaitable) 5648 g.send(None) # Run foo() till completion, to avoid warning. 5649 5650 def test_coroutine(self): 5651 ns = {} 5652 exec( 5653 "async def foo():\n" 5654 " return\n", 5655 globals(), ns) 5656 foo = ns['foo'] 5657 g = foo() 5658 self.assertIsInstance(g, typing.Coroutine) 5659 with self.assertRaises(TypeError): 5660 isinstance(g, typing.Coroutine[int]) 5661 self.assertNotIsInstance(foo, typing.Coroutine) 5662 try: 5663 g.send(None) 5664 except StopIteration: 5665 pass 5666 5667 def test_async_iterable(self): 5668 base_it = range(10) # type: Iterator[int] 5669 it = AsyncIteratorWrapper(base_it) 5670 self.assertIsInstance(it, typing.AsyncIterable) 5671 self.assertIsInstance(it, typing.AsyncIterable) 5672 self.assertNotIsInstance(42, typing.AsyncIterable) 5673 5674 def test_async_iterator(self): 5675 base_it = range(10) # type: Iterator[int] 5676 it = AsyncIteratorWrapper(base_it) 5677 self.assertIsInstance(it, typing.AsyncIterator) 5678 self.assertNotIsInstance(42, typing.AsyncIterator) 5679 5680 def test_sized(self): 5681 self.assertIsInstance([], typing.Sized) 5682 self.assertNotIsInstance(42, typing.Sized) 5683 5684 def test_container(self): 5685 self.assertIsInstance([], typing.Container) 5686 self.assertNotIsInstance(42, typing.Container) 5687 5688 def test_collection(self): 5689 self.assertIsInstance(tuple(), typing.Collection) 5690 self.assertIsInstance(frozenset(), typing.Collection) 5691 self.assertIsSubclass(dict, typing.Collection) 5692 self.assertNotIsInstance(42, typing.Collection) 5693 5694 def test_abstractset(self): 5695 self.assertIsInstance(set(), typing.AbstractSet) 5696 self.assertNotIsInstance(42, typing.AbstractSet) 5697 5698 def test_mutableset(self): 5699 self.assertIsInstance(set(), typing.MutableSet) 5700 self.assertNotIsInstance(frozenset(), typing.MutableSet) 5701 5702 def test_mapping(self): 5703 self.assertIsInstance({}, typing.Mapping) 5704 self.assertNotIsInstance(42, typing.Mapping) 5705 5706 def test_mutablemapping(self): 5707 self.assertIsInstance({}, typing.MutableMapping) 5708 self.assertNotIsInstance(42, typing.MutableMapping) 5709 5710 def test_sequence(self): 5711 self.assertIsInstance([], typing.Sequence) 5712 self.assertNotIsInstance(42, typing.Sequence) 5713 5714 def test_mutablesequence(self): 5715 self.assertIsInstance([], typing.MutableSequence) 5716 self.assertNotIsInstance((), typing.MutableSequence) 5717 5718 def test_bytestring(self): 5719 self.assertIsInstance(b'', typing.ByteString) 5720 self.assertIsInstance(bytearray(b''), typing.ByteString) 5721 5722 def test_list(self): 5723 self.assertIsSubclass(list, typing.List) 5724 5725 def test_deque(self): 5726 self.assertIsSubclass(collections.deque, typing.Deque) 5727 class MyDeque(typing.Deque[int]): ... 5728 self.assertIsInstance(MyDeque(), collections.deque) 5729 5730 def test_counter(self): 5731 self.assertIsSubclass(collections.Counter, typing.Counter) 5732 5733 def test_set(self): 5734 self.assertIsSubclass(set, typing.Set) 5735 self.assertNotIsSubclass(frozenset, typing.Set) 5736 5737 def test_frozenset(self): 5738 self.assertIsSubclass(frozenset, typing.FrozenSet) 5739 self.assertNotIsSubclass(set, typing.FrozenSet) 5740 5741 def test_dict(self): 5742 self.assertIsSubclass(dict, typing.Dict) 5743 5744 def test_dict_subscribe(self): 5745 K = TypeVar('K') 5746 V = TypeVar('V') 5747 self.assertEqual(Dict[K, V][str, int], Dict[str, int]) 5748 self.assertEqual(Dict[K, int][str], Dict[str, int]) 5749 self.assertEqual(Dict[str, V][int], Dict[str, int]) 5750 self.assertEqual(Dict[K, List[V]][str, int], Dict[str, List[int]]) 5751 self.assertEqual(Dict[K, List[int]][str], Dict[str, List[int]]) 5752 self.assertEqual(Dict[K, list[V]][str, int], Dict[str, list[int]]) 5753 self.assertEqual(Dict[K, list[int]][str], Dict[str, list[int]]) 5754 5755 def test_no_list_instantiation(self): 5756 with self.assertRaises(TypeError): 5757 typing.List() 5758 with self.assertRaises(TypeError): 5759 typing.List[T]() 5760 with self.assertRaises(TypeError): 5761 typing.List[int]() 5762 5763 def test_list_subclass(self): 5764 5765 class MyList(typing.List[int]): 5766 pass 5767 5768 a = MyList() 5769 self.assertIsInstance(a, MyList) 5770 self.assertIsInstance(a, typing.Sequence) 5771 5772 self.assertIsSubclass(MyList, list) 5773 self.assertNotIsSubclass(list, MyList) 5774 5775 def test_no_dict_instantiation(self): 5776 with self.assertRaises(TypeError): 5777 typing.Dict() 5778 with self.assertRaises(TypeError): 5779 typing.Dict[KT, VT]() 5780 with self.assertRaises(TypeError): 5781 typing.Dict[str, int]() 5782 5783 def test_dict_subclass(self): 5784 5785 class MyDict(typing.Dict[str, int]): 5786 pass 5787 5788 d = MyDict() 5789 self.assertIsInstance(d, MyDict) 5790 self.assertIsInstance(d, typing.MutableMapping) 5791 5792 self.assertIsSubclass(MyDict, dict) 5793 self.assertNotIsSubclass(dict, MyDict) 5794 5795 def test_defaultdict_instantiation(self): 5796 self.assertIs(type(typing.DefaultDict()), collections.defaultdict) 5797 self.assertIs(type(typing.DefaultDict[KT, VT]()), collections.defaultdict) 5798 self.assertIs(type(typing.DefaultDict[str, int]()), collections.defaultdict) 5799 5800 def test_defaultdict_subclass(self): 5801 5802 class MyDefDict(typing.DefaultDict[str, int]): 5803 pass 5804 5805 dd = MyDefDict() 5806 self.assertIsInstance(dd, MyDefDict) 5807 5808 self.assertIsSubclass(MyDefDict, collections.defaultdict) 5809 self.assertNotIsSubclass(collections.defaultdict, MyDefDict) 5810 5811 def test_ordereddict_instantiation(self): 5812 self.assertIs(type(typing.OrderedDict()), collections.OrderedDict) 5813 self.assertIs(type(typing.OrderedDict[KT, VT]()), collections.OrderedDict) 5814 self.assertIs(type(typing.OrderedDict[str, int]()), collections.OrderedDict) 5815 5816 def test_ordereddict_subclass(self): 5817 5818 class MyOrdDict(typing.OrderedDict[str, int]): 5819 pass 5820 5821 od = MyOrdDict() 5822 self.assertIsInstance(od, MyOrdDict) 5823 5824 self.assertIsSubclass(MyOrdDict, collections.OrderedDict) 5825 self.assertNotIsSubclass(collections.OrderedDict, MyOrdDict) 5826 5827 def test_chainmap_instantiation(self): 5828 self.assertIs(type(typing.ChainMap()), collections.ChainMap) 5829 self.assertIs(type(typing.ChainMap[KT, VT]()), collections.ChainMap) 5830 self.assertIs(type(typing.ChainMap[str, int]()), collections.ChainMap) 5831 class CM(typing.ChainMap[KT, VT]): ... 5832 self.assertIs(type(CM[int, str]()), CM) 5833 5834 def test_chainmap_subclass(self): 5835 5836 class MyChainMap(typing.ChainMap[str, int]): 5837 pass 5838 5839 cm = MyChainMap() 5840 self.assertIsInstance(cm, MyChainMap) 5841 5842 self.assertIsSubclass(MyChainMap, collections.ChainMap) 5843 self.assertNotIsSubclass(collections.ChainMap, MyChainMap) 5844 5845 def test_deque_instantiation(self): 5846 self.assertIs(type(typing.Deque()), collections.deque) 5847 self.assertIs(type(typing.Deque[T]()), collections.deque) 5848 self.assertIs(type(typing.Deque[int]()), collections.deque) 5849 class D(typing.Deque[T]): ... 5850 self.assertIs(type(D[int]()), D) 5851 5852 def test_counter_instantiation(self): 5853 self.assertIs(type(typing.Counter()), collections.Counter) 5854 self.assertIs(type(typing.Counter[T]()), collections.Counter) 5855 self.assertIs(type(typing.Counter[int]()), collections.Counter) 5856 class C(typing.Counter[T]): ... 5857 self.assertIs(type(C[int]()), C) 5858 5859 def test_counter_subclass_instantiation(self): 5860 5861 class MyCounter(typing.Counter[int]): 5862 pass 5863 5864 d = MyCounter() 5865 self.assertIsInstance(d, MyCounter) 5866 self.assertIsInstance(d, typing.Counter) 5867 self.assertIsInstance(d, collections.Counter) 5868 5869 def test_no_set_instantiation(self): 5870 with self.assertRaises(TypeError): 5871 typing.Set() 5872 with self.assertRaises(TypeError): 5873 typing.Set[T]() 5874 with self.assertRaises(TypeError): 5875 typing.Set[int]() 5876 5877 def test_set_subclass_instantiation(self): 5878 5879 class MySet(typing.Set[int]): 5880 pass 5881 5882 d = MySet() 5883 self.assertIsInstance(d, MySet) 5884 5885 def test_no_frozenset_instantiation(self): 5886 with self.assertRaises(TypeError): 5887 typing.FrozenSet() 5888 with self.assertRaises(TypeError): 5889 typing.FrozenSet[T]() 5890 with self.assertRaises(TypeError): 5891 typing.FrozenSet[int]() 5892 5893 def test_frozenset_subclass_instantiation(self): 5894 5895 class MyFrozenSet(typing.FrozenSet[int]): 5896 pass 5897 5898 d = MyFrozenSet() 5899 self.assertIsInstance(d, MyFrozenSet) 5900 5901 def test_no_tuple_instantiation(self): 5902 with self.assertRaises(TypeError): 5903 Tuple() 5904 with self.assertRaises(TypeError): 5905 Tuple[T]() 5906 with self.assertRaises(TypeError): 5907 Tuple[int]() 5908 5909 def test_generator(self): 5910 def foo(): 5911 yield 42 5912 g = foo() 5913 self.assertIsSubclass(type(g), typing.Generator) 5914 5915 def test_no_generator_instantiation(self): 5916 with self.assertRaises(TypeError): 5917 typing.Generator() 5918 with self.assertRaises(TypeError): 5919 typing.Generator[T, T, T]() 5920 with self.assertRaises(TypeError): 5921 typing.Generator[int, int, int]() 5922 5923 def test_async_generator(self): 5924 ns = {} 5925 exec("async def f():\n" 5926 " yield 42\n", globals(), ns) 5927 g = ns['f']() 5928 self.assertIsSubclass(type(g), typing.AsyncGenerator) 5929 5930 def test_no_async_generator_instantiation(self): 5931 with self.assertRaises(TypeError): 5932 typing.AsyncGenerator() 5933 with self.assertRaises(TypeError): 5934 typing.AsyncGenerator[T, T]() 5935 with self.assertRaises(TypeError): 5936 typing.AsyncGenerator[int, int]() 5937 5938 def test_subclassing(self): 5939 5940 class MMA(typing.MutableMapping): 5941 pass 5942 5943 with self.assertRaises(TypeError): # It's abstract 5944 MMA() 5945 5946 class MMC(MMA): 5947 def __getitem__(self, k): 5948 return None 5949 def __setitem__(self, k, v): 5950 pass 5951 def __delitem__(self, k): 5952 pass 5953 def __iter__(self): 5954 return iter(()) 5955 def __len__(self): 5956 return 0 5957 5958 self.assertEqual(len(MMC()), 0) 5959 self.assertTrue(callable(MMC.update)) 5960 self.assertIsInstance(MMC(), typing.Mapping) 5961 5962 class MMB(typing.MutableMapping[KT, VT]): 5963 def __getitem__(self, k): 5964 return None 5965 def __setitem__(self, k, v): 5966 pass 5967 def __delitem__(self, k): 5968 pass 5969 def __iter__(self): 5970 return iter(()) 5971 def __len__(self): 5972 return 0 5973 5974 self.assertEqual(len(MMB()), 0) 5975 self.assertEqual(len(MMB[str, str]()), 0) 5976 self.assertEqual(len(MMB[KT, VT]()), 0) 5977 5978 self.assertNotIsSubclass(dict, MMA) 5979 self.assertNotIsSubclass(dict, MMB) 5980 5981 self.assertIsSubclass(MMA, typing.Mapping) 5982 self.assertIsSubclass(MMB, typing.Mapping) 5983 self.assertIsSubclass(MMC, typing.Mapping) 5984 5985 self.assertIsInstance(MMB[KT, VT](), typing.Mapping) 5986 self.assertIsInstance(MMB[KT, VT](), collections.abc.Mapping) 5987 5988 self.assertIsSubclass(MMA, collections.abc.Mapping) 5989 self.assertIsSubclass(MMB, collections.abc.Mapping) 5990 self.assertIsSubclass(MMC, collections.abc.Mapping) 5991 5992 with self.assertRaises(TypeError): 5993 issubclass(MMB[str, str], typing.Mapping) 5994 self.assertIsSubclass(MMC, MMA) 5995 5996 class I(typing.Iterable): ... 5997 self.assertNotIsSubclass(list, I) 5998 5999 class G(typing.Generator[int, int, int]): ... 6000 def g(): yield 0 6001 self.assertIsSubclass(G, typing.Generator) 6002 self.assertIsSubclass(G, typing.Iterable) 6003 self.assertIsSubclass(G, collections.abc.Generator) 6004 self.assertIsSubclass(G, collections.abc.Iterable) 6005 self.assertNotIsSubclass(type(g), G) 6006 6007 def test_subclassing_async_generator(self): 6008 class G(typing.AsyncGenerator[int, int]): 6009 def asend(self, value): 6010 pass 6011 def athrow(self, typ, val=None, tb=None): 6012 pass 6013 6014 ns = {} 6015 exec('async def g(): yield 0', globals(), ns) 6016 g = ns['g'] 6017 self.assertIsSubclass(G, typing.AsyncGenerator) 6018 self.assertIsSubclass(G, typing.AsyncIterable) 6019 self.assertIsSubclass(G, collections.abc.AsyncGenerator) 6020 self.assertIsSubclass(G, collections.abc.AsyncIterable) 6021 self.assertNotIsSubclass(type(g), G) 6022 6023 instance = G() 6024 self.assertIsInstance(instance, typing.AsyncGenerator) 6025 self.assertIsInstance(instance, typing.AsyncIterable) 6026 self.assertIsInstance(instance, collections.abc.AsyncGenerator) 6027 self.assertIsInstance(instance, collections.abc.AsyncIterable) 6028 self.assertNotIsInstance(type(g), G) 6029 self.assertNotIsInstance(g, G) 6030 6031 def test_subclassing_subclasshook(self): 6032 6033 class Base(typing.Iterable): 6034 @classmethod 6035 def __subclasshook__(cls, other): 6036 if other.__name__ == 'Foo': 6037 return True 6038 else: 6039 return False 6040 6041 class C(Base): ... 6042 class Foo: ... 6043 class Bar: ... 6044 self.assertIsSubclass(Foo, Base) 6045 self.assertIsSubclass(Foo, C) 6046 self.assertNotIsSubclass(Bar, C) 6047 6048 def test_subclassing_register(self): 6049 6050 class A(typing.Container): ... 6051 class B(A): ... 6052 6053 class C: ... 6054 A.register(C) 6055 self.assertIsSubclass(C, A) 6056 self.assertNotIsSubclass(C, B) 6057 6058 class D: ... 6059 B.register(D) 6060 self.assertIsSubclass(D, A) 6061 self.assertIsSubclass(D, B) 6062 6063 class M(): ... 6064 collections.abc.MutableMapping.register(M) 6065 self.assertIsSubclass(M, typing.Mapping) 6066 6067 def test_collections_as_base(self): 6068 6069 class M(collections.abc.Mapping): ... 6070 self.assertIsSubclass(M, typing.Mapping) 6071 self.assertIsSubclass(M, typing.Iterable) 6072 6073 class S(collections.abc.MutableSequence): ... 6074 self.assertIsSubclass(S, typing.MutableSequence) 6075 self.assertIsSubclass(S, typing.Iterable) 6076 6077 class I(collections.abc.Iterable): ... 6078 self.assertIsSubclass(I, typing.Iterable) 6079 6080 class A(collections.abc.Mapping, metaclass=abc.ABCMeta): ... 6081 class B: ... 6082 A.register(B) 6083 self.assertIsSubclass(B, typing.Mapping) 6084 6085 def test_or_and_ror(self): 6086 self.assertEqual(typing.Sized | typing.Awaitable, Union[typing.Sized, typing.Awaitable]) 6087 self.assertEqual(typing.Coroutine | typing.Hashable, Union[typing.Coroutine, typing.Hashable]) 6088 6089 6090class OtherABCTests(BaseTestCase): 6091 6092 def test_contextmanager(self): 6093 @contextlib.contextmanager 6094 def manager(): 6095 yield 42 6096 6097 cm = manager() 6098 self.assertIsInstance(cm, typing.ContextManager) 6099 self.assertNotIsInstance(42, typing.ContextManager) 6100 6101 def test_async_contextmanager(self): 6102 class NotACM: 6103 pass 6104 self.assertIsInstance(ACM(), typing.AsyncContextManager) 6105 self.assertNotIsInstance(NotACM(), typing.AsyncContextManager) 6106 @contextlib.contextmanager 6107 def manager(): 6108 yield 42 6109 6110 cm = manager() 6111 self.assertNotIsInstance(cm, typing.AsyncContextManager) 6112 self.assertEqual(typing.AsyncContextManager[int].__args__, (int,)) 6113 with self.assertRaises(TypeError): 6114 isinstance(42, typing.AsyncContextManager[int]) 6115 with self.assertRaises(TypeError): 6116 typing.AsyncContextManager[int, str] 6117 6118 6119class TypeTests(BaseTestCase): 6120 6121 def test_type_basic(self): 6122 6123 class User: pass 6124 class BasicUser(User): pass 6125 class ProUser(User): pass 6126 6127 def new_user(user_class: Type[User]) -> User: 6128 return user_class() 6129 6130 new_user(BasicUser) 6131 6132 def test_type_typevar(self): 6133 6134 class User: pass 6135 class BasicUser(User): pass 6136 class ProUser(User): pass 6137 6138 U = TypeVar('U', bound=User) 6139 6140 def new_user(user_class: Type[U]) -> U: 6141 return user_class() 6142 6143 new_user(BasicUser) 6144 6145 def test_type_optional(self): 6146 A = Optional[Type[BaseException]] 6147 6148 def foo(a: A) -> Optional[BaseException]: 6149 if a is None: 6150 return None 6151 else: 6152 return a() 6153 6154 self.assertIsInstance(foo(KeyboardInterrupt), KeyboardInterrupt) 6155 self.assertIsNone(foo(None)) 6156 6157 6158class TestModules(TestCase): 6159 func_names = ['_idfunc'] 6160 6161 def test_py_functions(self): 6162 for fname in self.func_names: 6163 self.assertEqual(getattr(py_typing, fname).__module__, 'typing') 6164 6165 @skipUnless(c_typing, 'requires _typing') 6166 def test_c_functions(self): 6167 for fname in self.func_names: 6168 self.assertEqual(getattr(c_typing, fname).__module__, '_typing') 6169 6170 6171class NewTypeTests: 6172 def cleanup(self): 6173 for f in self.module._cleanups: 6174 f() 6175 6176 @classmethod 6177 def setUpClass(cls): 6178 sys.modules['typing'] = cls.module 6179 global UserId 6180 UserId = cls.module.NewType('UserId', int) 6181 cls.UserName = cls.module.NewType(cls.__qualname__ + '.UserName', str) 6182 6183 @classmethod 6184 def tearDownClass(cls): 6185 global UserId 6186 del UserId 6187 del cls.UserName 6188 sys.modules['typing'] = typing 6189 6190 def tearDown(self): 6191 self.cleanup() 6192 6193 def test_basic(self): 6194 self.assertIsInstance(UserId(5), int) 6195 self.assertIsInstance(self.UserName('Joe'), str) 6196 self.assertEqual(UserId(5) + 1, 6) 6197 6198 def test_errors(self): 6199 with self.assertRaises(TypeError): 6200 issubclass(UserId, int) 6201 with self.assertRaises(TypeError): 6202 class D(UserId): 6203 pass 6204 6205 def test_or(self): 6206 for cls in (int, self.UserName): 6207 with self.subTest(cls=cls): 6208 self.assertEqual(UserId | cls, self.module.Union[UserId, cls]) 6209 self.assertEqual(cls | UserId, self.module.Union[cls, UserId]) 6210 6211 self.assertEqual(self.module.get_args(UserId | cls), (UserId, cls)) 6212 self.assertEqual(self.module.get_args(cls | UserId), (cls, UserId)) 6213 6214 def test_special_attrs(self): 6215 self.assertEqual(UserId.__name__, 'UserId') 6216 self.assertEqual(UserId.__qualname__, 'UserId') 6217 self.assertEqual(UserId.__module__, __name__) 6218 self.assertEqual(UserId.__supertype__, int) 6219 6220 UserName = self.UserName 6221 self.assertEqual(UserName.__name__, 'UserName') 6222 self.assertEqual(UserName.__qualname__, 6223 self.__class__.__qualname__ + '.UserName') 6224 self.assertEqual(UserName.__module__, __name__) 6225 self.assertEqual(UserName.__supertype__, str) 6226 6227 def test_repr(self): 6228 self.assertEqual(repr(UserId), f'{__name__}.UserId') 6229 self.assertEqual(repr(self.UserName), 6230 f'{__name__}.{self.__class__.__qualname__}.UserName') 6231 6232 def test_pickle(self): 6233 UserAge = self.module.NewType('UserAge', float) 6234 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 6235 with self.subTest(proto=proto): 6236 pickled = pickle.dumps(UserId, proto) 6237 loaded = pickle.loads(pickled) 6238 self.assertIs(loaded, UserId) 6239 6240 pickled = pickle.dumps(self.UserName, proto) 6241 loaded = pickle.loads(pickled) 6242 self.assertIs(loaded, self.UserName) 6243 6244 with self.assertRaises(pickle.PicklingError): 6245 pickle.dumps(UserAge, proto) 6246 6247 def test_missing__name__(self): 6248 code = ("import typing\n" 6249 "NT = typing.NewType('NT', int)\n" 6250 ) 6251 exec(code, {}) 6252 6253 def test_error_message_when_subclassing(self): 6254 with self.assertRaisesRegex( 6255 TypeError, 6256 re.escape( 6257 "Cannot subclass an instance of NewType. Perhaps you were looking for: " 6258 "`ProUserId = NewType('ProUserId', UserId)`" 6259 ) 6260 ): 6261 class ProUserId(UserId): 6262 ... 6263 6264 6265class NewTypePythonTests(NewTypeTests, BaseTestCase): 6266 module = py_typing 6267 6268 6269@skipUnless(c_typing, 'requires _typing') 6270class NewTypeCTests(NewTypeTests, BaseTestCase): 6271 module = c_typing 6272 6273 6274class NamedTupleTests(BaseTestCase): 6275 class NestedEmployee(NamedTuple): 6276 name: str 6277 cool: int 6278 6279 def test_basics(self): 6280 Emp = NamedTuple('Emp', [('name', str), ('id', int)]) 6281 self.assertIsSubclass(Emp, tuple) 6282 joe = Emp('Joe', 42) 6283 jim = Emp(name='Jim', id=1) 6284 self.assertIsInstance(joe, Emp) 6285 self.assertIsInstance(joe, tuple) 6286 self.assertEqual(joe.name, 'Joe') 6287 self.assertEqual(joe.id, 42) 6288 self.assertEqual(jim.name, 'Jim') 6289 self.assertEqual(jim.id, 1) 6290 self.assertEqual(Emp.__name__, 'Emp') 6291 self.assertEqual(Emp._fields, ('name', 'id')) 6292 self.assertEqual(Emp.__annotations__, 6293 collections.OrderedDict([('name', str), ('id', int)])) 6294 6295 def test_annotation_usage(self): 6296 tim = CoolEmployee('Tim', 9000) 6297 self.assertIsInstance(tim, CoolEmployee) 6298 self.assertIsInstance(tim, tuple) 6299 self.assertEqual(tim.name, 'Tim') 6300 self.assertEqual(tim.cool, 9000) 6301 self.assertEqual(CoolEmployee.__name__, 'CoolEmployee') 6302 self.assertEqual(CoolEmployee._fields, ('name', 'cool')) 6303 self.assertEqual(CoolEmployee.__annotations__, 6304 collections.OrderedDict(name=str, cool=int)) 6305 6306 def test_annotation_usage_with_default(self): 6307 jelle = CoolEmployeeWithDefault('Jelle') 6308 self.assertIsInstance(jelle, CoolEmployeeWithDefault) 6309 self.assertIsInstance(jelle, tuple) 6310 self.assertEqual(jelle.name, 'Jelle') 6311 self.assertEqual(jelle.cool, 0) 6312 cooler_employee = CoolEmployeeWithDefault('Sjoerd', 1) 6313 self.assertEqual(cooler_employee.cool, 1) 6314 6315 self.assertEqual(CoolEmployeeWithDefault.__name__, 'CoolEmployeeWithDefault') 6316 self.assertEqual(CoolEmployeeWithDefault._fields, ('name', 'cool')) 6317 self.assertEqual(CoolEmployeeWithDefault.__annotations__, 6318 dict(name=str, cool=int)) 6319 self.assertEqual(CoolEmployeeWithDefault._field_defaults, dict(cool=0)) 6320 6321 with self.assertRaises(TypeError): 6322 class NonDefaultAfterDefault(NamedTuple): 6323 x: int = 3 6324 y: int 6325 6326 def test_annotation_usage_with_methods(self): 6327 self.assertEqual(XMeth(1).double(), 2) 6328 self.assertEqual(XMeth(42).x, XMeth(42)[0]) 6329 self.assertEqual(str(XRepr(42)), '42 -> 1') 6330 self.assertEqual(XRepr(1, 2) + XRepr(3), 0) 6331 6332 with self.assertRaises(AttributeError): 6333 class XMethBad(NamedTuple): 6334 x: int 6335 def _fields(self): 6336 return 'no chance for this' 6337 6338 with self.assertRaises(AttributeError): 6339 class XMethBad2(NamedTuple): 6340 x: int 6341 def _source(self): 6342 return 'no chance for this as well' 6343 6344 def test_multiple_inheritance(self): 6345 class A: 6346 pass 6347 with self.assertRaises(TypeError): 6348 class X(NamedTuple, A): 6349 x: int 6350 with self.assertRaises(TypeError): 6351 class X(NamedTuple, tuple): 6352 x: int 6353 with self.assertRaises(TypeError): 6354 class X(NamedTuple, NamedTuple): 6355 x: int 6356 class A(NamedTuple): 6357 x: int 6358 with self.assertRaises(TypeError): 6359 class X(NamedTuple, A): 6360 y: str 6361 6362 def test_generic(self): 6363 class X(NamedTuple, Generic[T]): 6364 x: T 6365 self.assertEqual(X.__bases__, (tuple, Generic)) 6366 self.assertEqual(X.__orig_bases__, (NamedTuple, Generic[T])) 6367 self.assertEqual(X.__mro__, (X, tuple, Generic, object)) 6368 6369 class Y(Generic[T], NamedTuple): 6370 x: T 6371 self.assertEqual(Y.__bases__, (Generic, tuple)) 6372 self.assertEqual(Y.__orig_bases__, (Generic[T], NamedTuple)) 6373 self.assertEqual(Y.__mro__, (Y, Generic, tuple, object)) 6374 6375 for G in X, Y: 6376 with self.subTest(type=G): 6377 self.assertEqual(G.__parameters__, (T,)) 6378 A = G[int] 6379 self.assertIs(A.__origin__, G) 6380 self.assertEqual(A.__args__, (int,)) 6381 self.assertEqual(A.__parameters__, ()) 6382 6383 a = A(3) 6384 self.assertIs(type(a), G) 6385 self.assertEqual(a.x, 3) 6386 6387 with self.assertRaises(TypeError): 6388 G[int, str] 6389 6390 def test_non_generic_subscript(self): 6391 # For backward compatibility, subscription works 6392 # on arbitrary NamedTuple types. 6393 class Group(NamedTuple): 6394 key: T 6395 group: list[T] 6396 A = Group[int] 6397 self.assertEqual(A.__origin__, Group) 6398 self.assertEqual(A.__parameters__, ()) 6399 self.assertEqual(A.__args__, (int,)) 6400 a = A(1, [2]) 6401 self.assertIs(type(a), Group) 6402 self.assertEqual(a, (1, [2])) 6403 6404 def test_namedtuple_keyword_usage(self): 6405 LocalEmployee = NamedTuple("LocalEmployee", name=str, age=int) 6406 nick = LocalEmployee('Nick', 25) 6407 self.assertIsInstance(nick, tuple) 6408 self.assertEqual(nick.name, 'Nick') 6409 self.assertEqual(LocalEmployee.__name__, 'LocalEmployee') 6410 self.assertEqual(LocalEmployee._fields, ('name', 'age')) 6411 self.assertEqual(LocalEmployee.__annotations__, dict(name=str, age=int)) 6412 with self.assertRaises(TypeError): 6413 NamedTuple('Name', [('x', int)], y=str) 6414 6415 def test_namedtuple_special_keyword_names(self): 6416 NT = NamedTuple("NT", cls=type, self=object, typename=str, fields=list) 6417 self.assertEqual(NT.__name__, 'NT') 6418 self.assertEqual(NT._fields, ('cls', 'self', 'typename', 'fields')) 6419 a = NT(cls=str, self=42, typename='foo', fields=[('bar', tuple)]) 6420 self.assertEqual(a.cls, str) 6421 self.assertEqual(a.self, 42) 6422 self.assertEqual(a.typename, 'foo') 6423 self.assertEqual(a.fields, [('bar', tuple)]) 6424 6425 def test_empty_namedtuple(self): 6426 NT = NamedTuple('NT') 6427 6428 class CNT(NamedTuple): 6429 pass # empty body 6430 6431 for struct in [NT, CNT]: 6432 with self.subTest(struct=struct): 6433 self.assertEqual(struct._fields, ()) 6434 self.assertEqual(struct._field_defaults, {}) 6435 self.assertEqual(struct.__annotations__, {}) 6436 self.assertIsInstance(struct(), struct) 6437 6438 def test_namedtuple_errors(self): 6439 with self.assertRaises(TypeError): 6440 NamedTuple.__new__() 6441 with self.assertRaises(TypeError): 6442 NamedTuple() 6443 with self.assertRaises(TypeError): 6444 NamedTuple('Emp', [('name', str)], None) 6445 with self.assertRaises(ValueError): 6446 NamedTuple('Emp', [('_name', str)]) 6447 with self.assertRaises(TypeError): 6448 NamedTuple(typename='Emp', name=str, id=int) 6449 6450 def test_copy_and_pickle(self): 6451 global Emp # pickle wants to reference the class by name 6452 Emp = NamedTuple('Emp', [('name', str), ('cool', int)]) 6453 for cls in Emp, CoolEmployee, self.NestedEmployee: 6454 with self.subTest(cls=cls): 6455 jane = cls('jane', 37) 6456 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 6457 z = pickle.dumps(jane, proto) 6458 jane2 = pickle.loads(z) 6459 self.assertEqual(jane2, jane) 6460 self.assertIsInstance(jane2, cls) 6461 6462 jane2 = copy(jane) 6463 self.assertEqual(jane2, jane) 6464 self.assertIsInstance(jane2, cls) 6465 6466 jane2 = deepcopy(jane) 6467 self.assertEqual(jane2, jane) 6468 self.assertIsInstance(jane2, cls) 6469 6470 6471class TypedDictTests(BaseTestCase): 6472 def test_basics_functional_syntax(self): 6473 Emp = TypedDict('Emp', {'name': str, 'id': int}) 6474 self.assertIsSubclass(Emp, dict) 6475 self.assertIsSubclass(Emp, typing.MutableMapping) 6476 self.assertNotIsSubclass(Emp, collections.abc.Sequence) 6477 jim = Emp(name='Jim', id=1) 6478 self.assertIs(type(jim), dict) 6479 self.assertEqual(jim['name'], 'Jim') 6480 self.assertEqual(jim['id'], 1) 6481 self.assertEqual(Emp.__name__, 'Emp') 6482 self.assertEqual(Emp.__module__, __name__) 6483 self.assertEqual(Emp.__bases__, (dict,)) 6484 self.assertEqual(Emp.__annotations__, {'name': str, 'id': int}) 6485 self.assertEqual(Emp.__total__, True) 6486 self.assertEqual(Emp.__required_keys__, {'name', 'id'}) 6487 self.assertIsInstance(Emp.__required_keys__, frozenset) 6488 self.assertEqual(Emp.__optional_keys__, set()) 6489 self.assertIsInstance(Emp.__optional_keys__, frozenset) 6490 6491 def test_basics_keywords_syntax(self): 6492 with self.assertWarns(DeprecationWarning): 6493 Emp = TypedDict('Emp', name=str, id=int) 6494 self.assertIsSubclass(Emp, dict) 6495 self.assertIsSubclass(Emp, typing.MutableMapping) 6496 self.assertNotIsSubclass(Emp, collections.abc.Sequence) 6497 jim = Emp(name='Jim', id=1) 6498 self.assertIs(type(jim), dict) 6499 self.assertEqual(jim['name'], 'Jim') 6500 self.assertEqual(jim['id'], 1) 6501 self.assertEqual(Emp.__name__, 'Emp') 6502 self.assertEqual(Emp.__module__, __name__) 6503 self.assertEqual(Emp.__bases__, (dict,)) 6504 self.assertEqual(Emp.__annotations__, {'name': str, 'id': int}) 6505 self.assertEqual(Emp.__total__, True) 6506 6507 def test_typeddict_special_keyword_names(self): 6508 with self.assertWarns(DeprecationWarning): 6509 TD = TypedDict("TD", cls=type, self=object, typename=str, _typename=int, fields=list, _fields=dict) 6510 self.assertEqual(TD.__name__, 'TD') 6511 self.assertEqual(TD.__annotations__, {'cls': type, 'self': object, 'typename': str, '_typename': int, 'fields': list, '_fields': dict}) 6512 a = TD(cls=str, self=42, typename='foo', _typename=53, fields=[('bar', tuple)], _fields={'baz', set}) 6513 self.assertEqual(a['cls'], str) 6514 self.assertEqual(a['self'], 42) 6515 self.assertEqual(a['typename'], 'foo') 6516 self.assertEqual(a['_typename'], 53) 6517 self.assertEqual(a['fields'], [('bar', tuple)]) 6518 self.assertEqual(a['_fields'], {'baz', set}) 6519 6520 def test_typeddict_create_errors(self): 6521 with self.assertRaises(TypeError): 6522 TypedDict.__new__() 6523 with self.assertRaises(TypeError): 6524 TypedDict() 6525 with self.assertRaises(TypeError): 6526 TypedDict('Emp', [('name', str)], None) 6527 with self.assertRaises(TypeError): 6528 TypedDict(_typename='Emp', name=str, id=int) 6529 6530 def test_typeddict_errors(self): 6531 Emp = TypedDict('Emp', {'name': str, 'id': int}) 6532 self.assertEqual(TypedDict.__module__, 'typing') 6533 jim = Emp(name='Jim', id=1) 6534 with self.assertRaises(TypeError): 6535 isinstance({}, Emp) 6536 with self.assertRaises(TypeError): 6537 isinstance(jim, Emp) 6538 with self.assertRaises(TypeError): 6539 issubclass(dict, Emp) 6540 with self.assertRaises(TypeError): 6541 TypedDict('Hi', [('x', int)], y=int) 6542 6543 def test_py36_class_syntax_usage(self): 6544 self.assertEqual(LabelPoint2D.__name__, 'LabelPoint2D') 6545 self.assertEqual(LabelPoint2D.__module__, __name__) 6546 self.assertEqual(LabelPoint2D.__annotations__, {'x': int, 'y': int, 'label': str}) 6547 self.assertEqual(LabelPoint2D.__bases__, (dict,)) 6548 self.assertEqual(LabelPoint2D.__total__, True) 6549 self.assertNotIsSubclass(LabelPoint2D, typing.Sequence) 6550 not_origin = Point2D(x=0, y=1) 6551 self.assertEqual(not_origin['x'], 0) 6552 self.assertEqual(not_origin['y'], 1) 6553 other = LabelPoint2D(x=0, y=1, label='hi') 6554 self.assertEqual(other['label'], 'hi') 6555 6556 def test_pickle(self): 6557 global EmpD # pickle wants to reference the class by name 6558 EmpD = TypedDict('EmpD', {'name': str, 'id': int}) 6559 jane = EmpD({'name': 'jane', 'id': 37}) 6560 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 6561 z = pickle.dumps(jane, proto) 6562 jane2 = pickle.loads(z) 6563 self.assertEqual(jane2, jane) 6564 self.assertEqual(jane2, {'name': 'jane', 'id': 37}) 6565 ZZ = pickle.dumps(EmpD, proto) 6566 EmpDnew = pickle.loads(ZZ) 6567 self.assertEqual(EmpDnew({'name': 'jane', 'id': 37}), jane) 6568 6569 def test_pickle_generic(self): 6570 point = Point2DGeneric(a=5.0, b=3.0) 6571 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 6572 z = pickle.dumps(point, proto) 6573 point2 = pickle.loads(z) 6574 self.assertEqual(point2, point) 6575 self.assertEqual(point2, {'a': 5.0, 'b': 3.0}) 6576 ZZ = pickle.dumps(Point2DGeneric, proto) 6577 Point2DGenericNew = pickle.loads(ZZ) 6578 self.assertEqual(Point2DGenericNew({'a': 5.0, 'b': 3.0}), point) 6579 6580 def test_optional(self): 6581 EmpD = TypedDict('EmpD', {'name': str, 'id': int}) 6582 6583 self.assertEqual(typing.Optional[EmpD], typing.Union[None, EmpD]) 6584 self.assertNotEqual(typing.List[EmpD], typing.Tuple[EmpD]) 6585 6586 def test_total(self): 6587 D = TypedDict('D', {'x': int}, total=False) 6588 self.assertEqual(D(), {}) 6589 self.assertEqual(D(x=1), {'x': 1}) 6590 self.assertEqual(D.__total__, False) 6591 self.assertEqual(D.__required_keys__, frozenset()) 6592 self.assertIsInstance(D.__required_keys__, frozenset) 6593 self.assertEqual(D.__optional_keys__, {'x'}) 6594 self.assertIsInstance(D.__optional_keys__, frozenset) 6595 6596 self.assertEqual(Options(), {}) 6597 self.assertEqual(Options(log_level=2), {'log_level': 2}) 6598 self.assertEqual(Options.__total__, False) 6599 self.assertEqual(Options.__required_keys__, frozenset()) 6600 self.assertEqual(Options.__optional_keys__, {'log_level', 'log_path'}) 6601 6602 def test_optional_keys(self): 6603 class Point2Dor3D(Point2D, total=False): 6604 z: int 6605 6606 self.assertEqual(Point2Dor3D.__required_keys__, frozenset(['x', 'y'])) 6607 self.assertIsInstance(Point2Dor3D.__required_keys__, frozenset) 6608 self.assertEqual(Point2Dor3D.__optional_keys__, frozenset(['z'])) 6609 self.assertIsInstance(Point2Dor3D.__optional_keys__, frozenset) 6610 6611 def test_keys_inheritance(self): 6612 class BaseAnimal(TypedDict): 6613 name: str 6614 6615 class Animal(BaseAnimal, total=False): 6616 voice: str 6617 tail: bool 6618 6619 class Cat(Animal): 6620 fur_color: str 6621 6622 self.assertEqual(BaseAnimal.__required_keys__, frozenset(['name'])) 6623 self.assertEqual(BaseAnimal.__optional_keys__, frozenset([])) 6624 self.assertEqual(BaseAnimal.__annotations__, {'name': str}) 6625 6626 self.assertEqual(Animal.__required_keys__, frozenset(['name'])) 6627 self.assertEqual(Animal.__optional_keys__, frozenset(['tail', 'voice'])) 6628 self.assertEqual(Animal.__annotations__, { 6629 'name': str, 6630 'tail': bool, 6631 'voice': str, 6632 }) 6633 6634 self.assertEqual(Cat.__required_keys__, frozenset(['name', 'fur_color'])) 6635 self.assertEqual(Cat.__optional_keys__, frozenset(['tail', 'voice'])) 6636 self.assertEqual(Cat.__annotations__, { 6637 'fur_color': str, 6638 'name': str, 6639 'tail': bool, 6640 'voice': str, 6641 }) 6642 6643 def test_required_notrequired_keys(self): 6644 self.assertEqual(NontotalMovie.__required_keys__, 6645 frozenset({"title"})) 6646 self.assertEqual(NontotalMovie.__optional_keys__, 6647 frozenset({"year"})) 6648 6649 self.assertEqual(TotalMovie.__required_keys__, 6650 frozenset({"title"})) 6651 self.assertEqual(TotalMovie.__optional_keys__, 6652 frozenset({"year"})) 6653 6654 self.assertEqual(_typed_dict_helper.VeryAnnotated.__required_keys__, 6655 frozenset()) 6656 self.assertEqual(_typed_dict_helper.VeryAnnotated.__optional_keys__, 6657 frozenset({"a"})) 6658 6659 self.assertEqual(AnnotatedMovie.__required_keys__, 6660 frozenset({"title"})) 6661 self.assertEqual(AnnotatedMovie.__optional_keys__, 6662 frozenset({"year"})) 6663 6664 self.assertEqual(WeirdlyQuotedMovie.__required_keys__, 6665 frozenset({"title"})) 6666 self.assertEqual(WeirdlyQuotedMovie.__optional_keys__, 6667 frozenset({"year"})) 6668 6669 self.assertEqual(ChildTotalMovie.__required_keys__, 6670 frozenset({"title"})) 6671 self.assertEqual(ChildTotalMovie.__optional_keys__, 6672 frozenset({"year"})) 6673 6674 self.assertEqual(ChildDeeplyAnnotatedMovie.__required_keys__, 6675 frozenset({"title"})) 6676 self.assertEqual(ChildDeeplyAnnotatedMovie.__optional_keys__, 6677 frozenset({"year"})) 6678 6679 def test_multiple_inheritance(self): 6680 class One(TypedDict): 6681 one: int 6682 class Two(TypedDict): 6683 two: str 6684 class Untotal(TypedDict, total=False): 6685 untotal: str 6686 Inline = TypedDict('Inline', {'inline': bool}) 6687 class Regular: 6688 pass 6689 6690 class Child(One, Two): 6691 child: bool 6692 self.assertEqual( 6693 Child.__required_keys__, 6694 frozenset(['one', 'two', 'child']), 6695 ) 6696 self.assertEqual( 6697 Child.__optional_keys__, 6698 frozenset([]), 6699 ) 6700 self.assertEqual( 6701 Child.__annotations__, 6702 {'one': int, 'two': str, 'child': bool}, 6703 ) 6704 6705 class ChildWithOptional(One, Untotal): 6706 child: bool 6707 self.assertEqual( 6708 ChildWithOptional.__required_keys__, 6709 frozenset(['one', 'child']), 6710 ) 6711 self.assertEqual( 6712 ChildWithOptional.__optional_keys__, 6713 frozenset(['untotal']), 6714 ) 6715 self.assertEqual( 6716 ChildWithOptional.__annotations__, 6717 {'one': int, 'untotal': str, 'child': bool}, 6718 ) 6719 6720 class ChildWithTotalFalse(One, Untotal, total=False): 6721 child: bool 6722 self.assertEqual( 6723 ChildWithTotalFalse.__required_keys__, 6724 frozenset(['one']), 6725 ) 6726 self.assertEqual( 6727 ChildWithTotalFalse.__optional_keys__, 6728 frozenset(['untotal', 'child']), 6729 ) 6730 self.assertEqual( 6731 ChildWithTotalFalse.__annotations__, 6732 {'one': int, 'untotal': str, 'child': bool}, 6733 ) 6734 6735 class ChildWithInlineAndOptional(Untotal, Inline): 6736 child: bool 6737 self.assertEqual( 6738 ChildWithInlineAndOptional.__required_keys__, 6739 frozenset(['inline', 'child']), 6740 ) 6741 self.assertEqual( 6742 ChildWithInlineAndOptional.__optional_keys__, 6743 frozenset(['untotal']), 6744 ) 6745 self.assertEqual( 6746 ChildWithInlineAndOptional.__annotations__, 6747 {'inline': bool, 'untotal': str, 'child': bool}, 6748 ) 6749 6750 wrong_bases = [ 6751 (One, Regular), 6752 (Regular, One), 6753 (One, Two, Regular), 6754 (Inline, Regular), 6755 (Untotal, Regular), 6756 ] 6757 for bases in wrong_bases: 6758 with self.subTest(bases=bases): 6759 with self.assertRaisesRegex( 6760 TypeError, 6761 'cannot inherit from both a TypedDict type and a non-TypedDict', 6762 ): 6763 class Wrong(*bases): 6764 pass 6765 6766 def test_is_typeddict(self): 6767 self.assertIs(is_typeddict(Point2D), True) 6768 self.assertIs(is_typeddict(Union[str, int]), False) 6769 # classes, not instances 6770 self.assertIs(is_typeddict(Point2D()), False) 6771 call_based = TypedDict('call_based', {'a': int}) 6772 self.assertIs(is_typeddict(call_based), True) 6773 self.assertIs(is_typeddict(call_based()), False) 6774 6775 T = TypeVar("T") 6776 class BarGeneric(TypedDict, Generic[T]): 6777 a: T 6778 self.assertIs(is_typeddict(BarGeneric), True) 6779 self.assertIs(is_typeddict(BarGeneric[int]), False) 6780 self.assertIs(is_typeddict(BarGeneric()), False) 6781 6782 # The TypedDict constructor is not itself a TypedDict 6783 self.assertIs(is_typeddict(TypedDict), False) 6784 6785 def test_get_type_hints(self): 6786 self.assertEqual( 6787 get_type_hints(Bar), 6788 {'a': typing.Optional[int], 'b': int} 6789 ) 6790 6791 def test_get_type_hints_generic(self): 6792 self.assertEqual( 6793 get_type_hints(BarGeneric), 6794 {'a': typing.Optional[T], 'b': int} 6795 ) 6796 6797 class FooBarGeneric(BarGeneric[int]): 6798 c: str 6799 6800 self.assertEqual( 6801 get_type_hints(FooBarGeneric), 6802 {'a': typing.Optional[T], 'b': int, 'c': str} 6803 ) 6804 6805 def test_generic_inheritance(self): 6806 class A(TypedDict, Generic[T]): 6807 a: T 6808 6809 self.assertEqual(A.__bases__, (Generic, dict)) 6810 self.assertEqual(A.__orig_bases__, (TypedDict, Generic[T])) 6811 self.assertEqual(A.__mro__, (A, Generic, dict, object)) 6812 self.assertEqual(A.__parameters__, (T,)) 6813 self.assertEqual(A[str].__parameters__, ()) 6814 self.assertEqual(A[str].__args__, (str,)) 6815 6816 class A2(Generic[T], TypedDict): 6817 a: T 6818 6819 self.assertEqual(A2.__bases__, (Generic, dict)) 6820 self.assertEqual(A2.__orig_bases__, (Generic[T], TypedDict)) 6821 self.assertEqual(A2.__mro__, (A2, Generic, dict, object)) 6822 self.assertEqual(A2.__parameters__, (T,)) 6823 self.assertEqual(A2[str].__parameters__, ()) 6824 self.assertEqual(A2[str].__args__, (str,)) 6825 6826 class B(A[KT], total=False): 6827 b: KT 6828 6829 self.assertEqual(B.__bases__, (Generic, dict)) 6830 self.assertEqual(B.__orig_bases__, (A[KT],)) 6831 self.assertEqual(B.__mro__, (B, Generic, dict, object)) 6832 self.assertEqual(B.__parameters__, (KT,)) 6833 self.assertEqual(B.__total__, False) 6834 self.assertEqual(B.__optional_keys__, frozenset(['b'])) 6835 self.assertEqual(B.__required_keys__, frozenset(['a'])) 6836 6837 self.assertEqual(B[str].__parameters__, ()) 6838 self.assertEqual(B[str].__args__, (str,)) 6839 self.assertEqual(B[str].__origin__, B) 6840 6841 class C(B[int]): 6842 c: int 6843 6844 self.assertEqual(C.__bases__, (Generic, dict)) 6845 self.assertEqual(C.__orig_bases__, (B[int],)) 6846 self.assertEqual(C.__mro__, (C, Generic, dict, object)) 6847 self.assertEqual(C.__parameters__, ()) 6848 self.assertEqual(C.__total__, True) 6849 self.assertEqual(C.__optional_keys__, frozenset(['b'])) 6850 self.assertEqual(C.__required_keys__, frozenset(['a', 'c'])) 6851 self.assertEqual(C.__annotations__, { 6852 'a': T, 6853 'b': KT, 6854 'c': int, 6855 }) 6856 with self.assertRaises(TypeError): 6857 C[str] 6858 6859 6860 class Point3D(Point2DGeneric[T], Generic[T, KT]): 6861 c: KT 6862 6863 self.assertEqual(Point3D.__bases__, (Generic, dict)) 6864 self.assertEqual(Point3D.__orig_bases__, (Point2DGeneric[T], Generic[T, KT])) 6865 self.assertEqual(Point3D.__mro__, (Point3D, Generic, dict, object)) 6866 self.assertEqual(Point3D.__parameters__, (T, KT)) 6867 self.assertEqual(Point3D.__total__, True) 6868 self.assertEqual(Point3D.__optional_keys__, frozenset()) 6869 self.assertEqual(Point3D.__required_keys__, frozenset(['a', 'b', 'c'])) 6870 self.assertEqual(Point3D.__annotations__, { 6871 'a': T, 6872 'b': T, 6873 'c': KT, 6874 }) 6875 self.assertEqual(Point3D[int, str].__origin__, Point3D) 6876 6877 with self.assertRaises(TypeError): 6878 Point3D[int] 6879 6880 with self.assertRaises(TypeError): 6881 class Point3D(Point2DGeneric[T], Generic[KT]): 6882 c: KT 6883 6884 def test_implicit_any_inheritance(self): 6885 class A(TypedDict, Generic[T]): 6886 a: T 6887 6888 class B(A[KT], total=False): 6889 b: KT 6890 6891 class WithImplicitAny(B): 6892 c: int 6893 6894 self.assertEqual(WithImplicitAny.__bases__, (Generic, dict,)) 6895 self.assertEqual(WithImplicitAny.__mro__, (WithImplicitAny, Generic, dict, object)) 6896 # Consistent with GenericTests.test_implicit_any 6897 self.assertEqual(WithImplicitAny.__parameters__, ()) 6898 self.assertEqual(WithImplicitAny.__total__, True) 6899 self.assertEqual(WithImplicitAny.__optional_keys__, frozenset(['b'])) 6900 self.assertEqual(WithImplicitAny.__required_keys__, frozenset(['a', 'c'])) 6901 self.assertEqual(WithImplicitAny.__annotations__, { 6902 'a': T, 6903 'b': KT, 6904 'c': int, 6905 }) 6906 with self.assertRaises(TypeError): 6907 WithImplicitAny[str] 6908 6909 def test_non_generic_subscript(self): 6910 # For backward compatibility, subscription works 6911 # on arbitrary TypedDict types. 6912 class TD(TypedDict): 6913 a: T 6914 A = TD[int] 6915 self.assertEqual(A.__origin__, TD) 6916 self.assertEqual(A.__parameters__, ()) 6917 self.assertEqual(A.__args__, (int,)) 6918 a = A(a = 1) 6919 self.assertIs(type(a), dict) 6920 self.assertEqual(a, {'a': 1}) 6921 6922 6923class RequiredTests(BaseTestCase): 6924 6925 def test_basics(self): 6926 with self.assertRaises(TypeError): 6927 Required[NotRequired] 6928 with self.assertRaises(TypeError): 6929 Required[int, str] 6930 with self.assertRaises(TypeError): 6931 Required[int][str] 6932 6933 def test_repr(self): 6934 self.assertEqual(repr(Required), 'typing.Required') 6935 cv = Required[int] 6936 self.assertEqual(repr(cv), 'typing.Required[int]') 6937 cv = Required[Employee] 6938 self.assertEqual(repr(cv), f'typing.Required[{__name__}.Employee]') 6939 6940 def test_cannot_subclass(self): 6941 with self.assertRaises(TypeError): 6942 class C(type(Required)): 6943 pass 6944 with self.assertRaises(TypeError): 6945 class C(type(Required[int])): 6946 pass 6947 with self.assertRaises(TypeError): 6948 class C(Required): 6949 pass 6950 with self.assertRaises(TypeError): 6951 class C(Required[int]): 6952 pass 6953 6954 def test_cannot_init(self): 6955 with self.assertRaises(TypeError): 6956 Required() 6957 with self.assertRaises(TypeError): 6958 type(Required)() 6959 with self.assertRaises(TypeError): 6960 type(Required[Optional[int]])() 6961 6962 def test_no_isinstance(self): 6963 with self.assertRaises(TypeError): 6964 isinstance(1, Required[int]) 6965 with self.assertRaises(TypeError): 6966 issubclass(int, Required) 6967 6968 6969class NotRequiredTests(BaseTestCase): 6970 6971 def test_basics(self): 6972 with self.assertRaises(TypeError): 6973 NotRequired[Required] 6974 with self.assertRaises(TypeError): 6975 NotRequired[int, str] 6976 with self.assertRaises(TypeError): 6977 NotRequired[int][str] 6978 6979 def test_repr(self): 6980 self.assertEqual(repr(NotRequired), 'typing.NotRequired') 6981 cv = NotRequired[int] 6982 self.assertEqual(repr(cv), 'typing.NotRequired[int]') 6983 cv = NotRequired[Employee] 6984 self.assertEqual(repr(cv), f'typing.NotRequired[{__name__}.Employee]') 6985 6986 def test_cannot_subclass(self): 6987 with self.assertRaises(TypeError): 6988 class C(type(NotRequired)): 6989 pass 6990 with self.assertRaises(TypeError): 6991 class C(type(NotRequired[int])): 6992 pass 6993 with self.assertRaises(TypeError): 6994 class C(NotRequired): 6995 pass 6996 with self.assertRaises(TypeError): 6997 class C(NotRequired[int]): 6998 pass 6999 7000 def test_cannot_init(self): 7001 with self.assertRaises(TypeError): 7002 NotRequired() 7003 with self.assertRaises(TypeError): 7004 type(NotRequired)() 7005 with self.assertRaises(TypeError): 7006 type(NotRequired[Optional[int]])() 7007 7008 def test_no_isinstance(self): 7009 with self.assertRaises(TypeError): 7010 isinstance(1, NotRequired[int]) 7011 with self.assertRaises(TypeError): 7012 issubclass(int, NotRequired) 7013 7014 7015class IOTests(BaseTestCase): 7016 7017 def test_io(self): 7018 7019 def stuff(a: IO) -> AnyStr: 7020 return a.readline() 7021 7022 a = stuff.__annotations__['a'] 7023 self.assertEqual(a.__parameters__, (AnyStr,)) 7024 7025 def test_textio(self): 7026 7027 def stuff(a: TextIO) -> str: 7028 return a.readline() 7029 7030 a = stuff.__annotations__['a'] 7031 self.assertEqual(a.__parameters__, ()) 7032 7033 def test_binaryio(self): 7034 7035 def stuff(a: BinaryIO) -> bytes: 7036 return a.readline() 7037 7038 a = stuff.__annotations__['a'] 7039 self.assertEqual(a.__parameters__, ()) 7040 7041 def test_io_submodule(self): 7042 with warnings.catch_warnings(record=True) as w: 7043 warnings.filterwarnings("default", category=DeprecationWarning) 7044 from typing.io import IO, TextIO, BinaryIO, __all__, __name__ 7045 self.assertIs(IO, typing.IO) 7046 self.assertIs(TextIO, typing.TextIO) 7047 self.assertIs(BinaryIO, typing.BinaryIO) 7048 self.assertEqual(set(__all__), set(['IO', 'TextIO', 'BinaryIO'])) 7049 self.assertEqual(__name__, 'typing.io') 7050 self.assertEqual(len(w), 1) 7051 7052 7053class RETests(BaseTestCase): 7054 # Much of this is really testing _TypeAlias. 7055 7056 def test_basics(self): 7057 pat = re.compile('[a-z]+', re.I) 7058 self.assertIsSubclass(pat.__class__, Pattern) 7059 self.assertIsSubclass(type(pat), Pattern) 7060 self.assertIsInstance(pat, Pattern) 7061 7062 mat = pat.search('12345abcde.....') 7063 self.assertIsSubclass(mat.__class__, Match) 7064 self.assertIsSubclass(type(mat), Match) 7065 self.assertIsInstance(mat, Match) 7066 7067 # these should just work 7068 Pattern[Union[str, bytes]] 7069 Match[Union[bytes, str]] 7070 7071 def test_alias_equality(self): 7072 self.assertEqual(Pattern[str], Pattern[str]) 7073 self.assertNotEqual(Pattern[str], Pattern[bytes]) 7074 self.assertNotEqual(Pattern[str], Match[str]) 7075 self.assertNotEqual(Pattern[str], str) 7076 7077 def test_errors(self): 7078 m = Match[Union[str, bytes]] 7079 with self.assertRaises(TypeError): 7080 m[str] 7081 with self.assertRaises(TypeError): 7082 # We don't support isinstance(). 7083 isinstance(42, Pattern[str]) 7084 with self.assertRaises(TypeError): 7085 # We don't support issubclass(). 7086 issubclass(Pattern[bytes], Pattern[str]) 7087 7088 def test_repr(self): 7089 self.assertEqual(repr(Pattern), 'typing.Pattern') 7090 self.assertEqual(repr(Pattern[str]), 'typing.Pattern[str]') 7091 self.assertEqual(repr(Pattern[bytes]), 'typing.Pattern[bytes]') 7092 self.assertEqual(repr(Match), 'typing.Match') 7093 self.assertEqual(repr(Match[str]), 'typing.Match[str]') 7094 self.assertEqual(repr(Match[bytes]), 'typing.Match[bytes]') 7095 7096 def test_re_submodule(self): 7097 with warnings.catch_warnings(record=True) as w: 7098 warnings.filterwarnings("default", category=DeprecationWarning) 7099 from typing.re import Match, Pattern, __all__, __name__ 7100 self.assertIs(Match, typing.Match) 7101 self.assertIs(Pattern, typing.Pattern) 7102 self.assertEqual(set(__all__), set(['Match', 'Pattern'])) 7103 self.assertEqual(__name__, 'typing.re') 7104 self.assertEqual(len(w), 1) 7105 7106 def test_cannot_subclass(self): 7107 with self.assertRaises(TypeError) as ex: 7108 7109 class A(typing.Match): 7110 pass 7111 7112 self.assertEqual(str(ex.exception), 7113 "type 're.Match' is not an acceptable base type") 7114 7115 7116class AnnotatedTests(BaseTestCase): 7117 7118 def test_new(self): 7119 with self.assertRaisesRegex( 7120 TypeError, 7121 'Type Annotated cannot be instantiated', 7122 ): 7123 Annotated() 7124 7125 def test_repr(self): 7126 self.assertEqual( 7127 repr(Annotated[int, 4, 5]), 7128 "typing.Annotated[int, 4, 5]" 7129 ) 7130 self.assertEqual( 7131 repr(Annotated[List[int], 4, 5]), 7132 "typing.Annotated[typing.List[int], 4, 5]" 7133 ) 7134 7135 def test_dir(self): 7136 dir_items = set(dir(Annotated[int, 4])) 7137 for required_item in [ 7138 '__args__', '__parameters__', '__origin__', 7139 '__metadata__', 7140 ]: 7141 with self.subTest(required_item=required_item): 7142 self.assertIn(required_item, dir_items) 7143 7144 def test_flatten(self): 7145 A = Annotated[Annotated[int, 4], 5] 7146 self.assertEqual(A, Annotated[int, 4, 5]) 7147 self.assertEqual(A.__metadata__, (4, 5)) 7148 self.assertEqual(A.__origin__, int) 7149 7150 def test_specialize(self): 7151 L = Annotated[List[T], "my decoration"] 7152 LI = Annotated[List[int], "my decoration"] 7153 self.assertEqual(L[int], Annotated[List[int], "my decoration"]) 7154 self.assertEqual(L[int].__metadata__, ("my decoration",)) 7155 self.assertEqual(L[int].__origin__, List[int]) 7156 with self.assertRaises(TypeError): 7157 LI[int] 7158 with self.assertRaises(TypeError): 7159 L[int, float] 7160 7161 def test_hash_eq(self): 7162 self.assertEqual(len({Annotated[int, 4, 5], Annotated[int, 4, 5]}), 1) 7163 self.assertNotEqual(Annotated[int, 4, 5], Annotated[int, 5, 4]) 7164 self.assertNotEqual(Annotated[int, 4, 5], Annotated[str, 4, 5]) 7165 self.assertNotEqual(Annotated[int, 4], Annotated[int, 4, 4]) 7166 self.assertEqual( 7167 {Annotated[int, 4, 5], Annotated[int, 4, 5], Annotated[T, 4, 5]}, 7168 {Annotated[int, 4, 5], Annotated[T, 4, 5]} 7169 ) 7170 7171 def test_instantiate(self): 7172 class C: 7173 classvar = 4 7174 7175 def __init__(self, x): 7176 self.x = x 7177 7178 def __eq__(self, other): 7179 if not isinstance(other, C): 7180 return NotImplemented 7181 return other.x == self.x 7182 7183 A = Annotated[C, "a decoration"] 7184 a = A(5) 7185 c = C(5) 7186 self.assertEqual(a, c) 7187 self.assertEqual(a.x, c.x) 7188 self.assertEqual(a.classvar, c.classvar) 7189 7190 def test_instantiate_generic(self): 7191 MyCount = Annotated[typing.Counter[T], "my decoration"] 7192 self.assertEqual(MyCount([4, 4, 5]), {4: 2, 5: 1}) 7193 self.assertEqual(MyCount[int]([4, 4, 5]), {4: 2, 5: 1}) 7194 7195 def test_cannot_instantiate_forward(self): 7196 A = Annotated["int", (5, 6)] 7197 with self.assertRaises(TypeError): 7198 A(5) 7199 7200 def test_cannot_instantiate_type_var(self): 7201 A = Annotated[T, (5, 6)] 7202 with self.assertRaises(TypeError): 7203 A(5) 7204 7205 def test_cannot_getattr_typevar(self): 7206 with self.assertRaises(AttributeError): 7207 Annotated[T, (5, 7)].x 7208 7209 def test_attr_passthrough(self): 7210 class C: 7211 classvar = 4 7212 7213 A = Annotated[C, "a decoration"] 7214 self.assertEqual(A.classvar, 4) 7215 A.x = 5 7216 self.assertEqual(C.x, 5) 7217 7218 def test_special_form_containment(self): 7219 class C: 7220 classvar: Annotated[ClassVar[int], "a decoration"] = 4 7221 const: Annotated[Final[int], "Const"] = 4 7222 7223 self.assertEqual(get_type_hints(C, globals())['classvar'], ClassVar[int]) 7224 self.assertEqual(get_type_hints(C, globals())['const'], Final[int]) 7225 7226 def test_cannot_subclass(self): 7227 with self.assertRaisesRegex(TypeError, "Cannot subclass .*Annotated"): 7228 class C(Annotated): 7229 pass 7230 7231 def test_cannot_check_instance(self): 7232 with self.assertRaises(TypeError): 7233 isinstance(5, Annotated[int, "positive"]) 7234 7235 def test_cannot_check_subclass(self): 7236 with self.assertRaises(TypeError): 7237 issubclass(int, Annotated[int, "positive"]) 7238 7239 def test_too_few_type_args(self): 7240 with self.assertRaisesRegex(TypeError, 'at least two arguments'): 7241 Annotated[int] 7242 7243 def test_pickle(self): 7244 samples = [typing.Any, typing.Union[int, str], 7245 typing.Optional[str], Tuple[int, ...], 7246 typing.Callable[[str], bytes]] 7247 7248 for t in samples: 7249 x = Annotated[t, "a"] 7250 7251 for prot in range(pickle.HIGHEST_PROTOCOL + 1): 7252 with self.subTest(protocol=prot, type=t): 7253 pickled = pickle.dumps(x, prot) 7254 restored = pickle.loads(pickled) 7255 self.assertEqual(x, restored) 7256 7257 global _Annotated_test_G 7258 7259 class _Annotated_test_G(Generic[T]): 7260 x = 1 7261 7262 G = Annotated[_Annotated_test_G[int], "A decoration"] 7263 G.foo = 42 7264 G.bar = 'abc' 7265 7266 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 7267 z = pickle.dumps(G, proto) 7268 x = pickle.loads(z) 7269 self.assertEqual(x.foo, 42) 7270 self.assertEqual(x.bar, 'abc') 7271 self.assertEqual(x.x, 1) 7272 7273 def test_subst(self): 7274 dec = "a decoration" 7275 dec2 = "another decoration" 7276 7277 S = Annotated[T, dec2] 7278 self.assertEqual(S[int], Annotated[int, dec2]) 7279 7280 self.assertEqual(S[Annotated[int, dec]], Annotated[int, dec, dec2]) 7281 L = Annotated[List[T], dec] 7282 7283 self.assertEqual(L[int], Annotated[List[int], dec]) 7284 with self.assertRaises(TypeError): 7285 L[int, int] 7286 7287 self.assertEqual(S[L[int]], Annotated[List[int], dec, dec2]) 7288 7289 D = Annotated[typing.Dict[KT, VT], dec] 7290 self.assertEqual(D[str, int], Annotated[typing.Dict[str, int], dec]) 7291 with self.assertRaises(TypeError): 7292 D[int] 7293 7294 It = Annotated[int, dec] 7295 with self.assertRaises(TypeError): 7296 It[None] 7297 7298 LI = L[int] 7299 with self.assertRaises(TypeError): 7300 LI[None] 7301 7302 def test_typevar_subst(self): 7303 dec = "a decoration" 7304 Ts = TypeVarTuple('Ts') 7305 T = TypeVar('T') 7306 T1 = TypeVar('T1') 7307 T2 = TypeVar('T2') 7308 7309 A = Annotated[tuple[*Ts], dec] 7310 self.assertEqual(A[int], Annotated[tuple[int], dec]) 7311 self.assertEqual(A[str, int], Annotated[tuple[str, int], dec]) 7312 with self.assertRaises(TypeError): 7313 Annotated[*Ts, dec] 7314 7315 B = Annotated[Tuple[Unpack[Ts]], dec] 7316 self.assertEqual(B[int], Annotated[Tuple[int], dec]) 7317 self.assertEqual(B[str, int], Annotated[Tuple[str, int], dec]) 7318 with self.assertRaises(TypeError): 7319 Annotated[Unpack[Ts], dec] 7320 7321 C = Annotated[tuple[T, *Ts], dec] 7322 self.assertEqual(C[int], Annotated[tuple[int], dec]) 7323 self.assertEqual(C[int, str], Annotated[tuple[int, str], dec]) 7324 self.assertEqual( 7325 C[int, str, float], 7326 Annotated[tuple[int, str, float], dec] 7327 ) 7328 with self.assertRaises(TypeError): 7329 C[()] 7330 7331 D = Annotated[Tuple[T, Unpack[Ts]], dec] 7332 self.assertEqual(D[int], Annotated[Tuple[int], dec]) 7333 self.assertEqual(D[int, str], Annotated[Tuple[int, str], dec]) 7334 self.assertEqual( 7335 D[int, str, float], 7336 Annotated[Tuple[int, str, float], dec] 7337 ) 7338 with self.assertRaises(TypeError): 7339 D[()] 7340 7341 E = Annotated[tuple[*Ts, T], dec] 7342 self.assertEqual(E[int], Annotated[tuple[int], dec]) 7343 self.assertEqual(E[int, str], Annotated[tuple[int, str], dec]) 7344 self.assertEqual( 7345 E[int, str, float], 7346 Annotated[tuple[int, str, float], dec] 7347 ) 7348 with self.assertRaises(TypeError): 7349 E[()] 7350 7351 F = Annotated[Tuple[Unpack[Ts], T], dec] 7352 self.assertEqual(F[int], Annotated[Tuple[int], dec]) 7353 self.assertEqual(F[int, str], Annotated[Tuple[int, str], dec]) 7354 self.assertEqual( 7355 F[int, str, float], 7356 Annotated[Tuple[int, str, float], dec] 7357 ) 7358 with self.assertRaises(TypeError): 7359 F[()] 7360 7361 G = Annotated[tuple[T1, *Ts, T2], dec] 7362 self.assertEqual(G[int, str], Annotated[tuple[int, str], dec]) 7363 self.assertEqual( 7364 G[int, str, float], 7365 Annotated[tuple[int, str, float], dec] 7366 ) 7367 self.assertEqual( 7368 G[int, str, bool, float], 7369 Annotated[tuple[int, str, bool, float], dec] 7370 ) 7371 with self.assertRaises(TypeError): 7372 G[int] 7373 7374 H = Annotated[Tuple[T1, Unpack[Ts], T2], dec] 7375 self.assertEqual(H[int, str], Annotated[Tuple[int, str], dec]) 7376 self.assertEqual( 7377 H[int, str, float], 7378 Annotated[Tuple[int, str, float], dec] 7379 ) 7380 self.assertEqual( 7381 H[int, str, bool, float], 7382 Annotated[Tuple[int, str, bool, float], dec] 7383 ) 7384 with self.assertRaises(TypeError): 7385 H[int] 7386 7387 # Now let's try creating an alias from an alias. 7388 7389 Ts2 = TypeVarTuple('Ts2') 7390 T3 = TypeVar('T3') 7391 T4 = TypeVar('T4') 7392 7393 # G is Annotated[tuple[T1, *Ts, T2], dec]. 7394 I = G[T3, *Ts2, T4] 7395 J = G[T3, Unpack[Ts2], T4] 7396 7397 for x, y in [ 7398 (I, Annotated[tuple[T3, *Ts2, T4], dec]), 7399 (J, Annotated[tuple[T3, Unpack[Ts2], T4], dec]), 7400 (I[int, str], Annotated[tuple[int, str], dec]), 7401 (J[int, str], Annotated[tuple[int, str], dec]), 7402 (I[int, str, float], Annotated[tuple[int, str, float], dec]), 7403 (J[int, str, float], Annotated[tuple[int, str, float], dec]), 7404 (I[int, str, bool, float], 7405 Annotated[tuple[int, str, bool, float], dec]), 7406 (J[int, str, bool, float], 7407 Annotated[tuple[int, str, bool, float], dec]), 7408 ]: 7409 self.assertEqual(x, y) 7410 7411 with self.assertRaises(TypeError): 7412 I[int] 7413 with self.assertRaises(TypeError): 7414 J[int] 7415 7416 def test_annotated_in_other_types(self): 7417 X = List[Annotated[T, 5]] 7418 self.assertEqual(X[int], List[Annotated[int, 5]]) 7419 7420 def test_annotated_mro(self): 7421 class X(Annotated[int, (1, 10)]): ... 7422 self.assertEqual(X.__mro__, (X, int, object), 7423 "Annotated should be transparent.") 7424 7425 7426class TypeAliasTests(BaseTestCase): 7427 def test_canonical_usage_with_variable_annotation(self): 7428 Alias: TypeAlias = Employee 7429 7430 def test_canonical_usage_with_type_comment(self): 7431 Alias = Employee # type: TypeAlias 7432 7433 def test_cannot_instantiate(self): 7434 with self.assertRaises(TypeError): 7435 TypeAlias() 7436 7437 def test_no_isinstance(self): 7438 with self.assertRaises(TypeError): 7439 isinstance(42, TypeAlias) 7440 7441 def test_stringized_usage(self): 7442 class A: 7443 a: "TypeAlias" 7444 self.assertEqual(get_type_hints(A), {'a': TypeAlias}) 7445 7446 def test_no_issubclass(self): 7447 with self.assertRaises(TypeError): 7448 issubclass(Employee, TypeAlias) 7449 7450 with self.assertRaises(TypeError): 7451 issubclass(TypeAlias, Employee) 7452 7453 def test_cannot_subclass(self): 7454 with self.assertRaises(TypeError): 7455 class C(TypeAlias): 7456 pass 7457 7458 with self.assertRaises(TypeError): 7459 class C(type(TypeAlias)): 7460 pass 7461 7462 def test_repr(self): 7463 self.assertEqual(repr(TypeAlias), 'typing.TypeAlias') 7464 7465 def test_cannot_subscript(self): 7466 with self.assertRaises(TypeError): 7467 TypeAlias[int] 7468 7469 7470class ParamSpecTests(BaseTestCase): 7471 7472 def test_basic_plain(self): 7473 P = ParamSpec('P') 7474 self.assertEqual(P, P) 7475 self.assertIsInstance(P, ParamSpec) 7476 self.assertEqual(P.__name__, 'P') 7477 7478 def test_valid_uses(self): 7479 P = ParamSpec('P') 7480 T = TypeVar('T') 7481 C1 = Callable[P, int] 7482 self.assertEqual(C1.__args__, (P, int)) 7483 self.assertEqual(C1.__parameters__, (P,)) 7484 C2 = Callable[P, T] 7485 self.assertEqual(C2.__args__, (P, T)) 7486 self.assertEqual(C2.__parameters__, (P, T)) 7487 # Test collections.abc.Callable too. 7488 C3 = collections.abc.Callable[P, int] 7489 self.assertEqual(C3.__args__, (P, int)) 7490 self.assertEqual(C3.__parameters__, (P,)) 7491 C4 = collections.abc.Callable[P, T] 7492 self.assertEqual(C4.__args__, (P, T)) 7493 self.assertEqual(C4.__parameters__, (P, T)) 7494 7495 def test_args_kwargs(self): 7496 P = ParamSpec('P') 7497 P_2 = ParamSpec('P_2') 7498 self.assertIn('args', dir(P)) 7499 self.assertIn('kwargs', dir(P)) 7500 self.assertIsInstance(P.args, ParamSpecArgs) 7501 self.assertIsInstance(P.kwargs, ParamSpecKwargs) 7502 self.assertIs(P.args.__origin__, P) 7503 self.assertIs(P.kwargs.__origin__, P) 7504 self.assertEqual(P.args, P.args) 7505 self.assertEqual(P.kwargs, P.kwargs) 7506 self.assertNotEqual(P.args, P_2.args) 7507 self.assertNotEqual(P.kwargs, P_2.kwargs) 7508 self.assertNotEqual(P.args, P.kwargs) 7509 self.assertNotEqual(P.kwargs, P.args) 7510 self.assertNotEqual(P.args, P_2.kwargs) 7511 self.assertEqual(repr(P.args), "P.args") 7512 self.assertEqual(repr(P.kwargs), "P.kwargs") 7513 7514 def test_stringized(self): 7515 P = ParamSpec('P') 7516 class C(Generic[P]): 7517 func: Callable["P", int] 7518 def foo(self, *args: "P.args", **kwargs: "P.kwargs"): 7519 pass 7520 7521 self.assertEqual(gth(C, globals(), locals()), {"func": Callable[P, int]}) 7522 self.assertEqual( 7523 gth(C.foo, globals(), locals()), {"args": P.args, "kwargs": P.kwargs} 7524 ) 7525 7526 def test_user_generics(self): 7527 T = TypeVar("T") 7528 P = ParamSpec("P") 7529 P_2 = ParamSpec("P_2") 7530 7531 class X(Generic[T, P]): 7532 f: Callable[P, int] 7533 x: T 7534 G1 = X[int, P_2] 7535 self.assertEqual(G1.__args__, (int, P_2)) 7536 self.assertEqual(G1.__parameters__, (P_2,)) 7537 with self.assertRaisesRegex(TypeError, "few arguments for"): 7538 X[int] 7539 with self.assertRaisesRegex(TypeError, "many arguments for"): 7540 X[int, P_2, str] 7541 7542 G2 = X[int, Concatenate[int, P_2]] 7543 self.assertEqual(G2.__args__, (int, Concatenate[int, P_2])) 7544 self.assertEqual(G2.__parameters__, (P_2,)) 7545 7546 G3 = X[int, [int, bool]] 7547 self.assertEqual(G3.__args__, (int, (int, bool))) 7548 self.assertEqual(G3.__parameters__, ()) 7549 7550 G4 = X[int, ...] 7551 self.assertEqual(G4.__args__, (int, Ellipsis)) 7552 self.assertEqual(G4.__parameters__, ()) 7553 7554 class Z(Generic[P]): 7555 f: Callable[P, int] 7556 7557 G5 = Z[[int, str, bool]] 7558 self.assertEqual(G5.__args__, ((int, str, bool),)) 7559 self.assertEqual(G5.__parameters__, ()) 7560 7561 G6 = Z[int, str, bool] 7562 self.assertEqual(G6.__args__, ((int, str, bool),)) 7563 self.assertEqual(G6.__parameters__, ()) 7564 7565 # G5 and G6 should be equivalent according to the PEP 7566 self.assertEqual(G5.__args__, G6.__args__) 7567 self.assertEqual(G5.__origin__, G6.__origin__) 7568 self.assertEqual(G5.__parameters__, G6.__parameters__) 7569 self.assertEqual(G5, G6) 7570 7571 G7 = Z[int] 7572 self.assertEqual(G7.__args__, ((int,),)) 7573 self.assertEqual(G7.__parameters__, ()) 7574 7575 with self.assertRaisesRegex(TypeError, "many arguments for"): 7576 Z[[int, str], bool] 7577 with self.assertRaisesRegex(TypeError, "many arguments for"): 7578 Z[P_2, bool] 7579 7580 def test_multiple_paramspecs_in_user_generics(self): 7581 P = ParamSpec("P") 7582 P2 = ParamSpec("P2") 7583 7584 class X(Generic[P, P2]): 7585 f: Callable[P, int] 7586 g: Callable[P2, str] 7587 7588 G1 = X[[int, str], [bytes]] 7589 G2 = X[[int], [str, bytes]] 7590 self.assertNotEqual(G1, G2) 7591 self.assertEqual(G1.__args__, ((int, str), (bytes,))) 7592 self.assertEqual(G2.__args__, ((int,), (str, bytes))) 7593 7594 def test_typevartuple_and_paramspecs_in_user_generics(self): 7595 Ts = TypeVarTuple("Ts") 7596 P = ParamSpec("P") 7597 7598 class X(Generic[*Ts, P]): 7599 f: Callable[P, int] 7600 g: Tuple[*Ts] 7601 7602 G1 = X[int, [bytes]] 7603 self.assertEqual(G1.__args__, (int, (bytes,))) 7604 G2 = X[int, str, [bytes]] 7605 self.assertEqual(G2.__args__, (int, str, (bytes,))) 7606 G3 = X[[bytes]] 7607 self.assertEqual(G3.__args__, ((bytes,),)) 7608 G4 = X[[]] 7609 self.assertEqual(G4.__args__, ((),)) 7610 with self.assertRaises(TypeError): 7611 X[()] 7612 7613 class Y(Generic[P, *Ts]): 7614 f: Callable[P, int] 7615 g: Tuple[*Ts] 7616 7617 G1 = Y[[bytes], int] 7618 self.assertEqual(G1.__args__, ((bytes,), int)) 7619 G2 = Y[[bytes], int, str] 7620 self.assertEqual(G2.__args__, ((bytes,), int, str)) 7621 G3 = Y[[bytes]] 7622 self.assertEqual(G3.__args__, ((bytes,),)) 7623 G4 = Y[[]] 7624 self.assertEqual(G4.__args__, ((),)) 7625 with self.assertRaises(TypeError): 7626 Y[()] 7627 7628 def test_typevartuple_and_paramspecs_in_generic_aliases(self): 7629 P = ParamSpec('P') 7630 T = TypeVar('T') 7631 Ts = TypeVarTuple('Ts') 7632 7633 for C in Callable, collections.abc.Callable: 7634 with self.subTest(generic=C): 7635 A = C[P, Tuple[*Ts]] 7636 B = A[[int, str], bytes, float] 7637 self.assertEqual(B.__args__, (int, str, Tuple[bytes, float])) 7638 7639 class X(Generic[T, P]): 7640 pass 7641 7642 A = X[Tuple[*Ts], P] 7643 B = A[bytes, float, [int, str]] 7644 self.assertEqual(B.__args__, (Tuple[bytes, float], (int, str,))) 7645 7646 class Y(Generic[P, T]): 7647 pass 7648 7649 A = Y[P, Tuple[*Ts]] 7650 B = A[[int, str], bytes, float] 7651 self.assertEqual(B.__args__, ((int, str,), Tuple[bytes, float])) 7652 7653 def test_var_substitution(self): 7654 P = ParamSpec("P") 7655 subst = P.__typing_subst__ 7656 self.assertEqual(subst((int, str)), (int, str)) 7657 self.assertEqual(subst([int, str]), (int, str)) 7658 self.assertEqual(subst([None]), (type(None),)) 7659 self.assertIs(subst(...), ...) 7660 self.assertIs(subst(P), P) 7661 self.assertEqual(subst(Concatenate[int, P]), Concatenate[int, P]) 7662 7663 def test_bad_var_substitution(self): 7664 T = TypeVar('T') 7665 P = ParamSpec('P') 7666 bad_args = (42, int, None, T, int|str, Union[int, str]) 7667 for arg in bad_args: 7668 with self.subTest(arg=arg): 7669 with self.assertRaises(TypeError): 7670 P.__typing_subst__(arg) 7671 with self.assertRaises(TypeError): 7672 typing.Callable[P, T][arg, str] 7673 with self.assertRaises(TypeError): 7674 collections.abc.Callable[P, T][arg, str] 7675 7676 def test_type_var_subst_for_other_type_vars(self): 7677 T = TypeVar('T') 7678 T2 = TypeVar('T2') 7679 P = ParamSpec('P') 7680 P2 = ParamSpec('P2') 7681 Ts = TypeVarTuple('Ts') 7682 7683 class Base(Generic[P]): 7684 pass 7685 7686 A1 = Base[T] 7687 self.assertEqual(A1.__parameters__, (T,)) 7688 self.assertEqual(A1.__args__, ((T,),)) 7689 self.assertEqual(A1[int], Base[int]) 7690 7691 A2 = Base[[T]] 7692 self.assertEqual(A2.__parameters__, (T,)) 7693 self.assertEqual(A2.__args__, ((T,),)) 7694 self.assertEqual(A2[int], Base[int]) 7695 7696 A3 = Base[[int, T]] 7697 self.assertEqual(A3.__parameters__, (T,)) 7698 self.assertEqual(A3.__args__, ((int, T),)) 7699 self.assertEqual(A3[str], Base[[int, str]]) 7700 7701 A4 = Base[[T, int, T2]] 7702 self.assertEqual(A4.__parameters__, (T, T2)) 7703 self.assertEqual(A4.__args__, ((T, int, T2),)) 7704 self.assertEqual(A4[str, bool], Base[[str, int, bool]]) 7705 7706 A5 = Base[[*Ts, int]] 7707 self.assertEqual(A5.__parameters__, (Ts,)) 7708 self.assertEqual(A5.__args__, ((*Ts, int),)) 7709 self.assertEqual(A5[str, bool], Base[[str, bool, int]]) 7710 7711 A5_2 = Base[[int, *Ts]] 7712 self.assertEqual(A5_2.__parameters__, (Ts,)) 7713 self.assertEqual(A5_2.__args__, ((int, *Ts),)) 7714 self.assertEqual(A5_2[str, bool], Base[[int, str, bool]]) 7715 7716 A6 = Base[[T, *Ts]] 7717 self.assertEqual(A6.__parameters__, (T, Ts)) 7718 self.assertEqual(A6.__args__, ((T, *Ts),)) 7719 self.assertEqual(A6[int, str, bool], Base[[int, str, bool]]) 7720 7721 A7 = Base[[T, T]] 7722 self.assertEqual(A7.__parameters__, (T,)) 7723 self.assertEqual(A7.__args__, ((T, T),)) 7724 self.assertEqual(A7[int], Base[[int, int]]) 7725 7726 A8 = Base[[T, list[T]]] 7727 self.assertEqual(A8.__parameters__, (T,)) 7728 self.assertEqual(A8.__args__, ((T, list[T]),)) 7729 self.assertEqual(A8[int], Base[[int, list[int]]]) 7730 7731 A9 = Base[[Tuple[*Ts], *Ts]] 7732 self.assertEqual(A9.__parameters__, (Ts,)) 7733 self.assertEqual(A9.__args__, ((Tuple[*Ts], *Ts),)) 7734 self.assertEqual(A9[int, str], Base[Tuple[int, str], int, str]) 7735 7736 A10 = Base[P2] 7737 self.assertEqual(A10.__parameters__, (P2,)) 7738 self.assertEqual(A10.__args__, (P2,)) 7739 self.assertEqual(A10[[int, str]], Base[[int, str]]) 7740 7741 class DoubleP(Generic[P, P2]): 7742 pass 7743 7744 B1 = DoubleP[P, P2] 7745 self.assertEqual(B1.__parameters__, (P, P2)) 7746 self.assertEqual(B1.__args__, (P, P2)) 7747 self.assertEqual(B1[[int, str], [bool]], DoubleP[[int, str], [bool]]) 7748 self.assertEqual(B1[[], []], DoubleP[[], []]) 7749 7750 B2 = DoubleP[[int, str], P2] 7751 self.assertEqual(B2.__parameters__, (P2,)) 7752 self.assertEqual(B2.__args__, ((int, str), P2)) 7753 self.assertEqual(B2[[bool, bool]], DoubleP[[int, str], [bool, bool]]) 7754 self.assertEqual(B2[[]], DoubleP[[int, str], []]) 7755 7756 B3 = DoubleP[P, [bool, bool]] 7757 self.assertEqual(B3.__parameters__, (P,)) 7758 self.assertEqual(B3.__args__, (P, (bool, bool))) 7759 self.assertEqual(B3[[int, str]], DoubleP[[int, str], [bool, bool]]) 7760 self.assertEqual(B3[[]], DoubleP[[], [bool, bool]]) 7761 7762 B4 = DoubleP[[T, int], [bool, T2]] 7763 self.assertEqual(B4.__parameters__, (T, T2)) 7764 self.assertEqual(B4.__args__, ((T, int), (bool, T2))) 7765 self.assertEqual(B4[str, float], DoubleP[[str, int], [bool, float]]) 7766 7767 B5 = DoubleP[[*Ts, int], [bool, T2]] 7768 self.assertEqual(B5.__parameters__, (Ts, T2)) 7769 self.assertEqual(B5.__args__, ((*Ts, int), (bool, T2))) 7770 self.assertEqual(B5[str, bytes, float], 7771 DoubleP[[str, bytes, int], [bool, float]]) 7772 7773 B6 = DoubleP[[T, int], [bool, *Ts]] 7774 self.assertEqual(B6.__parameters__, (T, Ts)) 7775 self.assertEqual(B6.__args__, ((T, int), (bool, *Ts))) 7776 self.assertEqual(B6[str, bytes, float], 7777 DoubleP[[str, int], [bool, bytes, float]]) 7778 7779 class PandT(Generic[P, T]): 7780 pass 7781 7782 C1 = PandT[P, T] 7783 self.assertEqual(C1.__parameters__, (P, T)) 7784 self.assertEqual(C1.__args__, (P, T)) 7785 self.assertEqual(C1[[int, str], bool], PandT[[int, str], bool]) 7786 7787 C2 = PandT[[int, T], T] 7788 self.assertEqual(C2.__parameters__, (T,)) 7789 self.assertEqual(C2.__args__, ((int, T), T)) 7790 self.assertEqual(C2[str], PandT[[int, str], str]) 7791 7792 C3 = PandT[[int, *Ts], T] 7793 self.assertEqual(C3.__parameters__, (Ts, T)) 7794 self.assertEqual(C3.__args__, ((int, *Ts), T)) 7795 self.assertEqual(C3[str, bool, bytes], PandT[[int, str, bool], bytes]) 7796 7797 def test_paramspec_in_nested_generics(self): 7798 # Although ParamSpec should not be found in __parameters__ of most 7799 # generics, they probably should be found when nested in 7800 # a valid location. 7801 T = TypeVar("T") 7802 P = ParamSpec("P") 7803 C1 = Callable[P, T] 7804 G1 = List[C1] 7805 G2 = list[C1] 7806 G3 = list[C1] | int 7807 self.assertEqual(G1.__parameters__, (P, T)) 7808 self.assertEqual(G2.__parameters__, (P, T)) 7809 self.assertEqual(G3.__parameters__, (P, T)) 7810 C = Callable[[int, str], float] 7811 self.assertEqual(G1[[int, str], float], List[C]) 7812 self.assertEqual(G2[[int, str], float], list[C]) 7813 self.assertEqual(G3[[int, str], float], list[C] | int) 7814 7815 def test_paramspec_gets_copied(self): 7816 # bpo-46581 7817 P = ParamSpec('P') 7818 P2 = ParamSpec('P2') 7819 C1 = Callable[P, int] 7820 self.assertEqual(C1.__parameters__, (P,)) 7821 self.assertEqual(C1[P2].__parameters__, (P2,)) 7822 self.assertEqual(C1[str].__parameters__, ()) 7823 self.assertEqual(C1[str, T].__parameters__, (T,)) 7824 self.assertEqual(C1[Concatenate[str, P2]].__parameters__, (P2,)) 7825 self.assertEqual(C1[Concatenate[T, P2]].__parameters__, (T, P2)) 7826 self.assertEqual(C1[...].__parameters__, ()) 7827 7828 C2 = Callable[Concatenate[str, P], int] 7829 self.assertEqual(C2.__parameters__, (P,)) 7830 self.assertEqual(C2[P2].__parameters__, (P2,)) 7831 self.assertEqual(C2[str].__parameters__, ()) 7832 self.assertEqual(C2[str, T].__parameters__, (T,)) 7833 self.assertEqual(C2[Concatenate[str, P2]].__parameters__, (P2,)) 7834 self.assertEqual(C2[Concatenate[T, P2]].__parameters__, (T, P2)) 7835 7836 7837class ConcatenateTests(BaseTestCase): 7838 def test_basics(self): 7839 P = ParamSpec('P') 7840 class MyClass: ... 7841 c = Concatenate[MyClass, P] 7842 self.assertNotEqual(c, Concatenate) 7843 7844 def test_dir(self): 7845 P = ParamSpec('P') 7846 dir_items = set(dir(Concatenate[int, P])) 7847 for required_item in [ 7848 '__args__', '__parameters__', '__origin__', 7849 ]: 7850 with self.subTest(required_item=required_item): 7851 self.assertIn(required_item, dir_items) 7852 7853 def test_valid_uses(self): 7854 P = ParamSpec('P') 7855 T = TypeVar('T') 7856 C1 = Callable[Concatenate[int, P], int] 7857 self.assertEqual(C1.__args__, (Concatenate[int, P], int)) 7858 self.assertEqual(C1.__parameters__, (P,)) 7859 C2 = Callable[Concatenate[int, T, P], T] 7860 self.assertEqual(C2.__args__, (Concatenate[int, T, P], T)) 7861 self.assertEqual(C2.__parameters__, (T, P)) 7862 7863 # Test collections.abc.Callable too. 7864 C3 = collections.abc.Callable[Concatenate[int, P], int] 7865 self.assertEqual(C3.__args__, (Concatenate[int, P], int)) 7866 self.assertEqual(C3.__parameters__, (P,)) 7867 C4 = collections.abc.Callable[Concatenate[int, T, P], T] 7868 self.assertEqual(C4.__args__, (Concatenate[int, T, P], T)) 7869 self.assertEqual(C4.__parameters__, (T, P)) 7870 7871 def test_var_substitution(self): 7872 T = TypeVar('T') 7873 P = ParamSpec('P') 7874 P2 = ParamSpec('P2') 7875 C = Concatenate[T, P] 7876 self.assertEqual(C[int, P2], Concatenate[int, P2]) 7877 self.assertEqual(C[int, [str, float]], (int, str, float)) 7878 self.assertEqual(C[int, []], (int,)) 7879 self.assertEqual(C[int, Concatenate[str, P2]], 7880 Concatenate[int, str, P2]) 7881 self.assertEqual(C[int, ...], Concatenate[int, ...]) 7882 7883 C = Concatenate[int, P] 7884 self.assertEqual(C[P2], Concatenate[int, P2]) 7885 self.assertEqual(C[[str, float]], (int, str, float)) 7886 self.assertEqual(C[str, float], (int, str, float)) 7887 self.assertEqual(C[[]], (int,)) 7888 self.assertEqual(C[Concatenate[str, P2]], Concatenate[int, str, P2]) 7889 self.assertEqual(C[...], Concatenate[int, ...]) 7890 7891class TypeGuardTests(BaseTestCase): 7892 def test_basics(self): 7893 TypeGuard[int] # OK 7894 7895 def foo(arg) -> TypeGuard[int]: ... 7896 self.assertEqual(gth(foo), {'return': TypeGuard[int]}) 7897 7898 with self.assertRaises(TypeError): 7899 TypeGuard[int, str] 7900 7901 def test_repr(self): 7902 self.assertEqual(repr(TypeGuard), 'typing.TypeGuard') 7903 cv = TypeGuard[int] 7904 self.assertEqual(repr(cv), 'typing.TypeGuard[int]') 7905 cv = TypeGuard[Employee] 7906 self.assertEqual(repr(cv), 'typing.TypeGuard[%s.Employee]' % __name__) 7907 cv = TypeGuard[tuple[int]] 7908 self.assertEqual(repr(cv), 'typing.TypeGuard[tuple[int]]') 7909 7910 def test_cannot_subclass(self): 7911 with self.assertRaises(TypeError): 7912 class C(type(TypeGuard)): 7913 pass 7914 with self.assertRaises(TypeError): 7915 class C(type(TypeGuard[int])): 7916 pass 7917 7918 def test_cannot_init(self): 7919 with self.assertRaises(TypeError): 7920 TypeGuard() 7921 with self.assertRaises(TypeError): 7922 type(TypeGuard)() 7923 with self.assertRaises(TypeError): 7924 type(TypeGuard[Optional[int]])() 7925 7926 def test_no_isinstance(self): 7927 with self.assertRaises(TypeError): 7928 isinstance(1, TypeGuard[int]) 7929 with self.assertRaises(TypeError): 7930 issubclass(int, TypeGuard) 7931 7932 7933SpecialAttrsP = typing.ParamSpec('SpecialAttrsP') 7934SpecialAttrsT = typing.TypeVar('SpecialAttrsT', int, float, complex) 7935 7936 7937class SpecialAttrsTests(BaseTestCase): 7938 7939 def test_special_attrs(self): 7940 cls_to_check = { 7941 # ABC classes 7942 typing.AbstractSet: 'AbstractSet', 7943 typing.AsyncContextManager: 'AsyncContextManager', 7944 typing.AsyncGenerator: 'AsyncGenerator', 7945 typing.AsyncIterable: 'AsyncIterable', 7946 typing.AsyncIterator: 'AsyncIterator', 7947 typing.Awaitable: 'Awaitable', 7948 typing.ByteString: 'ByteString', 7949 typing.Callable: 'Callable', 7950 typing.ChainMap: 'ChainMap', 7951 typing.Collection: 'Collection', 7952 typing.Container: 'Container', 7953 typing.ContextManager: 'ContextManager', 7954 typing.Coroutine: 'Coroutine', 7955 typing.Counter: 'Counter', 7956 typing.DefaultDict: 'DefaultDict', 7957 typing.Deque: 'Deque', 7958 typing.Dict: 'Dict', 7959 typing.FrozenSet: 'FrozenSet', 7960 typing.Generator: 'Generator', 7961 typing.Hashable: 'Hashable', 7962 typing.ItemsView: 'ItemsView', 7963 typing.Iterable: 'Iterable', 7964 typing.Iterator: 'Iterator', 7965 typing.KeysView: 'KeysView', 7966 typing.List: 'List', 7967 typing.Mapping: 'Mapping', 7968 typing.MappingView: 'MappingView', 7969 typing.MutableMapping: 'MutableMapping', 7970 typing.MutableSequence: 'MutableSequence', 7971 typing.MutableSet: 'MutableSet', 7972 typing.OrderedDict: 'OrderedDict', 7973 typing.Reversible: 'Reversible', 7974 typing.Sequence: 'Sequence', 7975 typing.Set: 'Set', 7976 typing.Sized: 'Sized', 7977 typing.Tuple: 'Tuple', 7978 typing.Type: 'Type', 7979 typing.ValuesView: 'ValuesView', 7980 # Subscribed ABC classes 7981 typing.AbstractSet[Any]: 'AbstractSet', 7982 typing.AsyncContextManager[Any]: 'AsyncContextManager', 7983 typing.AsyncGenerator[Any, Any]: 'AsyncGenerator', 7984 typing.AsyncIterable[Any]: 'AsyncIterable', 7985 typing.AsyncIterator[Any]: 'AsyncIterator', 7986 typing.Awaitable[Any]: 'Awaitable', 7987 typing.Callable[[], Any]: 'Callable', 7988 typing.Callable[..., Any]: 'Callable', 7989 typing.ChainMap[Any, Any]: 'ChainMap', 7990 typing.Collection[Any]: 'Collection', 7991 typing.Container[Any]: 'Container', 7992 typing.ContextManager[Any]: 'ContextManager', 7993 typing.Coroutine[Any, Any, Any]: 'Coroutine', 7994 typing.Counter[Any]: 'Counter', 7995 typing.DefaultDict[Any, Any]: 'DefaultDict', 7996 typing.Deque[Any]: 'Deque', 7997 typing.Dict[Any, Any]: 'Dict', 7998 typing.FrozenSet[Any]: 'FrozenSet', 7999 typing.Generator[Any, Any, Any]: 'Generator', 8000 typing.ItemsView[Any, Any]: 'ItemsView', 8001 typing.Iterable[Any]: 'Iterable', 8002 typing.Iterator[Any]: 'Iterator', 8003 typing.KeysView[Any]: 'KeysView', 8004 typing.List[Any]: 'List', 8005 typing.Mapping[Any, Any]: 'Mapping', 8006 typing.MappingView[Any]: 'MappingView', 8007 typing.MutableMapping[Any, Any]: 'MutableMapping', 8008 typing.MutableSequence[Any]: 'MutableSequence', 8009 typing.MutableSet[Any]: 'MutableSet', 8010 typing.OrderedDict[Any, Any]: 'OrderedDict', 8011 typing.Reversible[Any]: 'Reversible', 8012 typing.Sequence[Any]: 'Sequence', 8013 typing.Set[Any]: 'Set', 8014 typing.Tuple[Any]: 'Tuple', 8015 typing.Tuple[Any, ...]: 'Tuple', 8016 typing.Type[Any]: 'Type', 8017 typing.ValuesView[Any]: 'ValuesView', 8018 # Special Forms 8019 typing.Annotated: 'Annotated', 8020 typing.Any: 'Any', 8021 typing.ClassVar: 'ClassVar', 8022 typing.Concatenate: 'Concatenate', 8023 typing.Final: 'Final', 8024 typing.ForwardRef: 'ForwardRef', 8025 typing.Literal: 'Literal', 8026 typing.NewType: 'NewType', 8027 typing.NoReturn: 'NoReturn', 8028 typing.Never: 'Never', 8029 typing.Optional: 'Optional', 8030 typing.TypeAlias: 'TypeAlias', 8031 typing.TypeGuard: 'TypeGuard', 8032 typing.TypeVar: 'TypeVar', 8033 typing.Union: 'Union', 8034 typing.Self: 'Self', 8035 # Subscribed special forms 8036 typing.Annotated[Any, "Annotation"]: 'Annotated', 8037 typing.ClassVar[Any]: 'ClassVar', 8038 typing.Concatenate[Any, SpecialAttrsP]: 'Concatenate', 8039 typing.Final[Any]: 'Final', 8040 typing.Literal[Any]: 'Literal', 8041 typing.Literal[1, 2]: 'Literal', 8042 typing.Literal[True, 2]: 'Literal', 8043 typing.Optional[Any]: 'Optional', 8044 typing.TypeGuard[Any]: 'TypeGuard', 8045 typing.Union[Any]: 'Any', 8046 typing.Union[int, float]: 'Union', 8047 # Incompatible special forms (tested in test_special_attrs2) 8048 # - typing.ForwardRef('set[Any]') 8049 # - typing.NewType('TypeName', Any) 8050 # - typing.ParamSpec('SpecialAttrsP') 8051 # - typing.TypeVar('T') 8052 } 8053 8054 for cls, name in cls_to_check.items(): 8055 with self.subTest(cls=cls): 8056 self.assertEqual(cls.__name__, name, str(cls)) 8057 self.assertEqual(cls.__qualname__, name, str(cls)) 8058 self.assertEqual(cls.__module__, 'typing', str(cls)) 8059 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 8060 s = pickle.dumps(cls, proto) 8061 loaded = pickle.loads(s) 8062 self.assertIs(cls, loaded) 8063 8064 TypeName = typing.NewType('SpecialAttrsTests.TypeName', Any) 8065 8066 def test_special_attrs2(self): 8067 # Forward refs provide a different introspection API. __name__ and 8068 # __qualname__ make little sense for forward refs as they can store 8069 # complex typing expressions. 8070 fr = typing.ForwardRef('set[Any]') 8071 self.assertFalse(hasattr(fr, '__name__')) 8072 self.assertFalse(hasattr(fr, '__qualname__')) 8073 self.assertEqual(fr.__module__, 'typing') 8074 # Forward refs are currently unpicklable. 8075 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 8076 with self.assertRaises(TypeError): 8077 pickle.dumps(fr, proto) 8078 8079 self.assertEqual(SpecialAttrsTests.TypeName.__name__, 'TypeName') 8080 self.assertEqual( 8081 SpecialAttrsTests.TypeName.__qualname__, 8082 'SpecialAttrsTests.TypeName', 8083 ) 8084 self.assertEqual( 8085 SpecialAttrsTests.TypeName.__module__, 8086 __name__, 8087 ) 8088 # NewTypes are picklable assuming correct qualname information. 8089 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 8090 s = pickle.dumps(SpecialAttrsTests.TypeName, proto) 8091 loaded = pickle.loads(s) 8092 self.assertIs(SpecialAttrsTests.TypeName, loaded) 8093 8094 # Type variables don't support non-global instantiation per PEP 484 8095 # restriction that "The argument to TypeVar() must be a string equal 8096 # to the variable name to which it is assigned". Thus, providing 8097 # __qualname__ is unnecessary. 8098 self.assertEqual(SpecialAttrsT.__name__, 'SpecialAttrsT') 8099 self.assertFalse(hasattr(SpecialAttrsT, '__qualname__')) 8100 self.assertEqual(SpecialAttrsT.__module__, __name__) 8101 # Module-level type variables are picklable. 8102 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 8103 s = pickle.dumps(SpecialAttrsT, proto) 8104 loaded = pickle.loads(s) 8105 self.assertIs(SpecialAttrsT, loaded) 8106 8107 self.assertEqual(SpecialAttrsP.__name__, 'SpecialAttrsP') 8108 self.assertFalse(hasattr(SpecialAttrsP, '__qualname__')) 8109 self.assertEqual(SpecialAttrsP.__module__, __name__) 8110 # Module-level ParamSpecs are picklable. 8111 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 8112 s = pickle.dumps(SpecialAttrsP, proto) 8113 loaded = pickle.loads(s) 8114 self.assertIs(SpecialAttrsP, loaded) 8115 8116 def test_genericalias_dir(self): 8117 class Foo(Generic[T]): 8118 def bar(self): 8119 pass 8120 baz = 3 8121 __magic__ = 4 8122 8123 # The class attributes of the original class should be visible even 8124 # in dir() of the GenericAlias. See bpo-45755. 8125 dir_items = set(dir(Foo[int])) 8126 for required_item in [ 8127 'bar', 'baz', 8128 '__args__', '__parameters__', '__origin__', 8129 ]: 8130 with self.subTest(required_item=required_item): 8131 self.assertIn(required_item, dir_items) 8132 self.assertNotIn('__magic__', dir_items) 8133 8134 8135class RevealTypeTests(BaseTestCase): 8136 def test_reveal_type(self): 8137 obj = object() 8138 with captured_stderr() as stderr: 8139 self.assertIs(obj, reveal_type(obj)) 8140 self.assertEqual(stderr.getvalue(), "Runtime type is 'object'\n") 8141 8142 8143class DataclassTransformTests(BaseTestCase): 8144 def test_decorator(self): 8145 def create_model(*, frozen: bool = False, kw_only: bool = True): 8146 return lambda cls: cls 8147 8148 decorated = dataclass_transform(kw_only_default=True, order_default=False)(create_model) 8149 8150 class CustomerModel: 8151 id: int 8152 8153 self.assertIs(decorated, create_model) 8154 self.assertEqual( 8155 decorated.__dataclass_transform__, 8156 { 8157 "eq_default": True, 8158 "order_default": False, 8159 "kw_only_default": True, 8160 "field_specifiers": (), 8161 "kwargs": {}, 8162 } 8163 ) 8164 self.assertIs( 8165 decorated(frozen=True, kw_only=False)(CustomerModel), 8166 CustomerModel 8167 ) 8168 8169 def test_base_class(self): 8170 class ModelBase: 8171 def __init_subclass__(cls, *, frozen: bool = False): ... 8172 8173 Decorated = dataclass_transform( 8174 eq_default=True, 8175 order_default=True, 8176 # Arbitrary unrecognized kwargs are accepted at runtime. 8177 make_everything_awesome=True, 8178 )(ModelBase) 8179 8180 class CustomerModel(Decorated, frozen=True): 8181 id: int 8182 8183 self.assertIs(Decorated, ModelBase) 8184 self.assertEqual( 8185 Decorated.__dataclass_transform__, 8186 { 8187 "eq_default": True, 8188 "order_default": True, 8189 "kw_only_default": False, 8190 "field_specifiers": (), 8191 "kwargs": {"make_everything_awesome": True}, 8192 } 8193 ) 8194 self.assertIsSubclass(CustomerModel, Decorated) 8195 8196 def test_metaclass(self): 8197 class Field: ... 8198 8199 class ModelMeta(type): 8200 def __new__( 8201 cls, name, bases, namespace, *, init: bool = True, 8202 ): 8203 return super().__new__(cls, name, bases, namespace) 8204 8205 Decorated = dataclass_transform( 8206 order_default=True, field_specifiers=(Field,) 8207 )(ModelMeta) 8208 8209 class ModelBase(metaclass=Decorated): ... 8210 8211 class CustomerModel(ModelBase, init=False): 8212 id: int 8213 8214 self.assertIs(Decorated, ModelMeta) 8215 self.assertEqual( 8216 Decorated.__dataclass_transform__, 8217 { 8218 "eq_default": True, 8219 "order_default": True, 8220 "kw_only_default": False, 8221 "field_specifiers": (Field,), 8222 "kwargs": {}, 8223 } 8224 ) 8225 self.assertIsInstance(CustomerModel, Decorated) 8226 8227 8228class AllTests(BaseTestCase): 8229 """Tests for __all__.""" 8230 8231 def test_all(self): 8232 from typing import __all__ as a 8233 # Just spot-check the first and last of every category. 8234 self.assertIn('AbstractSet', a) 8235 self.assertIn('ValuesView', a) 8236 self.assertIn('cast', a) 8237 self.assertIn('overload', a) 8238 # Context managers. 8239 self.assertIn('ContextManager', a) 8240 self.assertIn('AsyncContextManager', a) 8241 # Check that io and re are not exported. 8242 self.assertNotIn('io', a) 8243 self.assertNotIn('re', a) 8244 # Spot-check that stdlib modules aren't exported. 8245 self.assertNotIn('os', a) 8246 self.assertNotIn('sys', a) 8247 # Check that Text is defined. 8248 self.assertIn('Text', a) 8249 # Check previously missing classes. 8250 self.assertIn('SupportsBytes', a) 8251 self.assertIn('SupportsComplex', a) 8252 8253 def test_all_exported_names(self): 8254 actual_all = set(typing.__all__) 8255 computed_all = { 8256 k for k, v in vars(typing).items() 8257 # explicitly exported, not a thing with __module__ 8258 if k in actual_all or ( 8259 # avoid private names 8260 not k.startswith('_') and 8261 k not in {'io', 're'} and 8262 # there's a few types and metaclasses that aren't exported 8263 not k.endswith(('Meta', '_contra', '_co')) and 8264 not k.upper() == k and 8265 # but export all things that have __module__ == 'typing' 8266 getattr(v, '__module__', None) == typing.__name__ 8267 ) 8268 } 8269 self.assertSetEqual(computed_all, actual_all) 8270 8271 8272class TypeIterationTests(BaseTestCase): 8273 _UNITERABLE_TYPES = ( 8274 Any, 8275 Union, 8276 Union[str, int], 8277 Union[str, T], 8278 List, 8279 Tuple, 8280 Callable, 8281 Callable[..., T], 8282 Callable[[T], str], 8283 Annotated, 8284 Annotated[T, ''], 8285 ) 8286 8287 def test_cannot_iterate(self): 8288 expected_error_regex = "object is not iterable" 8289 for test_type in self._UNITERABLE_TYPES: 8290 with self.subTest(type=test_type): 8291 with self.assertRaisesRegex(TypeError, expected_error_regex): 8292 iter(test_type) 8293 with self.assertRaisesRegex(TypeError, expected_error_regex): 8294 list(test_type) 8295 with self.assertRaisesRegex(TypeError, expected_error_regex): 8296 for _ in test_type: 8297 pass 8298 8299 def test_is_not_instance_of_iterable(self): 8300 for type_to_test in self._UNITERABLE_TYPES: 8301 self.assertNotIsInstance(type_to_test, collections.abc.Iterable) 8302 8303 8304if __name__ == '__main__': 8305 main() 8306