|
20 | 20 | from unittest import TestCase, main, skipUnless, skipIf
|
21 | 21 | from unittest.mock import patch
|
22 | 22 | import typing
|
23 |
| -from typing import TypeVar, Optional, Union, AnyStr |
| 23 | +from typing import Optional, Union, AnyStr |
24 | 24 | from typing import T, KT, VT # Not in __all__.
|
25 | 25 | from typing import Tuple, List, Set, Dict, Iterable, Iterator, Callable
|
26 | 26 | from typing import Generic
|
|
36 | 36 | from typing_extensions import assert_type, get_type_hints, get_origin, get_args, get_original_bases
|
37 | 37 | from typing_extensions import clear_overloads, get_overloads, overload
|
38 | 38 | from typing_extensions import NamedTuple
|
39 |
| -from typing_extensions import override, deprecated, Buffer, TypeAliasType |
| 39 | +from typing_extensions import override, deprecated, Buffer, TypeAliasType, TypeVar |
40 | 40 | from _typed_dict_test_helper import Foo, FooGeneric
|
41 | 41 |
|
42 | 42 | # Flags used to mark tests that only apply after a specific
|
@@ -3306,6 +3306,7 @@ def test_basic_plain(self):
|
3306 | 3306 | P = ParamSpec('P')
|
3307 | 3307 | self.assertEqual(P, P)
|
3308 | 3308 | self.assertIsInstance(P, ParamSpec)
|
| 3309 | + self.assertEqual(P.__name__, 'P') |
3309 | 3310 | # Should be hashable
|
3310 | 3311 | hash(P)
|
3311 | 3312 |
|
@@ -4375,10 +4376,153 @@ class GenericNamedTuple(NamedTuple, Generic[T]):
|
4375 | 4376 | self.assertEqual(CallNamedTuple.__orig_bases__, (NamedTuple,))
|
4376 | 4377 |
|
4377 | 4378 |
|
| 4379 | +class TypeVarTests(BaseTestCase): |
| 4380 | + def test_basic_plain(self): |
| 4381 | + T = TypeVar('T') |
| 4382 | + # T equals itself. |
| 4383 | + self.assertEqual(T, T) |
| 4384 | + # T is an instance of TypeVar |
| 4385 | + self.assertIsInstance(T, TypeVar) |
| 4386 | + self.assertEqual(T.__name__, 'T') |
| 4387 | + self.assertEqual(T.__constraints__, ()) |
| 4388 | + self.assertIs(T.__bound__, None) |
| 4389 | + self.assertIs(T.__covariant__, False) |
| 4390 | + self.assertIs(T.__contravariant__, False) |
| 4391 | + self.assertIs(T.__infer_variance__, False) |
| 4392 | + |
| 4393 | + def test_attributes(self): |
| 4394 | + T_bound = TypeVar('T_bound', bound=int) |
| 4395 | + self.assertEqual(T_bound.__name__, 'T_bound') |
| 4396 | + self.assertEqual(T_bound.__constraints__, ()) |
| 4397 | + self.assertIs(T_bound.__bound__, int) |
| 4398 | + |
| 4399 | + T_constraints = TypeVar('T_constraints', int, str) |
| 4400 | + self.assertEqual(T_constraints.__name__, 'T_constraints') |
| 4401 | + self.assertEqual(T_constraints.__constraints__, (int, str)) |
| 4402 | + self.assertIs(T_constraints.__bound__, None) |
| 4403 | + |
| 4404 | + T_co = TypeVar('T_co', covariant=True) |
| 4405 | + self.assertEqual(T_co.__name__, 'T_co') |
| 4406 | + self.assertIs(T_co.__covariant__, True) |
| 4407 | + self.assertIs(T_co.__contravariant__, False) |
| 4408 | + self.assertIs(T_co.__infer_variance__, False) |
| 4409 | + |
| 4410 | + T_contra = TypeVar('T_contra', contravariant=True) |
| 4411 | + self.assertEqual(T_contra.__name__, 'T_contra') |
| 4412 | + self.assertIs(T_contra.__covariant__, False) |
| 4413 | + self.assertIs(T_contra.__contravariant__, True) |
| 4414 | + self.assertIs(T_contra.__infer_variance__, False) |
| 4415 | + |
| 4416 | + T_infer = TypeVar('T_infer', infer_variance=True) |
| 4417 | + self.assertEqual(T_infer.__name__, 'T_infer') |
| 4418 | + self.assertIs(T_infer.__covariant__, False) |
| 4419 | + self.assertIs(T_infer.__contravariant__, False) |
| 4420 | + self.assertIs(T_infer.__infer_variance__, True) |
| 4421 | + |
| 4422 | + def test_typevar_instance_type_error(self): |
| 4423 | + T = TypeVar('T') |
| 4424 | + with self.assertRaises(TypeError): |
| 4425 | + isinstance(42, T) |
| 4426 | + |
| 4427 | + def test_typevar_subclass_type_error(self): |
| 4428 | + T = TypeVar('T') |
| 4429 | + with self.assertRaises(TypeError): |
| 4430 | + issubclass(int, T) |
| 4431 | + with self.assertRaises(TypeError): |
| 4432 | + issubclass(T, int) |
| 4433 | + |
| 4434 | + def test_constrained_error(self): |
| 4435 | + with self.assertRaises(TypeError): |
| 4436 | + X = TypeVar('X', int) |
| 4437 | + X |
| 4438 | + |
| 4439 | + def test_union_unique(self): |
| 4440 | + X = TypeVar('X') |
| 4441 | + Y = TypeVar('Y') |
| 4442 | + self.assertNotEqual(X, Y) |
| 4443 | + self.assertEqual(Union[X], X) |
| 4444 | + self.assertNotEqual(Union[X], Union[X, Y]) |
| 4445 | + self.assertEqual(Union[X, X], X) |
| 4446 | + self.assertNotEqual(Union[X, int], Union[X]) |
| 4447 | + self.assertNotEqual(Union[X, int], Union[int]) |
| 4448 | + self.assertEqual(Union[X, int].__args__, (X, int)) |
| 4449 | + self.assertEqual(Union[X, int].__parameters__, (X,)) |
| 4450 | + self.assertIs(Union[X, int].__origin__, Union) |
| 4451 | + |
| 4452 | + if hasattr(types, "UnionType"): |
| 4453 | + def test_or(self): |
| 4454 | + X = TypeVar('X') |
| 4455 | + # use a string because str doesn't implement |
| 4456 | + # __or__/__ror__ itself |
| 4457 | + self.assertEqual(X | "x", Union[X, "x"]) |
| 4458 | + self.assertEqual("x" | X, Union["x", X]) |
| 4459 | + # make sure the order is correct |
| 4460 | + self.assertEqual(get_args(X | "x"), (X, typing.ForwardRef("x"))) |
| 4461 | + self.assertEqual(get_args("x" | X), (typing.ForwardRef("x"), X)) |
| 4462 | + |
| 4463 | + def test_union_constrained(self): |
| 4464 | + A = TypeVar('A', str, bytes) |
| 4465 | + self.assertNotEqual(Union[A, str], Union[A]) |
| 4466 | + |
| 4467 | + def test_repr(self): |
| 4468 | + self.assertEqual(repr(T), '~T') |
| 4469 | + self.assertEqual(repr(KT), '~KT') |
| 4470 | + self.assertEqual(repr(VT), '~VT') |
| 4471 | + self.assertEqual(repr(AnyStr), '~AnyStr') |
| 4472 | + T_co = TypeVar('T_co', covariant=True) |
| 4473 | + self.assertEqual(repr(T_co), '+T_co') |
| 4474 | + T_contra = TypeVar('T_contra', contravariant=True) |
| 4475 | + self.assertEqual(repr(T_contra), '-T_contra') |
| 4476 | + |
| 4477 | + def test_no_redefinition(self): |
| 4478 | + self.assertNotEqual(TypeVar('T'), TypeVar('T')) |
| 4479 | + self.assertNotEqual(TypeVar('T', int, str), TypeVar('T', int, str)) |
| 4480 | + |
| 4481 | + def test_cannot_subclass(self): |
| 4482 | + with self.assertRaises(TypeError): |
| 4483 | + class V(TypeVar): pass |
| 4484 | + T = TypeVar("T") |
| 4485 | + with self.assertRaises(TypeError): |
| 4486 | + class V(T): pass |
| 4487 | + |
| 4488 | + def test_cannot_instantiate_vars(self): |
| 4489 | + with self.assertRaises(TypeError): |
| 4490 | + TypeVar('A')() |
| 4491 | + |
| 4492 | + def test_bound_errors(self): |
| 4493 | + with self.assertRaises(TypeError): |
| 4494 | + TypeVar('X', bound=Union) |
| 4495 | + with self.assertRaises(TypeError): |
| 4496 | + TypeVar('X', str, float, bound=Employee) |
| 4497 | + with self.assertRaisesRegex(TypeError, |
| 4498 | + r"Bound must be a type\. Got \(1, 2\)\."): |
| 4499 | + TypeVar('X', bound=(1, 2)) |
| 4500 | + |
| 4501 | + # Technically we could run it on later versions of 3.7 and 3.8, |
| 4502 | + # but that's not worth the effort. |
| 4503 | + @skipUnless(TYPING_3_9_0, "Fix was not backported") |
| 4504 | + def test_missing__name__(self): |
| 4505 | + # See bpo-39942 |
| 4506 | + code = ("import typing\n" |
| 4507 | + "T = typing.TypeVar('T')\n" |
| 4508 | + ) |
| 4509 | + exec(code, {}) |
| 4510 | + |
| 4511 | + def test_no_bivariant(self): |
| 4512 | + with self.assertRaises(ValueError): |
| 4513 | + TypeVar('T', covariant=True, contravariant=True) |
| 4514 | + |
| 4515 | + def test_cannot_combine_explicit_and_infer(self): |
| 4516 | + with self.assertRaises(ValueError): |
| 4517 | + TypeVar('T', covariant=True, infer_variance=True) |
| 4518 | + with self.assertRaises(ValueError): |
| 4519 | + TypeVar('T', contravariant=True, infer_variance=True) |
| 4520 | + |
| 4521 | + |
4378 | 4522 | class TypeVarLikeDefaultsTests(BaseTestCase):
|
4379 | 4523 | def test_typevar(self):
|
4380 | 4524 | T = typing_extensions.TypeVar('T', default=int)
|
4381 |
| - typing_T = TypeVar('T') |
| 4525 | + typing_T = typing.TypeVar('T') |
4382 | 4526 | self.assertEqual(T.__default__, int)
|
4383 | 4527 | self.assertIsInstance(T, typing_extensions.TypeVar)
|
4384 | 4528 | self.assertIsInstance(T, typing.TypeVar)
|
|
0 commit comments