Mercurial > cpython-lru_cache-weakref
comparison Python/pythonrun.c @ 48474:2ee09afee126
implement chained exception tracebacks
patch from Antoine Pitrou #3112
| author | Benjamin Peterson <benjamin@python.org> |
|---|---|
| date | Tue, 15 Jul 2008 15:32:09 +0000 |
| parents | da47e7e135ae |
| children | e26c724d5e23 |
comparison
equal
deleted
inserted
replaced
| 48473:7d570df5e90a | 48474:2ee09afee126 |
|---|---|
| 1240 } | 1240 } |
| 1241 PyErr_Fetch(&exception, &v, &tb); | 1241 PyErr_Fetch(&exception, &v, &tb); |
| 1242 if (exception == NULL) | 1242 if (exception == NULL) |
| 1243 return; | 1243 return; |
| 1244 PyErr_NormalizeException(&exception, &v, &tb); | 1244 PyErr_NormalizeException(&exception, &v, &tb); |
| 1245 tb = tb ? tb : Py_None; | |
| 1246 PyException_SetTraceback(v, tb); | |
| 1245 if (exception == NULL) | 1247 if (exception == NULL) |
| 1246 return; | 1248 return; |
| 1247 /* Now we know v != NULL too */ | 1249 /* Now we know v != NULL too */ |
| 1248 if (set_sys_last_vars) { | 1250 if (set_sys_last_vars) { |
| 1249 PySys_SetObject("last_type", exception); | 1251 PySys_SetObject("last_type", exception); |
| 1250 PySys_SetObject("last_value", v); | 1252 PySys_SetObject("last_value", v); |
| 1251 PySys_SetObject("last_traceback", tb ? tb : Py_None); | 1253 PySys_SetObject("last_traceback", tb); |
| 1252 } | 1254 } |
| 1253 hook = PySys_GetObject("excepthook"); | 1255 hook = PySys_GetObject("excepthook"); |
| 1254 if (hook) { | 1256 if (hook) { |
| 1255 PyObject *args = PyTuple_Pack(3, | 1257 PyObject *args = PyTuple_Pack(3, exception, v, tb); |
| 1256 exception, v, tb ? tb : Py_None); | |
| 1257 PyObject *result = PyEval_CallObject(hook, args); | 1258 PyObject *result = PyEval_CallObject(hook, args); |
| 1258 if (result == NULL) { | 1259 if (result == NULL) { |
| 1259 PyObject *exception2, *v2, *tb2; | 1260 PyObject *exception2, *v2, *tb2; |
| 1260 if (PyErr_ExceptionMatches(PyExc_SystemExit)) { | 1261 if (PyErr_ExceptionMatches(PyExc_SystemExit)) { |
| 1261 handle_system_exit(); | 1262 handle_system_exit(); |
| 1291 Py_XDECREF(exception); | 1292 Py_XDECREF(exception); |
| 1292 Py_XDECREF(v); | 1293 Py_XDECREF(v); |
| 1293 Py_XDECREF(tb); | 1294 Py_XDECREF(tb); |
| 1294 } | 1295 } |
| 1295 | 1296 |
| 1296 void | 1297 static void |
| 1297 PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) | 1298 print_exception(PyObject *f, PyObject *value) |
| 1298 { | 1299 { |
| 1299 int err = 0; | 1300 int err = 0; |
| 1300 PyObject *f = PySys_GetObject("stderr"); | 1301 PyObject *type, *tb; |
| 1302 | |
| 1301 Py_INCREF(value); | 1303 Py_INCREF(value); |
| 1302 if (f == Py_None) { | 1304 fflush(stdout); |
| 1303 /* pass */ | 1305 type = (PyObject *) Py_TYPE(value); |
| 1304 } | 1306 tb = PyException_GetTraceback(value); |
| 1305 else if (f == NULL) { | 1307 if (tb && tb != Py_None) |
| 1306 _PyObject_Dump(value); | 1308 err = PyTraceBack_Print(tb, f); |
| 1307 fprintf(stderr, "lost sys.stderr\n"); | 1309 if (err == 0 && |
| 1310 PyObject_HasAttrString(value, "print_file_and_line")) | |
| 1311 { | |
| 1312 PyObject *message; | |
| 1313 const char *filename, *text; | |
| 1314 int lineno, offset; | |
| 1315 if (!parse_syntax_error(value, &message, &filename, | |
| 1316 &lineno, &offset, &text)) | |
| 1317 PyErr_Clear(); | |
| 1318 else { | |
| 1319 char buf[10]; | |
| 1320 PyFile_WriteString(" File \"", f); | |
| 1321 if (filename == NULL) | |
| 1322 PyFile_WriteString("<string>", f); | |
| 1323 else | |
| 1324 PyFile_WriteString(filename, f); | |
| 1325 PyFile_WriteString("\", line ", f); | |
| 1326 PyOS_snprintf(buf, sizeof(buf), "%d", lineno); | |
| 1327 PyFile_WriteString(buf, f); | |
| 1328 PyFile_WriteString("\n", f); | |
| 1329 if (text != NULL) | |
| 1330 print_error_text(f, offset, text); | |
| 1331 Py_DECREF(value); | |
| 1332 value = message; | |
| 1333 /* Can't be bothered to check all those | |
| 1334 PyFile_WriteString() calls */ | |
| 1335 if (PyErr_Occurred()) | |
| 1336 err = -1; | |
| 1337 } | |
| 1338 } | |
| 1339 if (err) { | |
| 1340 /* Don't do anything else */ | |
| 1308 } | 1341 } |
| 1309 else { | 1342 else { |
| 1310 fflush(stdout); | 1343 assert(PyExceptionClass_Check(type)); |
| 1311 if (tb && tb != Py_None) | 1344 PyObject* moduleName; |
| 1312 err = PyTraceBack_Print(tb, f); | 1345 char* className = PyExceptionClass_Name(type); |
| 1313 if (err == 0 && | 1346 if (className != NULL) { |
| 1314 PyObject_HasAttrString(value, "print_file_and_line")) | 1347 char *dot = strrchr(className, '.'); |
| 1348 if (dot != NULL) | |
| 1349 className = dot+1; | |
| 1350 } | |
| 1351 | |
| 1352 moduleName = PyObject_GetAttrString(type, "__module__"); | |
| 1353 if (moduleName == NULL || !PyUnicode_Check(moduleName)) | |
| 1315 { | 1354 { |
| 1316 PyObject *message; | 1355 Py_DECREF(moduleName); |
| 1317 const char *filename, *text; | 1356 err = PyFile_WriteString("<unknown>", f); |
| 1318 int lineno, offset; | 1357 } |
| 1319 if (!parse_syntax_error(value, &message, &filename, | 1358 else { |
| 1320 &lineno, &offset, &text)) | 1359 char* modstr = PyUnicode_AsString(moduleName); |
| 1321 PyErr_Clear(); | 1360 if (modstr && strcmp(modstr, "builtins")) |
| 1322 else { | 1361 { |
| 1323 char buf[10]; | 1362 err = PyFile_WriteString(modstr, f); |
| 1324 PyFile_WriteString(" File \"", f); | 1363 err += PyFile_WriteString(".", f); |
| 1325 if (filename == NULL) | |
| 1326 PyFile_WriteString("<string>", f); | |
| 1327 else | |
| 1328 PyFile_WriteString(filename, f); | |
| 1329 PyFile_WriteString("\", line ", f); | |
| 1330 PyOS_snprintf(buf, sizeof(buf), "%d", lineno); | |
| 1331 PyFile_WriteString(buf, f); | |
| 1332 PyFile_WriteString("\n", f); | |
| 1333 if (text != NULL) | |
| 1334 print_error_text(f, offset, text); | |
| 1335 Py_DECREF(value); | |
| 1336 value = message; | |
| 1337 /* Can't be bothered to check all those | |
| 1338 PyFile_WriteString() calls */ | |
| 1339 if (PyErr_Occurred()) | |
| 1340 err = -1; | |
| 1341 } | 1364 } |
| 1342 } | 1365 Py_DECREF(moduleName); |
| 1343 if (err) { | 1366 } |
| 1344 /* Don't do anything else */ | 1367 if (err == 0) { |
| 1345 } | 1368 if (className == NULL) |
| 1346 else if (PyExceptionClass_Check(exception)) { | 1369 err = PyFile_WriteString("<unknown>", f); |
| 1347 PyObject* moduleName; | 1370 else |
| 1348 char* className = PyExceptionClass_Name(exception); | 1371 err = PyFile_WriteString(className, f); |
| 1349 if (className != NULL) { | 1372 } |
| 1350 char *dot = strrchr(className, '.'); | 1373 } |
| 1351 if (dot != NULL) | 1374 if (err == 0 && (value != Py_None)) { |
| 1352 className = dot+1; | 1375 PyObject *s = PyObject_Str(value); |
| 1353 } | 1376 /* only print colon if the str() of the |
| 1354 | 1377 object is not the empty string |
| 1355 moduleName = PyObject_GetAttrString(exception, "__module__"); | 1378 */ |
| 1356 if (moduleName == NULL || !PyUnicode_Check(moduleName)) | 1379 if (s == NULL) |
| 1357 { | 1380 err = -1; |
| 1358 Py_DECREF(moduleName); | 1381 else if (!PyUnicode_Check(s) || |
| 1359 err = PyFile_WriteString("<unknown>", f); | 1382 PyUnicode_GetSize(s) != 0) |
| 1360 } | 1383 err = PyFile_WriteString(": ", f); |
| 1361 else { | 1384 if (err == 0) |
| 1362 char* modstr = PyUnicode_AsString(moduleName); | 1385 err = PyFile_WriteObject(s, f, Py_PRINT_RAW); |
| 1363 if (modstr && strcmp(modstr, "builtins")) | 1386 Py_XDECREF(s); |
| 1364 { | 1387 } |
| 1365 err = PyFile_WriteString(modstr, f); | 1388 /* try to write a newline in any case */ |
| 1366 err += PyFile_WriteString(".", f); | 1389 err += PyFile_WriteString("\n", f); |
| 1367 } | 1390 Py_XDECREF(tb); |
| 1368 Py_DECREF(moduleName); | |
| 1369 } | |
| 1370 if (err == 0) { | |
| 1371 if (className == NULL) | |
| 1372 err = PyFile_WriteString("<unknown>", f); | |
| 1373 else | |
| 1374 err = PyFile_WriteString(className, f); | |
| 1375 } | |
| 1376 } | |
| 1377 else | |
| 1378 err = PyFile_WriteObject(exception, f, Py_PRINT_RAW); | |
| 1379 if (err == 0 && (value != Py_None)) { | |
| 1380 PyObject *s = PyObject_Str(value); | |
| 1381 /* only print colon if the str() of the | |
| 1382 object is not the empty string | |
| 1383 */ | |
| 1384 if (s == NULL) | |
| 1385 err = -1; | |
| 1386 else if (!PyUnicode_Check(s) || | |
| 1387 PyUnicode_GetSize(s) != 0) | |
| 1388 err = PyFile_WriteString(": ", f); | |
| 1389 if (err == 0) | |
| 1390 err = PyFile_WriteObject(s, f, Py_PRINT_RAW); | |
| 1391 Py_XDECREF(s); | |
| 1392 } | |
| 1393 /* try to write a newline in any case */ | |
| 1394 err += PyFile_WriteString("\n", f); | |
| 1395 } | |
| 1396 Py_DECREF(value); | 1391 Py_DECREF(value); |
| 1397 /* If an error happened here, don't show it. | 1392 /* If an error happened here, don't show it. |
| 1398 XXX This is wrong, but too many callers rely on this behavior. */ | 1393 XXX This is wrong, but too many callers rely on this behavior. */ |
| 1399 if (err != 0) | 1394 if (err != 0) |
| 1400 PyErr_Clear(); | 1395 PyErr_Clear(); |
| 1396 } | |
| 1397 | |
| 1398 static const char *cause_message = | |
| 1399 "\nThe above exception was the direct cause " | |
| 1400 "of the following exception:\n\n"; | |
| 1401 | |
| 1402 static const char *context_message = | |
| 1403 "\nDuring handling of the above exception, " | |
| 1404 "another exception occurred:\n\n"; | |
| 1405 | |
| 1406 static void | |
| 1407 print_exception_recursive(PyObject *f, PyObject *value, PyObject *seen) | |
| 1408 { | |
| 1409 int err = 0, res; | |
| 1410 PyObject *cause, *context; | |
| 1411 | |
| 1412 if (seen != NULL) { | |
| 1413 /* Exception chaining */ | |
| 1414 if (PySet_Add(seen, value) == -1) | |
| 1415 PyErr_Clear(); | |
| 1416 else if (PyExceptionInstance_Check(value)) { | |
| 1417 cause = PyException_GetCause(value); | |
| 1418 context = PyException_GetContext(value); | |
| 1419 if (cause) { | |
| 1420 res = PySet_Contains(seen, cause); | |
| 1421 if (res == -1) | |
| 1422 PyErr_Clear(); | |
| 1423 if (res == 0) { | |
| 1424 print_exception_recursive( | |
| 1425 f, cause, seen); | |
| 1426 err |= PyFile_WriteString( | |
| 1427 cause_message, f); | |
| 1428 } | |
| 1429 } | |
| 1430 if (context) { | |
| 1431 res = PySet_Contains(seen, context); | |
| 1432 if (res == -1) | |
| 1433 PyErr_Clear(); | |
| 1434 if (res == 0) { | |
| 1435 print_exception_recursive( | |
| 1436 f, context, seen); | |
| 1437 err |= PyFile_WriteString( | |
| 1438 context_message, f); | |
| 1439 } | |
| 1440 } | |
| 1441 Py_XDECREF(context); | |
| 1442 Py_XDECREF(cause); | |
| 1443 } | |
| 1444 } | |
| 1445 print_exception(f, value); | |
| 1446 if (err != 0) | |
| 1447 PyErr_Clear(); | |
| 1448 } | |
| 1449 | |
| 1450 void | |
| 1451 PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) | |
| 1452 { | |
| 1453 PyObject *seen; | |
| 1454 PyObject *f = PySys_GetObject("stderr"); | |
| 1455 if (f == Py_None) { | |
| 1456 /* pass */ | |
| 1457 } | |
| 1458 else if (f == NULL) { | |
| 1459 _PyObject_Dump(value); | |
| 1460 fprintf(stderr, "lost sys.stderr\n"); | |
| 1461 } | |
| 1462 else { | |
| 1463 /* We choose to ignore seen being possibly NULL, and report | |
| 1464 at least the main exception (it could be a MemoryError). | |
| 1465 */ | |
| 1466 seen = PySet_New(NULL); | |
| 1467 if (seen == NULL) | |
| 1468 PyErr_Clear(); | |
| 1469 print_exception_recursive(f, value, seen); | |
| 1470 Py_XDECREF(seen); | |
| 1471 } | |
| 1401 } | 1472 } |
| 1402 | 1473 |
| 1403 PyObject * | 1474 PyObject * |
| 1404 PyRun_StringFlags(const char *str, int start, PyObject *globals, | 1475 PyRun_StringFlags(const char *str, int start, PyObject *globals, |
| 1405 PyObject *locals, PyCompilerFlags *flags) | 1476 PyObject *locals, PyCompilerFlags *flags) |
