From f893bb2e01307c92ca19597f44874ecaffe7f06f Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Wed, 8 Dec 2021 18:47:27 +0000 Subject: [PATCH] bpo-45635: refactor print_exception() into smaller functions (GH-29981) Co-authored-by: Erlend Egeberg Aasland --- Python/pythonrun.c | 226 ++++++++++++++++++++++++++++----------------- 1 file changed, 139 insertions(+), 87 deletions(-) diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 5a118b4821e..cfc39361d5f 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -908,38 +908,35 @@ write_indented_margin(struct exception_print_context *ctx, PyObject *f) return _Py_WriteIndentedMargin(EXC_INDENT(ctx), EXC_MARGIN(ctx), f); } -static void -print_exception(struct exception_print_context *ctx, PyObject *value) +static int +print_exception_invalid_type(struct exception_print_context *ctx, + PyObject *value) { - int err = 0; - PyObject *type, *tb, *tmp; PyObject *f = ctx->file; - - _Py_IDENTIFIER(print_file_and_line); - - if (!PyExceptionInstance_Check(value)) { - if (err == 0) { - err = _Py_WriteIndent(EXC_INDENT(ctx), f); - } - if (err == 0) { - err = PyFile_WriteString("TypeError: print_exception(): Exception expected for value, ", f); - } - if (err == 0) { - err = PyFile_WriteString(Py_TYPE(value)->tp_name, f); - } - if (err == 0) { - err = PyFile_WriteString(" found\n", f); - } - if (err != 0) { - PyErr_Clear(); - } - return; + if (_Py_WriteIndent(EXC_INDENT(ctx), f) < 0) { + return -1; } + const char *const msg = "TypeError: print_exception(): Exception expected " + "for value, "; + if (PyFile_WriteString(msg, f) < 0) { + return -1; + } + if (PyFile_WriteString(Py_TYPE(value)->tp_name, f) < 0) { + return -1; + } + if (PyFile_WriteString(" found\n", f) < 0) { + return -1; + } + return 0; +} - Py_INCREF(value); - fflush(stdout); - type = (PyObject *) Py_TYPE(value); - tb = PyException_GetTraceback(value); +static int +print_exception_traceback(struct exception_print_context *ctx, PyObject *value) +{ + PyObject *f = ctx->file; + int err = 0; + + PyObject *tb = PyException_GetTraceback(value); if (tb && tb != Py_None) { const char *header = EXCEPTION_TB_HEADER; const char *header_margin = EXC_MARGIN(ctx); @@ -952,6 +949,117 @@ print_exception(struct exception_print_context *ctx, PyObject *value) err = _PyTraceBack_Print_Indented( tb, EXC_INDENT(ctx), EXC_MARGIN(ctx), header_margin, header, f); } + Py_XDECREF(tb); + return err; +} + +/* Prints the message line: module.qualname[: str(exc)] */ +static int +print_exception_message(struct exception_print_context *ctx, PyObject *type, + PyObject *value) +{ + PyObject *f = ctx->file; + + _Py_IDENTIFIER(__module__); + + assert(PyExceptionClass_Check(type)); + + if (write_indented_margin(ctx, f) < 0) { + return -1; + } + PyObject *modulename = _PyObject_GetAttrId(type, &PyId___module__); + if (modulename == NULL || !PyUnicode_Check(modulename)) { + Py_XDECREF(modulename); + PyErr_Clear(); + if (PyFile_WriteString(".", f) < 0) { + return -1; + } + } + else { + if (!_PyUnicode_EqualToASCIIId(modulename, &PyId_builtins) && + !_PyUnicode_EqualToASCIIId(modulename, &PyId___main__)) + { + int res = PyFile_WriteObject(modulename, f, Py_PRINT_RAW); + Py_DECREF(modulename); + if (res < 0) { + return -1; + } + if (PyFile_WriteString(".", f) < 0) { + return -1; + } + } + else { + Py_DECREF(modulename); + } + } + + PyObject *qualname = PyType_GetQualName((PyTypeObject *)type); + if (qualname == NULL || !PyUnicode_Check(qualname)) { + Py_XDECREF(qualname); + PyErr_Clear(); + if (PyFile_WriteString("", f) < 0) { + return -1; + } + } + else { + int res = PyFile_WriteObject(qualname, f, Py_PRINT_RAW); + Py_DECREF(qualname); + if (res < 0) { + return -1; + } + } + + if (Py_IsNone(value)) { + return 0; + } + + PyObject *s = PyObject_Str(value); + if (s == NULL) { + PyErr_Clear(); + if (PyFile_WriteString(": ", f) < 0) { + return -1; + } + } + else { + /* only print colon if the str() of the + object is not the empty string + */ + if (!PyUnicode_Check(s) || PyUnicode_GetLength(s) != 0) { + if (PyFile_WriteString(": ", f) < 0) { + Py_DECREF(s); + return -1; + } + } + int res = PyFile_WriteObject(s, f, Py_PRINT_RAW); + Py_DECREF(s); + if (res < 0) { + return -1; + } + } + + return 0; +} + +static void +print_exception(struct exception_print_context *ctx, PyObject *value) +{ + int err = 0; + PyObject *tmp; + PyObject *f = ctx->file; + + _Py_IDENTIFIER(print_file_and_line); + + if (!PyExceptionInstance_Check(value)) { + if (print_exception_invalid_type(ctx, value) < 0) { + PyErr_Clear(); /* TODO: change to return -1 */ + } + return; + } + + Py_INCREF(value); + fflush(stdout); + PyObject *type = (PyObject *) Py_TYPE(value); + err = print_exception_traceback(ctx, value); if (err == 0 && (err = _PyObject_LookupAttrId(value, &PyId_print_file_and_line, &tmp)) > 0) { @@ -1006,66 +1114,11 @@ print_exception(struct exception_print_context *ctx, PyObject *value) err = -1; } } - if (err != 0) { - /* Don't do anything else */ - } - else { - PyObject* modulename; - _Py_IDENTIFIER(__module__); - assert(PyExceptionClass_Check(type)); + if (err == 0) { + err = print_exception_message(ctx, type, value); + } - err = write_indented_margin(ctx, f); - if (err == 0) { - modulename = _PyObject_GetAttrId(type, &PyId___module__); - if (modulename == NULL || !PyUnicode_Check(modulename)) - { - Py_XDECREF(modulename); - PyErr_Clear(); - err = PyFile_WriteString(".", f); - } - else { - if (!_PyUnicode_EqualToASCIIId(modulename, &PyId_builtins) && - !_PyUnicode_EqualToASCIIId(modulename, &PyId___main__)) - { - err = PyFile_WriteObject(modulename, f, Py_PRINT_RAW); - if (err == 0) { - err = PyFile_WriteString(".", f); - } - } - Py_DECREF(modulename); - } - } - if (err == 0) { - PyObject* qualname = PyType_GetQualName((PyTypeObject *)type); - if (qualname == NULL || !PyUnicode_Check(qualname)) { - Py_XDECREF(qualname); - PyErr_Clear(); - err = PyFile_WriteString("", f); - } - else { - err = PyFile_WriteObject(qualname, f, Py_PRINT_RAW); - Py_DECREF(qualname); - } - } - } - if (err == 0 && (value != Py_None)) { - PyObject *s = PyObject_Str(value); - /* only print colon if the str() of the - object is not the empty string - */ - if (s == NULL) { - PyErr_Clear(); - err = -1; - PyFile_WriteString(": ", f); - } - else if (!PyUnicode_Check(s) || - PyUnicode_GetLength(s) != 0) - err = PyFile_WriteString(": ", f); - if (err == 0) - err = PyFile_WriteObject(s, f, Py_PRINT_RAW); - Py_XDECREF(s); - } /* try to write a newline in any case */ if (err < 0) { PyErr_Clear(); @@ -1118,7 +1171,6 @@ print_exception(struct exception_print_context *ctx, PyObject *value) } Py_XDECREF(note); } - Py_XDECREF(tb); Py_DECREF(value); /* If an error happened here, don't show it. XXX This is wrong, but too many callers rely on this behavior. */