[Python-checkins] bpo-36763: Use PyConfig_Clear() (GH-14445)

Victor Stinner webhook-mailer at python.org
Mon Jul 1 13:52:52 EDT 2019


https://github.com/python/cpython/commit/67310023f299b5a2fad71fca449b46d280036690
commit: 67310023f299b5a2fad71fca449b46d280036690
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2019-07-01T19:52:45+02:00
summary:

bpo-36763: Use PyConfig_Clear() (GH-14445)

Stop using "static PyConfig", PyConfig must now always use
dynamically allocated strings: use PyConfig_SetString(),
PyConfig_SetArgv() and PyConfig_Clear().

files:
M Lib/test/test_embed.py
M Modules/main.c
M Programs/_freeze_importlib.c
M Programs/_testembed.c

diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index e1cf4be50668..b2cd55016e46 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -695,10 +695,19 @@ def test_init_from_config(self):
 
             'pycache_prefix': 'conf_pycache_prefix',
             'program_name': './conf_program_name',
-            'argv': ['-c', 'arg2'],
+            'argv': ['-c', 'arg2', ],
             'parse_argv': 1,
-            'xoptions': ['xoption1=3', 'xoption2=', 'xoption3'],
-            'warnoptions': ['error::ResourceWarning', 'default::BytesWarning'],
+            'xoptions': [
+                'config_xoption1=3',
+                'config_xoption2=',
+                'config_xoption3',
+                'cmdline_xoption',
+            ],
+            'warnoptions': [
+                'config_warnoption',
+                'cmdline_warnoption',
+                'default::BytesWarning',
+            ],
             'run_command': 'pass\n',
 
             'site_import': 0,
diff --git a/Modules/main.c b/Modules/main.c
index 853afedd7b90..b126f4554d41 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -62,7 +62,7 @@ pymain_init(const _PyArgv *args)
     PyConfig config;
     status = PyConfig_InitPythonConfig(&config);
     if (_PyStatus_EXCEPTION(status)) {
-        return status;
+        goto done;
     }
 
     /* pass NULL as the config: config is read from command line arguments,
@@ -74,14 +74,18 @@ pymain_init(const _PyArgv *args)
         status = PyConfig_SetArgv(&config, args->argc, args->wchar_argv);
     }
     if (_PyStatus_EXCEPTION(status)) {
-        return status;
+        goto done;
     }
 
     status = Py_InitializeFromConfig(&config);
     if (_PyStatus_EXCEPTION(status)) {
-        return status;
+        goto done;
     }
-    return _PyStatus_OK();
+    status = _PyStatus_OK();
+
+done:
+    PyConfig_Clear(&config);
+    return status;
 }
 
 
diff --git a/Programs/_freeze_importlib.c b/Programs/_freeze_importlib.c
index 13375b0a3819..74735f279c58 100644
--- a/Programs/_freeze_importlib.c
+++ b/Programs/_freeze_importlib.c
@@ -88,7 +88,7 @@ main(int argc, char *argv[])
     config.site_import = 0;
 
     status = PyConfig_SetString(&config, &config.program_name,
-                                  L"./_freeze_importlib");
+                                L"./_freeze_importlib");
     if (PyStatus_Exception(status)) {
         PyConfig_Clear(&config);
         Py_ExitStatusException(status);
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
index 9633f4610b54..856144b85e17 100644
--- a/Programs/_testembed.c
+++ b/Programs/_testembed.c
@@ -329,6 +329,56 @@ static int test_init_initialize_config(void)
 }
 
 
+static void config_set_string(PyConfig *config, wchar_t **config_str, const wchar_t *str)
+{
+    PyStatus status = PyConfig_SetString(config, config_str, str);
+    if (PyStatus_Exception(status)) {
+        PyConfig_Clear(config);
+        Py_ExitStatusException(status);
+    }
+}
+
+
+static void config_set_argv(PyConfig *config, Py_ssize_t argc, wchar_t * const *argv)
+{
+    PyStatus status = PyConfig_SetArgv(config, argc, argv);
+    if (PyStatus_Exception(status)) {
+        PyConfig_Clear(config);
+        Py_ExitStatusException(status);
+    }
+}
+
+
+static void
+config_set_wide_string_list(PyConfig *config, PyWideStringList *list,
+                            Py_ssize_t length, wchar_t **items)
+{
+    PyStatus status = PyConfig_SetWideStringList(config, list, length, items);
+    if (PyStatus_Exception(status)) {
+        PyConfig_Clear(config);
+        Py_ExitStatusException(status);
+    }
+}
+
+
+static void config_set_program_name(PyConfig *config)
+{
+    /* Use path starting with "./" avoids a search along the PATH */
+    const wchar_t *program_name = L"./_testembed";
+    config_set_string(config, &config->program_name, program_name);
+}
+
+
+static void init_from_config_clear(PyConfig *config)
+{
+    PyStatus status = Py_InitializeFromConfig(config);
+    PyConfig_Clear(config);
+    if (PyStatus_Exception(status)) {
+        Py_ExitStatusException(status);
+    }
+}
+
+
 static int check_init_compat_config(int preinit)
 {
     PyStatus status;
@@ -345,12 +395,8 @@ static int check_init_compat_config(int preinit)
 
     PyConfig config;
     _PyConfig_InitCompatConfig(&config);
-    config.program_name = L"./_testembed";
-
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        Py_ExitStatusException(status);
-    }
+    config_set_program_name(&config);
+    init_from_config_clear(&config);
 
     dump_config();
     Py_Finalize();
@@ -438,7 +484,6 @@ static int test_init_from_config(void)
         Py_ExitStatusException(status);
     }
 
-    /* Test Py_InitializeFromConfig() */
     PyConfig config;
     _PyConfig_InitCompatConfig(&config);
     config.install_signal_handlers = 0;
@@ -468,34 +513,37 @@ static int test_init_from_config(void)
     config.malloc_stats = 1;
 
     putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
-    config.pycache_prefix = L"conf_pycache_prefix";
+    config_set_string(&config, &config.pycache_prefix, L"conf_pycache_prefix");
 
     Py_SetProgramName(L"./globalvar");
-    config.program_name = L"./conf_program_name";
+    config_set_string(&config, &config.program_name, L"./conf_program_name");
 
-    static wchar_t* argv[] = {
+    wchar_t* argv[] = {
         L"python3",
+        L"-W",
+        L"cmdline_warnoption",
+        L"-X",
+        L"cmdline_xoption",
         L"-c",
         L"pass",
         L"arg2",
     };
-    config.argv.length = Py_ARRAY_LENGTH(argv);
-    config.argv.items = argv;
+    config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
     config.parse_argv = 1;
 
-    static wchar_t* xoptions[3] = {
-        L"xoption1=3",
-        L"xoption2=",
-        L"xoption3",
+    wchar_t* xoptions[3] = {
+        L"config_xoption1=3",
+        L"config_xoption2=",
+        L"config_xoption3",
     };
-    config.xoptions.length = Py_ARRAY_LENGTH(xoptions);
-    config.xoptions.items = xoptions;
+    config_set_wide_string_list(&config, &config.xoptions,
+                                Py_ARRAY_LENGTH(xoptions), xoptions);
 
-    static wchar_t* warnoptions[1] = {
-        L"error::ResourceWarning",
+    wchar_t* warnoptions[1] = {
+        L"config_warnoption",
     };
-    config.warnoptions.length = Py_ARRAY_LENGTH(warnoptions);
-    config.warnoptions.items = warnoptions;
+    config_set_wide_string_list(&config, &config.warnoptions,
+                                Py_ARRAY_LENGTH(warnoptions), warnoptions);
 
     /* FIXME: test pythonpath_env */
     /* FIXME: test home */
@@ -544,22 +592,20 @@ static int test_init_from_config(void)
        Force it to 0 through the config. */
     config.legacy_windows_stdio = 0;
 #endif
-    config.stdio_encoding = L"iso8859-1";
-    config.stdio_errors = L"replace";
+    config_set_string(&config, &config.stdio_encoding, L"iso8859-1");
+    config_set_string(&config, &config.stdio_errors, L"replace");
 
     putenv("PYTHONNOUSERSITE=");
     Py_NoUserSiteDirectory = 0;
     config.user_site_directory = 0;
 
-    config.check_hash_pycs_mode = L"always";
+    config_set_string(&config, &config.check_hash_pycs_mode, L"always");
 
     Py_FrozenFlag = 0;
     config.pathconfig_warnings = 0;
 
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        Py_ExitStatusException(status);
-    }
+    init_from_config_clear(&config);
+
     dump_config();
     Py_Finalize();
     return 0;
@@ -576,7 +622,9 @@ static int check_init_parse_argv(int parse_argv)
         Py_ExitStatusException(status);
     }
 
-    static wchar_t* argv[] = {
+    config.parse_argv = parse_argv;
+
+    wchar_t* argv[] = {
         L"./argv0",
         L"-E",
         L"-c",
@@ -585,15 +633,9 @@ static int check_init_parse_argv(int parse_argv)
         L"-v",
         L"arg3",
     };
+    config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
+    init_from_config_clear(&config);
 
-    config.argv.length = Py_ARRAY_LENGTH(argv);
-    config.argv.items = argv;
-    config.parse_argv = parse_argv;
-
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        Py_ExitStatusException(status);
-    }
     dump_config();
     Py_Finalize();
     return 0;
@@ -664,12 +706,10 @@ static int test_init_python_env(void)
     if (PyStatus_Exception(status)) {
         Py_ExitStatusException(status);
     }
-    config.program_name = L"./_testembed";
 
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        Py_ExitStatusException(status);
-    }
+    config_set_program_name(&config);
+    init_from_config_clear(&config);
+
     dump_config();
     Py_Finalize();
     return 0;
@@ -723,14 +763,10 @@ static int test_init_isolated_flag(void)
     Py_IsolatedFlag = 0;
     config.isolated = 1;
 
-    /* Use path starting with "./" avoids a search along the PATH */
-    config.program_name = L"./_testembed";
-
+    config_set_program_name(&config);
     set_all_env_vars();
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        Py_ExitStatusException(status);
-    }
+    init_from_config_clear(&config);
+
     dump_config();
     Py_Finalize();
     return 0;
@@ -753,13 +789,10 @@ static int test_preinit_isolated1(void)
 
     PyConfig config;
     _PyConfig_InitCompatConfig(&config);
-    config.program_name = L"./_testembed";
-
+    config_set_program_name(&config);
     set_all_env_vars();
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        Py_ExitStatusException(status);
-    }
+    init_from_config_clear(&config);
+
     dump_config();
     Py_Finalize();
     return 0;
@@ -787,14 +820,10 @@ static int test_preinit_isolated2(void)
     Py_IsolatedFlag = 0;
     config.isolated = 1;
 
-    /* Use path starting with "./" avoids a search along the PATH */
-    config.program_name = L"./_testembed";
-
+    config_set_program_name(&config);
     set_all_env_vars();
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        Py_ExitStatusException(status);
-    }
+    init_from_config_clear(&config);
+
     dump_config();
     Py_Finalize();
     return 0;
@@ -819,44 +848,28 @@ static int test_preinit_dont_parse_argv(void)
                        L"script.py"};
     status = Py_PreInitializeFromArgs(&preconfig, Py_ARRAY_LENGTH(argv), argv);
     if (PyStatus_Exception(status)) {
-        goto failed;
+        Py_ExitStatusException(status);
     }
 
     PyConfig config;
 
     status = PyConfig_InitIsolatedConfig(&config);
     if (PyStatus_Exception(status)) {
-        goto failed;
+        PyConfig_Clear(&config);
+        Py_ExitStatusException(status);
     }
 
     config.isolated = 0;
 
     /* Pre-initialize implicitly using argv: make sure that -X dev
        is used to configure the allocation in preinitialization */
-    status = PyConfig_SetArgv(&config, Py_ARRAY_LENGTH(argv), argv);
-    if (PyStatus_Exception(status)) {
-        goto failed;
-    }
-
-    status = PyConfig_SetString(&config, &config.program_name,
-                                  L"./_testembed");
-    if (PyStatus_Exception(status)) {
-        goto failed;
-    }
-
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        goto failed;
-    }
-    PyConfig_Clear(&config);
+    config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
+    config_set_program_name(&config);
+    init_from_config_clear(&config);
 
     dump_config();
     Py_Finalize();
     return 0;
-
-failed:
-    PyConfig_Clear(&config);
-    Py_ExitStatusException(status);
 }
 
 
@@ -867,36 +880,20 @@ static int test_preinit_parse_argv(void)
 
     status = PyConfig_InitPythonConfig(&config);
     if (PyStatus_Exception(status)) {
-        goto failed;
+        PyConfig_Clear(&config);
+        Py_ExitStatusException(status);
     }
 
     /* Pre-initialize implicitly using argv: make sure that -X dev
        is used to configure the allocation in preinitialization */
     wchar_t *argv[] = {L"python3", L"-X", L"dev", L"script.py"};
-    status = PyConfig_SetArgv(&config, Py_ARRAY_LENGTH(argv), argv);
-    if (PyStatus_Exception(status)) {
-        goto failed;
-    }
-
-    status = PyConfig_SetString(&config, &config.program_name,
-                                  L"./_testembed");
-    if (PyStatus_Exception(status)) {
-        goto failed;
-    }
-
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        goto failed;
-    }
-    PyConfig_Clear(&config);
+    config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
+    config_set_program_name(&config);
+    init_from_config_clear(&config);
 
     dump_config();
     Py_Finalize();
     return 0;
-
-failed:
-    PyConfig_Clear(&config);
-    Py_ExitStatusException(status);
 }
 
 
@@ -955,13 +952,8 @@ static int check_preinit_isolated_config(int preinit)
         PyConfig_Clear(&config);
         Py_ExitStatusException(status);
     }
-    config.program_name = L"./_testembed";
-
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        PyConfig_Clear(&config);
-        Py_ExitStatusException(status);
-    }
+    config_set_program_name(&config);
+    init_from_config_clear(&config);
 
     rt_preconfig = &_PyRuntime.preconfig;
     assert(rt_preconfig->isolated == 1);
@@ -1017,12 +1009,9 @@ static int check_init_python_config(int preinit)
     if (PyStatus_Exception(status)) {
         Py_ExitStatusException(status);
     }
-    config.program_name = L"./_testembed";
+    config_set_program_name(&config);
+    init_from_config_clear(&config);
 
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        Py_ExitStatusException(status);
-    }
     dump_config();
     Py_Finalize();
     return 0;
@@ -1061,11 +1050,8 @@ static int test_init_dont_configure_locale(void)
     if (PyStatus_Exception(status)) {
         Py_ExitStatusException(status);
     }
-    config.program_name = L"./_testembed";
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        Py_ExitStatusException(status);
-    }
+    config_set_program_name(&config);
+    init_from_config_clear(&config);
 
     dump_config();
     Py_Finalize();
@@ -1084,11 +1070,9 @@ static int test_init_dev_mode(void)
     putenv("PYTHONFAULTHANDLER=");
     putenv("PYTHONMALLOC=");
     config.dev_mode = 1;
-    config.program_name = L"./_testembed";
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        Py_ExitStatusException(status);
-    }
+    config_set_program_name(&config);
+    init_from_config_clear(&config);
+
     dump_config();
     Py_Finalize();
     return 0;
@@ -1278,16 +1262,9 @@ static int test_init_read_set(void)
     }
 
     /* override executable computed by PyConfig_Read() */
-    status = PyConfig_SetString(&config, &config.executable, L"my_executable");
-    if (PyStatus_Exception(status)) {
-        goto fail;
-    }
+    config_set_string(&config, &config.executable, L"my_executable");
+    init_from_config_clear(&config);
 
-    status = Py_InitializeFromConfig(&config);
-    PyConfig_Clear(&config);
-    if (PyStatus_Exception(status)) {
-        goto fail;
-    }
     dump_config();
     Py_Finalize();
     return 0;
@@ -1297,19 +1274,18 @@ static int test_init_read_set(void)
 }
 
 
-wchar_t *init_main_argv[] = {
-    L"python3", L"-c",
-    (L"import _testinternalcapi, json; "
-     L"print(json.dumps(_testinternalcapi.get_configs()))"),
-    L"arg2"};
-
-
 static void configure_init_main(PyConfig *config)
 {
-    config->argv.length = Py_ARRAY_LENGTH(init_main_argv);
-    config->argv.items = init_main_argv;
+    wchar_t* argv[] = {
+        L"python3", L"-c",
+        (L"import _testinternalcapi, json; "
+         L"print(json.dumps(_testinternalcapi.get_configs()))"),
+        L"arg2"};
+
     config->parse_argv = 1;
-    config->program_name = L"./python3";
+
+    config_set_argv(config, Py_ARRAY_LENGTH(argv), argv);
+    config_set_string(config, &config->program_name, L"./python3");
 }
 
 
@@ -1322,11 +1298,7 @@ static int test_init_run_main(void)
         Py_ExitStatusException(status);
     }
     configure_init_main(&config);
-
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        Py_ExitStatusException(status);
-    }
+    init_from_config_clear(&config);
 
     return Py_RunMain();
 }
@@ -1343,11 +1315,7 @@ static int test_init_main(void)
     }
     configure_init_main(&config);
     config._init_main = 0;
-
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        Py_ExitStatusException(status);
-    }
+    init_from_config_clear(&config);
 
     /* sys.stdout don't exist yet: it is created by _Py_InitializeMain() */
     int res = PyRun_SimpleString(
@@ -1374,35 +1342,19 @@ static int test_run_main(void)
 
     status = PyConfig_InitPythonConfig(&config);
     if (PyStatus_Exception(status)) {
-        goto failed;
+        PyConfig_Clear(&config);
+        Py_ExitStatusException(status);
     }
 
     wchar_t *argv[] = {L"python3", L"-c",
                        (L"import sys; "
                         L"print(f'Py_RunMain(): sys.argv={sys.argv}')"),
                        L"arg2"};
-    status = PyConfig_SetArgv(&config, Py_ARRAY_LENGTH(argv), argv);
-    if (PyStatus_Exception(status)) {
-        goto failed;
-    }
-
-    status = PyConfig_SetString(&config, &config.program_name,
-                                  L"./python3");
-    if (PyStatus_Exception(status)) {
-        goto failed;
-    }
-
-    status = Py_InitializeFromConfig(&config);
-    if (PyStatus_Exception(status)) {
-        goto failed;
-    }
-    PyConfig_Clear(&config);
+    config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
+    config_set_string(&config, &config.program_name, L"./python3");
+    init_from_config_clear(&config);
 
     return Py_RunMain();
-
-failed:
-    PyConfig_Clear(&config);
-    Py_ExitStatusException(status);
 }
 
 



More information about the Python-checkins mailing list