diff options
| author | shadchin <[email protected]> | 2026-02-03 21:59:07 +0300 |
|---|---|---|
| committer | shadchin <[email protected]> | 2026-02-03 22:28:51 +0300 |
| commit | bce46f28de392862d5c6c3b185d844ee7c623be3 (patch) | |
| tree | 424878b5b90144f98970ce4a2745990c77330ad2 /contrib/tools/python3/Python/pythonrun.c | |
| parent | 0e0ee9fa48ce9411b4038aa769493d22ff6c10a2 (diff) | |
Import Python 3.13.11
commit_hash:bbb53cefb159aa3e7afaa475fd19d5a03b66945f
Diffstat (limited to 'contrib/tools/python3/Python/pythonrun.c')
| -rw-r--r-- | contrib/tools/python3/Python/pythonrun.c | 1123 |
1 files changed, 418 insertions, 705 deletions
diff --git a/contrib/tools/python3/Python/pythonrun.c b/contrib/tools/python3/Python/pythonrun.c index 89287bace08..c4a1275eb52 100644 --- a/contrib/tools/python3/Python/pythonrun.c +++ b/contrib/tools/python3/Python/pythonrun.c @@ -10,17 +10,18 @@ #include "Python.h" -#include "pycore_ast.h" // PyAST_mod2obj -#include "pycore_ceval.h" // _Py_EnterRecursiveCall +#include "pycore_ast.h" // PyAST_mod2obj() +#include "pycore_ceval.h" // _Py_EnterRecursiveCall() #include "pycore_compile.h" // _PyAST_Compile() #include "pycore_interp.h" // PyInterpreterState.importlib #include "pycore_object.h" // _PyDebug_PrintTotalRefs() #include "pycore_parser.h" // _PyParser_ASTFromString() -#include "pycore_pyerrors.h" // _PyErr_GetRaisedException, _Py_Offer_Suggestions -#include "pycore_pylifecycle.h" // _Py_UnhandledKeyboardInterrupt +#include "pycore_pyerrors.h" // _PyErr_GetRaisedException() +#include "pycore_pylifecycle.h" // _Py_FdIsInteractive() #include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_pythonrun.h" // export _PyRun_InteractiveLoopObject() #include "pycore_sysmodule.h" // _PySys_Audit() -#include "pycore_traceback.h" // _PyTraceBack_Print_Indented() +#include "pycore_traceback.h" // _PyTraceBack_Print() #include "errcode.h" // E_EOF #include "marshal.h" // PyMarshal_ReadLongFromFile() @@ -36,22 +37,20 @@ # include "windows.h" #endif - -#ifdef __cplusplus -extern "C" { -#endif - /* Forward */ static void flush_io(void); static PyObject *run_mod(mod_ty, PyObject *, PyObject *, PyObject *, - PyCompilerFlags *, PyArena *); + PyCompilerFlags *, PyArena *, PyObject*, int); static PyObject *run_pyc_file(FILE *, PyObject *, PyObject *, PyCompilerFlags *); static int PyRun_InteractiveOneObjectEx(FILE *, PyObject *, PyCompilerFlags *); static PyObject* pyrun_file(FILE *fp, PyObject *filename, int start, PyObject *globals, PyObject *locals, int closeit, PyCompilerFlags *flags); - +static PyObject * +_PyRun_StringFlagsWithName(const char *str, PyObject* name, int start, + PyObject *globals, PyObject *locals, PyCompilerFlags *flags, + int generate_new_source); int _PyRun_AnyFileObject(FILE *fp, PyObject *filename, int closeit, @@ -84,13 +83,11 @@ _PyRun_AnyFileObject(FILE *fp, PyObject *filename, int closeit, return res; } - -/* Parse input from a file and execute it */ int PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit, PyCompilerFlags *flags) { - PyObject *filename_obj; + PyObject *filename_obj = NULL; if (filename != NULL) { filename_obj = PyUnicode_DecodeFSDefault(filename); if (filename_obj == NULL) { @@ -98,9 +95,6 @@ PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit, return -1; } } - else { - filename_obj = NULL; - } int res = _PyRun_AnyFileObject(fp, filename_obj, closeit, flags); Py_XDECREF(filename_obj); return res; @@ -197,98 +191,160 @@ PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flag } -/* A PyRun_InteractiveOneObject() auxiliary function that does not print the - * error on failure. */ +// Call _PyParser_ASTFromFile() with sys.stdin.encoding, sys.ps1 and sys.ps2 static int -PyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename, - PyCompilerFlags *flags) +pyrun_one_parse_ast(FILE *fp, PyObject *filename, + PyCompilerFlags *flags, PyArena *arena, + mod_ty *pmod, PyObject** interactive_src) { - PyObject *m, *d, *v, *w, *oenc = NULL; - mod_ty mod; - PyArena *arena; - const char *ps1 = "", *ps2 = "", *enc = NULL; - int errcode = 0; - + // Get sys.stdin.encoding (as UTF-8) + PyObject *attr; + PyObject *encoding_obj = NULL; + const char *encoding = NULL; if (fp == stdin) { - /* Fetch encoding from sys.stdin if possible. */ - if (_PySys_GetOptionalAttr(&_Py_ID(stdin), &v) < 0) { - return -1; + if (_PySys_GetOptionalAttr(&_Py_ID(stdin), &attr) < 0) { + PyErr_Clear(); } - if (v && v != Py_None) { - oenc = PyObject_GetAttr(v, &_Py_ID(encoding)); - if (oenc) - enc = PyUnicode_AsUTF8(oenc); - if (!enc) + else if (attr != NULL && attr != Py_None) { + if (PyObject_GetOptionalAttr(attr, &_Py_ID(encoding), &encoding_obj) < 0) { PyErr_Clear(); + } + else if (encoding_obj && PyUnicode_Check(encoding_obj)) { + encoding = PyUnicode_AsUTF8(encoding_obj); + if (!encoding) { + PyErr_Clear(); + } + } } - Py_XDECREF(v); + Py_XDECREF(attr); } - if (_PySys_GetOptionalAttr(&_Py_ID(ps1), &v) < 0) { - Py_XDECREF(oenc); - return -1; + + // Get sys.ps1 (as UTF-8) + PyObject *ps1_obj = NULL; + const char *ps1 = ""; + if (_PySys_GetOptionalAttr(&_Py_ID(ps1), &attr) < 0) { + PyErr_Clear(); } - if (v != NULL) { - Py_SETREF(v, PyObject_Str(v)); - if (v == NULL) + else if (attr != NULL) { + ps1_obj = PyObject_Str(attr); + Py_DECREF(attr); + if (ps1_obj == NULL) { PyErr_Clear(); - else if (PyUnicode_Check(v)) { - ps1 = PyUnicode_AsUTF8(v); + } + else if (PyUnicode_Check(ps1_obj)) { + ps1 = PyUnicode_AsUTF8(ps1_obj); if (ps1 == NULL) { PyErr_Clear(); ps1 = ""; } } } - if (_PySys_GetOptionalAttr(&_Py_ID(ps2), &w) < 0) { - Py_XDECREF(oenc); - return -1; + + // Get sys.ps2 (as UTF-8) + PyObject *ps2_obj = NULL; + const char *ps2 = ""; + if (_PySys_GetOptionalAttr(&_Py_ID(ps2), &attr) < 0) { + PyErr_Clear(); } - if (w != NULL) { - Py_SETREF(w, PyObject_Str(w)); - if (w == NULL) + else if (attr != NULL) { + ps2_obj = PyObject_Str(attr); + Py_DECREF(attr); + if (ps2_obj == NULL) { PyErr_Clear(); - else if (PyUnicode_Check(w)) { - ps2 = PyUnicode_AsUTF8(w); + } + else if (PyUnicode_Check(ps2_obj)) { + ps2 = PyUnicode_AsUTF8(ps2_obj); if (ps2 == NULL) { PyErr_Clear(); ps2 = ""; } } } - arena = _PyArena_New(); - if (arena == NULL) { - Py_XDECREF(v); - Py_XDECREF(w); - Py_XDECREF(oenc); - return -1; - } - mod = _PyParser_ASTFromFile(fp, filename, enc, Py_single_input, - ps1, ps2, flags, &errcode, arena); + int errcode = 0; + *pmod = _PyParser_InteractiveASTFromFile(fp, filename, encoding, + Py_single_input, ps1, ps2, + flags, &errcode, interactive_src, arena); + Py_XDECREF(ps1_obj); + Py_XDECREF(ps2_obj); + Py_XDECREF(encoding_obj); - Py_XDECREF(v); - Py_XDECREF(w); - Py_XDECREF(oenc); - if (mod == NULL) { - _PyArena_Free(arena); + if (*pmod == NULL) { if (errcode == E_EOF) { PyErr_Clear(); return E_EOF; } return -1; } - m = PyImport_AddModuleObject(&_Py_ID(__main__)); - if (m == NULL) { + return 0; +} + + +/* A PyRun_InteractiveOneObject() auxiliary function that does not print the + * error on failure. */ +static int +PyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename, + PyCompilerFlags *flags) +{ + PyArena *arena = _PyArena_New(); + if (arena == NULL) { + return -1; + } + + mod_ty mod; + PyObject *interactive_src; + int parse_res = pyrun_one_parse_ast(fp, filename, flags, arena, &mod, &interactive_src); + if (parse_res != 0) { + _PyArena_Free(arena); + return parse_res; + } + + PyObject *main_module = PyImport_AddModuleRef("__main__"); + if (main_module == NULL) { _PyArena_Free(arena); return -1; } - d = PyModule_GetDict(m); - v = run_mod(mod, filename, d, d, flags, arena); + PyObject *main_dict = PyModule_GetDict(main_module); // borrowed ref + + PyObject *res = run_mod(mod, filename, main_dict, main_dict, flags, arena, interactive_src, 1); + Py_INCREF(interactive_src); _PyArena_Free(arena); - if (v == NULL) { + Py_DECREF(main_module); + if (res == NULL) { + PyThreadState *tstate = _PyThreadState_GET(); + PyObject *exc = _PyErr_GetRaisedException(tstate); + if (PyType_IsSubtype(Py_TYPE(exc), + (PyTypeObject *) PyExc_SyntaxError)) + { + /* fix "text" attribute */ + assert(interactive_src != NULL); + PyObject *xs = PyUnicode_Splitlines(interactive_src, 1); + if (xs == NULL) { + goto error; + } + PyObject *exc_lineno = PyObject_GetAttr(exc, &_Py_ID(lineno)); + if (exc_lineno == NULL) { + Py_DECREF(xs); + goto error; + } + int n = PyLong_AsInt(exc_lineno); + Py_DECREF(exc_lineno); + if (n <= 0 || n > PyList_GET_SIZE(xs)) { + Py_DECREF(xs); + goto error; + } + PyObject *line = PyList_GET_ITEM(xs, n - 1); + PyObject_SetAttr(exc, &_Py_ID(text), line); + Py_DECREF(xs); + } +error: + Py_DECREF(interactive_src); + _PyErr_SetRaisedException(tstate, exc); return -1; } - Py_DECREF(v); + Py_DECREF(interactive_src); + Py_DECREF(res); + flush_io(); return 0; } @@ -402,22 +458,23 @@ int _PyRun_SimpleFileObject(FILE *fp, PyObject *filename, int closeit, PyCompilerFlags *flags) { - PyObject *m, *d, *v; - int set_file_name = 0, ret = -1; + int ret = -1; - m = PyImport_AddModule("__main__"); - if (m == NULL) + PyObject *main_module = PyImport_AddModuleRef("__main__"); + if (main_module == NULL) return -1; - Py_INCREF(m); - d = PyModule_GetDict(m); - if (_PyDict_GetItemStringWithError(d, "__file__") == NULL) { - if (PyErr_Occurred()) { - goto done; - } - if (PyDict_SetItemString(d, "__file__", filename) < 0) { + PyObject *dict = PyModule_GetDict(main_module); // borrowed ref + + int set_file_name = 0; + int has_file = PyDict_ContainsString(dict, "__file__"); + if (has_file < 0) { + goto done; + } + if (!has_file) { + if (PyDict_SetItemString(dict, "__file__", filename) < 0) { goto done; } - if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) { + if (PyDict_SetItemString(dict, "__cached__", Py_None) < 0) { goto done; } set_file_name = 1; @@ -428,6 +485,7 @@ _PyRun_SimpleFileObject(FILE *fp, PyObject *filename, int closeit, goto done; } + PyObject *v; if (pyc) { FILE *pyc_fp; /* Try to run a pyc file. First, re-open in binary */ @@ -441,42 +499,43 @@ _PyRun_SimpleFileObject(FILE *fp, PyObject *filename, int closeit, goto done; } - if (set_main_loader(d, filename, "SourcelessFileLoader") < 0) { + if (set_main_loader(dict, filename, "SourcelessFileLoader") < 0) { fprintf(stderr, "python: failed to set __main__.__loader__\n"); ret = -1; fclose(pyc_fp); goto done; } - v = run_pyc_file(pyc_fp, d, d, flags); + v = run_pyc_file(pyc_fp, dict, dict, flags); } else { /* When running from stdin, leave __main__.__loader__ alone */ - if (PyUnicode_CompareWithASCIIString(filename, "<stdin>") != 0 && - set_main_loader(d, filename, "SourceFileLoader") < 0) { + if ((!PyUnicode_Check(filename) || !PyUnicode_EqualToUTF8(filename, "<stdin>")) && + set_main_loader(dict, filename, "SourceFileLoader") < 0) { fprintf(stderr, "python: failed to set __main__.__loader__\n"); ret = -1; goto done; } - v = pyrun_file(fp, filename, Py_file_input, d, d, + v = pyrun_file(fp, filename, Py_file_input, dict, dict, closeit, flags); } flush_io(); if (v == NULL) { - Py_CLEAR(m); + Py_CLEAR(main_module); PyErr_Print(); goto done; } Py_DECREF(v); ret = 0; + done: if (set_file_name) { - if (PyDict_DelItemString(d, "__file__")) { - PyErr_Clear(); + if (PyDict_PopString(dict, "__file__", NULL) < 0) { + PyErr_Print(); } - if (PyDict_DelItemString(d, "__cached__")) { - PyErr_Clear(); + if (PyDict_PopString(dict, "__cached__", NULL) < 0) { + PyErr_Print(); } } - Py_XDECREF(m); + Py_XDECREF(main_module); return ret; } @@ -496,214 +555,65 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, int -PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags) -{ - PyObject *m, *d, *v; - m = PyImport_AddModule("__main__"); - if (m == NULL) +_PyRun_SimpleStringFlagsWithName(const char *command, const char* name, PyCompilerFlags *flags) { + PyObject *main_module = PyImport_AddModuleRef("__main__"); + if (main_module == NULL) { return -1; - d = PyModule_GetDict(m); - v = PyRun_StringFlags(command, Py_file_input, d, d, flags); - if (v == NULL) { - PyErr_Print(); - return -1; - } - Py_DECREF(v); - return 0; -} - -static int -parse_syntax_error(PyObject *err, PyObject **message, PyObject **filename, - Py_ssize_t *lineno, Py_ssize_t *offset, - Py_ssize_t* end_lineno, Py_ssize_t* end_offset, - PyObject **text) -{ - Py_ssize_t hold; - PyObject *v; - - *message = NULL; - *filename = NULL; - - /* new style errors. `err' is an instance */ - *message = PyObject_GetAttr(err, &_Py_ID(msg)); - if (!*message) - goto finally; - - v = PyObject_GetAttr(err, &_Py_ID(filename)); - if (!v) - goto finally; - if (v == Py_None) { - Py_DECREF(v); - _Py_DECLARE_STR(anon_string, "<string>"); - *filename = Py_NewRef(&_Py_STR(anon_string)); - } - else { - *filename = v; } + PyObject *dict = PyModule_GetDict(main_module); // borrowed ref - v = PyObject_GetAttr(err, &_Py_ID(lineno)); - if (!v) - goto finally; - hold = PyLong_AsSsize_t(v); - Py_DECREF(v); - if (hold < 0 && PyErr_Occurred()) - goto finally; - *lineno = hold; - - v = PyObject_GetAttr(err, &_Py_ID(offset)); - if (!v) - goto finally; - if (v == Py_None) { - *offset = -1; - Py_DECREF(v); + PyObject *res = NULL; + if (name == NULL) { + res = PyRun_StringFlags(command, Py_file_input, dict, dict, flags); } else { - hold = PyLong_AsSsize_t(v); - Py_DECREF(v); - if (hold < 0 && PyErr_Occurred()) - goto finally; - *offset = hold; - } - - v = PyObject_GetAttr(err, &_Py_ID(end_lineno)); - if (!v) { - PyErr_Clear(); - *end_lineno = *lineno; - } - else if (v == Py_None) { - *end_lineno = *lineno; - Py_DECREF(v); - } else { - hold = PyLong_AsSsize_t(v); - Py_DECREF(v); - if (hold < 0 && PyErr_Occurred()) - goto finally; - *end_lineno = hold; - } - - v = PyObject_GetAttr(err, &_Py_ID(end_offset)); - if (!v) { - PyErr_Clear(); - *end_offset = -1; - } - else if (v == Py_None) { - *end_offset = -1; - Py_DECREF(v); - } else { - hold = PyLong_AsSsize_t(v); - Py_DECREF(v); - if (hold < 0 && PyErr_Occurred()) - goto finally; - *end_offset = hold; - } - - v = PyObject_GetAttr(err, &_Py_ID(text)); - if (!v) - goto finally; - if (v == Py_None) { - Py_DECREF(v); - *text = NULL; + PyObject* the_name = PyUnicode_FromString(name); + if (!the_name) { + PyErr_Print(); + return -1; + } + res = _PyRun_StringFlagsWithName(command, the_name, Py_file_input, dict, dict, flags, 0); + Py_DECREF(the_name); } - else { - *text = v; + Py_DECREF(main_module); + if (res == NULL) { + PyErr_Print(); + return -1; } - return 1; -finally: - Py_XDECREF(*message); - Py_XDECREF(*filename); + Py_DECREF(res); return 0; } -static int -print_error_text(PyObject *f, Py_ssize_t offset, Py_ssize_t end_offset, - PyObject *text_obj) +int +PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags) { - size_t caret_repetitions = (end_offset > 0 && end_offset > offset) ? - end_offset - offset : 1; - - /* Convert text to a char pointer; return if error */ - const char *text = PyUnicode_AsUTF8(text_obj); - if (text == NULL) { - return -1; - } - - /* Convert offset from 1-based to 0-based */ - offset--; - - /* Strip leading whitespace from text, adjusting offset as we go */ - while (*text == ' ' || *text == '\t' || *text == '\f') { - text++; - offset--; - } - - /* Calculate text length excluding trailing newline */ - Py_ssize_t len = strlen(text); - if (len > 0 && text[len-1] == '\n') { - len--; - } - - /* Clip offset to at most len */ - if (offset > len) { - offset = len; - } - - /* Skip past newlines embedded in text */ - for (;;) { - const char *nl = strchr(text, '\n'); - if (nl == NULL) { - break; - } - Py_ssize_t inl = nl - text; - if (inl >= offset) { - break; - } - inl += 1; - text += inl; - len -= inl; - offset -= (int)inl; - } - - /* Print text */ - if (PyFile_WriteString(" ", f) < 0) { - return -1; - } - if (PyFile_WriteString(text, f) < 0) { - return -1; - } - - /* Make sure there's a newline at the end */ - if (text[len] != '\n') { - if (PyFile_WriteString("\n", f) < 0) { - return -1; - } - } - - /* Don't print caret if it points to the left of the text */ - if (offset < 0) { - return 0; - } + return _PyRun_SimpleStringFlagsWithName(command, NULL, flags); +} - /* Write caret line */ - if (PyFile_WriteString(" ", f) < 0) { - return -1; - } - while (--offset >= 0) { - if (PyFile_WriteString(" ", f) < 0) { - return -1; - } - } - for (size_t caret_iter=0; caret_iter < caret_repetitions ; caret_iter++) { - if (PyFile_WriteString("^", f) < 0) { - return -1; +static int +parse_exit_code(PyObject *code, int *exitcode_p) +{ + if (PyLong_Check(code)) { + // gh-125842: Use a long long to avoid an overflow error when `long` + // is 32-bit. We still truncate the result to an int. + int exitcode = (int)PyLong_AsLongLong(code); + if (exitcode == -1 && PyErr_Occurred()) { + // On overflow or other error, clear the exception and use -1 + // as the exit code to match historical Python behavior. + PyErr_Clear(); + *exitcode_p = -1; + return 1; } + *exitcode_p = exitcode; + return 1; } - if (PyFile_WriteString("\n", f) < 0) { - return -1; + else if (code == Py_None) { + *exitcode_p = 0; + return 1; } return 0; } - int _Py_HandleSystemExit(int *exitcode_p) { @@ -720,51 +630,43 @@ _Py_HandleSystemExit(int *exitcode_p) fflush(stdout); - int exitcode = 0; - PyObject *exc = PyErr_GetRaisedException(); - if (exc == NULL) { - goto done; - } - assert(PyExceptionInstance_Check(exc)); + assert(exc != NULL && PyExceptionInstance_Check(exc)); - /* The error code should be in the `code' attribute. */ PyObject *code = PyObject_GetAttr(exc, &_Py_ID(code)); - if (code) { + if (code == NULL) { + // If the exception has no 'code' attribute, print the exception below + PyErr_Clear(); + } + else if (parse_exit_code(code, exitcode_p)) { + Py_DECREF(code); + Py_CLEAR(exc); + return 1; + } + else { + // If code is not an int or None, print it below Py_SETREF(exc, code); - if (exc == Py_None) { - goto done; - } } - /* If we failed to dig out the 'code' attribute, - * just let the else clause below print the error. - */ - if (PyLong_Check(exc)) { - exitcode = (int)PyLong_AsLong(exc); + PyObject *sys_stderr; + if (_PySys_GetOptionalAttr(&_Py_ID(stderr), &sys_stderr) < 0) { + PyErr_Clear(); + } + else if (sys_stderr != NULL && sys_stderr != Py_None) { + if (PyFile_WriteObject(exc, sys_stderr, Py_PRINT_RAW) < 0) { + PyErr_Clear(); + } } else { - PyObject *sys_stderr; - (void) _PySys_GetOptionalAttr(&_Py_ID(stderr), &sys_stderr); - /* We clear the exception here to avoid triggering the assertion - * in PyObject_Str that ensures it won't silently lose exception - * details. - */ - PyErr_Clear(); - if (sys_stderr != NULL && sys_stderr != Py_None) { - PyFile_WriteObject(exc, sys_stderr, Py_PRINT_RAW); - } else { - PyObject_Print(exc, stderr, Py_PRINT_RAW); - fflush(stderr); + if (PyObject_Print(exc, stderr, Py_PRINT_RAW) < 0) { + PyErr_Clear(); } - Py_XDECREF(sys_stderr); - PySys_WriteStderr("\n"); - exitcode = 1; + fflush(stderr); } - -done: + PySys_WriteStderr("\n"); + Py_XDECREF(sys_stderr); Py_CLEAR(exc); - *exitcode_p = exitcode; + *exitcode_p = 1; return 1; } @@ -820,14 +722,11 @@ _PyErr_PrintEx(PyThreadState *tstate, int set_sys_last_vars) PyErr_Clear(); goto done; } - _PyErr_WriteUnraisableMsg("in audit hook", NULL); + PyErr_FormatUnraisable("Exception ignored in audit hook"); } if (hook) { - PyObject* stack[3]; - stack[0] = typ; - stack[1] = exc; - stack[2] = tb; - PyObject *result = _PyObject_FastCall(hook, stack, 3); + PyObject* args[3] = {typ, exc, tb}; + PyObject *result = PyObject_Vectorcall(hook, args, 3, NULL); if (result == NULL) { handle_system_exit(); @@ -879,29 +778,13 @@ struct exception_print_context { PyObject *file; PyObject *seen; // Prevent cycles in recursion - int exception_group_depth; // nesting level of current exception group - bool need_close; // Need a closing bottom frame - int max_group_width; // Maximum number of children of each EG - int max_group_depth; // Maximum nesting level of EGs }; -#define EXC_MARGIN(ctx) ((ctx)->exception_group_depth ? "| " : "") -#define EXC_INDENT(ctx) (2 * (ctx)->exception_group_depth) - -static int -write_indented_margin(struct exception_print_context *ctx, PyObject *f) -{ - return _Py_WriteIndentedMargin(EXC_INDENT(ctx), EXC_MARGIN(ctx), f); -} - static int print_exception_invalid_type(struct exception_print_context *ctx, PyObject *value) { PyObject *f = ctx->file; - 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) { @@ -925,15 +808,7 @@ print_exception_traceback(struct exception_print_context *ctx, PyObject *value) PyObject *tb = PyException_GetTraceback(value); if (tb && tb != Py_None) { const char *header = EXCEPTION_TB_HEADER; - const char *header_margin = EXC_MARGIN(ctx); - if (_PyBaseExceptionGroup_Check(value)) { - header = EXCEPTION_GROUP_TB_HEADER; - if (ctx->exception_group_depth == 1) { - header_margin = "+ "; - } - } - err = _PyTraceBack_Print_Indented( - tb, EXC_INDENT(ctx), EXC_MARGIN(ctx), header_margin, header, f); + err = _PyTraceBack_Print(tb, header, f); } Py_XDECREF(tb); return err; @@ -946,7 +821,7 @@ print_exception_file_and_line(struct exception_print_context *ctx, PyObject *f = ctx->file; PyObject *tmp; - int res = _PyObject_LookupAttr(*value_p, &_Py_ID(print_file_and_line), &tmp); + int res = PyObject_GetOptionalAttr(*value_p, &_Py_ID(print_file_and_line), &tmp); if (res <= 0) { if (res < 0) { PyErr_Clear(); @@ -955,16 +830,20 @@ print_exception_file_and_line(struct exception_print_context *ctx, } Py_DECREF(tmp); - PyObject *message, *filename, *text; - Py_ssize_t lineno, offset, end_lineno, end_offset; - if (!parse_syntax_error(*value_p, &message, &filename, - &lineno, &offset, - &end_lineno, &end_offset, &text)) { - PyErr_Clear(); - return 0; + PyObject *filename = NULL; + Py_ssize_t lineno = 0; + PyObject* v = PyObject_GetAttr(*value_p, &_Py_ID(filename)); + if (!v) { + return -1; + } + if (v == Py_None) { + Py_DECREF(v); + _Py_DECLARE_STR(anon_string, "<string>"); + filename = Py_NewRef(&_Py_STR(anon_string)); + } + else { + filename = v; } - - Py_SETREF(*value_p, message); PyObject *line = PyUnicode_FromFormat(" File \"%S\", line %zd\n", filename, lineno); @@ -972,40 +851,16 @@ print_exception_file_and_line(struct exception_print_context *ctx, if (line == NULL) { goto error; } - if (write_indented_margin(ctx, f) < 0) { - goto error; - } if (PyFile_WriteObject(line, f, Py_PRINT_RAW) < 0) { goto error; } Py_CLEAR(line); - if (text != NULL) { - Py_ssize_t line_size; - const char *error_line = PyUnicode_AsUTF8AndSize(text, &line_size); - // If the location of the error spawn multiple lines, we want - // to just print the first one and highlight everything until - // the end of that one since we don't support multi-line error - // messages. - if (end_lineno > lineno) { - end_offset = (error_line != NULL) ? line_size : -1; - } - // Limit the amount of '^' that we can display to - // the size of the text in the source line. - if (error_line != NULL && end_offset > line_size + 1) { - end_offset = line_size + 1; - } - if (print_error_text(f, offset, end_offset, text) < 0) { - goto error; - } - Py_DECREF(text); - } assert(!PyErr_Occurred()); return 0; error: Py_XDECREF(line); - Py_XDECREF(text); return -1; } @@ -1016,11 +871,14 @@ print_exception_message(struct exception_print_context *ctx, PyObject *type, { PyObject *f = ctx->file; - assert(PyExceptionClass_Check(type)); - - if (write_indented_margin(ctx, f) < 0) { + if (PyErr_GivenExceptionMatches(value, PyExc_MemoryError)) { + // The Python APIs in this function require allocating memory + // for various objects. If we're out of memory, we can't do that, return -1; } + + assert(PyExceptionClass_Check(type)); + PyObject *modulename = PyObject_GetAttr(type, &_Py_ID(__module__)); if (modulename == NULL || !PyUnicode_Check(modulename)) { Py_XDECREF(modulename); @@ -1095,134 +953,8 @@ print_exception_message(struct exception_print_context *ctx, PyObject *type, } static int -print_exception_suggestions(struct exception_print_context *ctx, - PyObject *value) -{ - PyObject *f = ctx->file; - PyObject *suggestions = _Py_Offer_Suggestions(value); - if (suggestions) { - if (PyFile_WriteObject(suggestions, f, Py_PRINT_RAW) < 0) { - goto error; - } - Py_DECREF(suggestions); - } - else if (PyErr_Occurred()) { - PyErr_Clear(); - } - return 0; -error: - Py_XDECREF(suggestions); - return -1; -} - -static int -print_exception_notes(struct exception_print_context *ctx, PyObject *notes) -{ - PyObject *f = ctx->file; - - if (notes == NULL) { - return 0; - } - - if (!PySequence_Check(notes) || PyUnicode_Check(notes) || PyBytes_Check(notes)) { - int res = 0; - if (write_indented_margin(ctx, f) < 0) { - res = -1; - } - PyObject *s = PyObject_Repr(notes); - if (s == NULL) { - PyErr_Clear(); - res = PyFile_WriteString("<__notes__ repr() failed>", f); - } - else { - res = PyFile_WriteObject(s, f, Py_PRINT_RAW); - Py_DECREF(s); - } - if (PyFile_WriteString("\n", f) < 0) { - res = -1; - } - return res; - } - Py_ssize_t num_notes = PySequence_Length(notes); - PyObject *lines = NULL; - for (Py_ssize_t ni = 0; ni < num_notes; ni++) { - PyObject *note = PySequence_GetItem(notes, ni); - PyObject *note_str = PyObject_Str(note); - Py_DECREF(note); - - if (note_str == NULL) { - PyErr_Clear(); - if (PyFile_WriteString("<note str() failed>", f) < 0) { - goto error; - } - } - else { - lines = PyUnicode_Splitlines(note_str, 1); - Py_DECREF(note_str); - - if (lines == NULL) { - goto error; - } - - Py_ssize_t n = PyList_GET_SIZE(lines); - for (Py_ssize_t i = 0; i < n; i++) { - PyObject *line = PyList_GET_ITEM(lines, i); - assert(PyUnicode_Check(line)); - if (write_indented_margin(ctx, f) < 0) { - goto error; - } - if (PyFile_WriteObject(line, f, Py_PRINT_RAW) < 0) { - goto error; - } - } - Py_CLEAR(lines); - } - if (PyFile_WriteString("\n", f) < 0) { - goto error; - } - } - - return 0; -error: - Py_XDECREF(lines); - return -1; -} - -static int -get_exception_notes(struct exception_print_context *ctx, PyObject *value, PyObject **notes) { - PyObject *note = NULL; - - if (_PyObject_LookupAttr(value, &_Py_ID(__notes__), notes) < 0) { - PyObject *type, *errvalue, *tback; - PyErr_Fetch(&type, &errvalue, &tback); - PyErr_NormalizeException(&type, &errvalue, &tback); - note = PyUnicode_FromFormat("Ignored error getting __notes__: %R", errvalue); - Py_XDECREF(type); - Py_XDECREF(errvalue); - Py_XDECREF(tback); - if (!note) { - goto error; - } - *notes = PyList_New(1); - if (!*notes) { - goto error; - } - if (PyList_SetItem(*notes, 0, note) < 0) { - Py_DECREF(*notes); - goto error; - } - } - - return 0; -error: - Py_XDECREF(note); - return -1; -} - -static int print_exception(struct exception_print_context *ctx, PyObject *value) { - PyObject *notes = NULL; PyObject *f = ctx->file; if (!PyExceptionInstance_Check(value)) { @@ -1238,9 +970,6 @@ print_exception(struct exception_print_context *ctx, PyObject *value) /* grab the type and notes now because value can change below */ PyObject *type = (PyObject *) Py_TYPE(value); - if (get_exception_notes(ctx, value, ¬es) < 0) { - goto error; - } if (print_exception_file_and_line(ctx, &value) < 0) { goto error; @@ -1248,22 +977,13 @@ print_exception(struct exception_print_context *ctx, PyObject *value) if (print_exception_message(ctx, type, value) < 0) { goto error; } - if (print_exception_suggestions(ctx, value) < 0) { - goto error; - } if (PyFile_WriteString("\n", f) < 0) { goto error; } - if (print_exception_notes(ctx, notes) < 0) { - goto error; - } - - Py_XDECREF(notes); Py_DECREF(value); assert(!PyErr_Occurred()); return 0; error: - Py_XDECREF(notes); Py_DECREF(value); return -1; } @@ -1287,29 +1007,18 @@ print_chained(struct exception_print_context* ctx, PyObject *value, if (_Py_EnterRecursiveCall(" in print_chained")) { return -1; } - bool need_close = ctx->need_close; int res = print_exception_recursive(ctx, value); - ctx->need_close = need_close; _Py_LeaveRecursiveCall(); if (res < 0) { return -1; } - if (write_indented_margin(ctx, f) < 0) { - return -1; - } if (PyFile_WriteString("\n", f) < 0) { return -1; } - if (write_indented_margin(ctx, f) < 0) { - return -1; - } if (PyFile_WriteString(message, f) < 0) { return -1; } - if (write_indented_margin(ctx, f) < 0) { - return -1; - } if (PyFile_WriteString("\n", f) < 0) { return -1; } @@ -1387,133 +1096,6 @@ print_exception_cause_and_context(struct exception_print_context *ctx, } static int -print_exception_group(struct exception_print_context *ctx, PyObject *value) -{ - PyObject *f = ctx->file; - - if (ctx->exception_group_depth > ctx->max_group_depth) { - /* depth exceeds limit */ - - if (write_indented_margin(ctx, f) < 0) { - return -1; - } - - PyObject *line = PyUnicode_FromFormat("... (max_group_depth is %d)\n", - ctx->max_group_depth); - if (line == NULL) { - return -1; - } - int err = PyFile_WriteObject(line, f, Py_PRINT_RAW); - Py_DECREF(line); - return err; - } - - if (ctx->exception_group_depth == 0) { - ctx->exception_group_depth += 1; - } - if (print_exception(ctx, value) < 0) { - return -1; - } - - PyObject *excs = ((PyBaseExceptionGroupObject *)value)->excs; - assert(excs && PyTuple_Check(excs)); - Py_ssize_t num_excs = PyTuple_GET_SIZE(excs); - assert(num_excs > 0); - Py_ssize_t n; - if (num_excs <= ctx->max_group_width) { - n = num_excs; - } - else { - n = ctx->max_group_width + 1; - } - - ctx->need_close = false; - for (Py_ssize_t i = 0; i < n; i++) { - bool last_exc = (i == n - 1); - if (last_exc) { - // The closing frame may be added in a recursive call - ctx->need_close = true; - } - - if (_Py_WriteIndent(EXC_INDENT(ctx), f) < 0) { - return -1; - } - bool truncated = (i >= ctx->max_group_width); - PyObject *line; - if (!truncated) { - line = PyUnicode_FromFormat( - "%s+---------------- %zd ----------------\n", - (i == 0) ? "+-" : " ", i + 1); - } - else { - line = PyUnicode_FromFormat( - "%s+---------------- ... ----------------\n", - (i == 0) ? "+-" : " "); - } - if (line == NULL) { - return -1; - } - int err = PyFile_WriteObject(line, f, Py_PRINT_RAW); - Py_DECREF(line); - if (err < 0) { - return -1; - } - - ctx->exception_group_depth += 1; - PyObject *exc = PyTuple_GET_ITEM(excs, i); - - if (!truncated) { - if (_Py_EnterRecursiveCall(" in print_exception_group")) { - return -1; - } - int res = print_exception_recursive(ctx, exc); - _Py_LeaveRecursiveCall(); - if (res < 0) { - return -1; - } - } - else { - Py_ssize_t excs_remaining = num_excs - ctx->max_group_width; - - if (write_indented_margin(ctx, f) < 0) { - return -1; - } - - PyObject *line = PyUnicode_FromFormat( - "and %zd more exception%s\n", - excs_remaining, excs_remaining > 1 ? "s" : ""); - - if (line == NULL) { - return -1; - } - - int err = PyFile_WriteObject(line, f, Py_PRINT_RAW); - Py_DECREF(line); - if (err < 0) { - return -1; - } - } - - if (last_exc && ctx->need_close) { - if (_Py_WriteIndent(EXC_INDENT(ctx), f) < 0) { - return -1; - } - if (PyFile_WriteString( - "+------------------------------------\n", f) < 0) { - return -1; - } - ctx->need_close = false; - } - ctx->exception_group_depth -= 1; - } - - if (ctx->exception_group_depth == 1) { - ctx->exception_group_depth -= 1; - } - return 0; -} - -static int print_exception_recursive(struct exception_print_context *ctx, PyObject *value) { if (_Py_EnterRecursiveCall(" in print_exception_recursive")) { @@ -1525,12 +1107,7 @@ print_exception_recursive(struct exception_print_context *ctx, PyObject *value) goto error; } } - if (!_PyBaseExceptionGroup_Check(value)) { - if (print_exception(ctx, value) < 0) { - goto error; - } - } - else if (print_exception_group(ctx, value) < 0) { + if (print_exception(ctx, value) < 0) { goto error; } assert(!PyErr_Occurred()); @@ -1542,12 +1119,10 @@ error: return -1; } -#define PyErr_MAX_GROUP_WIDTH 15 -#define PyErr_MAX_GROUP_DEPTH 10 - void _PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb) { + assert(value != NULL); assert(file != NULL && file != Py_None); if (PyExceptionInstance_Check(value) && tb != NULL && PyTraceBack_Check(tb)) { @@ -1562,12 +1137,42 @@ _PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb) } } + int unhandled_keyboard_interrupt = _PyRuntime.signals.unhandled_keyboard_interrupt; + + // Try first with the stdlib traceback module + PyObject *traceback_module = PyImport_ImportModule("traceback"); + + if (traceback_module == NULL) { + goto fallback; + } + + PyObject *print_exception_fn = PyObject_GetAttrString(traceback_module, "_print_exception_bltin"); + + if (print_exception_fn == NULL || !PyCallable_Check(print_exception_fn)) { + Py_DECREF(traceback_module); + goto fallback; + } + + PyObject* result = PyObject_CallOneArg(print_exception_fn, value); + + Py_DECREF(traceback_module); + Py_XDECREF(print_exception_fn); + if (result) { + Py_DECREF(result); + _PyRuntime.signals.unhandled_keyboard_interrupt = unhandled_keyboard_interrupt; + return; + } +fallback: + _PyRuntime.signals.unhandled_keyboard_interrupt = unhandled_keyboard_interrupt; +#ifdef Py_DEBUG + if (PyErr_Occurred()) { + PyErr_FormatUnraisable( + "Exception ignored in the internal traceback machinery"); + } +#endif + PyErr_Clear(); struct exception_print_context ctx; ctx.file = file; - ctx.exception_group_depth = 0; - ctx.need_close = false; - ctx.max_group_width = PyErr_MAX_GROUP_WIDTH; - ctx.max_group_depth = PyErr_MAX_GROUP_DEPTH; /* We choose to ignore seen being possibly NULL, and report at least the main exception (it could be a MemoryError). @@ -1584,14 +1189,10 @@ _PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb) Py_XDECREF(ctx.seen); /* Call file.flush() */ - PyObject *res = _PyObject_CallMethodNoArgs(file, &_Py_ID(flush)); - if (!res) { + if (_PyFile_Flush(file) < 0) { /* Silently ignore file.flush() error */ PyErr_Clear(); } - else { - Py_DECREF(res); - } } void @@ -1629,9 +1230,10 @@ void PyErr_DisplayException(PyObject *exc) PyErr_Display(NULL, exc, NULL); } -PyObject * -PyRun_StringFlags(const char *str, int start, PyObject *globals, - PyObject *locals, PyCompilerFlags *flags) +static PyObject * +_PyRun_StringFlagsWithName(const char *str, PyObject* name, int start, + PyObject *globals, PyObject *locals, PyCompilerFlags *flags, + int generate_new_source) { PyObject *ret = NULL; mod_ty mod; @@ -1641,17 +1243,36 @@ PyRun_StringFlags(const char *str, int start, PyObject *globals, if (arena == NULL) return NULL; + PyObject* source = NULL; _Py_DECLARE_STR(anon_string, "<string>"); - mod = _PyParser_ASTFromString( - str, &_Py_STR(anon_string), start, flags, arena); - if (mod != NULL) - ret = run_mod(mod, &_Py_STR(anon_string), globals, locals, flags, arena); + if (name) { + source = PyUnicode_FromString(str); + if (!source) { + PyErr_Clear(); + } + } else { + name = &_Py_STR(anon_string); + } + + mod = _PyParser_ASTFromString(str, name, start, flags, arena); + + if (mod != NULL) { + ret = run_mod(mod, name, globals, locals, flags, arena, source, generate_new_source); + } + Py_XDECREF(source); _PyArena_Free(arena); return ret; } +PyObject * +PyRun_StringFlags(const char *str, int start, PyObject *globals, + PyObject *locals, PyCompilerFlags *flags) { + + return _PyRun_StringFlagsWithName(str, NULL, start, globals, locals, flags, 0); +} + static PyObject * pyrun_file(FILE *fp, PyObject *filename, int start, PyObject *globals, PyObject *locals, int closeit, PyCompilerFlags *flags) @@ -1671,7 +1292,7 @@ pyrun_file(FILE *fp, PyObject *filename, int start, PyObject *globals, PyObject *ret; if (mod != NULL) { - ret = run_mod(mod, filename, globals, locals, flags, arena); + ret = run_mod(mod, filename, globals, locals, flags, arena, NULL, 0); } else { ret = NULL; @@ -1706,11 +1327,7 @@ flush_io_stream(PyThreadState *tstate, PyObject *name) PyErr_Clear(); } if (f != NULL) { - PyObject *r = _PyObject_CallMethodNoArgs(f, &_Py_ID(flush)); - if (r) { - Py_DECREF(r); - } - else { + if (_PyFile_Flush(f) < 0) { PyErr_Clear(); } Py_DECREF(f); @@ -1745,9 +1362,16 @@ run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, Py _PyRuntime.signals.unhandled_keyboard_interrupt = 0; /* Set globals['__builtins__'] if it doesn't exist */ - if (globals != NULL && _PyDict_GetItemStringWithError(globals, "__builtins__") == NULL) { - if (PyErr_Occurred() || - PyDict_SetItemString(globals, "__builtins__", + if (!globals || !PyDict_Check(globals)) { + PyErr_SetString(PyExc_SystemError, "globals must be a real dict"); + return NULL; + } + int has_builtins = PyDict_ContainsString(globals, "__builtins__"); + if (has_builtins < 0) { + return NULL; + } + if (!has_builtins) { + if (PyDict_SetItemString(globals, "__builtins__", tstate->interp->builtins) < 0) { return NULL; @@ -1762,13 +1386,100 @@ run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, Py } static PyObject * +get_interactive_filename(PyObject *filename, Py_ssize_t count) +{ + PyObject *result; + Py_ssize_t len = PyUnicode_GET_LENGTH(filename); + + if (len >= 2 + && PyUnicode_ReadChar(filename, 0) == '<' + && PyUnicode_ReadChar(filename, len - 1) == '>') { + PyObject *middle = PyUnicode_Substring(filename, 1, len-1); + if (middle == NULL) { + return NULL; + } + result = PyUnicode_FromFormat("<%U-%d>", middle, count); + Py_DECREF(middle); + } else { + result = PyUnicode_FromFormat( + "%U-%d", filename, count); + } + return result; + +} + +static PyObject * run_mod(mod_ty mod, PyObject *filename, PyObject *globals, PyObject *locals, - PyCompilerFlags *flags, PyArena *arena) + PyCompilerFlags *flags, PyArena *arena, PyObject* interactive_src, + int generate_new_source) { PyThreadState *tstate = _PyThreadState_GET(); - PyCodeObject *co = _PyAST_Compile(mod, filename, flags, -1, arena); - if (co == NULL) + PyObject* interactive_filename = filename; + if (interactive_src) { + PyInterpreterState *interp = tstate->interp; + if (generate_new_source) { + interactive_filename = get_interactive_filename( + filename, interp->_interactive_src_count++); + } else { + Py_INCREF(interactive_filename); + } + if (interactive_filename == NULL) { + return NULL; + } + } + + PyCodeObject *co = _PyAST_Compile(mod, interactive_filename, flags, -1, arena); + if (co == NULL) { + if (interactive_src) { + Py_DECREF(interactive_filename); + } return NULL; + } + + if (interactive_src) { + PyObject *linecache_module = PyImport_ImportModule("linecache"); + + if (linecache_module == NULL) { + Py_DECREF(co); + Py_DECREF(interactive_filename); + return NULL; + } + + PyObject *print_tb_func = PyObject_GetAttrString(linecache_module, "_register_code"); + + if (print_tb_func == NULL) { + Py_DECREF(co); + Py_DECREF(interactive_filename); + Py_DECREF(linecache_module); + return NULL; + } + + if (!PyCallable_Check(print_tb_func)) { + Py_DECREF(co); + Py_DECREF(interactive_filename); + Py_DECREF(linecache_module); + Py_DECREF(print_tb_func); + PyErr_SetString(PyExc_ValueError, "linecache._register_code is not callable"); + return NULL; + } + + PyObject* result = PyObject_CallFunction( + print_tb_func, "OOO", + co, + interactive_src, + filename + ); + + Py_DECREF(interactive_filename); + + Py_DECREF(linecache_module); + Py_XDECREF(print_tb_func); + Py_XDECREF(result); + if (!result) { + Py_DECREF(co); + return NULL; + } + } if (_PySys_Audit(tstate, "exec", "O", co) < 0) { Py_DECREF(co); @@ -1839,6 +1550,12 @@ Py_CompileStringObject(const char *str, PyObject *filename, int start, return NULL; } if (flags && (flags->cf_flags & PyCF_ONLY_AST)) { + if ((flags->cf_flags & PyCF_OPTIMIZED_AST) == PyCF_OPTIMIZED_AST) { + if (_PyCompile_AstOptimize(mod, filename, flags, optimize, arena) < 0) { + _PyArena_Free(arena); + return NULL; + } + } PyObject *result = PyAST_mod2obj(mod); _PyArena_Free(arena); return result; @@ -2049,7 +1766,3 @@ PyRun_InteractiveLoop(FILE *f, const char *p) { return PyRun_InteractiveLoopFlags(f, p, NULL); } - -#ifdef __cplusplus -} -#endif |
