Skip to content

Commit 2693194

Browse files
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.
1 parent 97db2f3 commit 2693194

File tree

3 files changed

+50
-8
lines changed

3 files changed

+50
-8
lines changed

Lib/test/test_type_params.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -425,11 +425,11 @@ class Foo[T: Foo, U: (Foo, Foo)]:
425425
type_params = Foo.__type_params__
426426
self.assertEqual(len(type_params), 2)
427427
self.assertEqual(type_params[0].__name__, "T")
428-
self.assertEqual(type_params[0].__bound__, Foo)
429-
self.assertEqual(type_params[0].__constraints__, None)
428+
self.assertIs(type_params[0].__bound__, Foo)
429+
self.assertEqual(type_params[0].__constraints__, ())
430430

431431
self.assertEqual(type_params[1].__name__, "U")
432-
self.assertEqual(type_params[1].__bound__, None)
432+
self.assertIs(type_params[1].__bound__, None)
433433
self.assertEqual(type_params[1].__constraints__, (Foo, Foo))
434434

435435
def test_evaluation_error(self):
@@ -439,16 +439,16 @@ class Foo[T: Undefined, U: (Undefined,)]:
439439
type_params = Foo.__type_params__
440440
with self.assertRaises(NameError):
441441
type_params[0].__bound__
442-
self.assertEqual(type_params[0].__constraints__, None)
443-
self.assertEqual(type_params[1].__bound__, None)
442+
self.assertEqual(type_params[0].__constraints__, ())
443+
self.assertIs(type_params[1].__bound__, None)
444444
with self.assertRaises(NameError):
445445
type_params[1].__constraints__
446446

447447
Undefined = "defined"
448448
self.assertEqual(type_params[0].__bound__, "defined")
449-
self.assertEqual(type_params[0].__constraints__, None)
449+
self.assertEqual(type_params[0].__constraints__, ())
450450

451-
self.assertEqual(type_params[1].__bound__, None)
451+
self.assertIs(type_params[1].__bound__, None)
452452
self.assertEqual(type_params[1].__constraints__, ("defined",))
453453

454454

Lib/test/test_typing.py

+42
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,41 @@ def test_basic_plain(self):
367367
self.assertEqual(T, T)
368368
# T is an instance of TypeVar
369369
self.assertIsInstance(T, TypeVar)
370+
self.assertEqual(T.__name__, 'T')
371+
self.assertEqual(T.__constraints__, ())
372+
self.assertIs(T.__bound__, None)
373+
self.assertIs(T.__covariant__, False)
374+
self.assertIs(T.__contravariant__, False)
375+
self.assertIs(T.__infer_variance__, False)
376+
377+
def test_attributes(self):
378+
T_bound = TypeVar('T_bound', bound=int)
379+
self.assertEqual(T_bound.__name__, 'T_bound')
380+
self.assertEqual(T_bound.__constraints__, ())
381+
self.assertIs(T_bound.__bound__, int)
382+
383+
T_constraints = TypeVar('T_constraints', int, str)
384+
self.assertEqual(T_constraints.__name__, 'T_constraints')
385+
self.assertEqual(T_constraints.__constraints__, (int, str))
386+
self.assertIs(T_constraints.__bound__, None)
387+
388+
T_co = TypeVar('T_co', covariant=True)
389+
self.assertEqual(T_co.__name__, 'T_co')
390+
self.assertIs(T_co.__covariant__, True)
391+
self.assertIs(T_co.__contravariant__, False)
392+
self.assertIs(T_co.__infer_variance__, False)
393+
394+
T_contra = TypeVar('T_contra', contravariant=True)
395+
self.assertEqual(T_contra.__name__, 'T_contra')
396+
self.assertIs(T_contra.__covariant__, False)
397+
self.assertIs(T_contra.__contravariant__, True)
398+
self.assertIs(T_contra.__infer_variance__, False)
399+
400+
T_infer = TypeVar('T_infer', infer_variance=True)
401+
self.assertEqual(T_infer.__name__, 'T_infer')
402+
self.assertIs(T_infer.__covariant__, False)
403+
self.assertIs(T_infer.__contravariant__, False)
404+
self.assertIs(T_infer.__infer_variance__, True)
370405

371406
def test_typevar_instance_type_error(self):
372407
T = TypeVar('T')
@@ -458,6 +493,12 @@ def test_no_bivariant(self):
458493
with self.assertRaises(ValueError):
459494
TypeVar('T', covariant=True, contravariant=True)
460495

496+
def test_cannot_combine_explicit_and_infer(self):
497+
with self.assertRaises(ValueError):
498+
TypeVar('T', covariant=True, infer_variance=True)
499+
with self.assertRaises(ValueError):
500+
TypeVar('T', contravariant=True, infer_variance=True)
501+
461502
def test_var_substitution(self):
462503
T = TypeVar('T')
463504
subst = T.__typing_subst__
@@ -7812,6 +7853,7 @@ def test_basic_plain(self):
78127853
P = ParamSpec('P')
78137854
self.assertEqual(P, P)
78147855
self.assertIsInstance(P, ParamSpec)
7856+
self.assertEqual(P.__name__, 'P')
78157857

78167858
def test_valid_uses(self):
78177859
P = ParamSpec('P')

Objects/typevarobject.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ typevar_constraints(typevarobject *self, void *Py_UNUSED(ignored))
271271
return Py_NewRef(self->constraints);
272272
}
273273
if (self->evaluate_constraints == NULL) {
274-
Py_RETURN_NONE;
274+
return PyTuple_New(0);
275275
}
276276
PyObject *constraints = PyObject_CallNoArgs(self->evaluate_constraints);
277277
self->constraints = Py_XNewRef(constraints);

0 commit comments

Comments
 (0)