From d2a536b1706d4a79303b7ac53684bb82eac2de23 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Thu, 12 Oct 2023 16:00:12 -0700 Subject: [PATCH] gh-110782: Fix crash when TypeVar is constructed with keyword args (#110784) --- Lib/test/test_typing.py | 6 +++ ...-10-12-15-03-24.gh-issue-110782.EqzIzi.rst | 2 + Objects/typevarobject.c | 38 ++++++++++--------- 3 files changed, 28 insertions(+), 18 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-10-12-15-03-24.gh-issue-110782.EqzIzi.rst diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 66812f317c7..1a1e0a259fd 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -554,6 +554,12 @@ class TypeVarTests(BaseTestCase): vals[x] = cls(str(x)) del vals + def test_constructor(self): + T = TypeVar(name="T") + self.assertEqual(T.__name__, "T") + self.assertEqual(T.__constraints__, ()) + self.assertIs(T.__bound__, None) + def template_replace(templates: list[str], replacements: dict[str, list[str]]) -> list[tuple[str]]: """Renders templates with possible combinations of replacements. diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-10-12-15-03-24.gh-issue-110782.EqzIzi.rst b/Misc/NEWS.d/next/Core and Builtins/2023-10-12-15-03-24.gh-issue-110782.EqzIzi.rst new file mode 100644 index 00000000000..6eddcc01208 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-10-12-15-03-24.gh-issue-110782.EqzIzi.rst @@ -0,0 +1,2 @@ +Fix crash when :class:`typing.TypeVar` is constructed with a keyword +argument. Patch by Jelle Zijlstra. diff --git a/Objects/typevarobject.c b/Objects/typevarobject.c index 73cdf48788e..8a20b23c686 100644 --- a/Objects/typevarobject.c +++ b/Objects/typevarobject.c @@ -364,24 +364,26 @@ typevar_new_impl(PyTypeObject *type, PyObject *name, PyObject *constraints, } } - if (!PyTuple_CheckExact(constraints)) { - PyErr_SetString(PyExc_TypeError, - "constraints must be a tuple"); - return NULL; - } - Py_ssize_t n_constraints = PyTuple_GET_SIZE(constraints); - if (n_constraints == 1) { - PyErr_SetString(PyExc_TypeError, - "A single constraint is not allowed"); - Py_XDECREF(bound); - return NULL; - } else if (n_constraints == 0) { - constraints = NULL; - } else if (bound != NULL) { - PyErr_SetString(PyExc_TypeError, - "Constraints cannot be combined with bound=..."); - Py_XDECREF(bound); - return NULL; + if (constraints != NULL) { + if (!PyTuple_CheckExact(constraints)) { + PyErr_SetString(PyExc_TypeError, + "constraints must be a tuple"); + return NULL; + } + Py_ssize_t n_constraints = PyTuple_GET_SIZE(constraints); + if (n_constraints == 1) { + PyErr_SetString(PyExc_TypeError, + "A single constraint is not allowed"); + Py_XDECREF(bound); + return NULL; + } else if (n_constraints == 0) { + constraints = NULL; + } else if (bound != NULL) { + PyErr_SetString(PyExc_TypeError, + "Constraints cannot be combined with bound=..."); + Py_XDECREF(bound); + return NULL; + } } PyObject *module = caller(); if (module == NULL) {