From 74616557012f9750a442ba979d3af4c90b8b696c Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Mon, 11 Mar 2024 09:25:44 +0100 Subject: [PATCH 01/32] Improve repr() of AST nodes --- Parser/asdl_c.py | 163 ++++++++++++++++++++++++++++++++++++++++++++ Python/Python-ast.c | 163 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 326 insertions(+) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 59cc391881ab86..e9621a70b8dbca 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1129,8 +1129,171 @@ def visitModule(self, mod): {NULL} }; +static PyObject * +ast_repr_max_depth(AST_object *self, int depth); + +static PyObject * +ast_repr_list(PyObject *list, int depth) +{ + struct ast_state *state = get_ast_state(); + if (state == NULL) { + return NULL; + } + + Py_ssize_t length = PySequence_Size(list); + if (length == 0) { + return PyObject_Repr(list); + } + + _PyUnicodeWriter writer; + bool is_list = PyList_Check(list); + PyObject *items[2]; + + items[0] = PySequence_GetItem(list, 0); + if (length > 1) { + items[1] = PySequence_GetItem(list, length - 1); + } + + _PyUnicodeWriter_Init(&writer); + + if (_PyUnicodeWriter_WriteChar(&writer, is_list ? '[' : '(') < 0) { + goto error; + } + + for (Py_ssize_t i = 0; i < Py_MIN(length, 2); i++) { + PyObject *item = items[i]; + PyObject *item_repr; + + if (PyType_IsSubtype(Py_TYPE(item), (PyTypeObject *)state->AST_type)) { + item_repr = ast_repr_max_depth((AST_object*)item, depth - 1); + } else { + item_repr = PyObject_Repr(item); + } + if (!item_repr) { + goto error; + } + if (i > 0) { + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { + goto error; + } + } + if (_PyUnicodeWriter_WriteStr(&writer, item_repr) < 0) { + Py_DECREF(item_repr); + goto error; + } + if (i == 0 && length > 2) { + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ...", 5) < 0) { + Py_DECREF(item_repr); + goto error; + } + } + Py_DECREF(item_repr); + } + + if (_PyUnicodeWriter_WriteChar(&writer, is_list ? ']' : ')') < 0) { + goto error; + } + + return _PyUnicodeWriter_Finish(&writer); + +error: + _PyUnicodeWriter_Dealloc(&writer); + return NULL; +} + +static PyObject * +ast_repr_max_depth(AST_object *self, int depth) +{ + struct ast_state *state = get_ast_state(); + if (state == NULL) { + return NULL; + } + + if (depth == 0) { + return PyUnicode_FromFormat("%s(...)", Py_TYPE(self)->tp_name); + } + + int status = Py_ReprEnter((PyObject*)self); + if (status != 0) { + if (status < 0) + return NULL; + return PyUnicode_FromFormat("%s(...)", Py_TYPE(self)->tp_name); + } + + PyObject *fields; + PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields); + Py_ssize_t numfields = PySequence_Size(fields); + + if (numfields == 0) { + Py_ReprLeave((PyObject*)self); + Py_DECREF(fields); + return PyUnicode_FromFormat("%s()", Py_TYPE(self)->tp_name); + } + + PyObject *repr = NULL; + for (Py_ssize_t i = 0; i < numfields; i++) { + PyObject *name = PySequence_GetItem(fields, i); + if (!name) { + goto error; + } + + PyObject *value = PyObject_GetAttr((PyObject*)self, name); + if (!value) { + Py_DECREF(name); + goto error; + } + + PyObject *value_repr; + if (PyList_Check(value) || PyTuple_Check(value)) { + value_repr = ast_repr_list(value, depth); + } else if(PyType_IsSubtype(Py_TYPE(value), (PyTypeObject *)state->AST_type)) { + value_repr = ast_repr_max_depth((AST_object*)value, depth - 1); + } else { + value_repr = PyObject_Repr(value); + } + + if (!value_repr) { + Py_DECREF(name); + Py_DECREF(value); + goto error; + } + + if (i == 0) { + repr = PyUnicode_FromFormat("%U=%U", name, value_repr); + } else { + PyObject *prev_repr = repr; + PyObject *tmp = PyUnicode_FromFormat(", %U=%U", name, value_repr); + repr = PyUnicode_Concat(prev_repr, tmp); + Py_DECREF(prev_repr); + Py_DECREF(tmp); + } + Py_DECREF(name); + Py_DECREF(value); + Py_DECREF(value_repr); + } + + Py_ReprLeave((PyObject*)self); + Py_DECREF(fields); + PyObject *tmp = repr; + repr = PyUnicode_FromFormat("%s(%U)", Py_TYPE(self)->tp_name, repr); + Py_DECREF(tmp); + return repr; + +error: + Py_ReprLeave((PyObject*)self); + Py_DECREF(fields); + return NULL; +} + +static PyObject * +ast_repr(AST_object *self) +{ + return ast_repr_max_depth(self, 2); +} + static PyType_Slot AST_type_slots[] = { {Py_tp_dealloc, ast_dealloc}, + {Py_tp_repr, ast_repr}, {Py_tp_getattro, PyObject_GenericGetAttr}, {Py_tp_setattro, PyObject_GenericSetAttr}, {Py_tp_traverse, ast_traverse}, diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 7b591ddaa29869..9047422089f9d1 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5275,8 +5275,171 @@ static PyGetSetDef ast_type_getsets[] = { {NULL} }; +static PyObject * +ast_repr_max_depth(AST_object *self, int depth); + +static PyObject * +ast_repr_list(PyObject *list, int depth) +{ + struct ast_state *state = get_ast_state(); + if (state == NULL) { + return NULL; + } + + Py_ssize_t length = PySequence_Size(list); + if (length == 0) { + return PyObject_Repr(list); + } + + _PyUnicodeWriter writer; + bool is_list = PyList_Check(list); + PyObject *items[2]; + + items[0] = PySequence_GetItem(list, 0); + if (length > 1) { + items[1] = PySequence_GetItem(list, length - 1); + } + + _PyUnicodeWriter_Init(&writer); + + if (_PyUnicodeWriter_WriteChar(&writer, is_list ? '[' : '(') < 0) { + goto error; + } + + for (Py_ssize_t i = 0; i < Py_MIN(length, 2); i++) { + PyObject *item = items[i]; + PyObject *item_repr; + + if (PyType_IsSubtype(Py_TYPE(item), (PyTypeObject *)state->AST_type)) { + item_repr = ast_repr_max_depth((AST_object*)item, depth - 1); + } else { + item_repr = PyObject_Repr(item); + } + if (!item_repr) { + goto error; + } + if (i > 0) { + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { + goto error; + } + } + if (_PyUnicodeWriter_WriteStr(&writer, item_repr) < 0) { + Py_DECREF(item_repr); + goto error; + } + if (i == 0 && length > 2) { + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ...", 5) < 0) { + Py_DECREF(item_repr); + goto error; + } + } + Py_DECREF(item_repr); + } + + if (_PyUnicodeWriter_WriteChar(&writer, is_list ? ']' : ')') < 0) { + goto error; + } + + return _PyUnicodeWriter_Finish(&writer); + +error: + _PyUnicodeWriter_Dealloc(&writer); + return NULL; +} + +static PyObject * +ast_repr_max_depth(AST_object *self, int depth) +{ + struct ast_state *state = get_ast_state(); + if (state == NULL) { + return NULL; + } + + if (depth == 0) { + return PyUnicode_FromFormat("%s(...)", Py_TYPE(self)->tp_name); + } + + int status = Py_ReprEnter((PyObject*)self); + if (status != 0) { + if (status < 0) + return NULL; + return PyUnicode_FromFormat("%s(...)", Py_TYPE(self)->tp_name); + } + + PyObject *fields; + PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields); + Py_ssize_t numfields = PySequence_Size(fields); + + if (numfields == 0) { + Py_ReprLeave((PyObject*)self); + Py_DECREF(fields); + return PyUnicode_FromFormat("%s()", Py_TYPE(self)->tp_name); + } + + PyObject *repr = NULL; + for (Py_ssize_t i = 0; i < numfields; i++) { + PyObject *name = PySequence_GetItem(fields, i); + if (!name) { + goto error; + } + + PyObject *value = PyObject_GetAttr((PyObject*)self, name); + if (!value) { + Py_DECREF(name); + goto error; + } + + PyObject *value_repr; + if (PyList_Check(value) || PyTuple_Check(value)) { + value_repr = ast_repr_list(value, depth); + } else if(PyType_IsSubtype(Py_TYPE(value), (PyTypeObject *)state->AST_type)) { + value_repr = ast_repr_max_depth((AST_object*)value, depth - 1); + } else { + value_repr = PyObject_Repr(value); + } + + if (!value_repr) { + Py_DECREF(name); + Py_DECREF(value); + goto error; + } + + if (i == 0) { + repr = PyUnicode_FromFormat("%U=%U", name, value_repr); + } else { + PyObject *prev_repr = repr; + PyObject *tmp = PyUnicode_FromFormat(", %U=%U", name, value_repr); + repr = PyUnicode_Concat(prev_repr, tmp); + Py_DECREF(prev_repr); + Py_DECREF(tmp); + } + Py_DECREF(name); + Py_DECREF(value); + Py_DECREF(value_repr); + } + + Py_ReprLeave((PyObject*)self); + Py_DECREF(fields); + PyObject *tmp = repr; + repr = PyUnicode_FromFormat("%s(%U)", Py_TYPE(self)->tp_name, repr); + Py_DECREF(tmp); + return repr; + +error: + Py_ReprLeave((PyObject*)self); + Py_DECREF(fields); + return NULL; +} + +static PyObject * +ast_repr(AST_object *self) +{ + return ast_repr_max_depth(self, 2); +} + static PyType_Slot AST_type_slots[] = { {Py_tp_dealloc, ast_dealloc}, + {Py_tp_repr, ast_repr}, {Py_tp_getattro, PyObject_GenericGetAttr}, {Py_tp_setattro, PyObject_GenericSetAttr}, {Py_tp_traverse, ast_traverse}, From 447261b6467db14fdfc0adabe1f2430141970883 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Tue, 19 Mar 2024 22:21:30 +0100 Subject: [PATCH 02/32] Add news entry --- .../2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst b/Misc/NEWS.d/next/Core and Builtins/2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst new file mode 100644 index 00000000000000..f696a4e30fb89b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst @@ -0,0 +1 @@ +Improve ``repr()`` of AST nodes From 74759bcc3118426bb15d9f1eba36fac02fec1425 Mon Sep 17 00:00:00 2001 From: Tomas R Date: Wed, 20 Mar 2024 19:04:52 +0100 Subject: [PATCH 03/32] Improve news entry Co-authored-by: AN Long --- .../2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst b/Misc/NEWS.d/next/Core and Builtins/2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst index f696a4e30fb89b..25d1e62e8c862b 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst @@ -1 +1 @@ -Improve ``repr()`` of AST nodes +Improve :meth:`repr()` of AST nodes. From 4ffc1fbf90657b14033587433869793a12169c0a Mon Sep 17 00:00:00 2001 From: Tomas R Date: Wed, 20 Mar 2024 19:05:25 +0100 Subject: [PATCH 04/32] Follow PEP7 Co-authored-by: AN Long --- Parser/asdl_c.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index e9621a70b8dbca..80a6c1be433839 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1215,8 +1215,9 @@ def visitModule(self, mod): int status = Py_ReprEnter((PyObject*)self); if (status != 0) { - if (status < 0) + if (status < 0) { return NULL; + } return PyUnicode_FromFormat("%s(...)", Py_TYPE(self)->tp_name); } From 609410059802d6b97d058b5004a916e3878865f7 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Wed, 20 Mar 2024 19:11:26 +0100 Subject: [PATCH 05/32] Fix test --- Lib/test/test_ast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 7cecf319e3638f..3d1a2899e9fce2 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -982,7 +982,7 @@ def test_invalid_sum(self): m = ast.Module([ast.Expr(ast.expr(**pos), **pos)], []) with self.assertRaises(TypeError) as cm: compile(m, "", "exec") - self.assertIn("but got Date: Wed, 20 Mar 2024 19:32:38 +0100 Subject: [PATCH 06/32] Regenerate files --- Python/Python-ast.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 9047422089f9d1..41acff4dc741c1 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5361,8 +5361,9 @@ ast_repr_max_depth(AST_object *self, int depth) int status = Py_ReprEnter((PyObject*)self); if (status != 0) { - if (status < 0) + if (status < 0) { return NULL; + } return PyUnicode_FromFormat("%s(...)", Py_TYPE(self)->tp_name); } From e1b7643df21293aeb0682e787e2d0b70e03ad66d Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 2 May 2024 19:53:33 +0200 Subject: [PATCH 07/32] Fix missing whitespace --- Parser/asdl_c.py | 4 ++-- Python/Python-ast.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index fbcbf556223f1c..b4a8221888d59d 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1224,7 +1224,7 @@ def visitModule(self, mod): return PyUnicode_FromFormat("%s(...)", Py_TYPE(self)->tp_name); } - int status = Py_ReprEnter((PyObject*)self); + int status = Py_ReprEnter((PyObject *)self); if (status != 0) { if (status < 0) { return NULL; @@ -1258,7 +1258,7 @@ def visitModule(self, mod): PyObject *value_repr; if (PyList_Check(value) || PyTuple_Check(value)) { value_repr = ast_repr_list(value, depth); - } else if(PyType_IsSubtype(Py_TYPE(value), (PyTypeObject *)state->AST_type)) { + } else if (PyType_IsSubtype(Py_TYPE(value), (PyTypeObject *)state->AST_type)) { value_repr = ast_repr_max_depth((AST_object*)value, depth - 1); } else { value_repr = PyObject_Repr(value); diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 50b63c1ac10efd..cbb738d0d9665a 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5370,7 +5370,7 @@ ast_repr_max_depth(AST_object *self, int depth) return PyUnicode_FromFormat("%s(...)", Py_TYPE(self)->tp_name); } - int status = Py_ReprEnter((PyObject*)self); + int status = Py_ReprEnter((PyObject *)self); if (status != 0) { if (status < 0) { return NULL; @@ -5404,7 +5404,7 @@ ast_repr_max_depth(AST_object *self, int depth) PyObject *value_repr; if (PyList_Check(value) || PyTuple_Check(value)) { value_repr = ast_repr_list(value, depth); - } else if(PyType_IsSubtype(Py_TYPE(value), (PyTypeObject *)state->AST_type)) { + } else if (PyType_IsSubtype(Py_TYPE(value), (PyTypeObject *)state->AST_type)) { value_repr = ast_repr_max_depth((AST_object*)value, depth - 1); } else { value_repr = PyObject_Repr(value); From 0308982abc45a511388f7286b03eff47df0ed9c8 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 2 May 2024 19:57:51 +0200 Subject: [PATCH 08/32] Check return values --- Parser/asdl_c.py | 21 +++++++++++++++++++-- Python/Python-ast.c | 21 +++++++++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index b4a8221888d59d..c405e21ab93fb6 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1152,7 +1152,9 @@ def visitModule(self, mod): } Py_ssize_t length = PySequence_Size(list); - if (length == 0) { + if (length < 0) { + return NULL; + } else if (length == 0) { return PyObject_Repr(list); } @@ -1161,8 +1163,14 @@ def visitModule(self, mod): PyObject *items[2]; items[0] = PySequence_GetItem(list, 0); + if (!items[0]) { + return NULL; + } if (length > 1) { items[1] = PySequence_GetItem(list, length - 1); + if (!items[1]) { + return NULL; + } } _PyUnicodeWriter_Init(&writer); @@ -1233,8 +1241,17 @@ def visitModule(self, mod): } PyObject *fields; - PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields); + if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) == -1) { + Py_ReprLeave((PyObject*)self); + return NULL; + } + Py_ssize_t numfields = PySequence_Size(fields); + if (numfields < 0) { + Py_ReprLeave((PyObject*)self); + Py_DECREF(fields); + return NULL; + } if (numfields == 0) { Py_ReprLeave((PyObject*)self); diff --git a/Python/Python-ast.c b/Python/Python-ast.c index cbb738d0d9665a..2739ebc15ecdbd 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5298,7 +5298,9 @@ ast_repr_list(PyObject *list, int depth) } Py_ssize_t length = PySequence_Size(list); - if (length == 0) { + if (length < 0) { + return NULL; + } else if (length == 0) { return PyObject_Repr(list); } @@ -5307,8 +5309,14 @@ ast_repr_list(PyObject *list, int depth) PyObject *items[2]; items[0] = PySequence_GetItem(list, 0); + if (!items[0]) { + return NULL; + } if (length > 1) { items[1] = PySequence_GetItem(list, length - 1); + if (!items[1]) { + return NULL; + } } _PyUnicodeWriter_Init(&writer); @@ -5379,8 +5387,17 @@ ast_repr_max_depth(AST_object *self, int depth) } PyObject *fields; - PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields); + if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) == -1) { + Py_ReprLeave((PyObject*)self); + return NULL; + } + Py_ssize_t numfields = PySequence_Size(fields); + if (numfields < 0) { + Py_ReprLeave((PyObject*)self); + Py_DECREF(fields); + return NULL; + } if (numfields == 0) { Py_ReprLeave((PyObject*)self); From 3f2bf3f5e0f0440fa7712e82e3320be2611a3519 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 2 May 2024 20:10:16 +0200 Subject: [PATCH 09/32] Check for retval < 0 rather than == -1 --- Parser/asdl_c.py | 2 +- Python/Python-ast.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index c405e21ab93fb6..d32b013b931624 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1241,7 +1241,7 @@ def visitModule(self, mod): } PyObject *fields; - if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) == -1) { + if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) < 0) { Py_ReprLeave((PyObject*)self); return NULL; } diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 2739ebc15ecdbd..069ae7aaebeff5 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5387,7 +5387,7 @@ ast_repr_max_depth(AST_object *self, int depth) } PyObject *fields; - if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) == -1) { + if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) < 0) { Py_ReprLeave((PyObject*)self); return NULL; } From 4386a5ab8191056e3bb937c40fcff3be397d99b2 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 2 May 2024 20:12:48 +0200 Subject: [PATCH 10/32] Fix missing whitespace --- Parser/asdl_c.py | 14 +++++++------- Python/Python-ast.c | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index d32b013b931624..bbdbeb814bf6e9 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1241,20 +1241,20 @@ def visitModule(self, mod): } PyObject *fields; - if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) < 0) { - Py_ReprLeave((PyObject*)self); + if (PyObject_GetOptionalAttr((PyObject *)Py_TYPE(self), state->_fields, &fields) < 0) { + Py_ReprLeave((PyObject *)self); return NULL; } Py_ssize_t numfields = PySequence_Size(fields); if (numfields < 0) { - Py_ReprLeave((PyObject*)self); + Py_ReprLeave((PyObject *)self); Py_DECREF(fields); return NULL; } if (numfields == 0) { - Py_ReprLeave((PyObject*)self); + Py_ReprLeave((PyObject *)self); Py_DECREF(fields); return PyUnicode_FromFormat("%s()", Py_TYPE(self)->tp_name); } @@ -1266,7 +1266,7 @@ def visitModule(self, mod): goto error; } - PyObject *value = PyObject_GetAttr((PyObject*)self, name); + PyObject *value = PyObject_GetAttr((PyObject *)self, name); if (!value) { Py_DECREF(name); goto error; @@ -1301,7 +1301,7 @@ def visitModule(self, mod): Py_DECREF(value_repr); } - Py_ReprLeave((PyObject*)self); + Py_ReprLeave((PyObject *)self); Py_DECREF(fields); PyObject *tmp = repr; repr = PyUnicode_FromFormat("%s(%U)", Py_TYPE(self)->tp_name, repr); @@ -1309,7 +1309,7 @@ def visitModule(self, mod): return repr; error: - Py_ReprLeave((PyObject*)self); + Py_ReprLeave((PyObject *)self); Py_DECREF(fields); return NULL; } diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 069ae7aaebeff5..31eadd71f10581 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5387,20 +5387,20 @@ ast_repr_max_depth(AST_object *self, int depth) } PyObject *fields; - if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) < 0) { - Py_ReprLeave((PyObject*)self); + if (PyObject_GetOptionalAttr((PyObject *)Py_TYPE(self), state->_fields, &fields) < 0) { + Py_ReprLeave((PyObject *)self); return NULL; } Py_ssize_t numfields = PySequence_Size(fields); if (numfields < 0) { - Py_ReprLeave((PyObject*)self); + Py_ReprLeave((PyObject *)self); Py_DECREF(fields); return NULL; } if (numfields == 0) { - Py_ReprLeave((PyObject*)self); + Py_ReprLeave((PyObject *)self); Py_DECREF(fields); return PyUnicode_FromFormat("%s()", Py_TYPE(self)->tp_name); } @@ -5412,7 +5412,7 @@ ast_repr_max_depth(AST_object *self, int depth) goto error; } - PyObject *value = PyObject_GetAttr((PyObject*)self, name); + PyObject *value = PyObject_GetAttr((PyObject *)self, name); if (!value) { Py_DECREF(name); goto error; @@ -5447,7 +5447,7 @@ ast_repr_max_depth(AST_object *self, int depth) Py_DECREF(value_repr); } - Py_ReprLeave((PyObject*)self); + Py_ReprLeave((PyObject *)self); Py_DECREF(fields); PyObject *tmp = repr; repr = PyUnicode_FromFormat("%s(%U)", Py_TYPE(self)->tp_name, repr); @@ -5455,7 +5455,7 @@ ast_repr_max_depth(AST_object *self, int depth) return repr; error: - Py_ReprLeave((PyObject*)self); + Py_ReprLeave((PyObject *)self); Py_DECREF(fields); return NULL; } From af3b2a37c4a085f47b4820cfc447b6c6af59442e Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 2 May 2024 20:25:28 +0200 Subject: [PATCH 11/32] Simplify code --- Parser/asdl_c.py | 7 +++---- Python/Python-ast.c | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index bbdbeb814bf6e9..c8a5ebd574a57b 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1303,10 +1303,9 @@ def visitModule(self, mod): Py_ReprLeave((PyObject *)self); Py_DECREF(fields); - PyObject *tmp = repr; - repr = PyUnicode_FromFormat("%s(%U)", Py_TYPE(self)->tp_name, repr); - Py_DECREF(tmp); - return repr; + PyObject *ret = PyUnicode_FromFormat("%s(%U)", Py_TYPE(self)->tp_name, repr); + Py_DECREF(repr); + return ret; error: Py_ReprLeave((PyObject *)self); diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 31eadd71f10581..31f8da521833d0 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5449,10 +5449,9 @@ ast_repr_max_depth(AST_object *self, int depth) Py_ReprLeave((PyObject *)self); Py_DECREF(fields); - PyObject *tmp = repr; - repr = PyUnicode_FromFormat("%s(%U)", Py_TYPE(self)->tp_name, repr); - Py_DECREF(tmp); - return repr; + PyObject *ret = PyUnicode_FromFormat("%s(%U)", Py_TYPE(self)->tp_name, repr); + Py_DECREF(repr); + return ret; error: Py_ReprLeave((PyObject *)self); From 1aaa1c000a1d4dc51bda404f2908b79464239476 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Mon, 3 Jun 2024 03:36:41 -0700 Subject: [PATCH 12/32] Update Parser/asdl_c.py --- Parser/asdl_c.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index c8a5ebd574a57b..ace06253bcd9e3 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1228,7 +1228,7 @@ def visitModule(self, mod): return NULL; } - if (depth == 0) { + if (depth <= 0) { return PyUnicode_FromFormat("%s(...)", Py_TYPE(self)->tp_name); } From df70943d77daa0214ab40c47377ca33334e761bc Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Wed, 10 Jul 2024 22:09:40 +0200 Subject: [PATCH 13/32] Fix leaked references --- Parser/asdl_c.py | 7 ++++++- Python/Python-ast.c | 9 +++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index f201154be157cf..69a9eb8aead77a 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1170,7 +1170,7 @@ def visitModule(self, mod): _PyUnicodeWriter writer; bool is_list = PyList_Check(list); - PyObject *items[2]; + PyObject *items[2] = {NULL, NULL}; items[0] = PySequence_GetItem(list, 0); if (!items[0]) { @@ -1179,6 +1179,7 @@ def visitModule(self, mod): if (length > 1) { items[1] = PySequence_GetItem(list, length - 1); if (!items[1]) { + Py_DECREF(items[0]); return NULL; } } @@ -1223,9 +1224,13 @@ def visitModule(self, mod): goto error; } + Py_XDECREF(items[0]); + Py_XDECREF(items[1]); return _PyUnicodeWriter_Finish(&writer); error: + Py_XDECREF(items[0]); + Py_XDECREF(items[1]); _PyUnicodeWriter_Dealloc(&writer); return NULL; } diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 1dca17b8ee8f06..fb257a8e357448 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5369,7 +5369,7 @@ ast_repr_list(PyObject *list, int depth) _PyUnicodeWriter writer; bool is_list = PyList_Check(list); - PyObject *items[2]; + PyObject *items[2] = {NULL, NULL}; items[0] = PySequence_GetItem(list, 0); if (!items[0]) { @@ -5378,6 +5378,7 @@ ast_repr_list(PyObject *list, int depth) if (length > 1) { items[1] = PySequence_GetItem(list, length - 1); if (!items[1]) { + Py_DECREF(items[0]); return NULL; } } @@ -5422,9 +5423,13 @@ ast_repr_list(PyObject *list, int depth) goto error; } + Py_XDECREF(items[0]); + Py_XDECREF(items[1]); return _PyUnicodeWriter_Finish(&writer); error: + Py_XDECREF(items[0]); + Py_XDECREF(items[1]); _PyUnicodeWriter_Dealloc(&writer); return NULL; } @@ -5437,7 +5442,7 @@ ast_repr_max_depth(AST_object *self, int depth) return NULL; } - if (depth == 0) { + if (depth <= 0) { return PyUnicode_FromFormat("%s(...)", Py_TYPE(self)->tp_name); } From ed89975e69ee2d8e062751465a02f953e7b9d56c Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Wed, 10 Jul 2024 22:21:59 +0200 Subject: [PATCH 14/32] Add an assertion --- Parser/asdl_c.py | 5 +++-- Python/Python-ast.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 69a9eb8aead77a..a702df32e62687 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1156,6 +1156,8 @@ def visitModule(self, mod): static PyObject * ast_repr_list(PyObject *list, int depth) { + assert(PyList_Check(list) || PyTuple_Check(list)); + struct ast_state *state = get_ast_state(); if (state == NULL) { return NULL; @@ -1169,7 +1171,6 @@ def visitModule(self, mod): } _PyUnicodeWriter writer; - bool is_list = PyList_Check(list); PyObject *items[2] = {NULL, NULL}; items[0] = PySequence_GetItem(list, 0); @@ -1185,7 +1186,7 @@ def visitModule(self, mod): } _PyUnicodeWriter_Init(&writer); - + bool is_list = PyList_Check(list); if (_PyUnicodeWriter_WriteChar(&writer, is_list ? '[' : '(') < 0) { goto error; } diff --git a/Python/Python-ast.c b/Python/Python-ast.c index fb257a8e357448..12a24b57d6a2bd 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5355,6 +5355,8 @@ ast_repr_max_depth(AST_object *self, int depth); static PyObject * ast_repr_list(PyObject *list, int depth) { + assert(PyList_Check(list) || PyTuple_Check(list)); + struct ast_state *state = get_ast_state(); if (state == NULL) { return NULL; @@ -5368,7 +5370,6 @@ ast_repr_list(PyObject *list, int depth) } _PyUnicodeWriter writer; - bool is_list = PyList_Check(list); PyObject *items[2] = {NULL, NULL}; items[0] = PySequence_GetItem(list, 0); @@ -5384,7 +5385,7 @@ ast_repr_list(PyObject *list, int depth) } _PyUnicodeWriter_Init(&writer); - + bool is_list = PyList_Check(list); if (_PyUnicodeWriter_WriteChar(&writer, is_list ? '[' : '(') < 0) { goto error; } From d8b3bff9cd2cc973544834c25cad984955fb026a Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Wed, 10 Jul 2024 22:25:45 +0200 Subject: [PATCH 15/32] Simplify code --- Parser/asdl_c.py | 7 +++---- Python/Python-ast.c | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index a702df32e62687..586c6fbf5eb9f1 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1171,21 +1171,20 @@ def visitModule(self, mod): } _PyUnicodeWriter writer; + _PyUnicodeWriter_Init(&writer); PyObject *items[2] = {NULL, NULL}; items[0] = PySequence_GetItem(list, 0); if (!items[0]) { - return NULL; + goto error; } if (length > 1) { items[1] = PySequence_GetItem(list, length - 1); if (!items[1]) { - Py_DECREF(items[0]); - return NULL; + goto error; } } - _PyUnicodeWriter_Init(&writer); bool is_list = PyList_Check(list); if (_PyUnicodeWriter_WriteChar(&writer, is_list ? '[' : '(') < 0) { goto error; diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 12a24b57d6a2bd..4b6071ddec29c2 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5370,21 +5370,20 @@ ast_repr_list(PyObject *list, int depth) } _PyUnicodeWriter writer; + _PyUnicodeWriter_Init(&writer); PyObject *items[2] = {NULL, NULL}; items[0] = PySequence_GetItem(list, 0); if (!items[0]) { - return NULL; + goto error; } if (length > 1) { items[1] = PySequence_GetItem(list, length - 1); if (!items[1]) { - Py_DECREF(items[0]); - return NULL; + goto error; } } - _PyUnicodeWriter_Init(&writer); bool is_list = PyList_Check(list); if (_PyUnicodeWriter_WriteChar(&writer, is_list ? '[' : '(') < 0) { goto error; From cfd6cdfbe722558021892663af189028b5db1ead Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Wed, 10 Jul 2024 22:57:36 +0200 Subject: [PATCH 16/32] Add tests --- Lib/test/test_ast.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index f42e13c8e4b42e..a77a0bcbc4d672 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -9,6 +9,7 @@ import types import unittest import weakref +from pathlib import Path from textwrap import dedent try: import _testinternalcapi @@ -1025,6 +1026,31 @@ def test_none_checks(self) -> None: for node, attr, source in tests: self.assert_none_check(node, attr, source) + def test_repr(self): + const_1 = ast.Constant(1) + const_2 = ast.Constant(2) + self.assertEqual(repr(const_1), "Constant(value=1, kind=None)") + + add = ast.BinOp(op=ast.Add(), left=const_1, right=const_2) + self.assertEqual(repr(add), + "BinOp(left=Constant(value=1, kind=None), op=Add(), right=Constant(value=2, kind=None))") + + self.assertEqual(repr(ast.parse("x = 3")), + "Module(body=[Assign(targets=[Name(...)], value=Constant(...), type_comment=None)], " + "type_ignores=[])") + + self.assertEqual(repr(ast.parse("x=7; y=4; c,z=3,4")), + "Module(body=[Assign(targets=[Name(...)], value=Constant(...), type_comment=None), ..., " + "Assign(targets=[Tuple(...)], value=Tuple(...), type_comment=None)], type_ignores=[])") + + self.assertEqual(repr(ast.parse("def foo(): pass")), + "Module(body=[FunctionDef(name='foo', args=arguments(...), body=[Pass(...)], " + "decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[])") + + this_module = ast.parse(Path(__file__).read_text()) + self.assertEqual(repr(this_module), + "Module(body=[Import(names=[alias(...)]), ..., Expr(value=Call(...))], type_ignores=[])") + class ASTHelpers_Test(unittest.TestCase): maxDiff = None From f022378fbf1fb285150a4499a4a500816b8f3c25 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 11 Jul 2024 09:41:25 +0200 Subject: [PATCH 17/32] Use PyUnicodeWriter instead of string concatenation --- Parser/asdl_c.py | 27 ++++++++++++++------------- Python/Python-ast.c | 27 ++++++++++++++------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 586c6fbf5eb9f1..31ea1271c3c903 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1274,7 +1274,11 @@ def visitModule(self, mod): return PyUnicode_FromFormat("%s()", Py_TYPE(self)->tp_name); } - PyObject *repr = NULL; + const char* tp_name = Py_TYPE(self)->tp_name; + _PyUnicodeWriter writer; + _PyUnicodeWriter_Init(&writer); + _PyUnicodeWriter_WriteASCIIString(&writer, tp_name, strlen(tp_name)); + _PyUnicodeWriter_WriteChar(&writer, '('); for (Py_ssize_t i = 0; i < numfields; i++) { PyObject *name = PySequence_GetItem(fields, i); if (!name) { @@ -1302,29 +1306,26 @@ def visitModule(self, mod): goto error; } - if (i == 0) { - repr = PyUnicode_FromFormat("%U=%U", name, value_repr); - } else { - PyObject *prev_repr = repr; - PyObject *tmp = PyUnicode_FromFormat(", %U=%U", name, value_repr); - repr = PyUnicode_Concat(prev_repr, tmp); - Py_DECREF(prev_repr); - Py_DECREF(tmp); + if (i > 0) { + _PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2); } + _PyUnicodeWriter_WriteStr(&writer, name); + _PyUnicodeWriter_WriteChar(&writer, '='); + _PyUnicodeWriter_WriteStr(&writer, value_repr); + Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); } - + _PyUnicodeWriter_WriteChar(&writer, ')'); Py_ReprLeave((PyObject *)self); Py_DECREF(fields); - PyObject *ret = PyUnicode_FromFormat("%s(%U)", Py_TYPE(self)->tp_name, repr); - Py_DECREF(repr); - return ret; + return _PyUnicodeWriter_Finish(&writer); error: Py_ReprLeave((PyObject *)self); Py_DECREF(fields); + _PyUnicodeWriter_Dealloc(&writer); return NULL; } diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 4b6071ddec29c2..bcc0e19f93ef04 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5473,7 +5473,11 @@ ast_repr_max_depth(AST_object *self, int depth) return PyUnicode_FromFormat("%s()", Py_TYPE(self)->tp_name); } - PyObject *repr = NULL; + const char* tp_name = Py_TYPE(self)->tp_name; + _PyUnicodeWriter writer; + _PyUnicodeWriter_Init(&writer); + _PyUnicodeWriter_WriteASCIIString(&writer, tp_name, strlen(tp_name)); + _PyUnicodeWriter_WriteChar(&writer, '('); for (Py_ssize_t i = 0; i < numfields; i++) { PyObject *name = PySequence_GetItem(fields, i); if (!name) { @@ -5501,29 +5505,26 @@ ast_repr_max_depth(AST_object *self, int depth) goto error; } - if (i == 0) { - repr = PyUnicode_FromFormat("%U=%U", name, value_repr); - } else { - PyObject *prev_repr = repr; - PyObject *tmp = PyUnicode_FromFormat(", %U=%U", name, value_repr); - repr = PyUnicode_Concat(prev_repr, tmp); - Py_DECREF(prev_repr); - Py_DECREF(tmp); + if (i > 0) { + _PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2); } + _PyUnicodeWriter_WriteStr(&writer, name); + _PyUnicodeWriter_WriteChar(&writer, '='); + _PyUnicodeWriter_WriteStr(&writer, value_repr); + Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); } - + _PyUnicodeWriter_WriteChar(&writer, ')'); Py_ReprLeave((PyObject *)self); Py_DECREF(fields); - PyObject *ret = PyUnicode_FromFormat("%s(%U)", Py_TYPE(self)->tp_name, repr); - Py_DECREF(repr); - return ret; + return _PyUnicodeWriter_Finish(&writer); error: Py_ReprLeave((PyObject *)self); Py_DECREF(fields); + _PyUnicodeWriter_Dealloc(&writer); return NULL; } From 0f916cce6d87e1f7aa642c4d85bbdea72a2909b2 Mon Sep 17 00:00:00 2001 From: Tomas R Date: Thu, 11 Jul 2024 13:44:12 +0200 Subject: [PATCH 18/32] Improve news entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- .../2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst b/Misc/NEWS.d/next/Core and Builtins/2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst index 25d1e62e8c862b..659ffb289129e2 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2024-03-19-22-21-22.gh-issue-116022.iyHENN.rst @@ -1 +1 @@ -Improve :meth:`repr()` of AST nodes. +Improve the :meth:`~object.__repr__` output of :class:`~ast.AST` nodes. From e2b0415c68e2d44e6f4c783da96f3dac509e88ab Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 11 Jul 2024 13:46:22 +0200 Subject: [PATCH 19/32] PEP7 fixes --- Parser/asdl_c.py | 9 ++++++--- Python/Python-ast.c | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 31ea1271c3c903..7cd0a5efab932a 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1166,7 +1166,8 @@ def visitModule(self, mod): Py_ssize_t length = PySequence_Size(list); if (length < 0) { return NULL; - } else if (length == 0) { + } + else if (length == 0) { return PyObject_Repr(list); } @@ -1294,9 +1295,11 @@ def visitModule(self, mod): PyObject *value_repr; if (PyList_Check(value) || PyTuple_Check(value)) { value_repr = ast_repr_list(value, depth); - } else if (PyType_IsSubtype(Py_TYPE(value), (PyTypeObject *)state->AST_type)) { + } + else if (PyType_IsSubtype(Py_TYPE(value), (PyTypeObject *)state->AST_type)) { value_repr = ast_repr_max_depth((AST_object*)value, depth - 1); - } else { + } + else { value_repr = PyObject_Repr(value); } diff --git a/Python/Python-ast.c b/Python/Python-ast.c index bcc0e19f93ef04..2be0909790ccc6 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5365,7 +5365,8 @@ ast_repr_list(PyObject *list, int depth) Py_ssize_t length = PySequence_Size(list); if (length < 0) { return NULL; - } else if (length == 0) { + } + else if (length == 0) { return PyObject_Repr(list); } @@ -5493,9 +5494,11 @@ ast_repr_max_depth(AST_object *self, int depth) PyObject *value_repr; if (PyList_Check(value) || PyTuple_Check(value)) { value_repr = ast_repr_list(value, depth); - } else if (PyType_IsSubtype(Py_TYPE(value), (PyTypeObject *)state->AST_type)) { + } + else if (PyType_IsSubtype(Py_TYPE(value), (PyTypeObject *)state->AST_type)) { value_repr = ast_repr_max_depth((AST_object*)value, depth - 1); - } else { + } + else { value_repr = PyObject_Repr(value); } From b06c8a4726a0421dbdc0d719ff8dd86a1bce2594 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 11 Jul 2024 15:54:30 +0200 Subject: [PATCH 20/32] Use the public Unicode Writer API where possible --- Parser/asdl_c.py | 44 ++++++++++++++++++++++++-------------------- Python/Python-ast.c | 44 ++++++++++++++++++++++++-------------------- 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 019681c3120ac6..d144607f205989 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1445,8 +1445,10 @@ def visitModule(self, mod): return PyObject_Repr(list); } - _PyUnicodeWriter writer; - _PyUnicodeWriter_Init(&writer); + PyUnicodeWriter *writer = PyUnicodeWriter_Create(0); + if (writer == NULL) { + return NULL; + } PyObject *items[2] = {NULL, NULL}; items[0] = PySequence_GetItem(list, 0); @@ -1461,7 +1463,7 @@ def visitModule(self, mod): } bool is_list = PyList_Check(list); - if (_PyUnicodeWriter_WriteChar(&writer, is_list ? '[' : '(') < 0) { + if (PyUnicodeWriter_WriteChar(writer, is_list ? '[' : '(') < 0) { goto error; } @@ -1478,16 +1480,16 @@ def visitModule(self, mod): goto error; } if (i > 0) { - if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { + if (_PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, ", ", 2) < 0) { goto error; } } - if (_PyUnicodeWriter_WriteStr(&writer, item_repr) < 0) { + if (PyUnicodeWriter_WriteStr(writer, item_repr) < 0) { Py_DECREF(item_repr); goto error; } if (i == 0 && length > 2) { - if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ...", 5) < 0) { + if (_PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, ", ...", 5) < 0) { Py_DECREF(item_repr); goto error; } @@ -1495,18 +1497,18 @@ def visitModule(self, mod): Py_DECREF(item_repr); } - if (_PyUnicodeWriter_WriteChar(&writer, is_list ? ']' : ')') < 0) { + if (PyUnicodeWriter_WriteChar(writer, is_list ? ']' : ')') < 0) { goto error; } Py_XDECREF(items[0]); Py_XDECREF(items[1]); - return _PyUnicodeWriter_Finish(&writer); + return PyUnicodeWriter_Finish(writer); error: Py_XDECREF(items[0]); Py_XDECREF(items[1]); - _PyUnicodeWriter_Dealloc(&writer); + PyUnicodeWriter_Discard(writer); return NULL; } @@ -1550,10 +1552,12 @@ def visitModule(self, mod): } const char* tp_name = Py_TYPE(self)->tp_name; - _PyUnicodeWriter writer; - _PyUnicodeWriter_Init(&writer); - _PyUnicodeWriter_WriteASCIIString(&writer, tp_name, strlen(tp_name)); - _PyUnicodeWriter_WriteChar(&writer, '('); + PyUnicodeWriter *writer = PyUnicodeWriter_Create(0); + if (writer == NULL) { + return NULL; + } + _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, tp_name, strlen(tp_name)); + PyUnicodeWriter_WriteChar(writer, '('); for (Py_ssize_t i = 0; i < numfields; i++) { PyObject *name = PySequence_GetItem(fields, i); if (!name) { @@ -1584,25 +1588,25 @@ def visitModule(self, mod): } if (i > 0) { - _PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2); + _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, ", ", 2); } - _PyUnicodeWriter_WriteStr(&writer, name); - _PyUnicodeWriter_WriteChar(&writer, '='); - _PyUnicodeWriter_WriteStr(&writer, value_repr); + PyUnicodeWriter_WriteStr(writer, name); + PyUnicodeWriter_WriteChar(writer, '='); + PyUnicodeWriter_WriteStr(writer, value_repr); Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); } - _PyUnicodeWriter_WriteChar(&writer, ')'); + PyUnicodeWriter_WriteChar(writer, ')'); Py_ReprLeave((PyObject *)self); Py_DECREF(fields); - return _PyUnicodeWriter_Finish(&writer); + return PyUnicodeWriter_Finish(writer); error: Py_ReprLeave((PyObject *)self); Py_DECREF(fields); - _PyUnicodeWriter_Dealloc(&writer); + PyUnicodeWriter_Discard(writer); return NULL; } diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 3a8f25ff1eeb34..a2806e3e3f8960 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5646,8 +5646,10 @@ ast_repr_list(PyObject *list, int depth) return PyObject_Repr(list); } - _PyUnicodeWriter writer; - _PyUnicodeWriter_Init(&writer); + PyUnicodeWriter *writer = PyUnicodeWriter_Create(0); + if (writer == NULL) { + return NULL; + } PyObject *items[2] = {NULL, NULL}; items[0] = PySequence_GetItem(list, 0); @@ -5662,7 +5664,7 @@ ast_repr_list(PyObject *list, int depth) } bool is_list = PyList_Check(list); - if (_PyUnicodeWriter_WriteChar(&writer, is_list ? '[' : '(') < 0) { + if (PyUnicodeWriter_WriteChar(writer, is_list ? '[' : '(') < 0) { goto error; } @@ -5679,16 +5681,16 @@ ast_repr_list(PyObject *list, int depth) goto error; } if (i > 0) { - if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { + if (_PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, ", ", 2) < 0) { goto error; } } - if (_PyUnicodeWriter_WriteStr(&writer, item_repr) < 0) { + if (PyUnicodeWriter_WriteStr(writer, item_repr) < 0) { Py_DECREF(item_repr); goto error; } if (i == 0 && length > 2) { - if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ...", 5) < 0) { + if (_PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, ", ...", 5) < 0) { Py_DECREF(item_repr); goto error; } @@ -5696,18 +5698,18 @@ ast_repr_list(PyObject *list, int depth) Py_DECREF(item_repr); } - if (_PyUnicodeWriter_WriteChar(&writer, is_list ? ']' : ')') < 0) { + if (PyUnicodeWriter_WriteChar(writer, is_list ? ']' : ')') < 0) { goto error; } Py_XDECREF(items[0]); Py_XDECREF(items[1]); - return _PyUnicodeWriter_Finish(&writer); + return PyUnicodeWriter_Finish(writer); error: Py_XDECREF(items[0]); Py_XDECREF(items[1]); - _PyUnicodeWriter_Dealloc(&writer); + PyUnicodeWriter_Discard(writer); return NULL; } @@ -5751,10 +5753,12 @@ ast_repr_max_depth(AST_object *self, int depth) } const char* tp_name = Py_TYPE(self)->tp_name; - _PyUnicodeWriter writer; - _PyUnicodeWriter_Init(&writer); - _PyUnicodeWriter_WriteASCIIString(&writer, tp_name, strlen(tp_name)); - _PyUnicodeWriter_WriteChar(&writer, '('); + PyUnicodeWriter *writer = PyUnicodeWriter_Create(0); + if (writer == NULL) { + return NULL; + } + _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, tp_name, strlen(tp_name)); + PyUnicodeWriter_WriteChar(writer, '('); for (Py_ssize_t i = 0; i < numfields; i++) { PyObject *name = PySequence_GetItem(fields, i); if (!name) { @@ -5785,25 +5789,25 @@ ast_repr_max_depth(AST_object *self, int depth) } if (i > 0) { - _PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2); + _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, ", ", 2); } - _PyUnicodeWriter_WriteStr(&writer, name); - _PyUnicodeWriter_WriteChar(&writer, '='); - _PyUnicodeWriter_WriteStr(&writer, value_repr); + PyUnicodeWriter_WriteStr(writer, name); + PyUnicodeWriter_WriteChar(writer, '='); + PyUnicodeWriter_WriteStr(writer, value_repr); Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); } - _PyUnicodeWriter_WriteChar(&writer, ')'); + PyUnicodeWriter_WriteChar(writer, ')'); Py_ReprLeave((PyObject *)self); Py_DECREF(fields); - return _PyUnicodeWriter_Finish(&writer); + return PyUnicodeWriter_Finish(writer); error: Py_ReprLeave((PyObject *)self); Py_DECREF(fields); - _PyUnicodeWriter_Dealloc(&writer); + PyUnicodeWriter_Discard(writer); return NULL; } From 32a516980565a9173828a7806c081f0786e1059a Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 11 Jul 2024 16:00:31 +0200 Subject: [PATCH 21/32] Increase max depth to 3 --- Lib/test/test_ast.py | 19 ++++++++++++------- Parser/asdl_c.py | 2 +- Python/Python-ast.c | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 138488914b5086..57259c2b4fdb1a 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -1156,20 +1156,25 @@ def test_repr(self): "BinOp(left=Constant(value=1, kind=None), op=Add(), right=Constant(value=2, kind=None))") self.assertEqual(repr(ast.parse("x = 3")), - "Module(body=[Assign(targets=[Name(...)], value=Constant(...), type_comment=None)], " - "type_ignores=[])") + "Module(body=[Assign(targets=[Name(id='x', ctx=Store(...))], " + "value=Constant(value=3, kind=None), type_comment=None)], type_ignores=[])") self.assertEqual(repr(ast.parse("x=7; y=4; c,z=3,4")), - "Module(body=[Assign(targets=[Name(...)], value=Constant(...), type_comment=None), ..., " - "Assign(targets=[Tuple(...)], value=Tuple(...), type_comment=None)], type_ignores=[])") + "Module(body=[Assign(targets=[Name(id='x', ctx=Store(...))], " + "value=Constant(value=7, kind=None), type_comment=None), ..., " + "Assign(targets=[Tuple(elts=[Name(...), Name(...)], ctx=Store(...))], " + "value=Tuple(elts=[Constant(...), Constant(...)], ctx=Load(...)), type_comment=None)], " + "type_ignores=[])") self.assertEqual(repr(ast.parse("def foo(): pass")), - "Module(body=[FunctionDef(name='foo', args=arguments(...), body=[Pass(...)], " - "decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[])") + "Module(body=[FunctionDef(name='foo', args=arguments(posonlyargs=[], args=[], vararg=None, " + "kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], " + "returns=None, type_comment=None, type_params=[])], type_ignores=[])") this_module = ast.parse(Path(__file__).read_text()) self.assertEqual(repr(this_module), - "Module(body=[Import(names=[alias(...)]), ..., Expr(value=Call(...))], type_ignores=[])") + "Module(body=[Import(names=[alias(name='ast', asname=None)]), ..., " + "Expr(value=Call(func=Name(...), args=[], keywords=[]))], type_ignores=[])") class CopyTests(unittest.TestCase): diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index d144607f205989..74729a933762ad 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1613,7 +1613,7 @@ def visitModule(self, mod): static PyObject * ast_repr(AST_object *self) { - return ast_repr_max_depth(self, 2); + return ast_repr_max_depth(self, 3); } static PyType_Slot AST_type_slots[] = { diff --git a/Python/Python-ast.c b/Python/Python-ast.c index a2806e3e3f8960..9c3cba2b9c3d80 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5814,7 +5814,7 @@ ast_repr_max_depth(AST_object *self, int depth) static PyObject * ast_repr(AST_object *self) { - return ast_repr_max_depth(self, 2); + return ast_repr_max_depth(self, 3); } static PyType_Slot AST_type_slots[] = { From 76039103f3ea6e4bc274faca67e98a103d833373 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 11 Jul 2024 16:13:44 +0200 Subject: [PATCH 22/32] Add comments --- Parser/asdl_c.py | 5 +++++ Python/Python-ast.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 74729a933762ad..6dd1725fa1db51 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1427,6 +1427,11 @@ def visitModule(self, mod): static PyObject * ast_repr_max_depth(AST_object *self, int depth); +/* Format list and tuple properties of AST nodes. + Note that, only the first and last elements are shown. + Anything in between is represented with an ellipsis ('...'). + For example, the list [1, 2, 3] is formatted as + 'List(elts=[Constant(1), ..., Constant(3)])'. */ static PyObject * ast_repr_list(PyObject *list, int depth) { diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 9c3cba2b9c3d80..4c11d53fa8c49a 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5628,6 +5628,11 @@ static PyGetSetDef ast_type_getsets[] = { static PyObject * ast_repr_max_depth(AST_object *self, int depth); +/* Format list and tuple properties of AST nodes. + Note that, only the first and last elements are shown. + Anything in between is represented with an ellipsis ('...'). + For example, the list [1, 2, 3] is formatted as + 'List(elts=[Constant(1), ..., Constant(3)])'. */ static PyObject * ast_repr_list(PyObject *list, int depth) { From 74c57a6c20b7fde3ccb1b8068f297ffb4576e0e6 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 11 Jul 2024 16:30:09 +0200 Subject: [PATCH 23/32] Add versionchanged note to ast module docs --- Doc/library/ast.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index f7e8afa7000392..3bcb6d7853c3d4 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -134,6 +134,11 @@ Node classes Simple indices are represented by their value, extended slices are represented as tuples. +.. versionchanged:: 3.14 + + The :meth:`~object.__repr__` output of :class:`~ast.AST` nodes includes + the values of the node fields. + .. deprecated:: 3.8 Old classes :class:`!ast.Num`, :class:`!ast.Str`, :class:`!ast.Bytes`, From ddd7e7102a7563010ebbfcf44ff0ef889078e53f Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Sun, 14 Jul 2024 13:39:44 +0200 Subject: [PATCH 24/32] Use `PyUnicodeWriter_WriteUTF8` --- Parser/asdl_c.py | 8 ++++---- Python/Python-ast.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 6dd1725fa1db51..3bcf393f4ea65d 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1485,7 +1485,7 @@ def visitModule(self, mod): goto error; } if (i > 0) { - if (_PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, ", ", 2) < 0) { + if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) { goto error; } } @@ -1494,7 +1494,7 @@ def visitModule(self, mod): goto error; } if (i == 0 && length > 2) { - if (_PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, ", ...", 5) < 0) { + if (PyUnicodeWriter_WriteUTF8(writer, ", ...", 5) < 0) { Py_DECREF(item_repr); goto error; } @@ -1561,7 +1561,7 @@ def visitModule(self, mod): if (writer == NULL) { return NULL; } - _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, tp_name, strlen(tp_name)); + PyUnicodeWriter_WriteUTF8(writer, tp_name, strlen(tp_name)); PyUnicodeWriter_WriteChar(writer, '('); for (Py_ssize_t i = 0; i < numfields; i++) { PyObject *name = PySequence_GetItem(fields, i); @@ -1593,7 +1593,7 @@ def visitModule(self, mod): } if (i > 0) { - _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, ", ", 2); + PyUnicodeWriter_WriteUTF8(writer, ", ", 2); } PyUnicodeWriter_WriteStr(writer, name); PyUnicodeWriter_WriteChar(writer, '='); diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 4c11d53fa8c49a..1e399d407e3700 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5686,7 +5686,7 @@ ast_repr_list(PyObject *list, int depth) goto error; } if (i > 0) { - if (_PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, ", ", 2) < 0) { + if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) { goto error; } } @@ -5695,7 +5695,7 @@ ast_repr_list(PyObject *list, int depth) goto error; } if (i == 0 && length > 2) { - if (_PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, ", ...", 5) < 0) { + if (PyUnicodeWriter_WriteUTF8(writer, ", ...", 5) < 0) { Py_DECREF(item_repr); goto error; } @@ -5762,7 +5762,7 @@ ast_repr_max_depth(AST_object *self, int depth) if (writer == NULL) { return NULL; } - _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, tp_name, strlen(tp_name)); + PyUnicodeWriter_WriteUTF8(writer, tp_name, strlen(tp_name)); PyUnicodeWriter_WriteChar(writer, '('); for (Py_ssize_t i = 0; i < numfields; i++) { PyObject *name = PySequence_GetItem(fields, i); @@ -5794,7 +5794,7 @@ ast_repr_max_depth(AST_object *self, int depth) } if (i > 0) { - _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter *)writer, ", ", 2); + PyUnicodeWriter_WriteUTF8(writer, ", ", 2); } PyUnicodeWriter_WriteStr(writer, name); PyUnicodeWriter_WriteChar(writer, '='); From 132932a5d11b1de07dd15f665eb535fae7e9ff34 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Sun, 14 Jul 2024 13:59:32 +0200 Subject: [PATCH 25/32] Check for errors --- Parser/asdl_c.py | 43 ++++++++++++++++++++++++++++++++++++------- Python/Python-ast.c | 43 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 72 insertions(+), 14 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 3bcf393f4ea65d..4c311d57f92344 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1561,8 +1561,14 @@ def visitModule(self, mod): if (writer == NULL) { return NULL; } - PyUnicodeWriter_WriteUTF8(writer, tp_name, strlen(tp_name)); - PyUnicodeWriter_WriteChar(writer, '('); + + if (PyUnicodeWriter_WriteUTF8(writer, tp_name, strlen(tp_name)) < 0) { + goto error; + } + if (PyUnicodeWriter_WriteChar(writer, '(') < 0) { + goto error; + } + for (Py_ssize_t i = 0; i < numfields; i++) { PyObject *name = PySequence_GetItem(fields, i); if (!name) { @@ -1593,17 +1599,40 @@ def visitModule(self, mod): } if (i > 0) { - PyUnicodeWriter_WriteUTF8(writer, ", ", 2); + if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) { + Py_DECREF(name); + Py_DECREF(value); + Py_DECREF(value_repr); + goto error; + } + } + if (PyUnicodeWriter_WriteStr(writer, name) < 0) { + Py_DECREF(name); + Py_DECREF(value); + Py_DECREF(value_repr); + goto error; + } + if (PyUnicodeWriter_WriteChar(writer, '=') < 0) { + Py_DECREF(name); + Py_DECREF(value); + Py_DECREF(value_repr); + goto error; + } + if (PyUnicodeWriter_WriteStr(writer, value_repr) < 0) { + Py_DECREF(name); + Py_DECREF(value); + Py_DECREF(value_repr); + goto error; } - PyUnicodeWriter_WriteStr(writer, name); - PyUnicodeWriter_WriteChar(writer, '='); - PyUnicodeWriter_WriteStr(writer, value_repr); Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); } - PyUnicodeWriter_WriteChar(writer, ')'); + + if (PyUnicodeWriter_WriteChar(writer, ')') < 0) { + goto error; + } Py_ReprLeave((PyObject *)self); Py_DECREF(fields); return PyUnicodeWriter_Finish(writer); diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 1e399d407e3700..0a352865511ba9 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5762,8 +5762,14 @@ ast_repr_max_depth(AST_object *self, int depth) if (writer == NULL) { return NULL; } - PyUnicodeWriter_WriteUTF8(writer, tp_name, strlen(tp_name)); - PyUnicodeWriter_WriteChar(writer, '('); + + if (PyUnicodeWriter_WriteUTF8(writer, tp_name, strlen(tp_name)) < 0) { + goto error; + } + if (PyUnicodeWriter_WriteChar(writer, '(') < 0) { + goto error; + } + for (Py_ssize_t i = 0; i < numfields; i++) { PyObject *name = PySequence_GetItem(fields, i); if (!name) { @@ -5794,17 +5800,40 @@ ast_repr_max_depth(AST_object *self, int depth) } if (i > 0) { - PyUnicodeWriter_WriteUTF8(writer, ", ", 2); + if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) { + Py_DECREF(name); + Py_DECREF(value); + Py_DECREF(value_repr); + goto error; + } + } + if (PyUnicodeWriter_WriteStr(writer, name) < 0) { + Py_DECREF(name); + Py_DECREF(value); + Py_DECREF(value_repr); + goto error; + } + if (PyUnicodeWriter_WriteChar(writer, '=') < 0) { + Py_DECREF(name); + Py_DECREF(value); + Py_DECREF(value_repr); + goto error; + } + if (PyUnicodeWriter_WriteStr(writer, value_repr) < 0) { + Py_DECREF(name); + Py_DECREF(value); + Py_DECREF(value_repr); + goto error; } - PyUnicodeWriter_WriteStr(writer, name); - PyUnicodeWriter_WriteChar(writer, '='); - PyUnicodeWriter_WriteStr(writer, value_repr); Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); } - PyUnicodeWriter_WriteChar(writer, ')'); + + if (PyUnicodeWriter_WriteChar(writer, ')') < 0) { + goto error; + } Py_ReprLeave((PyObject *)self); Py_DECREF(fields); return PyUnicodeWriter_Finish(writer); From a341c5743ed59e066ad47ab2809ffc2e61747620 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Sun, 14 Jul 2024 14:36:15 +0200 Subject: [PATCH 26/32] Use snapshots for testing --- Lib/test/ast_repr_data/data.txt | 209 ++++++++++++++++++++++++++++++++ Lib/test/test_ast.py | 48 +++----- 2 files changed, 228 insertions(+), 29 deletions(-) create mode 100644 Lib/test/ast_repr_data/data.txt diff --git a/Lib/test/ast_repr_data/data.txt b/Lib/test/ast_repr_data/data.txt new file mode 100644 index 00000000000000..3778b9e70a4605 --- /dev/null +++ b/Lib/test/ast_repr_data/data.txt @@ -0,0 +1,209 @@ +Module(body=[Expr(value=Constant(value='module docstring', kind=None))], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Expr(value=Constant(...))], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[arg(...)], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[arg(...)], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[Constant(...)]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=arg(...), kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=arg(...), kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=arg(...), kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=arg(...), kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=arg(...), defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[arg(...), ..., arg(...)], vararg=arg(...), kwonlyargs=[arg(...)], kw_defaults=[Constant(...)], kwarg=arg(...), defaults=[Constant(...), ..., Dict(...)]), body=[Expr(value=Constant(...))], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=Subscript(value=Name(...), slice=Tuple(...), ctx=Load(...)), type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=Subscript(value=Name(...), slice=Tuple(...), ctx=Load(...)), type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=Subscript(value=Name(...), slice=Tuple(...), ctx=Load(...)), type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[ClassDef(name='C', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[])], type_ignores=[]) +Module(body=[ClassDef(name='C', bases=[], keywords=[], body=[Expr(value=Constant(...))], decorator_list=[], type_params=[])], type_ignores=[]) +Module(body=[ClassDef(name='C', bases=[Name(id='object', ctx=Load(...))], keywords=[], body=[Pass()], decorator_list=[], type_params=[])], type_ignores=[]) +Module(body=[ClassDef(name='C', bases=[Name(id='A', ctx=Load(...)), Name(id='B', ctx=Load(...))], keywords=[], body=[Pass()], decorator_list=[], type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Return(value=Constant(...))], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Return(value=None)], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[Delete(targets=[Name(id='v', ctx=Del(...))])], type_ignores=[]) +Module(body=[Assign(targets=[Name(id='v', ctx=Store(...))], value=Constant(value=1, kind=None), type_comment=None)], type_ignores=[]) +Module(body=[Assign(targets=[Tuple(elts=[Name(...), Name(...)], ctx=Store(...))], value=Name(id='c', ctx=Load(...)), type_comment=None)], type_ignores=[]) +Module(body=[Assign(targets=[Tuple(elts=[Name(...), Name(...)], ctx=Store(...))], value=Name(id='c', ctx=Load(...)), type_comment=None)], type_ignores=[]) +Module(body=[Assign(targets=[List(elts=[Name(...), Name(...)], ctx=Store(...))], value=Name(id='c', ctx=Load(...)), type_comment=None)], type_ignores=[]) +Module(body=[Assign(targets=[Subscript(value=Name(...), slice=Name(...), ctx=Store(...))], value=Name(id='c', ctx=Load(...)), type_comment=None)], type_ignores=[]) +Module(body=[AnnAssign(target=Name(id='x', ctx=Store(...)), annotation=Subscript(value=Name(...), slice=Tuple(...), ctx=Load(...)), value=None, simple=1)], type_ignores=[]) +Module(body=[AnnAssign(target=Name(id='x', ctx=Store(...)), annotation=Subscript(value=Name(...), slice=Tuple(...), ctx=Load(...)), value=None, simple=1)], type_ignores=[]) +Module(body=[AnnAssign(target=Name(id='x', ctx=Store(...)), annotation=Subscript(value=Name(...), slice=Tuple(...), ctx=Load(...)), value=None, simple=1)], type_ignores=[]) +Module(body=[AugAssign(target=Name(id='v', ctx=Store(...)), op=Add(), value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[AugAssign(target=Name(id='v', ctx=Store(...)), op=Sub(), value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[AugAssign(target=Name(id='v', ctx=Store(...)), op=Mult(), value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[AugAssign(target=Name(id='v', ctx=Store(...)), op=MatMult(), value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[AugAssign(target=Name(id='v', ctx=Store(...)), op=Div(), value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[AugAssign(target=Name(id='v', ctx=Store(...)), op=Mod(), value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[AugAssign(target=Name(id='v', ctx=Store(...)), op=Pow(), value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[AugAssign(target=Name(id='v', ctx=Store(...)), op=LShift(), value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[AugAssign(target=Name(id='v', ctx=Store(...)), op=RShift(), value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[AugAssign(target=Name(id='v', ctx=Store(...)), op=BitOr(), value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[AugAssign(target=Name(id='v', ctx=Store(...)), op=BitXor(), value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[AugAssign(target=Name(id='v', ctx=Store(...)), op=BitAnd(), value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[AugAssign(target=Name(id='v', ctx=Store(...)), op=FloorDiv(), value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[For(target=Name(id='v', ctx=Store(...)), iter=Name(id='v', ctx=Load(...)), body=[Pass()], orelse=[], type_comment=None)], type_ignores=[]) +Module(body=[For(target=Name(id='v', ctx=Store(...)), iter=Name(id='v', ctx=Load(...)), body=[Pass()], orelse=[Pass()], type_comment=None)], type_ignores=[]) +Module(body=[While(test=Name(id='v', ctx=Load(...)), body=[Pass()], orelse=[])], type_ignores=[]) +Module(body=[While(test=Name(id='v', ctx=Load(...)), body=[Pass()], orelse=[Pass()])], type_ignores=[]) +Module(body=[If(test=Name(id='v', ctx=Load(...)), body=[Pass()], orelse=[])], type_ignores=[]) +Module(body=[If(test=Name(id='a', ctx=Load(...)), body=[Pass()], orelse=[If(test=Name(...), body=[Pass(...)], orelse=[])])], type_ignores=[]) +Module(body=[If(test=Name(id='a', ctx=Load(...)), body=[Pass()], orelse=[Pass()])], type_ignores=[]) +Module(body=[If(test=Name(id='a', ctx=Load(...)), body=[Pass()], orelse=[If(test=Name(...), body=[Pass(...)], orelse=[Pass(...)])])], type_ignores=[]) +Module(body=[If(test=Name(id='a', ctx=Load(...)), body=[Pass()], orelse=[If(test=Name(...), body=[Pass(...)], orelse=[If(...)])])], type_ignores=[]) +Module(body=[With(items=[withitem(context_expr=Name(...), optional_vars=None)], body=[Pass()], type_comment=None)], type_ignores=[]) +Module(body=[With(items=[withitem(context_expr=Name(...), optional_vars=None), withitem(context_expr=Name(...), optional_vars=None)], body=[Pass()], type_comment=None)], type_ignores=[]) +Module(body=[With(items=[withitem(context_expr=Name(...), optional_vars=Name(...))], body=[Pass()], type_comment=None)], type_ignores=[]) +Module(body=[With(items=[withitem(context_expr=Name(...), optional_vars=Name(...)), withitem(context_expr=Name(...), optional_vars=Name(...))], body=[Pass()], type_comment=None)], type_ignores=[]) +Module(body=[With(items=[withitem(context_expr=Name(...), optional_vars=Name(...))], body=[Pass()], type_comment=None)], type_ignores=[]) +Module(body=[With(items=[withitem(context_expr=Name(...), optional_vars=None), withitem(context_expr=Name(...), optional_vars=None)], body=[Pass()], type_comment=None)], type_ignores=[]) +Module(body=[Raise(exc=None, cause=None)], type_ignores=[]) +Module(body=[Raise(exc=Call(func=Name(...), args=[Constant(...)], keywords=[]), cause=None)], type_ignores=[]) +Module(body=[Raise(exc=Name(id='Exception', ctx=Load(...)), cause=None)], type_ignores=[]) +Module(body=[Raise(exc=Call(func=Name(...), args=[Constant(...)], keywords=[]), cause=Constant(value=None, kind=None))], type_ignores=[]) +Module(body=[Try(body=[Pass()], handlers=[ExceptHandler(type=Name(...), name=None, body=[Pass(...)])], orelse=[], finalbody=[])], type_ignores=[]) +Module(body=[Try(body=[Pass()], handlers=[ExceptHandler(type=Name(...), name='exc', body=[Pass(...)])], orelse=[], finalbody=[])], type_ignores=[]) +Module(body=[Try(body=[Pass()], handlers=[], orelse=[], finalbody=[Pass()])], type_ignores=[]) +Module(body=[TryStar(body=[Pass()], handlers=[ExceptHandler(type=Name(...), name=None, body=[Pass(...)])], orelse=[], finalbody=[])], type_ignores=[]) +Module(body=[TryStar(body=[Pass()], handlers=[ExceptHandler(type=Name(...), name='exc', body=[Pass(...)])], orelse=[], finalbody=[])], type_ignores=[]) +Module(body=[Try(body=[Pass()], handlers=[ExceptHandler(type=Name(...), name=None, body=[Pass(...)])], orelse=[Pass()], finalbody=[Pass()])], type_ignores=[]) +Module(body=[Try(body=[Pass()], handlers=[ExceptHandler(type=Name(...), name='exc', body=[Pass(...)])], orelse=[Pass()], finalbody=[Pass()])], type_ignores=[]) +Module(body=[TryStar(body=[Pass()], handlers=[ExceptHandler(type=Name(...), name='exc', body=[Pass(...)])], orelse=[Pass()], finalbody=[Pass()])], type_ignores=[]) +Module(body=[Assert(test=Name(id='v', ctx=Load(...)), msg=None)], type_ignores=[]) +Module(body=[Assert(test=Name(id='v', ctx=Load(...)), msg=Constant(value='message', kind=None))], type_ignores=[]) +Module(body=[Import(names=[alias(name='sys', asname=None)])], type_ignores=[]) +Module(body=[Import(names=[alias(name='foo', asname='bar')])], type_ignores=[]) +Module(body=[ImportFrom(module='sys', names=[alias(name='x', asname='y')], level=0)], type_ignores=[]) +Module(body=[ImportFrom(module='sys', names=[alias(name='v', asname=None)], level=0)], type_ignores=[]) +Module(body=[Global(names=['v'])], type_ignores=[]) +Module(body=[Expr(value=Constant(value=1, kind=None))], type_ignores=[]) +Module(body=[Pass()], type_ignores=[]) +Module(body=[For(target=Name(id='v', ctx=Store(...)), iter=Name(id='v', ctx=Load(...)), body=[Break()], orelse=[], type_comment=None)], type_ignores=[]) +Module(body=[For(target=Name(id='v', ctx=Store(...)), iter=Name(id='v', ctx=Load(...)), body=[Continue()], orelse=[], type_comment=None)], type_ignores=[]) +Module(body=[For(target=Tuple(elts=[Name(...), Name(...)], ctx=Store(...)), iter=Name(id='c', ctx=Load(...)), body=[Pass()], orelse=[], type_comment=None)], type_ignores=[]) +Module(body=[For(target=Tuple(elts=[Name(...), Name(...)], ctx=Store(...)), iter=Name(id='c', ctx=Load(...)), body=[Pass()], orelse=[], type_comment=None)], type_ignores=[]) +Module(body=[For(target=List(elts=[Name(...), Name(...)], ctx=Store(...)), iter=Name(id='c', ctx=Load(...)), body=[Pass()], orelse=[], type_comment=None)], type_ignores=[]) +Module(body=[Expr(value=GeneratorExp(elt=Tuple(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=DictComp(key=Name(...), value=Name(...), generators=[comprehension(...), comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=DictComp(key=Name(...), value=Name(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=SetComp(elt=Name(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=SetComp(elt=Name(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[AsyncFunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Expr(value=Constant(...)), Expr(value=Await(...))], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[AsyncFunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[AsyncFor(target=Name(...), iter=Name(...), body=[Expr(...)], orelse=[Expr(...)], type_comment=None)], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[AsyncFunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[AsyncWith(items=[withitem(...)], body=[Expr(...)], type_comment=None)], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[Expr(value=Dict(keys=[None, Constant(...)], values=[Dict(...), Constant(...)]))], type_ignores=[]) +Module(body=[Expr(value=Set(elts=[Starred(...), Constant(...)]))], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Expr(value=Yield(...))], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Expr(value=YieldFrom(...))], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[AsyncFunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Expr(value=ListComp(...))], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[Name(id='deco1', ctx=Load(...)), ..., Call(func=Name(...), args=[Constant(...)], keywords=[])], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[AsyncFunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[Name(id='deco1', ctx=Load(...)), ..., Call(func=Name(...), args=[Constant(...)], keywords=[])], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[ClassDef(name='C', bases=[], keywords=[], body=[Pass()], decorator_list=[Name(id='deco1', ctx=Load(...)), ..., Call(func=Name(...), args=[Constant(...)], keywords=[])], type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[Call(func=Name(...), args=[GeneratorExp(...)], keywords=[])], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[Attribute(value=Attribute(...), attr='c', ctx=Load(...))], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[Expr(value=NamedExpr(target=Name(...), value=Constant(...)))], type_ignores=[]) +Module(body=[If(test=NamedExpr(target=Name(...), value=Call(...)), body=[Pass()], orelse=[])], type_ignores=[]) +Module(body=[While(test=NamedExpr(target=Name(...), value=Call(...)), body=[Pass()], orelse=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[arg(...)], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[arg(...)], args=[arg(...), ..., arg(...)], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[arg(...)], args=[arg(...)], vararg=None, kwonlyargs=[arg(...), arg(...)], kw_defaults=[None, None], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[arg(...)], args=[arg(...)], vararg=None, kwonlyargs=[arg(...), arg(...)], kw_defaults=[None, None], kwarg=arg(...), defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[arg(...)], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[Constant(...)]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[arg(...)], args=[arg(...), arg(...)], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[Constant(...), ..., Constant(...)]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[arg(...)], args=[arg(...)], vararg=None, kwonlyargs=[arg(...)], kw_defaults=[Constant(...)], kwarg=None, defaults=[Constant(...), Constant(...)]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[arg(...)], args=[arg(...)], vararg=None, kwonlyargs=[arg(...)], kw_defaults=[None], kwarg=None, defaults=[Constant(...), Constant(...)]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[arg(...)], args=[arg(...)], vararg=None, kwonlyargs=[arg(...)], kw_defaults=[Constant(...)], kwarg=arg(...), defaults=[Constant(...), Constant(...)]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[arg(...)], args=[arg(...)], vararg=None, kwonlyargs=[arg(...)], kw_defaults=[None], kwarg=arg(...), defaults=[Constant(...), Constant(...)]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[])], type_ignores=[]) +Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[], value=Name(id='int', ctx=Load(...)))], type_ignores=[]) +Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=None, default_value=None)], value=Name(id='int', ctx=Load(...)))], type_ignores=[]) +Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', default_value=None)], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=Name(...), default_value=None), ..., ParamSpec(name='P', default_value=None)], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=Tuple(...), default_value=None), ..., ParamSpec(name='P', default_value=None)], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[TypeAlias(name=Name(id='X', ctx=Store(...)), type_params=[TypeVar(name='T', bound=Name(...), default_value=Constant(...)), ..., ParamSpec(name='P', default_value=Constant(...))], value=Tuple(elts=[Name(...), ..., Name(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=None, default_value=None)])], type_ignores=[]) +Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', default_value=None)])], type_ignores=[]) +Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=Name(...), default_value=None), ..., ParamSpec(name='P', default_value=None)])], type_ignores=[]) +Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=Tuple(...), default_value=None), ..., ParamSpec(name='P', default_value=None)])], type_ignores=[]) +Module(body=[ClassDef(name='X', bases=[], keywords=[], body=[Pass()], decorator_list=[], type_params=[TypeVar(name='T', bound=Name(...), default_value=Constant(...)), ..., ParamSpec(name='P', default_value=Constant(...))])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=None, default_value=None)])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=None, default_value=None), ..., ParamSpec(name='P', default_value=None)])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=Name(...), default_value=None), ..., ParamSpec(name='P', default_value=None)])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=Tuple(...), default_value=None), ..., ParamSpec(name='P', default_value=None)])], type_ignores=[]) +Module(body=[FunctionDef(name='f', args=arguments(posonlyargs=[], args=[], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], returns=None, type_comment=None, type_params=[TypeVar(name='T', bound=Name(...), default_value=Constant(...)), ..., ParamSpec(name='P', default_value=Constant(...))])], type_ignores=[]) +Module(body=[Match(subject=Name(id='x', ctx=Load(...)), cases=[match_case(pattern=MatchValue(...), guard=None, body=[Pass(...)])])], type_ignores=[]) +Module(body=[Match(subject=Name(id='x', ctx=Load(...)), cases=[match_case(pattern=MatchValue(...), guard=None, body=[Pass(...)]), match_case(pattern=MatchAs(...), guard=None, body=[Pass(...)])])], type_ignores=[]) +Module(body=[Expr(value=Constant(value=None, kind=None))], type_ignores=[]) +Module(body=[Expr(value=Constant(value=True, kind=None))], type_ignores=[]) +Module(body=[Expr(value=Constant(value=False, kind=None))], type_ignores=[]) +Module(body=[Expr(value=BoolOp(op=And(...), values=[Name(...), Name(...)]))], type_ignores=[]) +Module(body=[Expr(value=BoolOp(op=Or(...), values=[Name(...), Name(...)]))], type_ignores=[]) +Module(body=[Expr(value=BinOp(left=Name(...), op=Add(...), right=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=BinOp(left=Name(...), op=Sub(...), right=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=BinOp(left=Name(...), op=Mult(...), right=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=BinOp(left=Name(...), op=Div(...), right=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=BinOp(left=Name(...), op=MatMult(...), right=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=BinOp(left=Name(...), op=FloorDiv(...), right=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=BinOp(left=Name(...), op=Pow(...), right=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=BinOp(left=Name(...), op=Mod(...), right=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=BinOp(left=Name(...), op=RShift(...), right=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=BinOp(left=Name(...), op=LShift(...), right=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=BinOp(left=Name(...), op=BitXor(...), right=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=BinOp(left=Name(...), op=BitOr(...), right=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=BinOp(left=Name(...), op=BitAnd(...), right=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=UnaryOp(op=Not(...), operand=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=UnaryOp(op=UAdd(...), operand=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=UnaryOp(op=USub(...), operand=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=UnaryOp(op=Invert(...), operand=Name(...)))], type_ignores=[]) +Module(body=[Expr(value=Lambda(args=arguments(...), body=Constant(...)))], type_ignores=[]) +Module(body=[Expr(value=Dict(keys=[Constant(...)], values=[Constant(...)]))], type_ignores=[]) +Module(body=[Expr(value=Dict(keys=[], values=[]))], type_ignores=[]) +Module(body=[Expr(value=Set(elts=[Constant(...)]))], type_ignores=[]) +Module(body=[Expr(value=Dict(keys=[Constant(...)], values=[Constant(...)]))], type_ignores=[]) +Module(body=[Expr(value=List(elts=[Constant(...), Constant(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=Tuple(elts=[Constant(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=Set(elts=[Constant(...), Constant(...)]))], type_ignores=[]) +Module(body=[Expr(value=ListComp(elt=Name(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=GeneratorExp(elt=Name(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=SetComp(elt=Name(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=DictComp(key=Name(...), value=Name(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=ListComp(elt=Tuple(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=ListComp(elt=Tuple(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=ListComp(elt=Tuple(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=SetComp(elt=Tuple(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=SetComp(elt=Tuple(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=SetComp(elt=Tuple(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=GeneratorExp(elt=Tuple(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=GeneratorExp(elt=Tuple(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=GeneratorExp(elt=Tuple(...), generators=[comprehension(...)]))], type_ignores=[]) +Module(body=[Expr(value=Compare(left=Constant(...), ops=[Lt(...), Lt(...)], comparators=[Constant(...), Constant(...)]))], type_ignores=[]) +Module(body=[Expr(value=Compare(left=Name(...), ops=[Eq(...)], comparators=[Name(...)]))], type_ignores=[]) +Module(body=[Expr(value=Compare(left=Name(...), ops=[LtE(...)], comparators=[Name(...)]))], type_ignores=[]) +Module(body=[Expr(value=Compare(left=Name(...), ops=[GtE(...)], comparators=[Name(...)]))], type_ignores=[]) +Module(body=[Expr(value=Compare(left=Name(...), ops=[NotEq(...)], comparators=[Name(...)]))], type_ignores=[]) +Module(body=[Expr(value=Compare(left=Name(...), ops=[Is(...)], comparators=[Name(...)]))], type_ignores=[]) +Module(body=[Expr(value=Compare(left=Name(...), ops=[IsNot(...)], comparators=[Name(...)]))], type_ignores=[]) +Module(body=[Expr(value=Compare(left=Name(...), ops=[In(...)], comparators=[Name(...)]))], type_ignores=[]) +Module(body=[Expr(value=Compare(left=Name(...), ops=[NotIn(...)], comparators=[Name(...)]))], type_ignores=[]) +Module(body=[Expr(value=Call(func=Name(...), args=[], keywords=[]))], type_ignores=[]) +Module(body=[Expr(value=Call(func=Name(...), args=[Constant(...), ..., Starred(...)], keywords=[keyword(...), keyword(...)]))], type_ignores=[]) +Module(body=[Expr(value=Call(func=Name(...), args=[Starred(...)], keywords=[]))], type_ignores=[]) +Module(body=[Expr(value=Call(func=Name(...), args=[GeneratorExp(...)], keywords=[]))], type_ignores=[]) +Module(body=[Expr(value=Constant(value=10, kind=None))], type_ignores=[]) +Module(body=[Expr(value=Constant(value=1j, kind=None))], type_ignores=[]) +Module(body=[Expr(value=Constant(value='string', kind=None))], type_ignores=[]) +Module(body=[Expr(value=Attribute(value=Name(...), attr='b', ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=Subscript(value=Name(...), slice=Slice(...), ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=Name(id='v', ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=List(elts=[Constant(...), ..., Constant(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=List(elts=[], ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=Tuple(elts=[Constant(...), ..., Constant(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=Tuple(elts=[Constant(...), ..., Constant(...)], ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=Tuple(elts=[], ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=Call(func=Attribute(...), args=[Subscript(...)], keywords=[]))], type_ignores=[]) +Module(body=[Expr(value=Subscript(value=List(...), slice=Slice(...), ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=Subscript(value=List(...), slice=Slice(...), ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=Subscript(value=List(...), slice=Slice(...), ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=Subscript(value=List(...), slice=Slice(...), ctx=Load(...)))], type_ignores=[]) +Module(body=[Expr(value=IfExp(test=Name(...), body=Call(...), orelse=Call(...)))], type_ignores=[]) +Module(body=[Expr(value=JoinedStr(values=[FormattedValue(...)]))], type_ignores=[]) +Module(body=[Expr(value=JoinedStr(values=[FormattedValue(...)]))], type_ignores=[]) +Module(body=[Expr(value=JoinedStr(values=[FormattedValue(...)]))], type_ignores=[]) +Module(body=[Expr(value=JoinedStr(values=[Constant(...), ..., Constant(...)]))], type_ignores=[]) \ No newline at end of file diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 57259c2b4fdb1a..c20cf602ecc980 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -403,6 +403,17 @@ def to_tuple(t): "f'foo({a})'", ] +ast_repr_data_file = Path(__file__).parent / "ast_repr_data" / "data.txt" + + +def ast_repr_get_test_cases() -> list[str]: + return exec_tests + eval_tests + + +def ast_repr_update_snaphots() -> None: + data = [repr(ast.parse(test)) for test in ast_repr_get_test_cases()] + ast_repr_data_file.write_text("\n".join(data)) + class AST_Tests(unittest.TestCase): maxDiff = None @@ -1146,35 +1157,11 @@ def test_none_checks(self) -> None: for node, attr, source in tests: self.assert_none_check(node, attr, source) - def test_repr(self): - const_1 = ast.Constant(1) - const_2 = ast.Constant(2) - self.assertEqual(repr(const_1), "Constant(value=1, kind=None)") - - add = ast.BinOp(op=ast.Add(), left=const_1, right=const_2) - self.assertEqual(repr(add), - "BinOp(left=Constant(value=1, kind=None), op=Add(), right=Constant(value=2, kind=None))") - - self.assertEqual(repr(ast.parse("x = 3")), - "Module(body=[Assign(targets=[Name(id='x', ctx=Store(...))], " - "value=Constant(value=3, kind=None), type_comment=None)], type_ignores=[])") - - self.assertEqual(repr(ast.parse("x=7; y=4; c,z=3,4")), - "Module(body=[Assign(targets=[Name(id='x', ctx=Store(...))], " - "value=Constant(value=7, kind=None), type_comment=None), ..., " - "Assign(targets=[Tuple(elts=[Name(...), Name(...)], ctx=Store(...))], " - "value=Tuple(elts=[Constant(...), Constant(...)], ctx=Load(...)), type_comment=None)], " - "type_ignores=[])") - - self.assertEqual(repr(ast.parse("def foo(): pass")), - "Module(body=[FunctionDef(name='foo', args=arguments(posonlyargs=[], args=[], vararg=None, " - "kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[Pass()], decorator_list=[], " - "returns=None, type_comment=None, type_params=[])], type_ignores=[])") - - this_module = ast.parse(Path(__file__).read_text()) - self.assertEqual(repr(this_module), - "Module(body=[Import(names=[alias(name='ast', asname=None)]), ..., " - "Expr(value=Call(func=Name(...), args=[], keywords=[]))], type_ignores=[])") + 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): + with self.subTest(test_input=test): + self.assertEqual(repr(ast.parse(test)), snapshot) class CopyTests(unittest.TestCase): @@ -3441,6 +3428,9 @@ def main(): print("]") print("main()") raise SystemExit + elif sys.argv[1] == '--snapshot-update': + ast_repr_update_snaphots() + sys.exit(0) unittest.main() #### EVERYTHING BELOW IS GENERATED BY python Lib/test/test_ast.py -g ##### From d03c3d19fe6f48ff02b898982b4da588a115d7a5 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Sun, 14 Jul 2024 14:46:21 +0200 Subject: [PATCH 27/32] Fix typo --- Lib/test/test_ast.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index c20cf602ecc980..9dc17965ef29b9 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -410,7 +410,7 @@ def ast_repr_get_test_cases() -> list[str]: return exec_tests + eval_tests -def ast_repr_update_snaphots() -> None: +def ast_repr_update_snapshots() -> None: data = [repr(ast.parse(test)) for test in ast_repr_get_test_cases()] ast_repr_data_file.write_text("\n".join(data)) @@ -3429,7 +3429,7 @@ def main(): print("main()") raise SystemExit elif sys.argv[1] == '--snapshot-update': - ast_repr_update_snaphots() + ast_repr_update_snapshots() sys.exit(0) unittest.main() From 44b33031ba26d8f7cda1a457de43b8fa4abe1611 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Sun, 14 Jul 2024 21:19:04 +0200 Subject: [PATCH 28/32] Add test folder to Makefile --- Makefile.pre.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.pre.in b/Makefile.pre.in index 0bece8717ef4c0..38e74c39c360c6 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2387,6 +2387,7 @@ TESTSUBDIRS= idlelib/idle_test \ test/support \ test/support/_hypothesis_stubs \ test/support/interpreters \ + test/ast_repr_data \ test/test_asyncio \ test/test_capi \ test/test_cext \ From 0b52a6530a7e080415aeb5ec83afae6974fc4d5b Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Tue, 16 Jul 2024 20:25:57 +0200 Subject: [PATCH 29/32] Switch back to the private API --- Parser/asdl_c.py | 46 ++++++++++++++++++++++----------------------- Python/Python-ast.c | 46 ++++++++++++++++++++++----------------------- 2 files changed, 44 insertions(+), 48 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 4c311d57f92344..22c2a848cc2706 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1450,10 +1450,9 @@ def visitModule(self, mod): return PyObject_Repr(list); } - PyUnicodeWriter *writer = PyUnicodeWriter_Create(0); - if (writer == NULL) { - return NULL; - } + _PyUnicodeWriter writer; + _PyUnicodeWriter_Init(&writer); + writer.overallocate = 1; PyObject *items[2] = {NULL, NULL}; items[0] = PySequence_GetItem(list, 0); @@ -1468,7 +1467,7 @@ def visitModule(self, mod): } bool is_list = PyList_Check(list); - if (PyUnicodeWriter_WriteChar(writer, is_list ? '[' : '(') < 0) { + if (_PyUnicodeWriter_WriteChar(&writer, is_list ? '[' : '(') < 0) { goto error; } @@ -1485,16 +1484,16 @@ def visitModule(self, mod): goto error; } if (i > 0) { - if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) { + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { goto error; } } - if (PyUnicodeWriter_WriteStr(writer, item_repr) < 0) { + if (_PyUnicodeWriter_WriteStr(&writer, item_repr) < 0) { Py_DECREF(item_repr); goto error; } if (i == 0 && length > 2) { - if (PyUnicodeWriter_WriteUTF8(writer, ", ...", 5) < 0) { + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ...", 5) < 0) { Py_DECREF(item_repr); goto error; } @@ -1502,18 +1501,18 @@ def visitModule(self, mod): Py_DECREF(item_repr); } - if (PyUnicodeWriter_WriteChar(writer, is_list ? ']' : ')') < 0) { + if (_PyUnicodeWriter_WriteChar(&writer, is_list ? ']' : ')') < 0) { goto error; } Py_XDECREF(items[0]); Py_XDECREF(items[1]); - return PyUnicodeWriter_Finish(writer); + return _PyUnicodeWriter_Finish(&writer); error: Py_XDECREF(items[0]); Py_XDECREF(items[1]); - PyUnicodeWriter_Discard(writer); + _PyUnicodeWriter_Dealloc(&writer); return NULL; } @@ -1557,15 +1556,14 @@ def visitModule(self, mod): } const char* tp_name = Py_TYPE(self)->tp_name; - PyUnicodeWriter *writer = PyUnicodeWriter_Create(0); - if (writer == NULL) { - return NULL; - } + _PyUnicodeWriter writer; + _PyUnicodeWriter_Init(&writer); + writer.overallocate = 1; - if (PyUnicodeWriter_WriteUTF8(writer, tp_name, strlen(tp_name)) < 0) { + if (_PyUnicodeWriter_WriteASCIIString(&writer, tp_name, strlen(tp_name)) < 0) { goto error; } - if (PyUnicodeWriter_WriteChar(writer, '(') < 0) { + if (_PyUnicodeWriter_WriteChar(&writer, '(') < 0) { goto error; } @@ -1599,26 +1597,26 @@ def visitModule(self, mod): } if (i > 0) { - if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) { + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); goto error; } } - if (PyUnicodeWriter_WriteStr(writer, name) < 0) { + if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) { Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); goto error; } - if (PyUnicodeWriter_WriteChar(writer, '=') < 0) { + if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) { Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); goto error; } - if (PyUnicodeWriter_WriteStr(writer, value_repr) < 0) { + if (_PyUnicodeWriter_WriteStr(&writer, value_repr) < 0) { Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); @@ -1630,17 +1628,17 @@ def visitModule(self, mod): Py_DECREF(value_repr); } - if (PyUnicodeWriter_WriteChar(writer, ')') < 0) { + if (_PyUnicodeWriter_WriteChar(&writer, ')') < 0) { goto error; } Py_ReprLeave((PyObject *)self); Py_DECREF(fields); - return PyUnicodeWriter_Finish(writer); + return _PyUnicodeWriter_Finish(&writer); error: Py_ReprLeave((PyObject *)self); Py_DECREF(fields); - PyUnicodeWriter_Discard(writer); + _PyUnicodeWriter_Dealloc(&writer); return NULL; } diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 0a352865511ba9..48bf4babbf8fbf 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5651,10 +5651,9 @@ ast_repr_list(PyObject *list, int depth) return PyObject_Repr(list); } - PyUnicodeWriter *writer = PyUnicodeWriter_Create(0); - if (writer == NULL) { - return NULL; - } + _PyUnicodeWriter writer; + _PyUnicodeWriter_Init(&writer); + writer.overallocate = 1; PyObject *items[2] = {NULL, NULL}; items[0] = PySequence_GetItem(list, 0); @@ -5669,7 +5668,7 @@ ast_repr_list(PyObject *list, int depth) } bool is_list = PyList_Check(list); - if (PyUnicodeWriter_WriteChar(writer, is_list ? '[' : '(') < 0) { + if (_PyUnicodeWriter_WriteChar(&writer, is_list ? '[' : '(') < 0) { goto error; } @@ -5686,16 +5685,16 @@ ast_repr_list(PyObject *list, int depth) goto error; } if (i > 0) { - if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) { + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { goto error; } } - if (PyUnicodeWriter_WriteStr(writer, item_repr) < 0) { + if (_PyUnicodeWriter_WriteStr(&writer, item_repr) < 0) { Py_DECREF(item_repr); goto error; } if (i == 0 && length > 2) { - if (PyUnicodeWriter_WriteUTF8(writer, ", ...", 5) < 0) { + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ...", 5) < 0) { Py_DECREF(item_repr); goto error; } @@ -5703,18 +5702,18 @@ ast_repr_list(PyObject *list, int depth) Py_DECREF(item_repr); } - if (PyUnicodeWriter_WriteChar(writer, is_list ? ']' : ')') < 0) { + if (_PyUnicodeWriter_WriteChar(&writer, is_list ? ']' : ')') < 0) { goto error; } Py_XDECREF(items[0]); Py_XDECREF(items[1]); - return PyUnicodeWriter_Finish(writer); + return _PyUnicodeWriter_Finish(&writer); error: Py_XDECREF(items[0]); Py_XDECREF(items[1]); - PyUnicodeWriter_Discard(writer); + _PyUnicodeWriter_Dealloc(&writer); return NULL; } @@ -5758,15 +5757,14 @@ ast_repr_max_depth(AST_object *self, int depth) } const char* tp_name = Py_TYPE(self)->tp_name; - PyUnicodeWriter *writer = PyUnicodeWriter_Create(0); - if (writer == NULL) { - return NULL; - } + _PyUnicodeWriter writer; + _PyUnicodeWriter_Init(&writer); + writer.overallocate = 1; - if (PyUnicodeWriter_WriteUTF8(writer, tp_name, strlen(tp_name)) < 0) { + if (_PyUnicodeWriter_WriteASCIIString(&writer, tp_name, strlen(tp_name)) < 0) { goto error; } - if (PyUnicodeWriter_WriteChar(writer, '(') < 0) { + if (_PyUnicodeWriter_WriteChar(&writer, '(') < 0) { goto error; } @@ -5800,26 +5798,26 @@ ast_repr_max_depth(AST_object *self, int depth) } if (i > 0) { - if (PyUnicodeWriter_WriteUTF8(writer, ", ", 2) < 0) { + if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); goto error; } } - if (PyUnicodeWriter_WriteStr(writer, name) < 0) { + if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) { Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); goto error; } - if (PyUnicodeWriter_WriteChar(writer, '=') < 0) { + if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) { Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); goto error; } - if (PyUnicodeWriter_WriteStr(writer, value_repr) < 0) { + if (_PyUnicodeWriter_WriteStr(&writer, value_repr) < 0) { Py_DECREF(name); Py_DECREF(value); Py_DECREF(value_repr); @@ -5831,17 +5829,17 @@ ast_repr_max_depth(AST_object *self, int depth) Py_DECREF(value_repr); } - if (PyUnicodeWriter_WriteChar(writer, ')') < 0) { + if (_PyUnicodeWriter_WriteChar(&writer, ')') < 0) { goto error; } Py_ReprLeave((PyObject *)self); Py_DECREF(fields); - return PyUnicodeWriter_Finish(writer); + return _PyUnicodeWriter_Finish(&writer); error: Py_ReprLeave((PyObject *)self); Py_DECREF(fields); - PyUnicodeWriter_Discard(writer); + _PyUnicodeWriter_Dealloc(&writer); return NULL; } From 2ed3f99f52b84468a897741cb823d6bbbb4a8dcc Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Mon, 12 Aug 2024 15:57:34 +0200 Subject: [PATCH 30/32] Move test data inside test_ast --- Lib/test/{ast_repr_data/data.txt => test_ast/data/ast_repr.txt} | 0 Lib/test/test_ast/test_ast.py | 2 +- Makefile.pre.in | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) rename Lib/test/{ast_repr_data/data.txt => test_ast/data/ast_repr.txt} (100%) diff --git a/Lib/test/ast_repr_data/data.txt b/Lib/test/test_ast/data/ast_repr.txt similarity index 100% rename from Lib/test/ast_repr_data/data.txt rename to Lib/test/test_ast/data/ast_repr.txt diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 0b121cb08ff9c8..052416370c5de8 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -30,7 +30,7 @@ STDLIB_FILES = [fn for fn in os.listdir(STDLIB) if fn.endswith(".py")] STDLIB_FILES.extend(["test/test_grammar.py", "test/test_unpack_ex.py"]) -AST_REPR_DATA_FILE = Path(__file__).parents[1] / "ast_repr_data" / "data.txt" +AST_REPR_DATA_FILE = Path(__file__).parent / "data" / "ast_repr.txt" def ast_repr_get_test_cases() -> list[str]: return exec_tests + eval_tests diff --git a/Makefile.pre.in b/Makefile.pre.in index 18400b2c0242e8..5608e593ac9aca 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2388,7 +2388,6 @@ TESTSUBDIRS= idlelib/idle_test \ test/support \ test/support/_hypothesis_stubs \ test/support/interpreters \ - test/ast_repr_data \ test/test_asyncio \ test/test_capi \ test/test_cext \ From 6ca6b5b0e9308d31ba5c7c5bcae54f7f27350030 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Wed, 14 Aug 2024 20:29:47 +0200 Subject: [PATCH 31/32] Fix tests --- Makefile.pre.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.pre.in b/Makefile.pre.in index 6eb9afefada313..cef9ec794e1a4b 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2369,6 +2369,7 @@ LIBSUBDIRS= asyncio \ TESTSUBDIRS= idlelib/idle_test \ test \ test/test_ast \ + test/test_ast/data \ test/archivetestdata \ test/audiodata \ test/certdata \ From df34a0454a8fcd3779c4af30306361ff7cebd6e6 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Wed, 14 Aug 2024 20:35:28 +0200 Subject: [PATCH 32/32] Apply review suggestions --- Parser/asdl_c.py | 13 +++++-------- Python/Python-ast.c | 13 +++++-------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 9db0673f58a56e..fac9a7740a1fe6 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1601,6 +1601,8 @@ def visitModule(self, mod): value_repr = PyObject_Repr(value); } + Py_DECREF(value); + if (!value_repr) { Py_DECREF(name); Py_DECREF(value); @@ -1610,32 +1612,27 @@ def visitModule(self, mod): if (i > 0) { if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { Py_DECREF(name); - Py_DECREF(value); Py_DECREF(value_repr); goto error; } } if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) { Py_DECREF(name); - Py_DECREF(value); Py_DECREF(value_repr); goto error; } + + Py_DECREF(name); + if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) { - Py_DECREF(name); - Py_DECREF(value); Py_DECREF(value_repr); goto error; } if (_PyUnicodeWriter_WriteStr(&writer, value_repr) < 0) { - Py_DECREF(name); - Py_DECREF(value); Py_DECREF(value_repr); goto error; } - Py_DECREF(name); - Py_DECREF(value); Py_DECREF(value_repr); } diff --git a/Python/Python-ast.c b/Python/Python-ast.c index f9d9da3821dd6c..860447ef9ed702 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5802,6 +5802,8 @@ ast_repr_max_depth(AST_object *self, int depth) value_repr = PyObject_Repr(value); } + Py_DECREF(value); + if (!value_repr) { Py_DECREF(name); Py_DECREF(value); @@ -5811,32 +5813,27 @@ ast_repr_max_depth(AST_object *self, int depth) if (i > 0) { if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) { Py_DECREF(name); - Py_DECREF(value); Py_DECREF(value_repr); goto error; } } if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) { Py_DECREF(name); - Py_DECREF(value); Py_DECREF(value_repr); goto error; } + + Py_DECREF(name); + if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) { - Py_DECREF(name); - Py_DECREF(value); Py_DECREF(value_repr); goto error; } if (_PyUnicodeWriter_WriteStr(&writer, value_repr) < 0) { - Py_DECREF(name); - Py_DECREF(value); Py_DECREF(value_repr); goto error; } - Py_DECREF(name); - Py_DECREF(value); Py_DECREF(value_repr); }