diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index ef6c62dca1e124..1018e515724244 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -1079,6 +1079,11 @@ Imports alias(name='z')], level=0)]) + .. versionchanged:: next + + Previously, the ``level`` field was marked as optional in the interface + definition, although the CPython parser always sets this field to an integer. + .. class:: alias(name, asname) diff --git a/Misc/NEWS.d/next/Library/2025-06-25-18-58-12.gh-issue-135959.ZvUHYw.rst b/Misc/NEWS.d/next/Library/2025-06-25-18-58-12.gh-issue-135959.ZvUHYw.rst new file mode 100644 index 00000000000000..4a8524e772131d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-06-25-18-58-12.gh-issue-135959.ZvUHYw.rst @@ -0,0 +1,2 @@ +The ``level`` field on :class:`ast.ImportFrom` is now marked as required. +The parser always sets it to an integer. diff --git a/Parser/Python.asdl b/Parser/Python.asdl index 96f3914b029d4c..8c279882b68c5e 100644 --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -46,7 +46,7 @@ module Python | Assert(expr test, expr? msg) | Import(alias* names) - | ImportFrom(identifier? module, alias* names, int? level) + | ImportFrom(identifier? module, alias* names, int level) | Global(identifier* names) | Nonlocal(identifier* names) diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 660bc598a4862c..ae6fb4c7004cd3 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2302,12 +2302,7 @@ add_ast_annotations(struct ast_state *state) } { PyObject *type = (PyObject *)&PyLong_Type; - type = _Py_union_type_or(type, Py_None); - cond = type != NULL; - if (!cond) { - Py_DECREF(ImportFrom_annotations); - return 0; - } + Py_INCREF(type); cond = PyDict_SetItemString(ImportFrom_annotations, "level", type) == 0; Py_DECREF(type); if (!cond) { @@ -6219,7 +6214,7 @@ init_types(void *arg) " | TryStar(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\n" " | Assert(expr test, expr? msg)\n" " | Import(alias* names)\n" - " | ImportFrom(identifier? module, alias* names, int? level)\n" + " | ImportFrom(identifier? module, alias* names, int level)\n" " | Global(identifier* names)\n" " | Nonlocal(identifier* names)\n" " | Expr(expr value)\n" @@ -6353,12 +6348,10 @@ init_types(void *arg) if (!state->Import_type) return -1; state->ImportFrom_type = make_type(state, "ImportFrom", state->stmt_type, ImportFrom_fields, 3, - "ImportFrom(identifier? module, alias* names, int? level)"); + "ImportFrom(identifier? module, alias* names, int level)"); if (!state->ImportFrom_type) return -1; if (PyObject_SetAttr(state->ImportFrom_type, state->module, Py_None) == -1) return -1; - if (PyObject_SetAttr(state->ImportFrom_type, state->level, Py_None) == -1) - return -1; state->Global_type = make_type(state, "Global", state->stmt_type, Global_fields, 1, "Global(identifier* names)"); @@ -13593,9 +13586,9 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (PyObject_GetOptionalAttr(obj, state->level, &tmp) < 0) { return -1; } - if (tmp == NULL || tmp == Py_None) { - Py_CLEAR(tmp); - level = 0; + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"level\" missing from ImportFrom"); + return -1; } else { int res;
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: