Skip to content

Commit dc4a212

Browse files
iritkatrielErlend Egeberg Aasland
andauthored
bpo-45635: continue refactor of print_exception() to standardize error handling (GH-29996)
Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no>
1 parent b123ad8 commit dc4a212

File tree

1 file changed

+105
-78
lines changed

1 file changed

+105
-78
lines changed

Python/pythonrun.c

Lines changed: 105 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,78 @@ print_exception_message(struct exception_print_context *ctx, PyObject *type,
10401040
return 0;
10411041
}
10421042

1043+
static int
1044+
print_exception_suggestions(struct exception_print_context *ctx,
1045+
PyObject *value)
1046+
{
1047+
PyObject *f = ctx->file;
1048+
PyObject *suggestions = _Py_Offer_Suggestions(value);
1049+
if (suggestions) {
1050+
// Add a trailer ". Did you mean: (...)?"
1051+
if (PyFile_WriteString(". Did you mean: '", f) < 0) {
1052+
goto error;
1053+
}
1054+
if (PyFile_WriteObject(suggestions, f, Py_PRINT_RAW) < 0) {
1055+
goto error;
1056+
}
1057+
if (PyFile_WriteString("'?", f) < 0) {
1058+
goto error;
1059+
}
1060+
Py_DECREF(suggestions);
1061+
}
1062+
else if (PyErr_Occurred()) {
1063+
PyErr_Clear();
1064+
}
1065+
return 0;
1066+
error:
1067+
Py_XDECREF(suggestions);
1068+
return -1;
1069+
}
1070+
1071+
static int
1072+
print_exception_note(struct exception_print_context *ctx, PyObject *value)
1073+
{
1074+
PyObject *f = ctx->file;
1075+
_Py_IDENTIFIER(__note__);
1076+
1077+
PyObject *note = _PyObject_GetAttrId(value, &PyId___note__);
1078+
if (note == NULL) {
1079+
return -1;
1080+
}
1081+
if (!PyUnicode_Check(note)) {
1082+
Py_DECREF(note);
1083+
return 0;
1084+
}
1085+
1086+
PyObject *lines = PyUnicode_Splitlines(note, 1);
1087+
Py_DECREF(note);
1088+
1089+
if (lines == NULL) {
1090+
return -1;
1091+
}
1092+
1093+
Py_ssize_t n = PyList_GET_SIZE(lines);
1094+
for (Py_ssize_t i = 0; i < n; i++) {
1095+
PyObject *line = PyList_GET_ITEM(lines, i);
1096+
assert(PyUnicode_Check(line));
1097+
if (write_indented_margin(ctx, f) < 0) {
1098+
goto error;
1099+
}
1100+
if (PyFile_WriteObject(line, f, Py_PRINT_RAW) < 0) {
1101+
goto error;
1102+
}
1103+
}
1104+
if (PyFile_WriteString("\n", f) < 0) {
1105+
goto error;
1106+
}
1107+
1108+
Py_DECREF(lines);
1109+
return 0;
1110+
error:
1111+
Py_DECREF(lines);
1112+
return -1;
1113+
}
1114+
10431115
static void
10441116
print_exception(struct exception_print_context *ctx, PyObject *value)
10451117
{
@@ -1073,13 +1145,12 @@ print_exception(struct exception_print_context *ctx, PyObject *value)
10731145
PyErr_Clear();
10741146
}
10751147
else {
1076-
PyObject *line;
10771148

10781149
Py_DECREF(value);
10791150
value = message;
10801151

1081-
line = PyUnicode_FromFormat(" File \"%S\", line %zd\n",
1082-
filename, lineno);
1152+
PyObject *line = PyUnicode_FromFormat(" File \"%S\", line %zd\n",
1153+
filename, lineno);
10831154
Py_DECREF(filename);
10841155
if (line != NULL) {
10851156
err = write_indented_margin(ctx, f);
@@ -1118,59 +1189,16 @@ print_exception(struct exception_print_context *ctx, PyObject *value)
11181189
if (err == 0) {
11191190
err = print_exception_message(ctx, type, value);
11201191
}
1121-
1122-
/* try to write a newline in any case */
1123-
if (err < 0) {
1124-
PyErr_Clear();
1192+
if (err == 0) {
1193+
err = print_exception_suggestions(ctx, value);
11251194
}
1126-
PyObject* suggestions = _Py_Offer_Suggestions(value);
1127-
if (suggestions) {
1128-
// Add a trailer ". Did you mean: (...)?"
1129-
err = PyFile_WriteString(". Did you mean: '", f);
1130-
if (err == 0) {
1131-
err = PyFile_WriteObject(suggestions, f, Py_PRINT_RAW);
1132-
err += PyFile_WriteString("'?", f);
1133-
}
1134-
Py_DECREF(suggestions);
1135-
} else if (PyErr_Occurred()) {
1136-
PyErr_Clear();
1195+
if (err == 0) {
1196+
err = PyFile_WriteString("\n", f);
11371197
}
1138-
err += PyFile_WriteString("\n", f);
1139-
11401198
if (err == 0 && PyExceptionInstance_Check(value)) {
1141-
_Py_IDENTIFIER(__note__);
1142-
1143-
PyObject *note = _PyObject_GetAttrId(value, &PyId___note__);
1144-
if (note == NULL) {
1145-
err = -1;
1146-
}
1147-
if (err == 0 && PyUnicode_Check(note)) {
1148-
_Py_static_string(PyId_newline, "\n");
1149-
PyObject *lines = PyUnicode_Split(
1150-
note, _PyUnicode_FromId(&PyId_newline), -1);
1151-
if (lines == NULL) {
1152-
err = -1;
1153-
}
1154-
else {
1155-
Py_ssize_t n = PyList_GET_SIZE(lines);
1156-
for (Py_ssize_t i = 0; i < n; i++) {
1157-
if (err == 0) {
1158-
PyObject *line = PyList_GET_ITEM(lines, i);
1159-
assert(PyUnicode_Check(line));
1160-
err = write_indented_margin(ctx, f);
1161-
if (err == 0) {
1162-
err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
1163-
}
1164-
if (err == 0) {
1165-
err = PyFile_WriteString("\n", f);
1166-
}
1167-
}
1168-
}
1169-
}
1170-
Py_DECREF(lines);
1171-
}
1172-
Py_XDECREF(note);
1199+
err = print_exception_note(ctx, value);
11731200
}
1201+
11741202
Py_DECREF(value);
11751203
/* If an error happened here, don't show it.
11761204
XXX This is wrong, but too many callers rely on this behavior. */
@@ -1194,36 +1222,35 @@ print_chained(struct exception_print_context* ctx, PyObject *value,
11941222
const char * message, const char *tag)
11951223
{
11961224
PyObject *f = ctx->file;
1197-
bool need_close = ctx->need_close;
1198-
1199-
int err = Py_EnterRecursiveCall(" in print_chained");
1200-
if (err == 0) {
1201-
print_exception_recursive(ctx, value);
1202-
Py_LeaveRecursiveCall();
12031225

1204-
if (err == 0) {
1205-
err = write_indented_margin(ctx, f);
1206-
}
1207-
if (err == 0) {
1208-
err = PyFile_WriteString("\n", f);
1209-
}
1210-
if (err == 0) {
1211-
err = write_indented_margin(ctx, f);
1212-
}
1213-
if (err == 0) {
1214-
err = PyFile_WriteString(message, f);
1215-
}
1216-
if (err == 0) {
1217-
err = write_indented_margin(ctx, f);
1218-
}
1219-
if (err == 0) {
1220-
err = PyFile_WriteString("\n", f);
1221-
}
1226+
if (Py_EnterRecursiveCall(" in print_chained") < 0) {
1227+
return -1;
12221228
}
1223-
1229+
bool need_close = ctx->need_close;
1230+
print_exception_recursive(ctx, value);
12241231
ctx->need_close = need_close;
12251232

1226-
return err;
1233+
Py_LeaveRecursiveCall();
1234+
1235+
if (write_indented_margin(ctx, f) < 0) {
1236+
return -1;
1237+
}
1238+
if (PyFile_WriteString("\n", f) < 0) {
1239+
return -1;
1240+
}
1241+
if (write_indented_margin(ctx, f) < 0) {
1242+
return -1;
1243+
}
1244+
if (PyFile_WriteString(message, f) < 0) {
1245+
return -1;
1246+
}
1247+
if (write_indented_margin(ctx, f) < 0) {
1248+
return -1;
1249+
}
1250+
if (PyFile_WriteString("\n", f) < 0) {
1251+
return -1;
1252+
}
1253+
return 0;
12271254
}
12281255

12291256
static void

0 commit comments

Comments
 (0)