summaryrefslogtreecommitdiffstats
path: root/Parser
diff options
context:
space:
mode:
authorTomas R <tomas.roun8@gmail.com>2024-09-18 17:28:22 (GMT)
committerGitHub <noreply@github.com>2024-09-18 17:28:22 (GMT)
commit21d2a9ab2f4dcbf1be462d3b7f7a231a46bc1cb7 (patch)
tree5bb4398ecb1cd8325d109d00878b60da8e29adfd /Parser
parentf9fa6ba4f8d90ae12bc1f6a792d66903bb169ba8 (diff)
downloadcpython-21d2a9ab2f4dcbf1be462d3b7f7a231a46bc1cb7.zip
cpython-21d2a9ab2f4dcbf1be462d3b7f7a231a46bc1cb7.tar.gz
cpython-21d2a9ab2f4dcbf1be462d3b7f7a231a46bc1cb7.tar.bz2
gh-116022: Improve `repr()` of AST nodes (#117046)
Co-authored-by: AN Long <aisk@users.noreply.github.com> Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com> Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com> Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Diffstat (limited to 'Parser')
-rwxr-xr-xParser/asdl_c.py222
1 files changed, 222 insertions, 0 deletions
diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py
index 9fed69b..fac9a77 100755
--- a/Parser/asdl_c.py
+++ b/Parser/asdl_c.py
@@ -1435,8 +1435,230 @@ static PyGetSetDef ast_type_getsets[] = {
{NULL}
};
+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)
+{
+ assert(PyList_Check(list) || PyTuple_Check(list));
+
+ struct ast_state *state = get_ast_state();
+ if (state == NULL) {
+ return NULL;
+ }
+
+ Py_ssize_t length = PySequence_Size(list);
+ if (length < 0) {
+ return NULL;
+ }
+ else if (length == 0) {
+ return PyObject_Repr(list);
+ }
+
+ _PyUnicodeWriter writer;
+ _PyUnicodeWriter_Init(&writer);
+ writer.overallocate = 1;
+ PyObject *items[2] = {NULL, NULL};
+
+ items[0] = PySequence_GetItem(list, 0);
+ if (!items[0]) {
+ goto error;
+ }
+ if (length > 1) {
+ items[1] = PySequence_GetItem(list, length - 1);
+ if (!items[1]) {
+ goto error;
+ }
+ }
+
+ bool is_list = PyList_Check(list);
+ 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;
+ }
+
+ 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;
+}
+
+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;
+ 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_DECREF(fields);
+ return NULL;
+ }
+
+ if (numfields == 0) {
+ Py_ReprLeave((PyObject *)self);
+ Py_DECREF(fields);
+ return PyUnicode_FromFormat("%s()", Py_TYPE(self)->tp_name);
+ }
+
+ const char* tp_name = Py_TYPE(self)->tp_name;
+ _PyUnicodeWriter writer;
+ _PyUnicodeWriter_Init(&writer);
+ writer.overallocate = 1;
+
+ if (_PyUnicodeWriter_WriteASCIIString(&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) {
+ 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);
+ }
+
+ Py_DECREF(value);
+
+ if (!value_repr) {
+ Py_DECREF(name);
+ Py_DECREF(value);
+ goto error;
+ }
+
+ if (i > 0) {
+ if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) {
+ Py_DECREF(name);
+ Py_DECREF(value_repr);
+ goto error;
+ }
+ }
+ if (_PyUnicodeWriter_WriteStr(&writer, name) < 0) {
+ Py_DECREF(name);
+ Py_DECREF(value_repr);
+ goto error;
+ }
+
+ Py_DECREF(name);
+
+ if (_PyUnicodeWriter_WriteChar(&writer, '=') < 0) {
+ Py_DECREF(value_repr);
+ goto error;
+ }
+ if (_PyUnicodeWriter_WriteStr(&writer, value_repr) < 0) {
+ Py_DECREF(value_repr);
+ goto error;
+ }
+
+ Py_DECREF(value_repr);
+ }
+
+ if (_PyUnicodeWriter_WriteChar(&writer, ')') < 0) {
+ goto error;
+ }
+ Py_ReprLeave((PyObject *)self);
+ Py_DECREF(fields);
+ return _PyUnicodeWriter_Finish(&writer);
+
+error:
+ Py_ReprLeave((PyObject *)self);
+ Py_DECREF(fields);
+ _PyUnicodeWriter_Dealloc(&writer);
+ return NULL;
+}
+
+static PyObject *
+ast_repr(AST_object *self)
+{
+ return ast_repr_max_depth(self, 3);
+}
+
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},