diff options
author | Jelle Zijlstra <jelle.zijlstra@gmail.com> | 2023-05-17 13:08:21 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-17 13:08:21 (GMT) |
commit | 26931944dd8abd6554249239344fa62b789b9028 (patch) | |
tree | 0fcef464cf2aead5ff482458c970e725e3e970be | |
parent | 97db2f3e07bf7d56750e215e4f32653bf3867ef8 (diff) | |
download | cpython-26931944dd8abd6554249239344fa62b789b9028.zip cpython-26931944dd8abd6554249239344fa62b789b9028.tar.gz cpython-26931944dd8abd6554249239344fa62b789b9028.tar.bz2 |
typing: Add more tests for TypeVar (#104571)
During the PEP 695 implementation at one point I made
TypeVar.__name__ return garbage, and all of test_typing passed.
So I decided to add a few more tests. In the process I discovered
a minor incompatibility from the C implementation of TypeVar:
empty constraints were returned as None instead of an empty tuple.
-rw-r--r-- | Lib/test/test_type_params.py | 14 | ||||
-rw-r--r-- | Lib/test/test_typing.py | 42 | ||||
-rw-r--r-- | Objects/typevarobject.c | 2 |
3 files changed, 50 insertions, 8 deletions
diff --git a/Lib/test/test_type_params.py b/Lib/test/test_type_params.py index 3ca13c2..96bd1fa 100644 --- a/Lib/test/test_type_params.py +++ b/Lib/test/test_type_params.py @@ -425,11 +425,11 @@ class TypeParamsLazyEvaluationTest(unittest.TestCase): type_params = Foo.__type_params__ self.assertEqual(len(type_params), 2) self.assertEqual(type_params[0].__name__, "T") - self.assertEqual(type_params[0].__bound__, Foo) - self.assertEqual(type_params[0].__constraints__, None) + self.assertIs(type_params[0].__bound__, Foo) + self.assertEqual(type_params[0].__constraints__, ()) self.assertEqual(type_params[1].__name__, "U") - self.assertEqual(type_params[1].__bound__, None) + self.assertIs(type_params[1].__bound__, None) self.assertEqual(type_params[1].__constraints__, (Foo, Foo)) def test_evaluation_error(self): @@ -439,16 +439,16 @@ class TypeParamsLazyEvaluationTest(unittest.TestCase): type_params = Foo.__type_params__ with self.assertRaises(NameError): type_params[0].__bound__ - self.assertEqual(type_params[0].__constraints__, None) - self.assertEqual(type_params[1].__bound__, None) + self.assertEqual(type_params[0].__constraints__, ()) + self.assertIs(type_params[1].__bound__, None) with self.assertRaises(NameError): type_params[1].__constraints__ Undefined = "defined" self.assertEqual(type_params[0].__bound__, "defined") - self.assertEqual(type_params[0].__constraints__, None) + self.assertEqual(type_params[0].__constraints__, ()) - self.assertEqual(type_params[1].__bound__, None) + self.assertIs(type_params[1].__bound__, None) self.assertEqual(type_params[1].__constraints__, ("defined",)) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 0cd67c5..045f2a3 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -367,6 +367,41 @@ class TypeVarTests(BaseTestCase): self.assertEqual(T, T) # T is an instance of TypeVar self.assertIsInstance(T, TypeVar) + self.assertEqual(T.__name__, 'T') + self.assertEqual(T.__constraints__, ()) + self.assertIs(T.__bound__, None) + self.assertIs(T.__covariant__, False) + self.assertIs(T.__contravariant__, False) + self.assertIs(T.__infer_variance__, False) + + def test_attributes(self): + T_bound = TypeVar('T_bound', bound=int) + self.assertEqual(T_bound.__name__, 'T_bound') + self.assertEqual(T_bound.__constraints__, ()) + self.assertIs(T_bound.__bound__, int) + + T_constraints = TypeVar('T_constraints', int, str) + self.assertEqual(T_constraints.__name__, 'T_constraints') + self.assertEqual(T_constraints.__constraints__, (int, str)) + self.assertIs(T_constraints.__bound__, None) + + T_co = TypeVar('T_co', covariant=True) + self.assertEqual(T_co.__name__, 'T_co') + self.assertIs(T_co.__covariant__, True) + self.assertIs(T_co.__contravariant__, False) + self.assertIs(T_co.__infer_variance__, False) + + T_contra = TypeVar('T_contra', contravariant=True) + self.assertEqual(T_contra.__name__, 'T_contra') + self.assertIs(T_contra.__covariant__, False) + self.assertIs(T_contra.__contravariant__, True) + self.assertIs(T_contra.__infer_variance__, False) + + T_infer = TypeVar('T_infer', infer_variance=True) + self.assertEqual(T_infer.__name__, 'T_infer') + self.assertIs(T_infer.__covariant__, False) + self.assertIs(T_infer.__contravariant__, False) + self.assertIs(T_infer.__infer_variance__, True) def test_typevar_instance_type_error(self): T = TypeVar('T') @@ -458,6 +493,12 @@ class TypeVarTests(BaseTestCase): with self.assertRaises(ValueError): TypeVar('T', covariant=True, contravariant=True) + def test_cannot_combine_explicit_and_infer(self): + with self.assertRaises(ValueError): + TypeVar('T', covariant=True, infer_variance=True) + with self.assertRaises(ValueError): + TypeVar('T', contravariant=True, infer_variance=True) + def test_var_substitution(self): T = TypeVar('T') subst = T.__typing_subst__ @@ -7812,6 +7853,7 @@ class ParamSpecTests(BaseTestCase): P = ParamSpec('P') self.assertEqual(P, P) self.assertIsInstance(P, ParamSpec) + self.assertEqual(P.__name__, 'P') def test_valid_uses(self): P = ParamSpec('P') diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index b057875..4464e7a 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -271,7 +271,7 @@ typevar_constraints(typevarobject *self, void *Py_UNUSED(ignored)) return Py_NewRef(self->constraints); } if (self->evaluate_constraints == NULL) { - Py_RETURN_NONE; + return PyTuple_New(0); } PyObject *constraints = PyObject_CallNoArgs(self->evaluate_constraints); self->constraints = Py_XNewRef(constraints); |