https://github.com/python/cpython/commit/df66175cb819882828bb2583fb58e56ab23dc01d commit: df66175cb819882828bb2583fb58e56ab23dc01d branch: 3.15 author: Miss Islington (bot) <[email protected]> committer: JelleZijlstra <[email protected]> date: 2026-07-27T00:03:23Z summary:
[3.15] gh-151955: Allow more ParamSpec and TypeVarTuple bounds (GH-151956) (#152101) gh-151955: Allow more ParamSpec and TypeVarTuple bounds (GH-151956) (cherry picked from commit 0fb82b46df7bc95c2ba816afba56ff6a6c51caaf) Co-authored-by: Jelle Zijlstra <[email protected]> files: A Misc/NEWS.d/next/Library/2026-06-22-18-01-00.gh-issue-151955.6u5iwm.rst M Lib/test/test_typing.py M Objects/typevarobject.c diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 343159bf5dafa38..106ffdede6fd4ef 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1318,6 +1318,11 @@ def test_infer_variance(self): def test_bound(self): Ts_bound = TypeVarTuple('Ts_bound', bound=int) self.assertIs(Ts_bound.__bound__, int) + Ts_tuple_bound = TypeVarTuple('Ts_tuple_bound', bound=(int, str)) + self.assertEqual(Ts_tuple_bound.__bound__, (int, str)) + obj = object() + Ts_object = TypeVarTuple('Ts_object', bound=obj) + self.assertIs(Ts_object.__bound__, obj) Ts_no_bound = TypeVarTuple('Ts_no_bound') self.assertIsNone(Ts_no_bound.__bound__) @@ -10565,6 +10570,17 @@ def test_paramspec_in_nested_generics(self): self.assertEqual(G2[[int, str], float], list[C]) self.assertEqual(G3[[int, str], float], list[C] | int) + def test_paramspec_bound(self): + P = ParamSpec('P', bound=[int, str]) + self.assertEqual(P.__bound__, [int, str]) + P2 = ParamSpec('P2', bound=(int, str)) + self.assertEqual(P2.__bound__, (int, str)) + obj = object() + P3 = ParamSpec('P3', bound=obj) + self.assertIs(P3.__bound__, obj) + P4 = ParamSpec('P4') + self.assertIs(P4.__bound__, None) + def test_paramspec_gets_copied(self): # bpo-46581 P = ParamSpec('P') diff --git a/Misc/NEWS.d/next/Library/2026-06-22-18-01-00.gh-issue-151955.6u5iwm.rst b/Misc/NEWS.d/next/Library/2026-06-22-18-01-00.gh-issue-151955.6u5iwm.rst new file mode 100644 index 000000000000000..4cb5f04025327c4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-22-18-01-00.gh-issue-151955.6u5iwm.rst @@ -0,0 +1,2 @@ +Allow more types to be used in the ``bound`` argument to +:class:`typing.ParamSpec` and :class:`typing.TypeVarTuple`. diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index 78750a955d2a492..b2c3c79c93ff195 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -1340,20 +1340,12 @@ paramspec_new_impl(PyTypeObject *type, PyObject *name, PyObject *bound, PyErr_SetString(PyExc_ValueError, "Variance cannot be specified with infer_variance."); return NULL; } - if (bound != NULL) { - bound = type_check(bound, "Bound must be a type."); - if (bound == NULL) { - return NULL; - } - } PyObject *module = caller(); if (module == NULL) { - Py_XDECREF(bound); return NULL; } PyObject *ps = (PyObject *)paramspec_alloc( name, bound, default_value, covariant, contravariant, infer_variance, module); - Py_XDECREF(bound); Py_DECREF(module); return ps; } @@ -1634,23 +1626,12 @@ typevartuple_impl(PyTypeObject *type, PyObject *name, PyObject *bound, PyErr_SetString(PyExc_ValueError, "Variance cannot be specified with infer_variance."); return NULL; } - if (Py_IsNone(bound)) { - bound = NULL; - } - if (bound != NULL) { - bound = type_check(bound, "Bound must be a type."); - if (bound == NULL) { - return NULL; - } - } PyObject *module = caller(); if (module == NULL) { - Py_XDECREF(bound); return NULL; } PyObject *result = (PyObject *)typevartuple_alloc( name, bound, default_value, covariant, contravariant, infer_variance, module); - Py_XDECREF(bound); Py_DECREF(module); return result; } _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
