summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJelle Zijlstra <jelle.zijlstra@gmail.com>2023-10-12 23:00:12 (GMT)
committerGitHub <noreply@github.com>2023-10-12 23:00:12 (GMT)
commitd2a536b1706d4a79303b7ac53684bb82eac2de23 (patch)
tree2b1c639967631b97093c78c8a8d6f3d473da6f55
parent2c472a87c7173d9fcdd52b1f35c05bc68d6c541e (diff)
downloadcpython-d2a536b1706d4a79303b7ac53684bb82eac2de23.zip
cpython-d2a536b1706d4a79303b7ac53684bb82eac2de23.tar.gz
cpython-d2a536b1706d4a79303b7ac53684bb82eac2de23.tar.bz2
gh-110782: Fix crash when TypeVar is constructed with keyword args (#110784)
-rw-r--r--Lib/test/test_typing.py6
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-10-12-15-03-24.gh-issue-110782.EqzIzi.rst2
-rw-r--r--Objects/typevarobject.c38
3 files changed, 28 insertions, 18 deletions
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 66812f3..1a1e0a25 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 0000000..6eddcc0
--- /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 73cdf48..8a20b23 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) {