#include "pycore_pylifecycle.h" // _Py_PreInitializeFromPyArgv()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_pythonrun.h" // _PyRun_AnyFile()
+#include "pycore_sysmodule.h" // _PySys_FormatV()
#include "pycore_tuple.h" // _PyTuple_FromPair
#include "pycore_unicodeobject.h" // _PyUnicode_Dedent()
/* --- pymain_run_python() ---------------------------------------- */
+static void
+pymain_error_format(const char *format, ...)
+{
+ va_list vargs;
+ va_start(vargs, format);
+
+ PySys_WriteStderr("python: ");
+ _PySys_FormatV(&_Py_ID(stderr), stderr, format, vargs);
+ PySys_WriteStderr("\n");
+
+ va_end(vargs);
+}
+
+// See also pyrun_error()
+static void
+pymain_error(const char *msg)
+{
+ PySys_FormatStderr("python: %s\n", msg);
+}
+
+static int
+pymain_check_signals(void)
+{
+ return Py_MakePendingCalls();
+}
+
/* Non-zero if filename, command (-c) or module (-m) is set
on the command line */
static inline int config_run_code(const PyConfig *config)
}
-/* Write an exitcode into *exitcode and return 1 if we have to exit Python.
- Return 0 otherwise. */
+// If filename is a package (ex: directory or ZIP file) which contains
+// __main__.py, main_importer_path is set to filename and will be prepended to
+// sys.path.
+//
+// Otherwise, main_importer_path is left unchanged.
+//
+// Write an exitcode into *exitcode and return 1 if we have to exit Python.
+// Return 0 otherwise.
static int
-pymain_get_importer(const wchar_t *filename, PyObject **importer_p, int *exitcode)
+pymain_get_importer(const PyConfig *config, PyObject **importer_p,
+ int *exitcode)
{
- PyObject *sys_path0 = NULL, *importer;
+ const wchar_t *filename = config->run_filename;
+ if (filename == NULL) {
+ return 0;
+ }
- sys_path0 = PyUnicode_FromWideChar(filename, -1);
+ PyObject *sys_path0 = PyUnicode_FromWideChar(filename, -1);
if (sys_path0 == NULL) {
goto error;
}
- importer = PyImport_GetImporter(sys_path0);
+ PyObject *importer = PyImport_GetImporter(sys_path0);
if (importer == NULL) {
goto error;
}
error:
Py_XDECREF(sys_path0);
- PySys_WriteStderr("Failed checking if argv[0] is an import path entry\n");
+ pymain_error("Failed checking if argv[0] is an import path entry:");
return pymain_err_print(exitcode);
}
static int
-pymain_sys_path_add_path0(PyInterpreterState *interp, PyObject *path0)
+pymain_sys_path_add_path0(PyObject *path0)
{
PyObject *sys_path;
+ PyInterpreterState *interp = _PyInterpreterState_GET();
PyObject *sysdict = interp->sysdict;
if (sysdict != NULL) {
sys_path = PyDict_GetItemWithError(sysdict, &_Py_ID(path));
}
-static void
+static int
pymain_import_readline(const PyConfig *config)
{
+ if (pymain_check_signals() < 0) {
+ return -1;
+ }
+
if (config->isolated) {
- return;
+ return 0;
}
if (!config->inspect && config_run_code(config)) {
- return;
+ return 0;
}
if (!isatty(fileno(stdin))) {
- return;
+ return 0;
}
PyObject *mod = PyImport_ImportModule("readline");
else {
Py_DECREF(mod);
}
+
mod = PyImport_ImportModule("rlcompleter");
if (mod == NULL) {
PyErr_Clear();
else {
Py_DECREF(mod);
}
+ return 0;
}
return 0;
error:
- PySys_WriteStderr("Unable to decode the command from the command line:\n");
+ pymain_error("Unable to decode the command from the command line:");
return pymain_exit_err_print();
}
PyObject *pyrepl = PyImport_ImportModule("_pyrepl.main");
if (pyrepl == NULL) {
- fprintf(stderr, "Could not import _pyrepl.main\n");
+ pymain_error("Could not import _pyrepl.main");
goto error;
}
console = PyObject_GetAttrString(pyrepl, "interactive_console");
if (console == NULL) {
- fprintf(stderr, "Could not access _pyrepl.main.interactive_console\n");
+ pymain_error("Could not access _pyrepl.main.interactive_console");
goto error;
}
static int
pymain_run_module(const wchar_t *modname, int set_argv0)
{
- PyObject *module, *runmodule, *runargs, *result;
+ int exitcode = 0;
+ PyObject *module = NULL;
+ PyObject *runmodule = NULL;
+ PyObject *runargs = NULL;
+ PyObject *result = NULL;
+
if (PySys_Audit("cpython.run_module", "u", modname) < 0) {
- return pymain_exit_err_print();
+ goto error;
}
+
runmodule = PyImport_ImportModuleAttrString("runpy",
"_run_module_as_main");
if (runmodule == NULL) {
- fprintf(stderr, "Could not import runpy._run_module_as_main\n");
- return pymain_exit_err_print();
+ pymain_error("Could not import runpy._run_module_as_main");
+ goto error;
}
+
module = PyUnicode_FromWideChar(modname, -1);
if (module == NULL) {
- fprintf(stderr, "Could not convert module name to unicode\n");
- Py_DECREF(runmodule);
- return pymain_exit_err_print();
+ pymain_error("Could not convert module name to unicode");
+ goto error;
}
+
runargs = _PyTuple_FromPair(module, set_argv0 ? Py_True : Py_False);
if (runargs == NULL) {
- fprintf(stderr,
- "Could not create arguments for runpy._run_module_as_main\n");
- Py_DECREF(runmodule);
- Py_DECREF(module);
- return pymain_exit_err_print();
+ pymain_error("Could not create arguments "
+ "for runpy._run_module_as_main");
+ goto error;
}
+
result = PyObject_Call(runmodule, runargs, NULL);
- Py_DECREF(runmodule);
- Py_DECREF(module);
- Py_DECREF(runargs);
if (result == NULL) {
- return pymain_exit_err_print();
+ goto error;
}
- Py_DECREF(result);
- return 0;
+
+done:
+ Py_XDECREF(module);
+ Py_XDECREF(runmodule);
+ Py_XDECREF(runargs);
+ Py_XDECREF(result);
+ return exitcode;
+
+error:
+ exitcode = pymain_exit_err_print();
+ goto done;
}
static int
-pymain_run_file_obj(PyObject *program_name, PyObject *filename,
- int skip_source_first_line)
+pymain_run_file_obj(PyObject *filename, int skip_source_first_line)
{
if (PySys_Audit("cpython.run_file", "O", filename) < 0) {
return pymain_exit_err_print();
FILE *fp = Py_fopen(filename, "rb");
if (fp == NULL) {
- // Ignore the OSError
- PyErr_Clear();
- // TODO(picnixz): strerror() is locale dependent but not PySys_FormatStderr().
- PySys_FormatStderr("%S: can't open file %R: [Errno %d] %s\n",
- program_name, filename, errno, strerror(errno));
+ pymain_error_format("can't open file %R:", filename);
+ pymain_exit_err_print();
return 2;
}
struct _Py_stat_struct sb;
if (_Py_fstat_noraise(fileno(fp), &sb) == 0 && S_ISDIR(sb.st_mode)) {
- PySys_FormatStderr("%S: %R is a directory, cannot continue\n",
- program_name, filename);
+ pymain_error_format("%R is a directory, cannot continue",
+ filename);
fclose(fp);
return 1;
}
- // Call pending calls like signal handlers (SIGINT)
- if (Py_MakePendingCalls() == -1) {
+ if (pymain_check_signals() < 0) {
fclose(fp);
return pymain_exit_err_print();
}
if (filename == NULL) {
return pymain_exit_err_print();
}
- PyObject *program_name = PyUnicode_FromWideChar(config->program_name, -1);
- if (program_name == NULL) {
- Py_DECREF(filename);
- return pymain_exit_err_print();
- }
- int exitcode = pymain_run_file_obj(program_name, filename,
- config->skip_source_first_line);
- Py_DECREF(filename);
- Py_DECREF(program_name);
+ int exitcode = pymain_run_file_obj(filename, config->skip_source_first_line);
+ Py_XDECREF(filename);
return exitcode;
}
pymain_run_startup(PyConfig *config, int *exitcode)
{
int ret = 0;
+ PyObject *startup = NULL;
+
if (!config->use_environment) {
- return 0;
+ goto done;
}
- PyObject *startup = NULL;
#ifdef MS_WINDOWS
const wchar_t *env = _wgetenv(L"PYTHONSTARTUP");
if (env == NULL || env[0] == L'\0') {
- return 0;
+ goto done;
}
+
startup = PyUnicode_FromWideChar(env, -1);
if (startup == NULL) {
goto error;
#else
const char *env = _Py_GetEnv(config->use_environment, "PYTHONSTARTUP");
if (env == NULL) {
- return 0;
+ goto done;
}
+
startup = PyUnicode_DecodeFSDefault(env);
if (startup == NULL) {
goto error;
FILE *fp = Py_fopen(startup, "r");
if (fp == NULL) {
- int save_errno = errno;
- PyErr_Clear();
- PySys_WriteStderr("Could not open PYTHONSTARTUP\n");
-
- errno = save_errno;
- PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, startup, NULL);
+ pymain_error("Could not open PYTHONSTARTUP");
goto error;
}
goto error;
}
Py_DECREF(result);
-
return 0;
error:
- PySys_WriteStderr("Failed calling sys.__interactivehook__\n");
+ pymain_error("Failed calling sys.__interactivehook__:");
return pymain_err_print(exitcode);
}
-static void
-pymain_set_inspect(PyConfig *config, int inspect)
+static int
+pymain_set_inspect(PyConfig *config, int inspect, int *exitcode)
{
PyObject *value = PyLong_FromLong(inspect);
if (value == NULL || PyConfig_Set("inspect", value) < 0) {
- fprintf(stderr, "Could not set the inspect flag\n");
- PyErr_Print();
+ Py_XDECREF(value);
+ pymain_error("Could not set the inspect flag");
+ return pymain_err_print(exitcode);
}
else {
assert(config->inspect == inspect);
}
Py_XDECREF(value);
+ return 0;
}
static int
_pymain_run_repl(PyConfig *config, int startup)
{
- /* call pending calls like signal handlers (SIGINT) */
- if (Py_MakePendingCalls() == -1) {
- return pymain_exit_err_print();
+ if (pymain_check_signals() < 0) {
+ goto error;
}
if (PySys_Audit("cpython.run_stdin", NULL) < 0) {
- return pymain_exit_err_print();
+ goto error;
}
if (isatty(fileno(stdin))
- && !_Py_GetEnv(config->use_environment, "PYTHON_BASIC_REPL")) {
+ && !_Py_GetEnv(config->use_environment, "PYTHON_BASIC_REPL"))
+ {
PyObject *pyrepl = PyImport_ImportModule("_pyrepl");
if (pyrepl != NULL) {
int exitcode = pymain_run_pyrepl(startup);
Py_DECREF(pyrepl);
return exitcode;
}
+
if (!PyErr_ExceptionMatches(PyExc_ModuleNotFoundError)) {
- fprintf(stderr, "Could not import _pyrepl.main\n");
- return pymain_exit_err_print();
+ pymain_error("Could not import _pyrepl.main");
+ goto error;
}
PyErr_Clear();
}
Py_DECREF(stdin_obj);
}
if (result == NULL) {
- return pymain_exit_err_print();
+ goto error;
}
Py_DECREF(result);
return 0;
+
+error:
+ return pymain_exit_err_print();
}
static int
{
if (stdin_is_interactive(config)) {
// do exit on SystemExit
- pymain_set_inspect(config, 0);
-
int exitcode;
+ if (pymain_set_inspect(config, 0, &exitcode)) {
+ return exitcode;
+ }
+
if (pymain_run_startup(config, &exitcode)) {
return exitcode;
}
/* Check this environment variable at the end, to give programs the
opportunity to set it from Python. */
if (!config->inspect && _Py_GetEnv(config->use_environment, "PYTHONINSPECT")) {
- pymain_set_inspect(config, 1);
+ if (pymain_set_inspect(config, 1, exitcode)) {
+ return;
+ }
}
if (!(config->inspect && stdin_is_interactive(config) && config_run_code(config))) {
return;
}
- pymain_set_inspect(config, 0);
+ if (pymain_set_inspect(config, 0, exitcode)) {
+ return;
+ }
if (pymain_run_interactive_hook(exitcode)) {
return;
}
}
+static int
+pymain_set_path0(PyObject *main_importer_path)
+{
+ PyConfig *config = (PyConfig *)_Py_GetConfig();
+
+ PyObject *path0 = NULL;
+ if (main_importer_path != NULL) {
+ path0 = Py_NewRef(main_importer_path);
+ }
+ else if (!config->safe_path) {
+ int res = _PyPathConfig_ComputeSysPath0(&config->argv, &path0);
+ if (res < 0) {
+ return -1;
+ }
+ else if (res == 0) {
+ Py_CLEAR(path0);
+ }
+ }
+
+ if (path0 == NULL) {
+ return 0;
+ }
+
+ // XXX Apply config->sys_path_0 in init_interp_main(). We have
+ // to be sure to get readline/rlcompleter imported at the correct time.
+ wchar_t *wstr = PyUnicode_AsWideCharString(path0, NULL);
+ if (wstr == NULL) {
+ goto error;
+ }
+
+ PyStatus status = PyConfig_SetString(config, &config->sys_path_0, wstr);
+ PyMem_Free(wstr);
+ if (_PyStatus_EXCEPTION(status)) {
+ _PyErr_SetFromPyStatus(status);
+ goto error;
+ }
+
+ int res = pymain_sys_path_add_path0(path0);
+ Py_DECREF(path0);
+
+ return res;
+
+error:
+ Py_DECREF(path0);
+ return -1;
+}
+
+
static void
pymain_run_python(int *exitcode)
{
+ int set_running_main = 0;
+
PyObject *main_importer_path = NULL;
PyInterpreterState *interp = _PyInterpreterState_GET();
/* pymain_repl() and pymain_run_stdin() modify the config */
PyConfig *config = (PyConfig*)_PyInterpreterState_GetConfig(interp);
/* ensure path config is written into global variables */
- if (_PyStatus_EXCEPTION(_PyPathConfig_UpdateGlobal(config))) {
+ PyStatus status = _PyPathConfig_UpdateGlobal(config);
+ if (_PyStatus_EXCEPTION(status)) {
+ _PyErr_SetFromPyStatus(status);
goto error;
}
// at that point.
assert(config->sys_path_0 == NULL);
- if (config->run_filename != NULL) {
- /* If filename is a package (ex: directory or ZIP file) which contains
- __main__.py, main_importer_path is set to filename and will be
- prepended to sys.path.
-
- Otherwise, main_importer_path is left unchanged. */
- if (pymain_get_importer(config->run_filename, &main_importer_path,
- exitcode)) {
- return;
- }
+ if (pymain_get_importer(config, &main_importer_path, exitcode)) {
+ return;
}
// import readline and rlcompleter before script dir is added to sys.path
- pymain_import_readline(config);
-
- PyObject *path0 = NULL;
- if (main_importer_path != NULL) {
- path0 = Py_NewRef(main_importer_path);
- }
- else if (!config->safe_path) {
- int res = _PyPathConfig_ComputeSysPath0(&config->argv, &path0);
- if (res < 0) {
- goto error;
- }
- else if (res == 0) {
- Py_CLEAR(path0);
- }
+ if (pymain_import_readline(config) < 0) {
+ goto error;
}
- // XXX Apply config->sys_path_0 in init_interp_main(). We have
- // to be sure to get readline/rlcompleter imported at the correct time.
- if (path0 != NULL) {
- wchar_t *wstr = PyUnicode_AsWideCharString(path0, NULL);
- if (wstr == NULL) {
- Py_DECREF(path0);
- goto error;
- }
- config->sys_path_0 = _PyMem_RawWcsdup(wstr);
- PyMem_Free(wstr);
- if (config->sys_path_0 == NULL) {
- Py_DECREF(path0);
- goto error;
- }
- int res = pymain_sys_path_add_path0(interp, path0);
- Py_DECREF(path0);
- if (res < 0) {
- goto error;
- }
+
+ if (pymain_set_path0(main_importer_path) < 0) {
+ goto error;
}
pymain_header(config);
_PyInterpreterState_SetRunningMain(interp);
+ set_running_main = 1;
assert(!PyErr_Occurred());
+ if (pymain_check_signals() < 0) {
+ goto error;
+ }
+
if (config->run_command) {
*exitcode = pymain_run_command(config->run_command);
}
*exitcode = pymain_run_stdin(config);
}
+ if (pymain_check_signals() < 0) {
+ goto error;
+ }
+
pymain_repl(config, exitcode);
goto done;
*exitcode = pymain_exit_err_print();
done:
- _PyInterpreterState_SetNotRunningMain(interp);
+ if (set_running_main) {
+ _PyInterpreterState_SetNotRunningMain(interp);
+ }
Py_XDECREF(main_importer_path);
}