bpo-34170: Cleanup pymain_run_python() (GH-8455)
* Move _PyMain.main_importer_path inside pymain_run_python * If main_importer_path is non-NULL, update sys.path[0] earlier
This commit is contained in:
parent
1dc6e3906a
commit
d3b191992e
174
Modules/main.c
174
Modules/main.c
|
@ -442,8 +442,6 @@ typedef struct {
|
||||||
wchar_t *filename; /* Trailing arg without -c or -m */
|
wchar_t *filename; /* Trailing arg without -c or -m */
|
||||||
wchar_t *command; /* -c argument */
|
wchar_t *command; /* -c argument */
|
||||||
wchar_t *module; /* -m argument */
|
wchar_t *module; /* -m argument */
|
||||||
|
|
||||||
PyObject *main_importer_path;
|
|
||||||
} _PyMain;
|
} _PyMain;
|
||||||
|
|
||||||
#define _PyMain_INIT {.err = _Py_INIT_OK()}
|
#define _PyMain_INIT {.err = _Py_INIT_OK()}
|
||||||
|
@ -815,26 +813,6 @@ pymain_clear_config(_PyCoreConfig *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
pymain_free_python(_PyMain *pymain)
|
|
||||||
{
|
|
||||||
Py_CLEAR(pymain->main_importer_path);
|
|
||||||
|
|
||||||
#ifdef __INSURE__
|
|
||||||
/* Insure++ is a memory analysis tool that aids in discovering
|
|
||||||
* memory leaks and other memory problems. On Python exit, the
|
|
||||||
* interned string dictionaries are flagged as being in use at exit
|
|
||||||
* (which it is). Under normal circumstances, this is fine because
|
|
||||||
* the memory will be automatically reclaimed by the system. Under
|
|
||||||
* memory debugging, it's a huge source of useless noise, so we
|
|
||||||
* trade off slower shutdown for less distraction in the memory
|
|
||||||
* reports. -baw
|
|
||||||
*/
|
|
||||||
_Py_ReleaseInternedUnicodeStrings();
|
|
||||||
#endif /* __INSURE__ */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pymain_free_raw(_PyMain *pymain)
|
pymain_free_raw(_PyMain *pymain)
|
||||||
{
|
{
|
||||||
|
@ -863,33 +841,47 @@ pymain_free_raw(_PyMain *pymain)
|
||||||
static void
|
static void
|
||||||
pymain_free(_PyMain *pymain)
|
pymain_free(_PyMain *pymain)
|
||||||
{
|
{
|
||||||
pymain_free_python(pymain);
|
|
||||||
pymain_free_raw(pymain);
|
pymain_free_raw(pymain);
|
||||||
|
|
||||||
|
#ifdef __INSURE__
|
||||||
|
/* Insure++ is a memory analysis tool that aids in discovering
|
||||||
|
* memory leaks and other memory problems. On Python exit, the
|
||||||
|
* interned string dictionaries are flagged as being in use at exit
|
||||||
|
* (which it is). Under normal circumstances, this is fine because
|
||||||
|
* the memory will be automatically reclaimed by the system. Under
|
||||||
|
* memory debugging, it's a huge source of useless noise, so we
|
||||||
|
* trade off slower shutdown for less distraction in the memory
|
||||||
|
* reports. -baw
|
||||||
|
*/
|
||||||
|
_Py_ReleaseInternedUnicodeStrings();
|
||||||
|
#endif /* __INSURE__ */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pymain_run_main_from_importer(_PyMain *pymain)
|
pymain_sys_path_add_path0(PyInterpreterState *interp, PyObject *path0)
|
||||||
{
|
{
|
||||||
/* Assume sys_path0 has already been checked by pymain_get_importer(),
|
PyObject *sys_path;
|
||||||
* so put it in sys.path[0] and import __main__ */
|
PyObject *sysdict = interp->sysdict;
|
||||||
PyObject *sys_path = PySys_GetObject("path");
|
if (sysdict != NULL) {
|
||||||
|
sys_path = PyDict_GetItemString(sysdict, "path");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sys_path = NULL;
|
||||||
|
}
|
||||||
if (sys_path == NULL) {
|
if (sys_path == NULL) {
|
||||||
PyErr_SetString(PyExc_RuntimeError, "unable to get sys.path");
|
PyErr_SetString(PyExc_RuntimeError, "unable to get sys.path");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PyList_Insert(sys_path, 0, pymain->main_importer_path)) {
|
if (PyList_Insert(sys_path, 0, path0)) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
int sts = pymain_run_module(L"__main__", 0);
|
|
||||||
return (sts != 0);
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
Py_CLEAR(pymain->main_importer_path);
|
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
return 1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1495,50 +1487,6 @@ wstrlist_as_pylist(int len, wchar_t **list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
pymain_compute_path0(_PyMain *pymain, _PyCoreConfig *config, PyObject **path0)
|
|
||||||
{
|
|
||||||
if (pymain->main_importer_path != NULL) {
|
|
||||||
/* Let pymain_run_main_from_importer() adjust sys.path[0] later */
|
|
||||||
*path0 = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Py_IsolatedFlag) {
|
|
||||||
*path0 = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*path0 = _PyPathConfig_ComputeArgv0(config->argc,
|
|
||||||
config->argv);
|
|
||||||
if (*path0 == NULL) {
|
|
||||||
pymain->err = _Py_INIT_NO_MEMORY();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
pymain_update_sys_path(_PyMain *pymain, PyObject *path0)
|
|
||||||
{
|
|
||||||
/* Prepend argv[0] to sys.path.
|
|
||||||
If argv[0] is a symlink, use the real path. */
|
|
||||||
PyObject *sys_path = PySys_GetObject("path");
|
|
||||||
if (sys_path == NULL) {
|
|
||||||
pymain->err = _Py_INIT_ERR("can't get sys.path");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepend path0 to sys.path */
|
|
||||||
if (PyList_Insert(sys_path, 0, path0) < 0) {
|
|
||||||
pymain->err = _Py_INIT_ERR("sys.path.insert(0, path0) failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pymain_import_readline(_PyMain *pymain)
|
pymain_import_readline(_PyMain *pymain)
|
||||||
{
|
{
|
||||||
|
@ -1639,7 +1587,8 @@ pymain_run_startup(_PyMain *pymain, _PyCoreConfig *config, PyCompilerFlags *cf)
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pymain_run_filename(_PyMain *pymain, _PyCoreConfig *config, PyCompilerFlags *cf)
|
pymain_run_filename(_PyMain *pymain, _PyCoreConfig *config,
|
||||||
|
PyCompilerFlags *cf)
|
||||||
{
|
{
|
||||||
if (pymain->filename == NULL && pymain->stdin_is_interactive) {
|
if (pymain->filename == NULL && pymain->stdin_is_interactive) {
|
||||||
Py_InspectFlag = 0; /* do exit on SystemExit */
|
Py_InspectFlag = 0; /* do exit on SystemExit */
|
||||||
|
@ -1647,11 +1596,6 @@ pymain_run_filename(_PyMain *pymain, _PyCoreConfig *config, PyCompilerFlags *cf)
|
||||||
pymain_run_interactive_hook();
|
pymain_run_interactive_hook();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pymain->main_importer_path != NULL) {
|
|
||||||
pymain->status = pymain_run_main_from_importer(pymain);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
if (pymain->filename != NULL) {
|
if (pymain->filename != NULL) {
|
||||||
fp = pymain_open_filename(pymain, config);
|
fp = pymain_open_filename(pymain, config);
|
||||||
|
@ -2480,37 +2424,45 @@ pymain_init_python_main(_PyMain *pymain, _PyCoreConfig *config,
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pymain_init_sys_path(_PyMain *pymain, _PyCoreConfig *config)
|
pymain_run_python(_PyMain *pymain, PyInterpreterState *interp)
|
||||||
{
|
{
|
||||||
|
int res = 0;
|
||||||
|
_PyCoreConfig *config = &interp->core_config;
|
||||||
|
|
||||||
|
PyObject *main_importer_path = NULL;
|
||||||
if (pymain->filename != NULL) {
|
if (pymain->filename != NULL) {
|
||||||
/* If filename is a package (ex: directory or ZIP file) which contains
|
/* If filename is a package (ex: directory or ZIP file) which contains
|
||||||
__main__.py, main_importer_path is set to filename and will be
|
__main__.py, main_importer_path is set to filename and will be
|
||||||
prepended to sys.path by pymain_run_main_from_importer(). Otherwise,
|
prepended to sys.path.
|
||||||
main_importer_path is set to NULL. */
|
|
||||||
pymain->main_importer_path = pymain_get_importer(pymain->filename);
|
Otherwise, main_importer_path is set to NULL. */
|
||||||
|
main_importer_path = pymain_get_importer(pymain->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *path0;
|
if (main_importer_path != NULL) {
|
||||||
if (pymain_compute_path0(pymain, config, &path0) < 0) {
|
if (pymain_sys_path_add_path0(interp, main_importer_path) < 0) {
|
||||||
return -1;
|
pymain->status = 1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!config->isolated) {
|
||||||
|
PyObject *path0 = _PyPathConfig_ComputeArgv0(config->argc,
|
||||||
|
config->argv);
|
||||||
|
if (path0 == NULL) {
|
||||||
|
pymain->err = _Py_INIT_NO_MEMORY();
|
||||||
|
res = -1;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path0 != NULL) {
|
if (pymain_sys_path_add_path0(interp, path0) < 0) {
|
||||||
if (pymain_update_sys_path(pymain, path0) < 0) {
|
|
||||||
Py_DECREF(path0);
|
Py_DECREF(path0);
|
||||||
return -1;
|
pymain->status = 1;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
Py_DECREF(path0);
|
Py_DECREF(path0);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
pymain_run_python(_PyMain *pymain)
|
|
||||||
{
|
|
||||||
PyCompilerFlags cf = {.cf_flags = 0};
|
PyCompilerFlags cf = {.cf_flags = 0};
|
||||||
_PyCoreConfig *config = &PyThreadState_GET()->interp->core_config;
|
|
||||||
|
|
||||||
pymain_header(pymain);
|
pymain_header(pymain);
|
||||||
pymain_import_readline(pymain);
|
pymain_import_readline(pymain);
|
||||||
|
@ -2521,11 +2473,19 @@ pymain_run_python(_PyMain *pymain)
|
||||||
else if (pymain->module) {
|
else if (pymain->module) {
|
||||||
pymain->status = (pymain_run_module(pymain->module, 1) != 0);
|
pymain->status = (pymain_run_module(pymain->module, 1) != 0);
|
||||||
}
|
}
|
||||||
|
else if (main_importer_path != NULL) {
|
||||||
|
int sts = pymain_run_module(L"__main__", 0);
|
||||||
|
pymain->status = (sts != 0);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
pymain_run_filename(pymain, config, &cf);
|
pymain_run_filename(pymain, config, &cf);
|
||||||
}
|
}
|
||||||
|
|
||||||
pymain_repl(pymain, config, &cf);
|
pymain_repl(pymain, config, &cf);
|
||||||
|
|
||||||
|
done:
|
||||||
|
Py_XDECREF(main_importer_path);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2617,7 +2577,7 @@ pymain_cmdline(_PyMain *pymain, _PyCoreConfig *config)
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pymain_init(_PyMain *pymain)
|
pymain_init(_PyMain *pymain, PyInterpreterState **interp_p)
|
||||||
{
|
{
|
||||||
/* 754 requires that FP exceptions run in "no stop" mode by default,
|
/* 754 requires that FP exceptions run in "no stop" mode by default,
|
||||||
* and until C vendors implement C99's ways to control FP exceptions,
|
* and until C vendors implement C99's ways to control FP exceptions,
|
||||||
|
@ -2652,6 +2612,7 @@ pymain_init(_PyMain *pymain)
|
||||||
if (_Py_INIT_FAILED(pymain->err)) {
|
if (_Py_INIT_FAILED(pymain->err)) {
|
||||||
_Py_FatalInitError(pymain->err);
|
_Py_FatalInitError(pymain->err);
|
||||||
}
|
}
|
||||||
|
*interp_p = interp;
|
||||||
|
|
||||||
pymain_clear_config(config);
|
pymain_clear_config(config);
|
||||||
config = &interp->core_config;
|
config = &interp->core_config;
|
||||||
|
@ -2659,10 +2620,6 @@ pymain_init(_PyMain *pymain)
|
||||||
if (pymain_init_python_main(pymain, config, interp) < 0) {
|
if (pymain_init_python_main(pymain, config, interp) < 0) {
|
||||||
_Py_FatalInitError(pymain->err);
|
_Py_FatalInitError(pymain->err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pymain_init_sys_path(pymain, config) < 0) {
|
|
||||||
_Py_FatalInitError(pymain->err);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2670,9 +2627,12 @@ pymain_init(_PyMain *pymain)
|
||||||
static int
|
static int
|
||||||
pymain_main(_PyMain *pymain)
|
pymain_main(_PyMain *pymain)
|
||||||
{
|
{
|
||||||
int res = pymain_init(pymain);
|
PyInterpreterState *interp;
|
||||||
|
int res = pymain_init(pymain, &interp);
|
||||||
if (res != 1) {
|
if (res != 1) {
|
||||||
pymain_run_python(pymain);
|
if (pymain_run_python(pymain, interp) < 0) {
|
||||||
|
_Py_FatalInitError(pymain->err);
|
||||||
|
}
|
||||||
|
|
||||||
if (Py_FinalizeEx() < 0) {
|
if (Py_FinalizeEx() < 0) {
|
||||||
/* Value unlikely to be confused with a non-error exit status or
|
/* Value unlikely to be confused with a non-error exit status or
|
||||||
|
|
Loading…
Reference in New Issue