bpo-45635: refactor print_exception() into smaller functions (GH-29981)

Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no>
This commit is contained in:
Irit Katriel 2021-12-08 18:47:27 +00:00 committed by GitHub
parent d4363d2140
commit f893bb2e01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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("<unknown>.", 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("<unknown>", 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(": <exception str() failed>", 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("<unknown>.", 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("<unknown>", 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(": <exception str() failed>", 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. */