[Python-checkins] bpo-32030: Cleanup pymain_main() (#4935)

Victor Stinner webhook-mailer at python.org
Tue Dec 19 19:42:02 EST 2017


https://github.com/python/cpython/commit/19760863623b636a63ccf649107d9504c6465a92
commit: 19760863623b636a63ccf649107d9504c6465a92
branch: master
author: Victor Stinner <victor.stinner at gmail.com>
committer: GitHub <noreply at github.com>
date: 2017-12-20T01:41:59+01:00
summary:

bpo-32030: Cleanup pymain_main() (#4935)

* Reorganize pymain_main() to make the code more flat
* Clear configurations before pymain_update_sys_path()
* Mark Py_FatalError() and _Py_FatalInitError() with _Py_NO_RETURN
* Replace _PyMain.run_code variable with a new RUN_CODE() macro
* Move _PyMain.cf into a local variable in pymain_run_python()

files:
M Modules/main.c
M Python/pylifecycle.c

diff --git a/Modules/main.c b/Modules/main.c
index 59e535d6ae7..429ecbc767d 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -389,6 +389,7 @@ typedef struct {
     wchar_t *command;            /* -c argument */
     const wchar_t *module;       /* -m argument */
     _Py_OptList warning_options; /* -W options */
+    _Py_OptList env_warning_options;  /* PYTHONWARNINGS env var */
     int print_help;              /* -h, -? options */
     int print_version;           /* -V option */
     int bytes_warning;           /* Py_BytesWarningFlag, -b */
@@ -412,41 +413,47 @@ typedef struct {
     int legacy_windows_stdio;        /* Py_LegacyWindowsStdioFlag,
                                         PYTHONLEGACYWINDOWSSTDIO */
 #endif
-    _Py_OptList env_warning_options;  /* PYTHONWARNINGS env var */
 } _Py_CommandLineDetails;
 
 /* Structure used by Py_Main() to pass data to subfunctions */
 typedef struct {
-    /* Exit status ("exit code") */
+    /* Input arguments */
+    int argc;
+    int use_bytes_argv;
+    char **bytes_argv;
+    wchar_t **wchar_argv;
+
+    /* Exit status or "exit code": result of pymain_main() */
     int status;
-    PyCompilerFlags cf;
+    /* Error message if a function failed */
+    _PyInitError err;
+
+    _Py_CommandLineDetails cmdline;
     /* non-zero is stdin is a TTY or if -i option is used */
     int stdin_is_interactive;
+
     _PyCoreConfig core_config;
     _PyMainInterpreterConfig config;
-    _Py_CommandLineDetails cmdline;
-    PyObject *main_importer_path;
-    /* non-zero if filename, command (-c) or module (-m) is set
-       on the command line */
-    int run_code;
-    /* Error message if a function failed */
-    _PyInitError err;
 
-    int argc;
-    int use_bytes_argv;
-    char **bytes_argv;
-    wchar_t **wchar_argv;
+    PyObject *main_importer_path;
 } _PyMain;
 
 /* .cmdline is initialized to zeros */
 #define _PyMain_INIT \
     {.core_config = _PyCoreConfig_INIT, \
      .config = _PyMainInterpreterConfig_INIT, \
-     .run_code = -1, \
      .err = _Py_INIT_OK()}
 /* Note: _PyMain_INIT sets other fields to 0/NULL */
 
 
+/* Non-zero if filename, command (-c) or module (-m) is set
+   on the command line */
+#define RUN_CODE(pymain) \
+    (pymain->cmdline.command != NULL \
+     || pymain->cmdline.filename != NULL \
+     || pymain->cmdline.module != NULL)
+
+
 static void
 pymain_optlist_clear(_Py_OptList *list)
 {
@@ -526,7 +533,6 @@ pymain_clear_cmdline(_PyMain *pymain)
     cmdline->argv = NULL;
 }
 
-
 static void
 pymain_clear_configs(_PyMain *pymain)
 {
@@ -816,9 +822,6 @@ pymain_parse_cmdline_impl(_PyMain *pymain)
         cmdline->filename = cmdline->argv[_PyOS_optind];
     }
 
-    pymain->run_code = (cmdline->command != NULL || cmdline->filename != NULL
-                        || cmdline->module != NULL);
-
     /* -c and -m options are exclusive */
     assert(!(cmdline->command != NULL && cmdline->module != NULL));
 
@@ -1174,12 +1177,11 @@ pymain_get_program_name(_PyMain *pymain)
 static void
 pymain_header(_PyMain *pymain)
 {
-    /* TODO: Move this to _PyRun_PrepareMain */
     if (Py_QuietFlag) {
         return;
     }
 
-    if (!Py_VerboseFlag && (pymain->run_code || !pymain->stdin_is_interactive)) {
+    if (!Py_VerboseFlag && (RUN_CODE(pymain) || !pymain->stdin_is_interactive)) {
         return;
     }
 
@@ -1291,17 +1293,32 @@ config_init_argv(_PyMainInterpreterConfig *config, const _PyCoreConfig *core_con
 
 
 static int
-pymain_update_sys_path(_PyMain *pymain)
+pymain_init_path0(_PyMain *pymain, 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(pymain->core_config.argc,
+                                        pymain->core_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");
@@ -1310,20 +1327,11 @@ pymain_update_sys_path(_PyMain *pymain)
         return -1;
     }
 
-    PyObject *path0 = _PyPathConfig_ComputeArgv0(pymain->core_config.argc, pymain->core_config.argv);
-    if (path0 == NULL) {
-        pymain->err = _Py_INIT_NO_MEMORY();
-        return -1;
-    }
-
     /* Prepend path0 to sys.path */
     if (PyList_Insert(sys_path, 0, path0) < 0) {
-        Py_DECREF(path0);
         pymain->err = _Py_INIT_ERR("sys.path.insert(0, path0) failed");
         return -1;
     }
-    Py_DECREF(path0);
-
     return 0;
 }
 
@@ -1357,7 +1365,7 @@ pymain_get_global_config(_PyMain *pymain)
 }
 
 
-/* Set Py_XXX global configuration variables */
+/* Set Py_xxx global configuration variables */
 static void
 pymain_set_global_config(_PyMain *pymain)
 {
@@ -1396,7 +1404,7 @@ pymain_import_readline(_PyMain *pymain)
     if (Py_IsolatedFlag) {
         return;
     }
-    if (!Py_InspectFlag && pymain->run_code) {
+    if (!Py_InspectFlag && RUN_CODE(pymain)) {
         return;
     }
     if (!isatty(fileno(stdin))) {
@@ -1464,13 +1472,13 @@ pymain_open_filename(_PyMain *pymain)
 
 
 static void
-pymain_run_filename(_PyMain *pymain)
+pymain_run_filename(_PyMain *pymain, PyCompilerFlags *cf)
 {
     _Py_CommandLineDetails *cmdline = &pymain->cmdline;
 
     if (cmdline->filename == NULL && pymain->stdin_is_interactive) {
         Py_InspectFlag = 0; /* do exit on SystemExit */
-        pymain_run_startup(&pymain->cf);
+        pymain_run_startup(cf);
         pymain_run_interactive_hook();
     }
 
@@ -1490,12 +1498,12 @@ pymain_run_filename(_PyMain *pymain)
         fp = stdin;
     }
 
-    pymain->status = pymain_run_file(fp, cmdline->filename, &pymain->cf);
+    pymain->status = pymain_run_file(fp, cmdline->filename, cf);
 }
 
 
 static void
-pymain_repl(_PyMain *pymain)
+pymain_repl(_PyMain *pymain, PyCompilerFlags *cf)
 {
     /* Check this environment variable at the end, to give programs the
        opportunity to set it from Python. */
@@ -1503,15 +1511,14 @@ pymain_repl(_PyMain *pymain)
         Py_InspectFlag = 1;
     }
 
-    if (!(Py_InspectFlag && pymain->stdin_is_interactive
-          && pymain->run_code)) {
+    if (!(Py_InspectFlag && pymain->stdin_is_interactive && RUN_CODE(pymain))) {
         return;
     }
 
     Py_InspectFlag = 0;
     pymain_run_interactive_hook();
 
-    int res = PyRun_AnyFileFlags(stdin, "<stdin>", &pymain->cf);
+    int res = PyRun_AnyFileFlags(stdin, "<stdin>", cf);
     pymain->status = (res != 0);
 }
 
@@ -1966,6 +1973,10 @@ pymain_read_conf_impl(_PyMain *pymain)
         return res;
     }
 
+    if (pymain_init_core_argv(pymain) < 0) {
+        return -1;
+    }
+
     /* Set Py_IgnoreEnvironmentFlag for Py_GETENV() */
     Py_IgnoreEnvironmentFlag = pymain->core_config.ignore_environment;
 
@@ -1973,10 +1984,6 @@ pymain_read_conf_impl(_PyMain *pymain)
         return -1;
     }
 
-    if (pymain_init_core_argv(pymain) < 0) {
-        return -1;
-    }
-
     _PyInitError err = _PyCoreConfig_Read(&pymain->core_config);
     if (_Py_INIT_FAILED(err)) {
         pymain->err = err;
@@ -1986,6 +1993,8 @@ pymain_read_conf_impl(_PyMain *pymain)
 }
 
 
+/* Read the configuration, but initialize also the LC_CTYPE locale:
+   enable UTF-8 mode (PEP 540) and/or coerce the C locale (PEP 538) */
 static int
 pymain_read_conf(_PyMain *pymain)
 {
@@ -2426,9 +2435,21 @@ pymain_init_python_main(_PyMain *pymain)
         pymain->main_importer_path = pymain_get_importer(pymain->cmdline.filename);
     }
 
-    if (pymain_update_sys_path(pymain) < 0) {
+    PyObject *path0;
+    if (pymain_init_path0(pymain, &path0) < 0) {
         return -1;
     }
+
+    pymain_clear_configs(pymain);
+
+    if (path0 != NULL) {
+        if (pymain_update_sys_path(pymain, path0) < 0) {
+            Py_DECREF(path0);
+            return -1;
+        }
+        Py_DECREF(path0);
+    }
+
     return 0;
 }
 
@@ -2436,21 +2457,22 @@ pymain_init_python_main(_PyMain *pymain)
 static void
 pymain_run_python(_PyMain *pymain)
 {
+    PyCompilerFlags cf = {.cf_flags = 0};
     _Py_CommandLineDetails *cmdline = &pymain->cmdline;
 
     pymain_header(pymain);
     pymain_import_readline(pymain);
 
     if (cmdline->command) {
-        pymain->status = pymain_run_command(cmdline->command, &pymain->cf);
+        pymain->status = pymain_run_command(cmdline->command, &cf);
     }
     else if (cmdline->module) {
         pymain->status = (pymain_run_module(cmdline->module, 1) != 0);
     }
     else {
-        pymain_run_filename(pymain);
+        pymain_run_filename(pymain, &cf);
     }
-    pymain_repl(pymain);
+    pymain_repl(pymain, &cf);
 }
 
 
@@ -2476,51 +2498,61 @@ pymain_init(_PyMain *pymain)
 
 
 static int
-pymain_impl(_PyMain *pymain)
+pymain_init_cmdline(_PyMain *pymain)
 {
     pymain->err = _PyRuntime_Initialize();
     if (_Py_INIT_FAILED(pymain->err)) {
         return -1;
     }
 
-    /* Read the configuration, but initialize also the LC_CTYPE locale:
-       enable UTF-8 mode (PEP 540) and/or coerce the C locale (PEP 538) */
     int res = pymain_read_conf(pymain);
     if (res < 0) {
         return -1;
     }
     if (res > 0) {
         /* --help or --version command: we are done */
-        return 0;
+        return 1;
     }
 
     _Py_CommandLineDetails *cmdline = &pymain->cmdline;
     if (cmdline->print_help) {
         pymain_usage(0, cmdline->argv[0]);
-        return 0;
+        return 1;
     }
 
     if (cmdline->print_version) {
         printf("Python %s\n",
                (cmdline->print_version >= 2) ? Py_GetVersion() : PY_VERSION);
-        return 0;
+        return 1;
     }
 
     /* For Py_GetArgcArgv(). Cleared by pymain_free(). */
     orig_argc = pymain->argc;
     orig_argv = cmdline->argv;
+    return 0;
+}
 
-    res = pymain_init_python_core(pymain);
+
+static int
+pymain_main(_PyMain *pymain)
+{
+    pymain_init(pymain);
+
+    int res = pymain_init_cmdline(pymain);
     if (res < 0) {
-        return -1;
+        _Py_FatalInitError(pymain->err);
+    }
+    if (res == 1) {
+        goto done;
     }
 
-    res = pymain_init_python_main(pymain);
-    if (res < 0) {
-        return -1;
+    if (pymain_init_python_core(pymain) < 0) {
+        _Py_FatalInitError(pymain->err);
     }
 
-    pymain_clear_configs(pymain);
+    if (pymain_init_python_main(pymain) < 0) {
+        _Py_FatalInitError(pymain->err);
+    }
 
     pymain_run_python(pymain);
 
@@ -2529,18 +2561,8 @@ pymain_impl(_PyMain *pymain)
            other special meaning */
         pymain->status = 120;
     }
-    return 0;
-}
-
 
-static int
-pymain_main(_PyMain *pymain)
-{
-    pymain_init(pymain);
-
-    if (pymain_impl(pymain) < 0) {
-        _Py_FatalInitError(pymain->err);
-    }
+done:
     pymain_free(pymain);
 
     return pymain->status;
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 678fbb63cc8..090694f7cae 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -2003,13 +2003,13 @@ fatal_error(const char *prefix, const char *msg, int status)
     }
 }
 
-void
+void _Py_NO_RETURN
 Py_FatalError(const char *msg)
 {
     fatal_error(NULL, msg, -1);
 }
 
-void
+void _Py_NO_RETURN
 _Py_FatalInitError(_PyInitError err)
 {
     /* On "user" error: exit with status 1.



More information about the Python-checkins mailing list