[Python-checkins] bpo-36301: Add _PyPreCmdline internal API (GH-12458)

Victor Stinner webhook-mailer at python.org
Tue Mar 19 23:25:41 EDT 2019


https://github.com/python/cpython/commit/fa1537684869186da7938e4330361bf02363bac8
commit: fa1537684869186da7938e4330361bf02363bac8
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2019-03-20T04:25:38+01:00
summary:

bpo-36301: Add _PyPreCmdline internal API (GH-12458)

_PyCoreConfig_ReadFromArgv() now reuses the code parsing command line
options from preconfig.c.

files:
M Include/internal/pycore_coreconfig.h
M Python/coreconfig.c
M Python/preconfig.c

diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h
index 8c5a072e5677..29261df5af75 100644
--- a/Include/internal/pycore_coreconfig.h
+++ b/Include/internal/pycore_coreconfig.h
@@ -9,6 +9,30 @@ extern "C" {
 #endif
 
 
+/* --- _PyPreCmdline ------------------------------------------------- */
+
+typedef struct {
+    _PyWstrList argv;
+    _PyWstrList xoptions;     /* "-X value" option */
+    int use_environment;      /* -E option */
+    int isolated;             /* -I option */
+} _PyPreCmdline;
+
+#define _PyPreCmdline_INIT \
+    (_PyPreCmdline){ \
+        .use_environment = -1, \
+        .isolated = -1}
+/* Note: _PyPreCmdline_INIT sets other fields to 0/NULL */
+
+PyAPI_FUNC(void) _PyPreCmdline_Clear(_PyPreCmdline *cmdline);
+PyAPI_FUNC(_PyInitError) _PyPreCmdline_Init(_PyPreCmdline *cmdline,
+    const _PyArgv *args);
+PyAPI_FUNC(_PyInitError) _PyPreCmdline_Read(_PyPreCmdline *cmdline);
+PyAPI_FUNC(void) _PyPreCmdline_SetPreConfig(
+    const _PyPreCmdline *cmdline,
+    _PyPreConfig *config);
+
+
 /* --- _PyWstrList ------------------------------------------------ */
 
 #ifndef NDEBUG
diff --git a/Python/coreconfig.c b/Python/coreconfig.c
index e1d883c51cbf..1881f00bf2f5 100644
--- a/Python/coreconfig.c
+++ b/Python/coreconfig.c
@@ -1658,7 +1658,7 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config)
 /* --- _PyCmdline ------------------------------------------------- */
 
 typedef struct {
-    _PyWstrList argv;
+    _PyPreCmdline precmdline;
     _PyWstrList warnoptions;     /* Command line -W options */
     _PyWstrList env_warnoptions; /* PYTHONWARNINGS environment variables */
     int print_help;              /* -h, -? options */
@@ -1669,9 +1669,9 @@ typedef struct {
 static void
 cmdline_clear(_PyCmdline *cmdline)
 {
+    _PyPreCmdline_Clear(&cmdline->precmdline);
     _PyWstrList_Clear(&cmdline->warnoptions);
     _PyWstrList_Clear(&cmdline->env_warnoptions);
-    _PyWstrList_Clear(&cmdline->argv);
 }
 
 
@@ -1682,10 +1682,12 @@ static _PyInitError
 config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
                      int *need_usage)
 {
+    const _PyWstrList *argv = &cmdline->precmdline.argv;
+
     _PyOS_ResetGetOpt();
     do {
         int longindex = -1;
-        int c = _PyOS_GetOpt(cmdline->argv.length, cmdline->argv.items, &longindex);
+        int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
         if (c == EOF) {
             break;
         }
@@ -1754,6 +1756,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
 
         case 'E':
         case 'I':
+        case 'X':
             /* option handled by _PyPreConfig_ReadFromArgv() */
             break;
 
@@ -1806,12 +1809,6 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
             }
             break;
 
-        case 'X':
-            if (_PyWstrList_Append(&config->xoptions, _PyOS_optarg) < 0) {
-                return _Py_INIT_NO_MEMORY();
-            }
-            break;
-
         case 'q':
             config->quiet++;
             break;
@@ -1830,11 +1827,11 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
     } while (1);
 
     if (config->run_command == NULL && config->run_module == NULL
-        && _PyOS_optind < cmdline->argv.length
-        && wcscmp(cmdline->argv.items[_PyOS_optind], L"-") != 0
+        && _PyOS_optind < argv->length
+        && wcscmp(argv->items[_PyOS_optind], L"-") != 0
         && config->run_filename == NULL)
     {
-        config->run_filename = _PyMem_RawWcsdup(cmdline->argv.items[_PyOS_optind]);
+        config->run_filename = _PyMem_RawWcsdup(argv->items[_PyOS_optind]);
         if (config->run_filename == NULL) {
             return _Py_INIT_NO_MEMORY();
         }
@@ -1892,9 +1889,10 @@ cmdline_init_env_warnoptions(_PyCmdline *cmdline, const _PyCoreConfig *config)
 static _PyInitError
 config_init_program(_PyCoreConfig *config, const _PyCmdline *cmdline)
 {
+    const _PyWstrList *argv = &cmdline->precmdline.argv;
     wchar_t *program;
-    if (cmdline->argv.length >= 1) {
-        program = cmdline->argv.items[0];
+    if (argv->length >= 1) {
+        program = argv->items[0];
     }
     else {
         program = L"";
@@ -1965,24 +1963,25 @@ config_init_warnoptions(_PyCoreConfig *config, const _PyCmdline *cmdline)
 static _PyInitError
 config_init_argv(_PyCoreConfig *config, const _PyCmdline *cmdline)
 {
-    _PyWstrList wargv = _PyWstrList_INIT;
+    const _PyWstrList *cmdline_argv = &cmdline->precmdline.argv;
+    _PyWstrList config_argv = _PyWstrList_INIT;
 
     /* Copy argv to be able to modify it (to force -c/-m) */
-    if (cmdline->argv.length <= _PyOS_optind) {
+    if (cmdline_argv->length <= _PyOS_optind) {
         /* Ensure at least one (empty) argument is seen */
-        if (_PyWstrList_Append(&wargv, L"") < 0) {
+        if (_PyWstrList_Append(&config_argv, L"") < 0) {
             return _Py_INIT_NO_MEMORY();
         }
     }
     else {
         _PyWstrList slice;
-        slice.length = cmdline->argv.length - _PyOS_optind;
-        slice.items = &cmdline->argv.items[_PyOS_optind];
-        if (_PyWstrList_Copy(&wargv, &slice) < 0) {
+        slice.length = cmdline_argv->length - _PyOS_optind;
+        slice.items = &cmdline_argv->items[_PyOS_optind];
+        if (_PyWstrList_Copy(&config_argv, &slice) < 0) {
             return _Py_INIT_NO_MEMORY();
         }
     }
-    assert(wargv.length >= 1);
+    assert(config_argv.length >= 1);
 
     wchar_t *arg0 = NULL;
     if (config->run_command != NULL) {
@@ -1996,16 +1995,16 @@ config_init_argv(_PyCoreConfig *config, const _PyCmdline *cmdline)
     if (arg0 != NULL) {
         arg0 = _PyMem_RawWcsdup(arg0);
         if (arg0 == NULL) {
-            _PyWstrList_Clear(&wargv);
+            _PyWstrList_Clear(&config_argv);
             return _Py_INIT_NO_MEMORY();
         }
 
-        PyMem_RawFree(wargv.items[0]);
-        wargv.items[0] = arg0;
+        PyMem_RawFree(config_argv.items[0]);
+        config_argv.items[0] = arg0;
     }
 
     _PyWstrList_Clear(&config->argv);
-    config->argv = wargv;
+    config->argv = config_argv;
     return _Py_INIT_OK();
 }
 
@@ -2046,6 +2045,16 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
         }
     }
 
+    err = _PyPreCmdline_Read(&cmdline->precmdline);
+    if (_Py_INIT_FAILED(err)) {
+        return err;
+    }
+
+    _PyPreCmdline_SetPreConfig(&cmdline->precmdline, &config->preconfig);
+    if (_PyWstrList_Extend(&config->xoptions, &cmdline->precmdline.xoptions) < 0) {
+        return _Py_INIT_NO_MEMORY();
+    }
+
     err = config_parse_cmdline(config, cmdline, &need_usage);
     if (_Py_INIT_FAILED(err)) {
         return err;
@@ -2089,7 +2098,8 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
         return err;
     }
 
-    if (_Py_SetArgcArgv(cmdline->argv.length, cmdline->argv.items) < 0) {
+    const _PyWstrList *argv = &cmdline->precmdline.argv;
+    if (_Py_SetArgcArgv(argv->length, argv->items) < 0) {
         return _Py_INIT_NO_MEMORY();
     }
     return _Py_INIT_OK();
@@ -2107,10 +2117,9 @@ _PyCoreConfig_ReadFromArgv(_PyCoreConfig *config, const _PyArgv *args,
 {
     _PyInitError err;
 
-    _PyCmdline cmdline;
-    memset(&cmdline, 0, sizeof(cmdline));
+    _PyCmdline cmdline = {.precmdline = _PyPreCmdline_INIT};
 
-    err = _PyArgv_AsWstrList(args, &cmdline.argv);
+    err = _PyPreCmdline_Init(&cmdline.precmdline, args);
     if (_Py_INIT_FAILED(err)) {
         goto done;
     }
diff --git a/Python/preconfig.c b/Python/preconfig.c
index a149ea54f65a..d856c124f3e9 100644
--- a/Python/preconfig.c
+++ b/Python/preconfig.c
@@ -102,20 +102,21 @@ _PyArgv_AsWstrList(const _PyArgv *args, _PyWstrList *list)
 
 /* --- _PyPreCmdline ------------------------------------------------- */
 
-typedef struct {
-    _PyWstrList argv;
-    _PyWstrList xoptions;     /* -X options */
-} _PyPreCmdline;
-
-
-static void
-precmdline_clear(_PyPreCmdline *cmdline)
+void
+_PyPreCmdline_Clear(_PyPreCmdline *cmdline)
 {
     _PyWstrList_Clear(&cmdline->argv);
     _PyWstrList_Clear(&cmdline->xoptions);
 }
 
 
+_PyInitError
+_PyPreCmdline_Init(_PyPreCmdline *cmdline, const _PyArgv *args)
+{
+    return _PyArgv_AsWstrList(args, &cmdline->argv);
+}
+
+
 /* --- _PyPreConfig ----------------------------------------------- */
 
 void
@@ -520,6 +521,21 @@ _PyPreConfig_Read(_PyPreConfig *config)
 }
 
 
+void
+_PyPreCmdline_SetPreConfig(const _PyPreCmdline *cmdline, _PyPreConfig *config)
+{
+#define COPY_ATTR(ATTR) \
+    if (cmdline->ATTR != -1) { \
+        config->ATTR = cmdline->ATTR; \
+    }
+
+    COPY_ATTR(use_environment);
+    COPY_ATTR(isolated);
+
+#undef COPY_ATTR
+}
+
+
 int
 _PyPreConfig_AsDict(const _PyPreConfig *config, PyObject *dict)
 {
@@ -567,16 +583,18 @@ _PyPreConfig_AsDict(const _PyPreConfig *config, PyObject *dict)
 
 
 /* Parse the command line arguments */
-static _PyInitError
-preconfig_parse_cmdline(_PyPreConfig *config, _PyPreCmdline *cmdline)
+_PyInitError
+_PyPreCmdline_Read(_PyPreCmdline *cmdline)
 {
+    _PyWstrList *argv = &cmdline->argv;
+
     _PyOS_ResetGetOpt();
     /* Don't log parsing errors into stderr here: _PyCoreConfig_ReadFromArgv()
        is responsible for that */
     _PyOS_opterr = 0;
     do {
         int longindex = -1;
-        int c = _PyOS_GetOpt(cmdline->argv.length, cmdline->argv.items, &longindex);
+        int c = _PyOS_GetOpt(argv->length, argv->items, &longindex);
 
         if (c == EOF || c == 'c' || c == 'm') {
             break;
@@ -584,11 +602,11 @@ preconfig_parse_cmdline(_PyPreConfig *config, _PyPreCmdline *cmdline)
 
         switch (c) {
         case 'E':
-            config->use_environment = 0;
+            cmdline->use_environment = 0;
             break;
 
         case 'I':
-            config->isolated++;
+            cmdline->isolated = 1;
             break;
 
         case 'X':
@@ -615,19 +633,20 @@ preconfig_from_argv(_PyPreConfig *config, const _PyArgv *args)
 {
     _PyInitError err;
 
-    _PyPreCmdline cmdline;
-    memset(&cmdline, 0, sizeof(cmdline));
+    _PyPreCmdline cmdline = _PyPreCmdline_INIT;
 
-    err = _PyArgv_AsWstrList(args, &cmdline.argv);
+    err = _PyPreCmdline_Init(&cmdline, args);
     if (_Py_INIT_FAILED(err)) {
         goto done;
     }
 
-    err = preconfig_parse_cmdline(config, &cmdline);
+    err = _PyPreCmdline_Read(&cmdline);
     if (_Py_INIT_FAILED(err)) {
         goto done;
     }
 
+    _PyPreCmdline_SetPreConfig(&cmdline, config);
+
     err = preconfig_read(config, &cmdline);
     if (_Py_INIT_FAILED(err)) {
         goto done;
@@ -635,7 +654,7 @@ preconfig_from_argv(_PyPreConfig *config, const _PyArgv *args)
     err = _Py_INIT_OK();
 
 done:
-    precmdline_clear(&cmdline);
+    _PyPreCmdline_Clear(&cmdline);
     return err;
 }
 



More information about the Python-checkins mailing list