From ae507e3b14a133b62b3aae9cd531a7dbfdaa8f24 Mon Sep 17 00:00:00 2001 From: jb2170 Date: Thu, 4 Jun 2026 10:06:02 +0100 Subject: [PATCH 1/8] gh-119670: Add `force` keyword only argument to `shlex.quote` (#148846) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are propositions to add a single-quote-double-quote switch (gh-90630), so to avoid hiccups of people passing `force` as a positional and it being used for the single-double switch, we make kwargs kwargs-only. Co-authored-by: Bartosz Sławecki --- Doc/library/shlex.rst | 20 ++++++++++++++++++- Doc/whatsnew/3.16.rst | 7 +++++++ Lib/shlex.py | 14 +++++++++---- Lib/test/test_shlex.py | 8 ++++++++ ...-04-21-06-30-59.gh-issue-119670.pMWZfY.rst | 2 ++ 5 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-04-21-06-30-59.gh-issue-119670.pMWZfY.rst diff --git a/Doc/library/shlex.rst b/Doc/library/shlex.rst index 2ab12f2f6f9169..2dfb0246d5d90c 100644 --- a/Doc/library/shlex.rst +++ b/Doc/library/shlex.rst @@ -44,12 +44,15 @@ The :mod:`!shlex` module defines the following functions: .. versionadded:: 3.8 -.. function:: quote(s) +.. function:: quote(s, *, force=False) Return a shell-escaped version of the string *s*. The returned value is a string that can safely be used as one token in a shell command line, for cases where you cannot use a list. + If *force* is :const:`True`, then *s* is unconditionally quoted, + even if it is already safe for a shell without being quoted. + .. _shlex-quote-warning: .. warning:: @@ -91,8 +94,23 @@ The :mod:`!shlex` module defines the following functions: >>> command ['ls', '-l', 'somefile; rm -rf ~'] + The *force* keyword can be used to produce consistent behavior when + escaping multiple strings: + + >>> from shlex import quote + >>> filenames = ['my first file', 'file2', 'file 3'] + >>> filenames_some_escaped = [quote(f) for f in filenames] + >>> filenames_some_escaped + ["'my first file'", 'file2', "'file 3'"] + >>> filenames_all_escaped = [quote(f, force=True) for f in filenames] + >>> filenames_all_escaped + ["'my first file'", "'file2'", "'file 3'"] + .. versionadded:: 3.3 + .. versionchanged:: next + The *force* keyword was added. + The :mod:`!shlex` module defines the following class: diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 0aff48dba61449..a055113dec0494 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -109,6 +109,13 @@ os process via a pidfd. Available on Linux 5.6+. (Contributed by Maurycy Pawłowski-Wieroński in :gh:`149464`.) +shlex +----- + +* Add keyword-only parameter *force* to :func:`shlex.quote` to force quoting + a string, even if it is already safe for a shell without being quoted. + (Contributed by Jay Berry in :gh:`148846`.) + xml --- diff --git a/Lib/shlex.py b/Lib/shlex.py index 5959f52dd12639..c7ffc918d53961 100644 --- a/Lib/shlex.py +++ b/Lib/shlex.py @@ -317,8 +317,12 @@ def join(split_command): return ' '.join(quote(arg) for arg in split_command) -def quote(s): - """Return a shell-escaped version of the string *s*.""" +def quote(s, *, force=False): + """Return a shell-escaped version of the string *s*. + + If *force* is *True*, then *s* is unconditionally quoted, + even if it is already safe for a shell without being quoted. + """ if not s: return "''" @@ -329,8 +333,10 @@ def quote(s): safe_chars = (b'%+,-./0123456789:=@' b'ABCDEFGHIJKLMNOPQRSTUVWXYZ_' b'abcdefghijklmnopqrstuvwxyz') - # No quoting is needed if `s` is an ASCII string consisting only of `safe_chars` - if s.isascii() and not s.encode().translate(None, delete=safe_chars): + # No quoting is needed if we are not forcing quoting + # and `s` is an ASCII string consisting only of `safe_chars`. + if (not force + and s.isascii() and not s.encode().translate(None, delete=safe_chars)): return s # use single quotes, and put single quotes into double quotes diff --git a/Lib/test/test_shlex.py b/Lib/test/test_shlex.py index 2a355abdeeb30f..2adaee81b06308 100644 --- a/Lib/test/test_shlex.py +++ b/Lib/test/test_shlex.py @@ -342,6 +342,14 @@ def testQuote(self): self.assertRaises(TypeError, shlex.quote, 42) self.assertRaises(TypeError, shlex.quote, b"abc") + def testForceQuote(self): + self.assertEqual(shlex.quote("spam"), "spam") + self.assertEqual(shlex.quote("spam", force=False), "spam") + self.assertEqual(shlex.quote("spam", force=True), "'spam'") + self.assertEqual(shlex.quote("spam eggs", force=False), "'spam eggs'") + self.assertEqual(shlex.quote("spam eggs", force=True), "'spam eggs'") + self.assertEqual(shlex.quote("two's-complement", force=False), "'two'\"'\"'s-complement'") + def testJoin(self): for split_command, command in [ (['a ', 'b'], "'a ' b"), diff --git a/Misc/NEWS.d/next/Library/2026-04-21-06-30-59.gh-issue-119670.pMWZfY.rst b/Misc/NEWS.d/next/Library/2026-04-21-06-30-59.gh-issue-119670.pMWZfY.rst new file mode 100644 index 00000000000000..fc1941be4dc792 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-21-06-30-59.gh-issue-119670.pMWZfY.rst @@ -0,0 +1,2 @@ +Add keyword-only parameter *force* to :func:`shlex.quote` to force quoting +a string, even if it is already safe for a shell without being quoted. From cb064e746de210fea8639b986c8d2a573b71c48f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Thu, 4 Jun 2026 11:42:06 +0200 Subject: [PATCH 2/8] Fix 2 broken links in documentation (#150892) Co-authored-by: Stan Ulbrych --- Doc/c-api/complex.rst | 2 +- Doc/extending/first-extension-module.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/c-api/complex.rst b/Doc/c-api/complex.rst index 629312bd771beb..10f96c7cb75e88 100644 --- a/Doc/c-api/complex.rst +++ b/Doc/c-api/complex.rst @@ -130,7 +130,7 @@ rather than dereferencing them through pointers. Please note, that these functions are :term:`soft deprecated` since Python 3.15. Avoid using this API in a new code to do complex arithmetic: either use -the `Number Protocol `_ API or use native complex types, like +the :ref:`Number Protocol ` API or use native complex types, like :c:expr:`double complex`. diff --git a/Doc/extending/first-extension-module.rst b/Doc/extending/first-extension-module.rst index 894f5bdbb8f09c..55a772e2aca24f 100644 --- a/Doc/extending/first-extension-module.rst +++ b/Doc/extending/first-extension-module.rst @@ -164,7 +164,7 @@ Then, create ``meson.build`` containing the following: .. note:: - See `meson-python documentation `_ for details on + See the `meson-python documentation `_ for details on configuration. Now, build install the *project in the current directory* (``.``) via ``pip``: From 3ff2117ea35195c90a766efacd66ac91b77437cc Mon Sep 17 00:00:00 2001 From: Batuhan Taskaya Date: Thu, 4 Jun 2026 13:58:51 +0300 Subject: [PATCH 3/8] bpo-38131: Improve messages when generating AST nodes from objects with wrong field values (GH-17715) --- Lib/test/test_ast/test_ast.py | 26 +- .../2019-12-27-19-20-33.bpo-38131.J5fv54.rst | 2 + Parser/asdl_c.py | 53 +- Python/Python-ast.c | 662 ++++++++++-------- 4 files changed, 437 insertions(+), 306 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2019-12-27-19-20-33.bpo-38131.J5fv54.rst diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 0112c9163fd0cd..fd3b33bab7f833 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -625,7 +625,7 @@ def test_invalid_identifier(self): ast.fix_missing_locations(m) with self.assertRaises(TypeError) as cm: compile(m, "", "exec") - self.assertIn("identifier must be of type str", str(cm.exception)) + self.assertIn("expecting a string object", str(cm.exception)) def test_invalid_constant(self): for invalid_constant in int, (1, 2, int), frozenset((1, 2, int)): @@ -1081,6 +1081,30 @@ def test_none_checks(self) -> None: for node, attr, source in tests: self.assert_none_check(node, attr, source) + def test_required_field_messages(self): + binop = ast.BinOp( + left=ast.Constant(value=2), + right=ast.Constant(value=2), + op=ast.Add(), + ) + expr_without_position = ast.Expression(body=binop) + expr_with_wrong_body = ast.Expression(body=[binop]) + + with self.assertRaisesRegex(TypeError, "required field") as cm: + compile(expr_without_position, "", "eval") + with self.assertRaisesRegex( + TypeError, + "field 'body' was expecting node of type 'expr', got 'list'", + ): + compile(expr_with_wrong_body, "", "eval") + + constant = ast.parse("u'test'", mode="eval") + constant.body.kind = 0xFF + with self.assertRaisesRegex( + TypeError, "field 'kind' was expecting a string or bytes object" + ): + compile(constant, "", "eval") + def test_repr(self) -> None: snapshots = AST_REPR_DATA_FILE.read_text().split("\n") for test, snapshot in zip(ast_repr_get_test_cases(), snapshots, strict=True): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2019-12-27-19-20-33.bpo-38131.J5fv54.rst b/Misc/NEWS.d/next/Core_and_Builtins/2019-12-27-19-20-33.bpo-38131.J5fv54.rst new file mode 100644 index 00000000000000..8b606c4335e033 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2019-12-27-19-20-33.bpo-38131.J5fv54.rst @@ -0,0 +1,2 @@ +Produce more meaningful messages when compiling AST objects with wrong field +values. Patch by Batuhan Taskaya. diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index ed1d2e08df8f40..e2a57177d20afb 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -487,7 +487,7 @@ def visitField(self, sum): class Obj2ModPrototypeVisitor(PickleVisitor): def visitProduct(self, prod, name): - code = "static int obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, PyArena* arena);" + code = "static int obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, const char* field, PyArena* arena);" self.emit(code % (name, get_c_type(name)), 0) visitSum = visitProduct @@ -511,7 +511,7 @@ def recursive_call(self, node, level): def funcHeader(self, name): ctype = get_c_type(name) self.emit("int", 0) - self.emit("obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0) + self.emit("obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, const char* field, PyArena* arena)" % (name, ctype), 0) self.emit("{", 0) self.emit("int isinstance;", 1) self.emit("", 0) @@ -547,6 +547,18 @@ def simpleSum(self, sum, name): def buildArgs(self, fields): return ", ".join(fields + ["arena"]) + def typeCheck(self, name): + self.emit("tp = state->%s_type;" % name, 1) + self.emit("isinstance = PyObject_IsInstance(obj, tp);", 1) + self.emit("if (isinstance == -1) {", 1) + self.emit("return 1;", 2) + self.emit("}", 1) + self.emit("if (!isinstance && field != NULL) {", 1) + error = "field '%%s' was expecting node of type '%s', got '%%s'" % name + self.emit("PyErr_Format(PyExc_TypeError, \"%s\", field, _PyType_Name(Py_TYPE(obj)));" % error, 2, reflow=False) + self.emit("return 1;", 2) + self.emit("}", 1) + def complexSum(self, sum, name): self.funcHeader(name) self.emit("PyObject *tmp = NULL;", 1) @@ -559,6 +571,7 @@ def complexSum(self, sum, name): self.emit("*out = NULL;", 2) self.emit("return 0;", 2) self.emit("}", 1) + self.typeCheck(name) for a in sum.attributes: self.visitField(a, name, sum=sum, depth=1) for t in sum.types: @@ -593,7 +606,7 @@ def visitSum(self, sum, name): def visitProduct(self, prod, name): ctype = get_c_type(name) self.emit("int", 0) - self.emit("obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0) + self.emit("obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, const char* field, PyArena* arena)" % (name, ctype), 0) self.emit("{", 0) self.emit("PyObject* tmp = NULL;", 1) for f in prod.fields: @@ -694,8 +707,8 @@ def visitField(self, field, name, sum=None, prod=None, depth=0): self.emit("%s val;" % ctype, depth+2) self.emit("PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i));", depth+2) with self.recursive_call(name, depth+2): - self.emit("res = obj2ast_%s(state, tmp2, &val, arena);" % - field.type, depth+2, reflow=False) + self.emit("res = obj2ast_%s(state, tmp2, &val, \"%s\", arena);" % + (field.type, field.name), depth+2, reflow=False) self.emit("Py_DECREF(tmp2);", depth+2) self.emit("if (res != 0) goto failed;", depth+2) self.emit("if (len != PyList_GET_SIZE(tmp)) {", depth+2) @@ -709,8 +722,8 @@ def visitField(self, field, name, sum=None, prod=None, depth=0): self.emit("}", depth+1) else: with self.recursive_call(name, depth+1): - self.emit("res = obj2ast_%s(state, tmp, &%s, arena);" % - (field.type, field.name), depth+1) + self.emit("res = obj2ast_%s(state, tmp, &%s, \"%s\", arena);" % + (field.type, field.name, field.name), depth+1) self.emit("if (res != 0) goto failed;", depth+1) self.emit("Py_CLEAR(tmp);", depth+1) @@ -1701,7 +1714,9 @@ def visitModule(self, mod): /* Conversion Python -> AST */ -static int obj2ast_object(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_object(struct ast_state *Py_UNUSED(state), PyObject* obj, + PyObject** out, + const char* Py_UNUSED(field), PyArena* arena) { if (obj == Py_None) obj = NULL; @@ -1718,7 +1733,9 @@ def visitModule(self, mod): return 0; } -static int obj2ast_constant(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_constant(struct ast_state *Py_UNUSED(state), PyObject* obj, + PyObject** out, + const char* Py_UNUSED(field), PyArena* arena) { if (_PyArena_AddPyObject(arena, obj) < 0) { *out = NULL; @@ -1728,29 +1745,29 @@ def visitModule(self, mod): return 0; } -static int obj2ast_identifier(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_identifier(struct ast_state *state, PyObject* obj, PyObject** out, const char* field, PyArena* arena) { if (!PyUnicode_CheckExact(obj) && obj != Py_None) { - PyErr_SetString(PyExc_TypeError, "AST identifier must be of type str"); + PyErr_Format(PyExc_TypeError, "field '%s' was expecting a string object", field); return -1; } - return obj2ast_object(state, obj, out, arena); + return obj2ast_object(state, obj, out, field, arena); } -static int obj2ast_string(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_string(struct ast_state *state, PyObject* obj, PyObject** out, const char* field, PyArena* arena) { if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) { - PyErr_SetString(PyExc_TypeError, "AST string must be of type str"); + PyErr_Format(PyExc_TypeError, "field '%s' was expecting a string or bytes object", field); return -1; } - return obj2ast_object(state, obj, out, arena); + return obj2ast_object(state, obj, out, field, arena); } -static int obj2ast_int(struct ast_state* Py_UNUSED(state), PyObject* obj, int* out, PyArena* arena) +static int obj2ast_int(struct ast_state* Py_UNUSED(state), PyObject* obj, int* out, const char* field, PyArena* arena) { int i; if (!PyLong_Check(obj)) { - PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj); + PyErr_Format(PyExc_ValueError, "field \\"%s\\" got an invalid integer value: %R", field, obj); return -1; } @@ -2150,7 +2167,7 @@ class PartingShots(StaticVisitor): } mod_ty res = NULL; - if (obj2ast_mod(state, ast, &res, arena) != 0) + if (obj2ast_mod(state, ast, &res, NULL, arena) != 0) return NULL; else return res; diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 5f3d9c4b17410f..49b6bf1d12b6fa 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -6026,7 +6026,9 @@ static PyObject* ast2obj_int(struct ast_state *Py_UNUSED(state), long b) /* Conversion Python -> AST */ -static int obj2ast_object(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_object(struct ast_state *Py_UNUSED(state), PyObject* obj, + PyObject** out, + const char* Py_UNUSED(field), PyArena* arena) { if (obj == Py_None) obj = NULL; @@ -6043,7 +6045,9 @@ static int obj2ast_object(struct ast_state *Py_UNUSED(state), PyObject* obj, PyO return 0; } -static int obj2ast_constant(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_constant(struct ast_state *Py_UNUSED(state), PyObject* obj, + PyObject** out, + const char* Py_UNUSED(field), PyArena* arena) { if (_PyArena_AddPyObject(arena, obj) < 0) { *out = NULL; @@ -6053,29 +6057,29 @@ static int obj2ast_constant(struct ast_state *Py_UNUSED(state), PyObject* obj, P return 0; } -static int obj2ast_identifier(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_identifier(struct ast_state *state, PyObject* obj, PyObject** out, const char* field, PyArena* arena) { if (!PyUnicode_CheckExact(obj) && obj != Py_None) { - PyErr_SetString(PyExc_TypeError, "AST identifier must be of type str"); + PyErr_Format(PyExc_TypeError, "field '%s' was expecting a string object", field); return -1; } - return obj2ast_object(state, obj, out, arena); + return obj2ast_object(state, obj, out, field, arena); } -static int obj2ast_string(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena) +static int obj2ast_string(struct ast_state *state, PyObject* obj, PyObject** out, const char* field, PyArena* arena) { if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) { - PyErr_SetString(PyExc_TypeError, "AST string must be of type str"); + PyErr_Format(PyExc_TypeError, "field '%s' was expecting a string or bytes object", field); return -1; } - return obj2ast_object(state, obj, out, arena); + return obj2ast_object(state, obj, out, field, arena); } -static int obj2ast_int(struct ast_state* Py_UNUSED(state), PyObject* obj, int* out, PyArena* arena) +static int obj2ast_int(struct ast_state* Py_UNUSED(state), PyObject* obj, int* out, const char* field, PyArena* arena) { int i; if (!PyLong_Check(obj)) { - PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj); + PyErr_Format(PyExc_ValueError, "field \"%s\" got an invalid integer value: %R", field, obj); return -1; } @@ -6954,43 +6958,52 @@ init_types(void *arg) } static int obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, - PyArena* arena); + const char* field, PyArena* arena); static int obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, - PyArena* arena); + const char* field, PyArena* arena); static int obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, - PyArena* arena); + const char* field, PyArena* arena); static int obj2ast_expr_context(struct ast_state *state, PyObject* obj, - expr_context_ty* out, PyArena* arena); + expr_context_ty* out, const char* field, + PyArena* arena); static int obj2ast_boolop(struct ast_state *state, PyObject* obj, boolop_ty* - out, PyArena* arena); + out, const char* field, PyArena* arena); static int obj2ast_operator(struct ast_state *state, PyObject* obj, - operator_ty* out, PyArena* arena); + operator_ty* out, const char* field, PyArena* + arena); static int obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* - out, PyArena* arena); + out, const char* field, PyArena* arena); static int obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, - PyArena* arena); + const char* field, PyArena* arena); static int obj2ast_comprehension(struct ast_state *state, PyObject* obj, - comprehension_ty* out, PyArena* arena); + comprehension_ty* out, const char* field, + PyArena* arena); static int obj2ast_excepthandler(struct ast_state *state, PyObject* obj, - excepthandler_ty* out, PyArena* arena); + excepthandler_ty* out, const char* field, + PyArena* arena); static int obj2ast_arguments(struct ast_state *state, PyObject* obj, - arguments_ty* out, PyArena* arena); + arguments_ty* out, const char* field, PyArena* + arena); static int obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, - PyArena* arena); + const char* field, PyArena* arena); static int obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* - out, PyArena* arena); + out, const char* field, PyArena* arena); static int obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, - PyArena* arena); + const char* field, PyArena* arena); static int obj2ast_withitem(struct ast_state *state, PyObject* obj, - withitem_ty* out, PyArena* arena); + withitem_ty* out, const char* field, PyArena* + arena); static int obj2ast_match_case(struct ast_state *state, PyObject* obj, - match_case_ty* out, PyArena* arena); + match_case_ty* out, const char* field, PyArena* + arena); static int obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* - out, PyArena* arena); + out, const char* field, PyArena* arena); static int obj2ast_type_ignore(struct ast_state *state, PyObject* obj, - type_ignore_ty* out, PyArena* arena); + type_ignore_ty* out, const char* field, PyArena* + arena); static int obj2ast_type_param(struct ast_state *state, PyObject* obj, - type_param_ty* out, PyArena* arena); + type_param_ty* out, const char* field, PyArena* + arena); mod_ty _PyAST_Module(asdl_stmt_seq * body, asdl_type_ignore_seq * type_ignores, @@ -10855,7 +10868,8 @@ ast2obj_type_param(struct ast_state *state, void* _o) int -obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) +obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, const char* + field, PyArena* arena) { int isinstance; @@ -10866,6 +10880,15 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) *out = NULL; return 0; } + tp = state->mod_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'mod', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } tp = state->Module_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { @@ -10901,7 +10924,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'Module' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -10939,7 +10962,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'Module' node")) { goto failed; } - res = obj2ast_type_ignore(state, tmp2, &val, arena); + res = obj2ast_type_ignore(state, tmp2, &val, "type_ignores", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -10989,7 +11012,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'Interactive' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11025,7 +11048,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'Expression' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &body, arena); + res = obj2ast_expr(state, tmp, &body, "body", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11069,7 +11092,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'FunctionType' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "argtypes", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11093,7 +11116,7 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'FunctionType' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &returns, arena); + res = obj2ast_expr(state, tmp, &returns, "returns", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11110,8 +11133,8 @@ obj2ast_mod(struct ast_state *state, PyObject* obj, mod_ty* out, PyArena* arena) } int -obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* - arena) +obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, const char* + field, PyArena* arena) { int isinstance; @@ -11126,6 +11149,15 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* *out = NULL; return 0; } + tp = state->stmt_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'stmt', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { return -1; } @@ -11138,7 +11170,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'stmt' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11155,7 +11187,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'stmt' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11172,7 +11204,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'stmt' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11189,7 +11221,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'stmt' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11220,7 +11252,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11237,7 +11269,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_arguments(state, tmp, &args, arena); + res = obj2ast_arguments(state, tmp, &args, "args", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11268,7 +11300,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11306,7 +11338,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "decorator_list", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11330,7 +11362,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &returns, arena); + res = obj2ast_expr(state, tmp, &returns, "returns", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11347,7 +11379,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11378,7 +11411,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FunctionDef' node")) { goto failed; } - res = obj2ast_type_param(state, tmp2, &val, arena); + res = obj2ast_type_param(state, tmp2, &val, "type_params", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11423,7 +11456,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11440,7 +11473,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_arguments(state, tmp, &args, arena); + res = obj2ast_arguments(state, tmp, &args, "args", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11471,7 +11504,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11509,7 +11542,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "decorator_list", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11533,7 +11566,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &returns, arena); + res = obj2ast_expr(state, tmp, &returns, "returns", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11550,7 +11583,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11581,7 +11615,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFunctionDef' node")) { goto failed; } - res = obj2ast_type_param(state, tmp2, &val, arena); + res = obj2ast_type_param(state, tmp2, &val, "type_params", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11625,7 +11659,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11656,7 +11690,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "bases", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11694,7 +11728,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { goto failed; } - res = obj2ast_keyword(state, tmp2, &val, arena); + res = obj2ast_keyword(state, tmp2, &val, "keywords", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11732,7 +11766,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11770,7 +11804,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "decorator_list", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11808,7 +11842,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ClassDef' node")) { goto failed; } - res = obj2ast_type_param(state, tmp2, &val, arena); + res = obj2ast_type_param(state, tmp2, &val, "type_params", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11846,7 +11880,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Return' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11890,7 +11924,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Delete' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "targets", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11943,7 +11977,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Assign' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "targets", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -11967,7 +12001,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Assign' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -11984,7 +12018,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Assign' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12016,7 +12051,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TypeAlias' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &name, arena); + res = obj2ast_expr(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12047,7 +12082,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TypeAlias' node")) { goto failed; } - res = obj2ast_type_param(state, tmp2, &val, arena); + res = obj2ast_type_param(state, tmp2, &val, "type_params", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12071,7 +12106,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TypeAlias' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12103,7 +12138,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AugAssign' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &target, arena); + res = obj2ast_expr(state, tmp, &target, "target", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12120,7 +12155,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AugAssign' node")) { goto failed; } - res = obj2ast_operator(state, tmp, &op, arena); + res = obj2ast_operator(state, tmp, &op, "op", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12137,7 +12172,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AugAssign' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12170,7 +12205,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &target, arena); + res = obj2ast_expr(state, tmp, &target, "target", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12187,7 +12222,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &annotation, arena); + res = obj2ast_expr(state, tmp, &annotation, "annotation", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12204,7 +12239,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12221,7 +12256,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AnnAssign' node")) { goto failed; } - res = obj2ast_int(state, tmp, &simple, arena); + res = obj2ast_int(state, tmp, &simple, "simple", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12255,7 +12290,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'For' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &target, arena); + res = obj2ast_expr(state, tmp, &target, "target", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12272,7 +12307,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'For' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &iter, arena); + res = obj2ast_expr(state, tmp, &iter, "iter", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12303,7 +12338,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'For' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12341,7 +12376,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'For' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "orelse", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12365,7 +12400,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'For' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12399,7 +12435,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &target, arena); + res = obj2ast_expr(state, tmp, &target, "target", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12416,7 +12452,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &iter, arena); + res = obj2ast_expr(state, tmp, &iter, "iter", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12447,7 +12483,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12485,7 +12521,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "orelse", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12509,7 +12545,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncFor' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12542,7 +12579,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'While' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &test, arena); + res = obj2ast_expr(state, tmp, &test, "test", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12573,7 +12610,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'While' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12611,7 +12648,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'While' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "orelse", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12650,7 +12687,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'If' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &test, arena); + res = obj2ast_expr(state, tmp, &test, "test", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12681,7 +12718,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'If' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12719,7 +12756,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'If' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "orelse", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12772,7 +12809,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'With' node")) { goto failed; } - res = obj2ast_withitem(state, tmp2, &val, arena); + res = obj2ast_withitem(state, tmp2, &val, "items", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12810,7 +12847,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'With' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12834,7 +12871,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'With' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12880,7 +12918,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncWith' node")) { goto failed; } - res = obj2ast_withitem(state, tmp2, &val, arena); + res = obj2ast_withitem(state, tmp2, &val, "items", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12918,7 +12956,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncWith' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -12942,7 +12980,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'AsyncWith' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -12973,7 +13012,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Match' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &subject, arena); + res = obj2ast_expr(state, tmp, &subject, "subject", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13004,7 +13043,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Match' node")) { goto failed; } - res = obj2ast_match_case(state, tmp2, &val, arena); + res = obj2ast_match_case(state, tmp2, &val, "cases", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13042,7 +13081,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Raise' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &exc, arena); + res = obj2ast_expr(state, tmp, &exc, "exc", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13059,7 +13098,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Raise' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &cause, arena); + res = obj2ast_expr(state, tmp, &cause, "cause", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13106,7 +13145,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Try' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13144,7 +13183,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Try' node")) { goto failed; } - res = obj2ast_excepthandler(state, tmp2, &val, arena); + res = obj2ast_excepthandler(state, tmp2, &val, "handlers", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13182,7 +13221,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Try' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "orelse", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13220,7 +13259,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Try' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "finalbody", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13274,7 +13313,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TryStar' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13312,7 +13351,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TryStar' node")) { goto failed; } - res = obj2ast_excepthandler(state, tmp2, &val, arena); + res = obj2ast_excepthandler(state, tmp2, &val, "handlers", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13350,7 +13389,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TryStar' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "orelse", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13388,7 +13427,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TryStar' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "finalbody", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13426,7 +13465,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Assert' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &test, arena); + res = obj2ast_expr(state, tmp, &test, "test", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13443,7 +13482,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Assert' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &msg, arena); + res = obj2ast_expr(state, tmp, &msg, "msg", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13488,7 +13527,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Import' node")) { goto failed; } - res = obj2ast_alias(state, tmp2, &val, arena); + res = obj2ast_alias(state, tmp2, &val, "names", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13512,7 +13551,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Import' node")) { goto failed; } - res = obj2ast_int(state, tmp, &is_lazy, arena); + res = obj2ast_int(state, tmp, &is_lazy, "is_lazy", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13545,7 +13584,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &module, arena); + res = obj2ast_identifier(state, tmp, &module, "module", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13576,7 +13615,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) { goto failed; } - res = obj2ast_alias(state, tmp2, &val, arena); + res = obj2ast_alias(state, tmp2, &val, "names", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13600,7 +13639,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) { goto failed; } - res = obj2ast_int(state, tmp, &level, arena); + res = obj2ast_int(state, tmp, &level, "level", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13617,7 +13656,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ImportFrom' node")) { goto failed; } - res = obj2ast_int(state, tmp, &is_lazy, arena); + res = obj2ast_int(state, tmp, &is_lazy, "is_lazy", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13661,7 +13700,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Global' node")) { goto failed; } - res = obj2ast_identifier(state, tmp2, &val, arena); + res = obj2ast_identifier(state, tmp2, &val, "names", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13712,7 +13751,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Nonlocal' node")) { goto failed; } - res = obj2ast_identifier(state, tmp2, &val, arena); + res = obj2ast_identifier(state, tmp2, &val, "names", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13749,7 +13788,7 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Expr' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13803,8 +13842,8 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* } int -obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* - arena) +obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, const char* + field, PyArena* arena) { int isinstance; @@ -13819,6 +13858,15 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* *out = NULL; return 0; } + tp = state->expr_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'expr', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { return -1; } @@ -13831,7 +13879,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'expr' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13848,7 +13896,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'expr' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13865,7 +13913,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'expr' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13882,7 +13930,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'expr' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13908,7 +13956,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'BoolOp' node")) { goto failed; } - res = obj2ast_boolop(state, tmp, &op, arena); + res = obj2ast_boolop(state, tmp, &op, "op", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13939,7 +13987,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'BoolOp' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "values", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -13977,7 +14025,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'NamedExpr' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &target, arena); + res = obj2ast_expr(state, tmp, &target, "target", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -13994,7 +14042,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'NamedExpr' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14026,7 +14074,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'BinOp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &left, arena); + res = obj2ast_expr(state, tmp, &left, "left", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14043,7 +14091,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'BinOp' node")) { goto failed; } - res = obj2ast_operator(state, tmp, &op, arena); + res = obj2ast_operator(state, tmp, &op, "op", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14060,7 +14108,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'BinOp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &right, arena); + res = obj2ast_expr(state, tmp, &right, "right", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14091,7 +14139,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'UnaryOp' node")) { goto failed; } - res = obj2ast_unaryop(state, tmp, &op, arena); + res = obj2ast_unaryop(state, tmp, &op, "op", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14108,7 +14156,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'UnaryOp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &operand, arena); + res = obj2ast_expr(state, tmp, &operand, "operand", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14139,7 +14187,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Lambda' node")) { goto failed; } - res = obj2ast_arguments(state, tmp, &args, arena); + res = obj2ast_arguments(state, tmp, &args, "args", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14156,7 +14204,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Lambda' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &body, arena); + res = obj2ast_expr(state, tmp, &body, "body", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14188,7 +14236,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'IfExp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &test, arena); + res = obj2ast_expr(state, tmp, &test, "test", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14205,7 +14253,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'IfExp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &body, arena); + res = obj2ast_expr(state, tmp, &body, "body", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14222,7 +14270,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'IfExp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &orelse, arena); + res = obj2ast_expr(state, tmp, &orelse, "orelse", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14267,7 +14315,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Dict' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "keys", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14305,7 +14353,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Dict' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "values", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14356,7 +14404,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Set' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "elts", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14394,7 +14442,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ListComp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &elt, arena); + res = obj2ast_expr(state, tmp, &elt, "elt", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14425,7 +14473,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'ListComp' node")) { goto failed; } - res = obj2ast_comprehension(state, tmp2, &val, arena); + res = obj2ast_comprehension(state, tmp2, &val, "generators", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14463,7 +14511,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'SetComp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &elt, arena); + res = obj2ast_expr(state, tmp, &elt, "elt", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14494,7 +14542,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'SetComp' node")) { goto failed; } - res = obj2ast_comprehension(state, tmp2, &val, arena); + res = obj2ast_comprehension(state, tmp2, &val, "generators", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14533,7 +14581,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'DictComp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &key, arena); + res = obj2ast_expr(state, tmp, &key, "key", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14550,7 +14598,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'DictComp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14581,7 +14629,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'DictComp' node")) { goto failed; } - res = obj2ast_comprehension(state, tmp2, &val, arena); + res = obj2ast_comprehension(state, tmp2, &val, "generators", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14619,7 +14667,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'GeneratorExp' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &elt, arena); + res = obj2ast_expr(state, tmp, &elt, "elt", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14650,7 +14698,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'GeneratorExp' node")) { goto failed; } - res = obj2ast_comprehension(state, tmp2, &val, arena); + res = obj2ast_comprehension(state, tmp2, &val, "generators", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14687,7 +14735,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Await' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14717,7 +14765,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Yield' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14747,7 +14795,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'YieldFrom' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14779,7 +14827,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Compare' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &left, arena); + res = obj2ast_expr(state, tmp, &left, "left", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14810,7 +14858,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Compare' node")) { goto failed; } - res = obj2ast_cmpop(state, tmp2, &val, arena); + res = obj2ast_cmpop(state, tmp2, &val, "ops", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14848,7 +14896,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Compare' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "comparators", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14887,7 +14935,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Call' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &func, arena); + res = obj2ast_expr(state, tmp, &func, "func", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -14918,7 +14966,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Call' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "args", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14956,7 +15004,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Call' node")) { goto failed; } - res = obj2ast_keyword(state, tmp2, &val, arena); + res = obj2ast_keyword(state, tmp2, &val, "keywords", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -14995,7 +15043,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FormattedValue' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15012,7 +15060,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FormattedValue' node")) { goto failed; } - res = obj2ast_int(state, tmp, &conversion, arena); + res = obj2ast_int(state, tmp, &conversion, "conversion", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15029,7 +15077,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'FormattedValue' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &format_spec, arena); + res = obj2ast_expr(state, tmp, &format_spec, "format_spec", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15063,7 +15111,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Interpolation' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15080,7 +15128,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Interpolation' node")) { goto failed; } - res = obj2ast_constant(state, tmp, &str, arena); + res = obj2ast_constant(state, tmp, &str, "str", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15097,7 +15145,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Interpolation' node")) { goto failed; } - res = obj2ast_int(state, tmp, &conversion, arena); + res = obj2ast_int(state, tmp, &conversion, "conversion", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15114,7 +15162,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Interpolation' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &format_spec, arena); + res = obj2ast_expr(state, tmp, &format_spec, "format_spec", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15159,7 +15207,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'JoinedStr' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "values", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -15210,7 +15258,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'TemplateStr' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "values", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -15248,7 +15296,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Constant' node")) { goto failed; } - res = obj2ast_constant(state, tmp, &value, arena); + res = obj2ast_constant(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15265,7 +15313,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Constant' node")) { goto failed; } - res = obj2ast_string(state, tmp, &kind, arena); + res = obj2ast_string(state, tmp, &kind, "kind", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15297,7 +15345,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Attribute' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15314,7 +15362,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Attribute' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &attr, arena); + res = obj2ast_identifier(state, tmp, &attr, "attr", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15331,7 +15379,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Attribute' node")) { goto failed; } - res = obj2ast_expr_context(state, tmp, &ctx, arena); + res = obj2ast_expr_context(state, tmp, &ctx, "ctx", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15363,7 +15411,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Subscript' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15380,7 +15428,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Subscript' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &slice, arena); + res = obj2ast_expr(state, tmp, &slice, "slice", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15397,7 +15445,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Subscript' node")) { goto failed; } - res = obj2ast_expr_context(state, tmp, &ctx, arena); + res = obj2ast_expr_context(state, tmp, &ctx, "ctx", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15428,7 +15476,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Starred' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15445,7 +15493,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Starred' node")) { goto failed; } - res = obj2ast_expr_context(state, tmp, &ctx, arena); + res = obj2ast_expr_context(state, tmp, &ctx, "ctx", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15476,7 +15524,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Name' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &id, arena); + res = obj2ast_identifier(state, tmp, &id, "id", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15493,7 +15541,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Name' node")) { goto failed; } - res = obj2ast_expr_context(state, tmp, &ctx, arena); + res = obj2ast_expr_context(state, tmp, &ctx, "ctx", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15538,7 +15586,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'List' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "elts", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -15562,7 +15610,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'List' node")) { goto failed; } - res = obj2ast_expr_context(state, tmp, &ctx, arena); + res = obj2ast_expr_context(state, tmp, &ctx, "ctx", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15607,7 +15655,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Tuple' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "elts", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -15631,7 +15679,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Tuple' node")) { goto failed; } - res = obj2ast_expr_context(state, tmp, &ctx, arena); + res = obj2ast_expr_context(state, tmp, &ctx, "ctx", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15663,7 +15711,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Slice' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &lower, arena); + res = obj2ast_expr(state, tmp, &lower, "lower", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15680,7 +15728,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Slice' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &upper, arena); + res = obj2ast_expr(state, tmp, &upper, "upper", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15697,7 +15745,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'Slice' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &step, arena); + res = obj2ast_expr(state, tmp, &step, "step", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -15716,7 +15764,7 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* int obj2ast_expr_context(struct ast_state *state, PyObject* obj, expr_context_ty* - out, PyArena* arena) + out, const char* field, PyArena* arena) { int isinstance; @@ -15750,8 +15798,8 @@ obj2ast_expr_context(struct ast_state *state, PyObject* obj, expr_context_ty* } int -obj2ast_boolop(struct ast_state *state, PyObject* obj, boolop_ty* out, PyArena* - arena) +obj2ast_boolop(struct ast_state *state, PyObject* obj, boolop_ty* out, const + char* field, PyArena* arena) { int isinstance; @@ -15778,7 +15826,7 @@ obj2ast_boolop(struct ast_state *state, PyObject* obj, boolop_ty* out, PyArena* int obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, - PyArena* arena) + const char* field, PyArena* arena) { int isinstance; @@ -15892,8 +15940,8 @@ obj2ast_operator(struct ast_state *state, PyObject* obj, operator_ty* out, } int -obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* out, - PyArena* arena) +obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* out, const + char* field, PyArena* arena) { int isinstance; @@ -15935,8 +15983,8 @@ obj2ast_unaryop(struct ast_state *state, PyObject* obj, unaryop_ty* out, } int -obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* - arena) +obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, const + char* field, PyArena* arena) { int isinstance; @@ -16027,7 +16075,7 @@ obj2ast_cmpop(struct ast_state *state, PyObject* obj, cmpop_ty* out, PyArena* int obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* - out, PyArena* arena) + out, const char* field, PyArena* arena) { PyObject* tmp = NULL; expr_ty target; @@ -16047,7 +16095,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* if (_Py_EnterRecursiveCall(" while traversing 'comprehension' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &target, arena); + res = obj2ast_expr(state, tmp, &target, "target", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16064,7 +16112,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* if (_Py_EnterRecursiveCall(" while traversing 'comprehension' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &iter, arena); + res = obj2ast_expr(state, tmp, &iter, "iter", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16095,7 +16143,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* if (_Py_EnterRecursiveCall(" while traversing 'comprehension' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "ifs", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16119,7 +16167,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* if (_Py_EnterRecursiveCall(" while traversing 'comprehension' node")) { goto failed; } - res = obj2ast_int(state, tmp, &is_async, arena); + res = obj2ast_int(state, tmp, &is_async, "is_async", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16134,7 +16182,7 @@ obj2ast_comprehension(struct ast_state *state, PyObject* obj, comprehension_ty* int obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* - out, PyArena* arena) + out, const char* field, PyArena* arena) { int isinstance; @@ -16149,6 +16197,15 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* *out = NULL; return 0; } + tp = state->excepthandler_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'excepthandler', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { return -1; } @@ -16161,7 +16218,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16178,7 +16235,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16195,7 +16252,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16212,7 +16269,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'excepthandler' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16239,7 +16296,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'ExceptHandler' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &type, arena); + res = obj2ast_expr(state, tmp, &type, "type", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16256,7 +16313,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'ExceptHandler' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16287,7 +16344,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* if (_Py_EnterRecursiveCall(" while traversing 'ExceptHandler' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16313,7 +16370,7 @@ obj2ast_excepthandler(struct ast_state *state, PyObject* obj, excepthandler_ty* int obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, - PyArena* arena) + const char* field, PyArena* arena) { PyObject* tmp = NULL; asdl_arg_seq* posonlyargs; @@ -16350,7 +16407,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_arg(state, tmp2, &val, arena); + res = obj2ast_arg(state, tmp2, &val, "posonlyargs", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16388,7 +16445,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_arg(state, tmp2, &val, arena); + res = obj2ast_arg(state, tmp2, &val, "args", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16412,7 +16469,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_arg(state, tmp, &vararg, arena); + res = obj2ast_arg(state, tmp, &vararg, "vararg", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16443,7 +16500,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_arg(state, tmp2, &val, arena); + res = obj2ast_arg(state, tmp2, &val, "kwonlyargs", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16481,7 +16538,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "kw_defaults", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16505,7 +16562,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_arg(state, tmp, &kwarg, arena); + res = obj2ast_arg(state, tmp, &kwarg, "kwarg", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16536,7 +16593,7 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'arguments' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "defaults", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -16558,7 +16615,8 @@ obj2ast_arguments(struct ast_state *state, PyObject* obj, arguments_ty* out, } int -obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) +obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, const char* + field, PyArena* arena) { PyObject* tmp = NULL; identifier arg; @@ -16581,7 +16639,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &arg, arena); + res = obj2ast_identifier(state, tmp, &arg, "arg", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16598,7 +16656,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &annotation, arena); + res = obj2ast_expr(state, tmp, &annotation, "annotation", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16615,7 +16673,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_string(state, tmp, &type_comment, arena); + res = obj2ast_string(state, tmp, &type_comment, "type_comment", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16632,7 +16690,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16649,7 +16707,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16666,7 +16724,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16683,7 +16741,7 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) if (_Py_EnterRecursiveCall(" while traversing 'arg' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16698,8 +16756,8 @@ obj2ast_arg(struct ast_state *state, PyObject* obj, arg_ty* out, PyArena* arena) } int -obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, - PyArena* arena) +obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, const + char* field, PyArena* arena) { PyObject* tmp = NULL; identifier arg; @@ -16721,7 +16779,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'keyword' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &arg, arena); + res = obj2ast_identifier(state, tmp, &arg, "arg", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16738,7 +16796,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'keyword' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16755,7 +16813,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'keyword' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16772,7 +16830,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'keyword' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16789,7 +16847,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'keyword' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16806,7 +16864,7 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'keyword' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16821,8 +16879,8 @@ obj2ast_keyword(struct ast_state *state, PyObject* obj, keyword_ty* out, } int -obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* - arena) +obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, const + char* field, PyArena* arena) { PyObject* tmp = NULL; identifier name; @@ -16844,7 +16902,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'alias' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16861,7 +16919,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'alias' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &asname, arena); + res = obj2ast_identifier(state, tmp, &asname, "asname", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16878,7 +16936,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'alias' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16895,7 +16953,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'alias' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16912,7 +16970,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'alias' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16929,7 +16987,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* if (_Py_EnterRecursiveCall(" while traversing 'alias' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16945,7 +17003,7 @@ obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* int obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, - PyArena* arena) + const char* field, PyArena* arena) { PyObject* tmp = NULL; expr_ty context_expr; @@ -16963,7 +17021,7 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'withitem' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &context_expr, arena); + res = obj2ast_expr(state, tmp, &context_expr, "context_expr", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16980,7 +17038,7 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'withitem' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &optional_vars, arena); + res = obj2ast_expr(state, tmp, &optional_vars, "optional_vars", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -16995,7 +17053,7 @@ obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, int obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, - PyArena* arena) + const char* field, PyArena* arena) { PyObject* tmp = NULL; pattern_ty pattern; @@ -17014,7 +17072,7 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'match_case' node")) { goto failed; } - res = obj2ast_pattern(state, tmp, &pattern, arena); + res = obj2ast_pattern(state, tmp, &pattern, "pattern", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17031,7 +17089,7 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'match_case' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &guard, arena); + res = obj2ast_expr(state, tmp, &guard, "guard", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17062,7 +17120,7 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'match_case' node")) { goto failed; } - res = obj2ast_stmt(state, tmp2, &val, arena); + res = obj2ast_stmt(state, tmp2, &val, "body", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17083,8 +17141,8 @@ obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, } int -obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, - PyArena* arena) +obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, const + char* field, PyArena* arena) { int isinstance; @@ -17099,6 +17157,15 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, *out = NULL; return 0; } + tp = state->pattern_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'pattern', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { return -1; } @@ -17111,7 +17178,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'pattern' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17128,7 +17195,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'pattern' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17145,7 +17212,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'pattern' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17162,7 +17229,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'pattern' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17187,7 +17254,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchValue' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &value, arena); + res = obj2ast_expr(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17217,7 +17284,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchSingleton' node")) { goto failed; } - res = obj2ast_constant(state, tmp, &value, arena); + res = obj2ast_constant(state, tmp, &value, "value", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17261,7 +17328,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchSequence' node")) { goto failed; } - res = obj2ast_pattern(state, tmp2, &val, arena); + res = obj2ast_pattern(state, tmp2, &val, "patterns", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17314,7 +17381,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchMapping' node")) { goto failed; } - res = obj2ast_expr(state, tmp2, &val, arena); + res = obj2ast_expr(state, tmp2, &val, "keys", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17352,7 +17419,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchMapping' node")) { goto failed; } - res = obj2ast_pattern(state, tmp2, &val, arena); + res = obj2ast_pattern(state, tmp2, &val, "patterns", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17376,7 +17443,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchMapping' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &rest, arena); + res = obj2ast_identifier(state, tmp, &rest, "rest", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17409,7 +17476,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchClass' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &cls, arena); + res = obj2ast_expr(state, tmp, &cls, "cls", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17440,7 +17507,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchClass' node")) { goto failed; } - res = obj2ast_pattern(state, tmp2, &val, arena); + res = obj2ast_pattern(state, tmp2, &val, "patterns", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17478,7 +17545,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchClass' node")) { goto failed; } - res = obj2ast_identifier(state, tmp2, &val, arena); + res = obj2ast_identifier(state, tmp2, &val, "kwd_attrs", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17516,7 +17583,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchClass' node")) { goto failed; } - res = obj2ast_pattern(state, tmp2, &val, arena); + res = obj2ast_pattern(state, tmp2, &val, "kwd_patterns", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17554,7 +17621,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchStar' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17585,7 +17652,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchAs' node")) { goto failed; } - res = obj2ast_pattern(state, tmp, &pattern, arena); + res = obj2ast_pattern(state, tmp, &pattern, "pattern", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17602,7 +17669,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchAs' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17646,7 +17713,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'MatchOr' node")) { goto failed; } - res = obj2ast_pattern(state, tmp2, &val, arena); + res = obj2ast_pattern(state, tmp2, &val, "patterns", arena); _Py_LeaveRecursiveCall(); Py_DECREF(tmp2); if (res != 0) goto failed; @@ -17672,7 +17739,7 @@ obj2ast_pattern(struct ast_state *state, PyObject* obj, pattern_ty* out, int obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* - out, PyArena* arena) + out, const char* field, PyArena* arena) { int isinstance; @@ -17683,6 +17750,15 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* *out = NULL; return 0; } + tp = state->type_ignore_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'type_ignore', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } tp = state->TypeIgnore_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { @@ -17704,7 +17780,7 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* if (_Py_EnterRecursiveCall(" while traversing 'TypeIgnore' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17721,7 +17797,7 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* if (_Py_EnterRecursiveCall(" while traversing 'TypeIgnore' node")) { goto failed; } - res = obj2ast_string(state, tmp, &tag, arena); + res = obj2ast_string(state, tmp, &tag, "tag", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17739,7 +17815,7 @@ obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* int obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, - PyArena* arena) + const char* field, PyArena* arena) { int isinstance; @@ -17754,6 +17830,15 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, *out = NULL; return 0; } + tp = state->type_param_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (!isinstance && field != NULL) { + PyErr_Format(PyExc_TypeError, "field '%s' was expecting node of type 'type_param', got '%s'", field, _PyType_Name(Py_TYPE(obj))); + return 1; + } if (PyObject_GetOptionalAttr(obj, state->lineno, &tmp) < 0) { return -1; } @@ -17766,7 +17851,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'type_param' node")) { goto failed; } - res = obj2ast_int(state, tmp, &lineno, arena); + res = obj2ast_int(state, tmp, &lineno, "lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17783,7 +17868,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'type_param' node")) { goto failed; } - res = obj2ast_int(state, tmp, &col_offset, arena); + res = obj2ast_int(state, tmp, &col_offset, "col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17800,7 +17885,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'type_param' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_lineno, arena); + res = obj2ast_int(state, tmp, &end_lineno, "end_lineno", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17817,7 +17902,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'type_param' node")) { goto failed; } - res = obj2ast_int(state, tmp, &end_col_offset, arena); + res = obj2ast_int(state, tmp, &end_col_offset, "end_col_offset", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17844,7 +17929,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'TypeVar' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17861,7 +17946,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'TypeVar' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &bound, arena); + res = obj2ast_expr(state, tmp, &bound, "bound", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17878,7 +17963,8 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'TypeVar' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &default_value, arena); + res = obj2ast_expr(state, tmp, &default_value, "default_value", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17909,7 +17995,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'ParamSpec' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17926,7 +18012,8 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'ParamSpec' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &default_value, arena); + res = obj2ast_expr(state, tmp, &default_value, "default_value", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17957,7 +18044,7 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'TypeVarTuple' node")) { goto failed; } - res = obj2ast_identifier(state, tmp, &name, arena); + res = obj2ast_identifier(state, tmp, &name, "name", arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -17974,7 +18061,8 @@ obj2ast_type_param(struct ast_state *state, PyObject* obj, type_param_ty* out, if (_Py_EnterRecursiveCall(" while traversing 'TypeVarTuple' node")) { goto failed; } - res = obj2ast_expr(state, tmp, &default_value, arena); + res = obj2ast_expr(state, tmp, &default_value, "default_value", + arena); _Py_LeaveRecursiveCall(); if (res != 0) goto failed; Py_CLEAR(tmp); @@ -18506,7 +18594,7 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) } mod_ty res = NULL; - if (obj2ast_mod(state, ast, &res, arena) != 0) + if (obj2ast_mod(state, ast, &res, NULL, arena) != 0) return NULL; else return res; From a96cba5c4aa3cf859a9cacab590fc1a51d6efbbb Mon Sep 17 00:00:00 2001 From: Adorilson Bezerra Date: Thu, 4 Jun 2026 12:39:14 +0100 Subject: [PATCH 4/8] gh-106318: Add doctest role and a 'See also' to the `str.split()` docs (#144367) --- Doc/library/stdtypes.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index ba896212925d89..f770809dfb4006 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2616,7 +2616,9 @@ expression support in the :mod:`re` module). :func:`re.split`). Splitting an empty string with a specified separator returns ``['']``. - For example:: + For example: + + .. doctest:: >>> '1,2,3'.split(',') ['1', '2', '3'] @@ -2634,7 +2636,9 @@ expression support in the :mod:`re` module). string or a string consisting of just whitespace with a ``None`` separator returns ``[]``. - For example:: + For example: + + .. doctest:: >>> '1 2 3'.split() ['1', '2', '3'] @@ -2646,7 +2650,9 @@ expression support in the :mod:`re` module). If *sep* is not specified or is ``None`` and *maxsplit* is ``0``, only leading runs of consecutive whitespace are considered. - For example:: + For example: + + .. doctest:: >>> "".split(None, 0) [] @@ -2655,7 +2661,7 @@ expression support in the :mod:`re` module). >>> " foo ".split(maxsplit=0) ['foo '] - See also :meth:`join`. + See also :meth:`join` and :meth:`rsplit`. .. index:: From d83d50b5b735cb58e175280d1c27d40c43d535b5 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Thu, 4 Jun 2026 16:31:31 +0300 Subject: [PATCH 5/8] gh-150750: Fix a race condition in `deque.index` with free-threading (#150779) --- Lib/test/test_deque.py | 16 +++++++++++++ .../test_free_threading/test_collections.py | 24 +++++++++++++++++++ ...-06-02-14-21-46.gh-issue-150750.SVS2o0.rst | 1 + Modules/_collectionsmodule.c | 15 ++++++------ Modules/clinic/_collectionsmodule.c.h | 4 ++-- Modules/posixmodule.c | 4 ++-- 6 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-06-02-14-21-46.gh-issue-150750.SVS2o0.rst diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py index 4e1a489205a685..3c45032cda9138 100644 --- a/Lib/test/test_deque.py +++ b/Lib/test/test_deque.py @@ -287,6 +287,22 @@ def test_index(self): else: self.assertEqual(d.index(element, start, stop), target) + # Test stop argument + for elem in d: + index = d.index(elem) + self.assertEqual( + index, + d.index(elem, 0), + ) + self.assertEqual( + index, + d.index(elem, 0, len(d)), + ) + self.assertEqual( + index, + d.index(elem, 0, len(d) + 100), + ) + # Test large start argument d = deque(range(0, 10000, 10)) for step in range(100): diff --git a/Lib/test/test_free_threading/test_collections.py b/Lib/test/test_free_threading/test_collections.py index 3a413ccf396d4b..849b0480e232fc 100644 --- a/Lib/test/test_free_threading/test_collections.py +++ b/Lib/test/test_free_threading/test_collections.py @@ -24,6 +24,30 @@ def copy_loop(): threading_helper.run_concurrently([mutate, copy_loop]) + def test_index_race_in_ac(self): + # gh-150750: There was a c_default specified as `Py_SIZE(self)`, + # it was used without a critical section. + + d = deque(range(100)) + + def index(): + for _ in range(10000): + try: + d.index(50) + except ValueError: + pass + + def mutate(): + for _ in range(10000): + d.append(0) + d.clear() + d.extend(range(100)) + d.appendleft(-1) + + threading_helper.run_concurrently( + [index, *[mutate for _ in range(3)]], + ) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2026-06-02-14-21-46.gh-issue-150750.SVS2o0.rst b/Misc/NEWS.d/next/Library/2026-06-02-14-21-46.gh-issue-150750.SVS2o0.rst new file mode 100644 index 00000000000000..bda500383e7cda --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-02-14-21-46.gh-issue-150750.SVS2o0.rst @@ -0,0 +1 @@ +Fix a race condition in :meth:`collections.deque.index` with free-threading. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index c5d4879312bc8a..5ca6362406a78b 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1251,7 +1251,7 @@ _collections.deque.index as deque_index deque: dequeobject value as v: object start: object(converter='_PyEval_SliceIndexNotNone', type='Py_ssize_t', c_default='0') = NULL - stop: object(converter='_PyEval_SliceIndexNotNone', type='Py_ssize_t', c_default='Py_SIZE(deque)') = NULL + stop: object(converter='_PyEval_SliceIndexNotNone', type='Py_ssize_t', c_default='PY_SSIZE_T_MAX') = NULL / Return first index of value. @@ -1262,7 +1262,7 @@ Raises ValueError if the value is not present. static PyObject * deque_index_impl(dequeobject *deque, PyObject *v, Py_ssize_t start, Py_ssize_t stop) -/*[clinic end generated code: output=df45132753175ef9 input=90f48833a91e1743]*/ +/*[clinic end generated code: output=df45132753175ef9 input=1c3b19632cf3484f]*/ { Py_ssize_t i, n; PyObject *item; @@ -1270,22 +1270,23 @@ deque_index_impl(dequeobject *deque, PyObject *v, Py_ssize_t start, Py_ssize_t index = deque->leftindex; size_t start_state = deque->state; int cmp; + Py_ssize_t size = Py_SIZE(deque); if (start < 0) { - start += Py_SIZE(deque); + start += size; if (start < 0) start = 0; } if (stop < 0) { - stop += Py_SIZE(deque); + stop += size; if (stop < 0) stop = 0; } - if (stop > Py_SIZE(deque)) - stop = Py_SIZE(deque); + if (stop > size) + stop = size; if (start > stop) start = stop; - assert(0 <= start && start <= stop && stop <= Py_SIZE(deque)); + assert(0 <= start && start <= stop && stop <= size); for (i=0 ; i < start - BLOCKLEN ; i += BLOCKLEN) { b = b->rightlink; diff --git a/Modules/clinic/_collectionsmodule.c.h b/Modules/clinic/_collectionsmodule.c.h index b5c315c680e782..6c60678a6fbd51 100644 --- a/Modules/clinic/_collectionsmodule.c.h +++ b/Modules/clinic/_collectionsmodule.c.h @@ -340,7 +340,7 @@ deque_index(PyObject *deque, PyObject *const *args, Py_ssize_t nargs) PyObject *return_value = NULL; PyObject *v; Py_ssize_t start = 0; - Py_ssize_t stop = Py_SIZE(deque); + Py_ssize_t stop = PY_SSIZE_T_MAX; if (!_PyArg_CheckPositional("index", nargs, 1, 3)) { goto exit; @@ -632,4 +632,4 @@ tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) exit: return return_value; } -/*[clinic end generated code: output=b9d4d647c221cb9f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f5a388add99d3d15 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index a06479fa60cdba..f9f53ca5cb5e49 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3123,7 +3123,7 @@ class path_t_converter(CConverter): impl_by_reference = True parse_by_reference = True default_type = () - c_init_default = "" # overridden in pre_render(() + c_init_default = "" # overridden in pre_render() converter = 'path_converter' @@ -3266,7 +3266,7 @@ class confname_converter(CConverter): """, argname=argname, converter=self.converter, table=self.table) [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=d58f18bdf3bd3565]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=ddbf3ac90a981122]*/ /*[clinic input] From fc9c4db1302f8be7527e70cf0938b629985a1d72 Mon Sep 17 00:00:00 2001 From: Jiseok CHOI Date: Thu, 4 Jun 2026 22:41:47 +0900 Subject: [PATCH 6/8] gh-150913: Fix sqlite3.Blob validation for empty slice assignment (GH-150915) ass_subscript_slice() returned early when the computed slice length was zero, bypassing validation performed for non-empty slices. --- Lib/test/test_sqlite3/test_dbapi.py | 12 ++++++++++++ ...26-06-04-21-49-18.gh-issue-150913.EmptyBl.rst | 3 +++ Modules/_sqlite/blob.c | 16 ++++++++++------ 3 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-06-04-21-49-18.gh-issue-150913.EmptyBl.rst diff --git a/Lib/test/test_sqlite3/test_dbapi.py b/Lib/test/test_sqlite3/test_dbapi.py index 73b40e82a96811..5f6cb527955ca1 100644 --- a/Lib/test/test_sqlite3/test_dbapi.py +++ b/Lib/test/test_sqlite3/test_dbapi.py @@ -1400,6 +1400,18 @@ def test_blob_set_empty_slice(self): self.blob[0:0] = b"" self.assertEqual(self.blob[:], self.data) + def test_blob_set_empty_slice_wrong_type(self): + with self.assertRaises(TypeError): + self.blob[5:5] = None + + def test_blob_set_empty_slice_wrong_size(self): + with self.assertRaisesRegex(IndexError, "wrong size"): + self.blob[5:5] = b"123" + + def test_blob_set_empty_slice_correct(self): + self.blob[5:5] = b"" + self.assertEqual(self.blob[:], self.data) + def test_blob_set_slice_with_skip(self): self.blob[0:10:2] = b"12345" actual = self.cx.execute("select b from test").fetchone()[0] diff --git a/Misc/NEWS.d/next/Library/2026-06-04-21-49-18.gh-issue-150913.EmptyBl.rst b/Misc/NEWS.d/next/Library/2026-06-04-21-49-18.gh-issue-150913.EmptyBl.rst new file mode 100644 index 00000000000000..f95a6ee6ee15bf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-04-21-49-18.gh-issue-150913.EmptyBl.rst @@ -0,0 +1,3 @@ +Fix :class:`sqlite3.Blob` slice assignment to raise +:exc:`TypeError` and :exc:`IndexError` for type and size mismatches +respectively, even when the target slice is empty. diff --git a/Modules/_sqlite/blob.c b/Modules/_sqlite/blob.c index 2cc62751054278..d81784409e5d91 100644 --- a/Modules/_sqlite/blob.c +++ b/Modules/_sqlite/blob.c @@ -531,21 +531,25 @@ ass_subscript_slice(pysqlite_Blob *self, PyObject *item, PyObject *value) return -1; } - if (len == 0) { - return 0; - } - Py_buffer vbuf; if (PyObject_GetBuffer(value, &vbuf, PyBUF_SIMPLE) < 0) { return -1; } - int rc = -1; if (vbuf.len != len) { PyErr_SetString(PyExc_IndexError, "Blob slice assignment is wrong size"); + PyBuffer_Release(&vbuf); + return -1; } - else if (step == 1) { + + if (len == 0) { + PyBuffer_Release(&vbuf); + return 0; + } + + int rc = -1; + if (step == 1) { rc = inner_write(self, vbuf.buf, len, start); } else { From ac3694b008e4f9d5d5ea6ff8584078f92f6906ab Mon Sep 17 00:00:00 2001 From: Ivan Marton Date: Thu, 4 Jun 2026 15:50:33 +0200 Subject: [PATCH 7/8] gh-84649: Make TimedRotatingFileHandler use CTIME instead of MTIME (GH-24660) The TimedRotatingFileHandler previously only used st_mtime attribute of the log file to detect whether it has to be rotate yet or not. In cases when the file is changed within the rotatation period the st_mtime is also updated to the current time and the rotation never happens. It's more appropriate to check the file creation time (st_ctime) instead. Whenever available, the more appropriate st_birthtime will be in use. (This feature is available on FreeBSD, MacOS and Windows at the moment.) If the st_mtime would be newer than st_ctime (e.g.: because the inode related to the file has been changed without any file content modification), then the earliest attribute will be used. --- Lib/logging/handlers.py | 11 +++- Lib/test/support/__init__.py | 5 ++ Lib/test/test_logging.py | 50 +++++++++++++++++++ Misc/ACKS | 1 + .../2021-02-26-13-17-57.bpo-40469.yJHeQg.rst | 6 +++ 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2021-02-26-13-17-57.bpo-40469.yJHeQg.rst diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index 575f2babbc4785..73782f53041008 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -282,7 +282,16 @@ def __init__(self, filename, when='h', interval=1, backupCount=0, # path object (see Issue #27493), but self.baseFilename will be a string filename = self.baseFilename if os.path.exists(filename): - t = int(os.stat(filename).st_mtime) + # Use the minimum of file creation and modification time as + # the base of the rollover calculation + stat_result = os.stat(filename) + # Use st_birthtime whenever it is available or use st_ctime + # instead otherwise + try: + creation_time = stat_result.st_birthtime + except AttributeError: + creation_time = stat_result.st_ctime + t = int(min(creation_time, stat_result.st_mtime)) else: t = int(time.time()) self.rolloverAt = self.computeRollover(t) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index cd85ef60a80f4b..84f735c1537efa 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -40,6 +40,7 @@ "has_fork_support", "requires_fork", "has_subprocess_support", "requires_subprocess", "has_socket_support", "requires_working_socket", + "has_st_birthtime", "has_remote_subprocess_debugging", "requires_remote_subprocess_debugging", "anticipate_failure", "load_package_tests", "detect_api_mismatch", "check__all__", "skip_if_buggy_ucrt_strfptime", @@ -620,6 +621,10 @@ def skip_wasi_stack_overflow(): or is_android ) +# At the moment, st_birthtime attribute is only supported on Windows, +# MacOS and FreeBSD. +has_st_birthtime = sys.platform.startswith(("win", "freebsd", "darwin")) + def requires_fork(): return unittest.skipUnless(has_fork_support, "requires working os.fork()") diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 08678119200d42..31c052bfb56cd7 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -6615,6 +6615,56 @@ def test_rollover(self): print(tf.read()) self.assertTrue(found, msg=msg) + @unittest.skipUnless(support.has_st_birthtime, + "st_birthtime not available or supported by Python on this OS") + def test_rollover_based_on_st_birthtime_only(self): + def add_record(message: str) -> None: + fh = logging.handlers.TimedRotatingFileHandler( + self.fn, when='S', interval=4, encoding="utf-8", backupCount=1) + fmt = logging.Formatter('%(asctime)s %(message)s') + fh.setFormatter(fmt) + record = logging.makeLogRecord({'msg': message}) + fh.emit(record) + fh.close() + + add_record('testing - initial') + self.assertLogFile(self.fn) + # Sleep a little over the half of rollover time - and this value + # must be over 2 seconds, since this is the mtime resolution on + # FAT32 filesystems. + time.sleep(2.1) + add_record('testing - update before rollover to renew the st_mtime') + time.sleep(2.1) # a little over the half of rollover time + add_record('testing - new record supposedly in the new file after rollover') + + # At this point, the log file should be rotated if the rotation + # is based on creation time but should be not if it's based on + # creation time. + found = False + now = datetime.datetime.now() + GO_BACK = 5 # seconds + for secs in range(GO_BACK): + prev = now - datetime.timedelta(seconds=secs) + fn = self.fn + prev.strftime(".%Y-%m-%d_%H-%M-%S") + found = os.path.exists(fn) + if found: + self.rmfiles.append(fn) + break + msg = 'No rotated files found, went back %d seconds' % GO_BACK + if not found: + # print additional diagnostics + dn, fn = os.path.split(self.fn) + files = [f for f in os.listdir(dn) if f.startswith(fn)] + print('Test time: %s' % now.strftime("%Y-%m-%d %H-%M-%S"), file=sys.stderr) + print('The only matching files are: %s' % files, file=sys.stderr) + for f in files: + print('Contents of %s:' % f) + path = os.path.join(dn, f) + print(os.stat(path)) + with open(path, 'r') as tf: + print(tf.read()) + self.assertTrue(found, msg=msg) + def test_rollover_at_midnight(self, weekly=False): os_helper.unlink(self.fn) now = datetime.datetime.now() diff --git a/Misc/ACKS b/Misc/ACKS index 14f0db7549534b..71466e0804ae3c 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1226,6 +1226,7 @@ Owen Martin Sidney San Martín Westley Martínez Sébastien Martini +Iván Márton Roger Masse Nick Mathewson Simon Mathieu diff --git a/Misc/NEWS.d/next/Library/2021-02-26-13-17-57.bpo-40469.yJHeQg.rst b/Misc/NEWS.d/next/Library/2021-02-26-13-17-57.bpo-40469.yJHeQg.rst new file mode 100644 index 00000000000000..eab474dfd2ea82 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-02-26-13-17-57.bpo-40469.yJHeQg.rst @@ -0,0 +1,6 @@ +A bug has been fixed that made the ``TimedRotatingFileHandler`` use the +MTIME attribute of the configured log file to to detect whether it has to be +rotated yet or not. In cases when the file was changed within the rotation +period the value of the MTIME was also updated to the current time and as a +result the rotation never happened. The file creation time (CTIME) is used +instead that makes the rotation file modification independent. From 038495db33723849b1c206e1bf7e3af1e1c41f0a Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 4 Jun 2026 15:11:33 +0100 Subject: [PATCH 8/8] GH-148960: Ensure that asserts are ignored if `NDEBUG` is set (#150916) --- Tools/jit/template.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tools/jit/template.c b/Tools/jit/template.c index 72379165f3b610..f1e2e25aaecdad 100644 --- a/Tools/jit/template.c +++ b/Tools/jit/template.c @@ -1,8 +1,10 @@ #include "Python.h" +#ifndef NDEBUG #undef assert #define assert(TEST) ((TEST) ? 0 : _Py_jit_assertion_failure(__LINE__)) +#endif #include "pycore_backoff.h" #include "pycore_call.h" @@ -40,8 +42,10 @@ #include "jit.h" +#ifndef NDEBUG #undef assert #define assert(TEST) ((TEST) ? 0 : _Py_jit_assertion_failure(__LINE__)) +#endif #undef CURRENT_OPERAND0_64 #define CURRENT_OPERAND0_64() (_operand0_64)