]> granicus.if.org Git - python/commitdiff
bpo-36763: Add _PyPreConfig._config_init (GH-13481)
authorVictor Stinner <vstinner@redhat.com>
Wed, 22 May 2019 21:58:50 +0000 (23:58 +0200)
committerGitHub <noreply@github.com>
Wed, 22 May 2019 21:58:50 +0000 (23:58 +0200)
* _PyPreConfig_GetGlobalConfig() and  _PyCoreConfig_GetGlobalConfig()
  now do nothing if the configuration was not initialized with
  _PyPreConfig_InitCompatConfig() and _PyCoreConfig_InitCompatConfig()
* Remove utf8_mode=-2 special case: use utf8_mode=-1 instead.
* Fix _PyPreConfig_InitPythonConfig():

  * isolated = 0 instead of -1
  * use_environment = 1 instead of -1

* Rename _PyConfig_INIT to  _PyConfig_INIT_COMPAT
* Rename _PyPreConfig_Init() to _PyPreConfig_InitCompatConfig()
* Rename _PyCoreConfig_Init() to _PyCoreConfig_InitCompatConfig()
* PyInterpreterState_New() now uses _PyCoreConfig_InitPythonConfig()
  as default configuration, but it's very quickly overriden anyway.
* _freeze_importlib.c uses _PyCoreConfig_SetString() to set
  program_name.
* Cleanup preconfig_init_utf8_mode(): cmdline is always non-NULL.

Include/cpython/coreconfig.h
Include/internal/pycore_coreconfig.h
Lib/test/test_embed.py
Programs/_freeze_importlib.c
Programs/_testembed.c
Python/coreconfig.c
Python/frozenmain.c
Python/pathconfig.c
Python/preconfig.c
Python/pylifecycle.c
Python/pystate.c

index decfb70e7345c5643f1dba0ed1e6f4c81293e8f4..ef5fde20e88d67707875db9359bf5dc32f610a56 100644 (file)
@@ -40,9 +40,18 @@ typedef struct {
 
 #define _Py_CONFIG_VERSION 1
 
+typedef enum {
+    /* Py_Initialize() API: backward compatibility with Python 3.6 and 3.7 */
+    _PyConfig_INIT_COMPAT = 1,
+    _PyConfig_INIT_PYTHON = 2,
+    _PyConfig_INIT_ISOLATED = 3
+} _PyConfigInitEnum;
+
+
 typedef struct {
     int _config_version;  /* Internal configuration version,
                              used for ABI compatibility */
+    int _config_init;     /* _PyConfigInitEnum value */
 
     /* Parse _Py_PreInitializeFromArgs() arguments?
        See _PyCoreConfig.parse_argv */
@@ -107,10 +116,7 @@ typedef struct {
        Set to 0 by "-X utf8=0" and PYTHONUTF8=0.
 
        If equals to -1, it is set to 1 if the LC_CTYPE locale is "C" or
-       "POSIX", otherwise it is set to 0.
-
-       If equals to -2, inherit Py_UTF8Mode value value (which is equal to 0
-       by default). */
+       "POSIX", otherwise it is set to 0. Inherit Py_UTF8Mode value value. */
     int utf8_mode;
 
     int dev_mode;           /* Development mode. PYTHONDEVMODE, -X dev */
@@ -126,16 +132,10 @@ PyAPI_FUNC(void) _PyPreConfig_InitIsolatedConfig(_PyPreConfig *config);
 
 /* --- _PyCoreConfig ---------------------------------------------- */
 
-typedef enum {
-    _PyCoreConfig_INIT = 0,
-    _PyCoreConfig_INIT_PYTHON = 1,
-    _PyCoreConfig_INIT_ISOLATED = 2
-} _PyCoreConfigInitEnum;
-
 typedef struct {
     int _config_version;  /* Internal configuration version,
                              used for ABI compatibility */
-    int _config_init;     /* _PyCoreConfigInitEnum value */
+    int _config_init;     /* _PyConfigInitEnum value */
 
     int isolated;         /* Isolated mode? see _PyPreConfig.isolated */
     int use_environment;  /* Use environment variables? see _PyPreConfig.use_environment */
index 324e0b82b90c60ede9a55e1768f5f19e0ece367d..b17737a90ba325207e666815b5a7968da85d0644 100644 (file)
@@ -120,7 +120,7 @@ PyAPI_FUNC(_PyInitError) _PyPreCmdline_Read(_PyPreCmdline *cmdline,
 
 /* --- _PyPreConfig ----------------------------------------------- */
 
-PyAPI_FUNC(void) _PyPreConfig_Init(_PyPreConfig *config);
+PyAPI_FUNC(void) _PyPreConfig_InitCompatConfig(_PyPreConfig *config);
 PyAPI_FUNC(void) _PyPreConfig_InitFromCoreConfig(
     _PyPreConfig *config,
     const _PyCoreConfig *coreconfig);
@@ -139,7 +139,7 @@ PyAPI_FUNC(_PyInitError) _PyPreConfig_Write(const _PyPreConfig *config);
 
 /* --- _PyCoreConfig ---------------------------------------------- */
 
-PyAPI_FUNC(void) _PyCoreConfig_Init(_PyCoreConfig *config);
+PyAPI_FUNC(void) _PyCoreConfig_InitCompatConfig(_PyCoreConfig *config);
 PyAPI_FUNC(_PyInitError) _PyCoreConfig_Copy(
     _PyCoreConfig *config,
     const _PyCoreConfig *config2);
index 4fe005dfa130e33e6f88185adde4cd7281257334..8101e70f9bc9d008a8de15bd05c6b504f4aaf73d 100644 (file)
@@ -13,13 +13,17 @@ import textwrap
 
 
 MS_WINDOWS = (os.name == 'nt')
+
 PYMEM_ALLOCATOR_NOT_SET = 0
 PYMEM_ALLOCATOR_DEBUG = 2
 PYMEM_ALLOCATOR_MALLOC = 3
 
-CONFIG_INIT = 0
-CONFIG_INIT_PYTHON = 1
-CONFIG_INIT_ISOLATED = 2
+# _PyCoreConfig_InitCompatConfig()
+API_COMPAT = 1
+# _PyCoreConfig_InitPythonConfig()
+API_PYTHON = 2
+# _PyCoreConfig_InitIsolatedConfig()
+API_ISOLATED = 3
 
 
 class EmbeddingTestsMixin:
@@ -282,7 +286,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
     # Marker to ignore a configuration parameter
     IGNORE_CONFIG = object()
 
-    DEFAULT_PRE_CONFIG = {
+    PRE_CONFIG_COMPAT = {
         'allocator': PYMEM_ALLOCATOR_NOT_SET,
         'parse_argv': 0,
         'configure_locale': 1,
@@ -291,15 +295,15 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
         'utf8_mode': 0,
     }
     if MS_WINDOWS:
-        DEFAULT_PRE_CONFIG.update({
+        PRE_CONFIG_COMPAT.update({
             'legacy_windows_fs_encoding': 0,
         })
-    PYTHON_PRE_CONFIG = dict(DEFAULT_PRE_CONFIG,
+    PRE_CONFIG_PYTHON = dict(PRE_CONFIG_COMPAT,
         parse_argv=1,
         coerce_c_locale=GET_DEFAULT_CONFIG,
         utf8_mode=GET_DEFAULT_CONFIG,
     )
-    ISOLATED_PRE_CONFIG = dict(DEFAULT_PRE_CONFIG,
+    PRE_CONFIG_ISOLATED = dict(PRE_CONFIG_COMPAT,
         configure_locale=0,
         isolated=1,
         use_environment=0,
@@ -314,8 +318,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
         'use_environment',
     ]
 
-    DEFAULT_CORE_CONFIG = {
-        '_config_init': CONFIG_INIT,
+    CORE_CONFIG_COMPAT = {
+        '_config_init': API_COMPAT,
         'isolated': 0,
         'use_environment': 1,
         'dev_mode': 0,
@@ -379,15 +383,15 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
         '_init_main': 1,
     }
     if MS_WINDOWS:
-        DEFAULT_CORE_CONFIG.update({
+        CORE_CONFIG_COMPAT.update({
             'legacy_windows_stdio': 0,
         })
 
-    PYTHON_CORE_CONFIG = dict(DEFAULT_CORE_CONFIG,
+    CORE_CONFIG_PYTHON = dict(CORE_CONFIG_COMPAT,
         configure_c_stdio=1,
         parse_argv=1,
     )
-    ISOLATED_CORE_CONFIG = dict(DEFAULT_CORE_CONFIG,
+    CORE_CONFIG_ISOLATED = dict(CORE_CONFIG_COMPAT,
         isolated=1,
         use_environment=0,
         user_site_directory=0,
@@ -399,7 +403,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
         pathconfig_warnings=0,
     )
     if MS_WINDOWS:
-        ISOLATED_CORE_CONFIG['legacy_windows_stdio'] = 0
+        CORE_CONFIG_ISOLATED['legacy_windows_stdio'] = 0
 
     # global config
     DEFAULT_GLOBAL_CONFIG = {
@@ -492,7 +496,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             if value is self.GET_DEFAULT_CONFIG:
                 expected_preconfig[key] = pre_config[key]
 
-        if not expected_preconfig['configure_locale'] or api == CONFIG_INIT:
+        if not expected_preconfig['configure_locale'] or api == API_COMPAT:
             # there is no easy way to get the locale encoding before
             # setlocale(LC_CTYPE, "") is called: don't test encodings
             for key in ('filesystem_encoding', 'filesystem_errors',
@@ -579,32 +583,33 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
 
         self.assertEqual(config['global_config'], expected)
 
-    def check_config(self, testname, expected_config=None, expected_preconfig=None,
-                     add_path=None, stderr=None, api=CONFIG_INIT):
+    def check_config(self, testname, expected_config=None,
+                     expected_preconfig=None, add_path=None, stderr=None,
+                     *, api):
         env = dict(os.environ)
         # Remove PYTHON* environment variables to get deterministic environment
         for key in list(env):
             if key.startswith('PYTHON'):
                 del env[key]
 
-        if api == CONFIG_INIT_ISOLATED:
-            default_preconfig = self.ISOLATED_PRE_CONFIG
-        elif api == CONFIG_INIT_PYTHON:
-            default_preconfig = self.PYTHON_PRE_CONFIG
+        if api == API_ISOLATED:
+            default_preconfig = self.PRE_CONFIG_ISOLATED
+        elif api == API_PYTHON:
+            default_preconfig = self.PRE_CONFIG_PYTHON
         else:
-            default_preconfig = self.DEFAULT_PRE_CONFIG
+            default_preconfig = self.PRE_CONFIG_COMPAT
         if expected_preconfig is None:
             expected_preconfig = {}
         expected_preconfig = dict(default_preconfig, **expected_preconfig)
         if expected_config is None:
             expected_config = {}
 
-        if api == CONFIG_INIT_PYTHON:
-            default_config = self.PYTHON_CORE_CONFIG
-        elif api == CONFIG_INIT_ISOLATED:
-            default_config = self.ISOLATED_CORE_CONFIG
+        if api == API_PYTHON:
+            default_config = self.CORE_CONFIG_PYTHON
+        elif api == API_ISOLATED:
+            default_config = self.CORE_CONFIG_ISOLATED
         else:
-            default_config = self.DEFAULT_CORE_CONFIG
+            default_config = self.CORE_CONFIG_COMPAT
         expected_config = dict(default_config, **expected_config)
         expected_config['_config_init'] = api
 
@@ -627,7 +632,13 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
         self.check_global_config(config)
 
     def test_init_default_config(self):
-        self.check_config("init_default_config", {}, {})
+        self.check_config("init_initialize_config", api=API_COMPAT)
+
+    def test_preinit_compat_config(self):
+        self.check_config("preinit_compat_config", api=API_COMPAT)
+
+    def test_init_compat_config(self):
+        self.check_config("init_compat_config", api=API_COMPAT)
 
     def test_init_global_config(self):
         preconfig = {
@@ -649,7 +660,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'user_site_directory': 0,
             'pathconfig_warnings': 0,
         }
-        self.check_config("init_global_config", config, preconfig)
+        self.check_config("init_global_config", config, preconfig,
+                          api=API_COMPAT)
 
     def test_init_from_config(self):
         preconfig = {
@@ -693,11 +705,13 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'check_hash_pycs_mode': 'always',
             'pathconfig_warnings': 0,
         }
-        self.check_config("init_from_config", config, preconfig)
+        self.check_config("init_from_config", config, preconfig,
+                          api=API_COMPAT)
 
     def test_init_env(self):
         preconfig = {
             'allocator': PYMEM_ALLOCATOR_MALLOC,
+            'utf8_mode': 1,
         }
         config = {
             'use_hash_seed': 1,
@@ -718,21 +732,24 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'faulthandler': 1,
             'warnoptions': ['EnvVar'],
         }
-        self.check_config("init_env", config, preconfig)
+        self.check_config("init_env", config, preconfig,
+                          api=API_COMPAT)
 
     def test_init_env_dev_mode(self):
         preconfig = dict(allocator=PYMEM_ALLOCATOR_DEBUG)
         config = dict(dev_mode=1,
                       faulthandler=1,
                       warnoptions=['default'])
-        self.check_config("init_env_dev_mode", config, preconfig)
+        self.check_config("init_env_dev_mode", config, preconfig,
+                          api=API_COMPAT)
 
     def test_init_env_dev_mode_alloc(self):
         preconfig = dict(allocator=PYMEM_ALLOCATOR_MALLOC)
         config = dict(dev_mode=1,
                       faulthandler=1,
                       warnoptions=['default'])
-        self.check_config("init_env_dev_mode_alloc", config, preconfig)
+        self.check_config("init_env_dev_mode_alloc", config, preconfig,
+                          api=API_COMPAT)
 
     def test_init_dev_mode(self):
         preconfig = {
@@ -744,7 +761,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'warnoptions': ['default'],
         }
         self.check_config("init_dev_mode", config, preconfig,
-                          api=CONFIG_INIT_PYTHON)
+                          api=API_PYTHON)
 
     def test_preinit_parse_argv(self):
         # Pre-initialize implicitly using argv: make sure that -X dev
@@ -761,7 +778,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'xoptions': ['dev'],
         }
         self.check_config("preinit_parse_argv", config, preconfig,
-                          api=CONFIG_INIT_PYTHON)
+                          api=API_PYTHON)
 
     def test_preinit_dont_parse_argv(self):
         # -X dev must be ignored by isolated preconfiguration
@@ -774,7 +791,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'isolated': 0,
         }
         self.check_config("preinit_dont_parse_argv", config, preconfig,
-                          api=CONFIG_INIT_ISOLATED)
+                          api=API_ISOLATED)
 
     def test_init_isolated_flag(self):
         config = {
@@ -782,7 +799,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'use_environment': 0,
             'user_site_directory': 0,
         }
-        self.check_config("init_isolated_flag", config, api=CONFIG_INIT_PYTHON)
+        self.check_config("init_isolated_flag", config, api=API_PYTHON)
 
     def test_preinit_isolated1(self):
         # _PyPreConfig.isolated=1, _PyCoreConfig.isolated not set
@@ -791,7 +808,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'use_environment': 0,
             'user_site_directory': 0,
         }
-        self.check_config("preinit_isolated1", config)
+        self.check_config("preinit_isolated1", config, api=API_COMPAT)
 
     def test_preinit_isolated2(self):
         # _PyPreConfig.isolated=0, _PyCoreConfig.isolated=1
@@ -800,16 +817,16 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'use_environment': 0,
             'user_site_directory': 0,
         }
-        self.check_config("preinit_isolated2", config)
+        self.check_config("preinit_isolated2", config, api=API_COMPAT)
 
     def test_preinit_isolated_config(self):
-        self.check_config("preinit_isolated_config", api=CONFIG_INIT_ISOLATED)
+        self.check_config("preinit_isolated_config", api=API_ISOLATED)
 
     def test_init_isolated_config(self):
-        self.check_config("init_isolated_config", api=CONFIG_INIT_ISOLATED)
+        self.check_config("init_isolated_config", api=API_ISOLATED)
 
     def test_init_python_config(self):
-        self.check_config("init_python_config", api=CONFIG_INIT_PYTHON)
+        self.check_config("init_python_config", api=API_PYTHON)
 
     def test_init_dont_configure_locale(self):
         # _PyPreConfig.configure_locale=0
@@ -818,7 +835,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'coerce_c_locale': 0,
         }
         self.check_config("init_dont_configure_locale", {}, preconfig,
-                          api=CONFIG_INIT_PYTHON)
+                          api=API_PYTHON)
 
     def test_init_read_set(self):
         core_config = {
@@ -826,7 +843,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'executable': 'my_executable',
         }
         self.check_config("init_read_set", core_config,
-                          api=CONFIG_INIT_PYTHON,
+                          api=API_PYTHON,
                           add_path="init_read_set_path")
 
     def test_init_run_main(self):
@@ -838,8 +855,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'run_command': code + '\n',
             'parse_argv': 1,
         }
-        self.check_config("init_run_main", core_config,
-                          api=CONFIG_INIT_PYTHON)
+        self.check_config("init_run_main", core_config, api=API_PYTHON)
 
     def test_init_main(self):
         code = ('import _testinternalcapi, json; '
@@ -852,7 +868,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             '_init_main': 0,
         }
         self.check_config("init_main", core_config,
-                          api=CONFIG_INIT_PYTHON,
+                          api=API_PYTHON,
                           stderr="Run Python code before _Py_InitializeMain")
 
     def test_init_parse_argv(self):
@@ -863,8 +879,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'run_command': 'pass\n',
             'use_environment': 0,
         }
-        self.check_config("init_parse_argv", core_config,
-                          api=CONFIG_INIT_PYTHON)
+        self.check_config("init_parse_argv", core_config, api=API_PYTHON)
 
     def test_init_dont_parse_argv(self):
         pre_config = {
@@ -876,7 +891,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
             'program_name': './argv0',
         }
         self.check_config("init_dont_parse_argv", core_config, pre_config,
-                          api=CONFIG_INIT_PYTHON)
+                          api=API_PYTHON)
 
 
 if __name__ == "__main__":
index 1a719e2f96735ec95b42cfb679b6ba978ef67877..8cf44d33bc02d9837299ad3d246665b04acf8aa0 100644 (file)
@@ -76,18 +76,30 @@ main(int argc, char *argv[])
     }
     text[text_size] = '\0';
 
+    _PyInitError err;
     _PyCoreConfig config;
-    _PyCoreConfig_InitIsolatedConfig(&config);
+
+    err = _PyCoreConfig_InitIsolatedConfig(&config);
+    if (_PyInitError_Failed(err)) {
+        _PyCoreConfig_Clear(&config);
+        _Py_ExitInitError(err);
+    }
 
     config.site_import = 0;
-    config.program_name = L"./_freeze_importlib";
+
+    err = _PyCoreConfig_SetString(&config, &config.program_name,
+                                  L"./_freeze_importlib");
+    if (_PyInitError_Failed(err)) {
+        _PyCoreConfig_Clear(&config);
+        _Py_ExitInitError(err);
+    }
+
     /* Don't install importlib, since it could execute outdated bytecode. */
     config._install_importlib = 0;
     config._init_main = 0;
 
-    _PyInitError err = _Py_InitializeFromConfig(&config);
-    /* No need to call _PyCoreConfig_Clear() since we didn't allocate any
-       memory: program_name is a constant string. */
+    err = _Py_InitializeFromConfig(&config);
+    _PyCoreConfig_Clear(&config);
     if (_PyInitError_Failed(err)) {
         _Py_ExitInitError(err);
     }
index bc549369393fc798ef35c87955c74cb4d6f8c190..a273930e10aef2071e9a46ed839de8df7204be03 100644 (file)
@@ -317,7 +317,7 @@ dump_config(void)
 }
 
 
-static int test_init_default_config(void)
+static int test_init_initialize_config(void)
 {
     _testembed_Py_Initialize();
     dump_config();
@@ -326,6 +326,47 @@ static int test_init_default_config(void)
 }
 
 
+static int check_init_compat_config(int preinit)
+{
+    _PyInitError err;
+
+    if (preinit) {
+        _PyPreConfig preconfig;
+        _PyPreConfig_InitCompatConfig(&preconfig);
+
+        err = _Py_PreInitialize(&preconfig);
+        if (_PyInitError_Failed(err)) {
+            _Py_ExitInitError(err);
+        }
+    }
+
+    _PyCoreConfig config;
+    _PyCoreConfig_InitCompatConfig(&config);
+    config.program_name = L"./_testembed";
+
+    err = _Py_InitializeFromConfig(&config);
+    if (_PyInitError_Failed(err)) {
+        _Py_ExitInitError(err);
+    }
+
+    dump_config();
+    Py_Finalize();
+    return 0;
+}
+
+
+static int test_preinit_compat_config(void)
+{
+    return check_init_compat_config(1);
+}
+
+
+static int test_init_compat_config(void)
+{
+    return check_init_compat_config(0);
+}
+
+
 static int test_init_global_config(void)
 {
     /* FIXME: test Py_IgnoreEnvironmentFlag */
@@ -380,7 +421,7 @@ static int test_init_from_config(void)
     _PyInitError err;
 
     _PyPreConfig preconfig;
-    _PyPreConfig_Init(&preconfig);
+    _PyPreConfig_InitCompatConfig(&preconfig);
 
     putenv("PYTHONMALLOC=malloc_debug");
     preconfig.allocator = PYMEM_ALLOCATOR_MALLOC;
@@ -396,7 +437,7 @@ static int test_init_from_config(void)
 
     /* Test _Py_InitializeFromConfig() */
     _PyCoreConfig config;
-    _PyCoreConfig_Init(&config);
+    _PyCoreConfig_InitCompatConfig(&config);
     config.install_signal_handlers = 0;
 
     /* FIXME: test use_environment */
@@ -676,7 +717,7 @@ static int test_preinit_isolated1(void)
     _PyInitError err;
 
     _PyPreConfig preconfig;
-    _PyPreConfig_Init(&preconfig);
+    _PyPreConfig_InitCompatConfig(&preconfig);
     preconfig.isolated = 1;
 
     err = _Py_PreInitialize(&preconfig);
@@ -685,7 +726,7 @@ static int test_preinit_isolated1(void)
     }
 
     _PyCoreConfig config;
-    _PyCoreConfig_Init(&config);
+    _PyCoreConfig_InitCompatConfig(&config);
     config.program_name = L"./_testembed";
 
     set_all_env_vars();
@@ -705,7 +746,7 @@ static int test_preinit_isolated2(void)
     _PyInitError err;
 
     _PyPreConfig preconfig;
-    _PyPreConfig_Init(&preconfig);
+    _PyPreConfig_InitCompatConfig(&preconfig);
     preconfig.isolated = 0;
 
     err = _Py_PreInitialize(&preconfig);
@@ -715,7 +756,7 @@ static int test_preinit_isolated2(void)
 
     /* Test _PyCoreConfig.isolated=1 */
     _PyCoreConfig config;
-    _PyCoreConfig_Init(&config);
+    _PyCoreConfig_InitCompatConfig(&config);
 
     Py_IsolatedFlag = 0;
     config.isolated = 1;
@@ -885,12 +926,14 @@ static int check_preinit_isolated_config(int preinit)
     _PyCoreConfig config;
     err = _PyCoreConfig_InitIsolatedConfig(&config);
     if (_PyInitError_Failed(err)) {
+        _PyCoreConfig_Clear(&config);
         _Py_ExitInitError(err);
     }
     config.program_name = L"./_testembed";
 
     err = _Py_InitializeFromConfig(&config);
     if (_PyInitError_Failed(err)) {
+        _PyCoreConfig_Clear(&config);
         _Py_ExitInitError(err);
     }
 
@@ -1207,7 +1250,9 @@ static struct TestCase TestCases[] = {
     { "bpo20891", test_bpo20891 },
     { "initialize_twice", test_initialize_twice },
     { "initialize_pymain", test_initialize_pymain },
-    { "init_default_config", test_init_default_config },
+    { "init_initialize_config", test_init_initialize_config },
+    { "preinit_compat_config", test_preinit_compat_config },
+    { "init_compat_config", test_init_compat_config },
     { "init_global_config", test_init_global_config },
     { "init_from_config", test_init_from_config },
     { "init_parse_argv", test_init_parse_argv },
index 958845e488d7f23f157714b94a7eb200d09b77cb..40dba4ee5e5e5434e2d91c85a72bebaf1829b343 100644 (file)
@@ -109,7 +109,7 @@ static const char usage_6[] =
 /* UTF-8 mode (PEP 540): if equals to 1, use the UTF-8 encoding, and change
    stdin and stdout error handler to "surrogateescape". It is equal to
    -1 by default: unknown, will be set by Py_Main() */
-int Py_UTF8Mode = 0;
+int Py_UTF8Mode = -1;
 int Py_DebugFlag = 0; /* Needed by parser.c */
 int Py_VerboseFlag = 0; /* Needed by import.c */
 int Py_QuietFlag = 0; /* Needed by sysmodule.c */
@@ -546,12 +546,12 @@ _PyCoreConfig_Clear(_PyCoreConfig *config)
 
 
 void
-_PyCoreConfig_Init(_PyCoreConfig *config)
+_PyCoreConfig_InitCompatConfig(_PyCoreConfig *config)
 {
     memset(config, 0, sizeof(*config));
 
     config->_config_version = _Py_CONFIG_VERSION;
-    config->_config_init = (int)_PyCoreConfig_INIT;
+    config->_config_init = (int)_PyConfig_INIT_COMPAT;
     config->isolated = -1;
     config->use_environment = -1;
     config->dev_mode = -1;
@@ -586,7 +586,7 @@ _PyCoreConfig_Init(_PyCoreConfig *config)
 static void
 _PyCoreConfig_InitDefaults(_PyCoreConfig *config)
 {
-    _PyCoreConfig_Init(config);
+    _PyCoreConfig_InitCompatConfig(config);
 
     config->isolated = 0;
     config->use_environment = 1;
@@ -613,7 +613,7 @@ _PyCoreConfig_InitPythonConfig(_PyCoreConfig *config)
 {
     _PyCoreConfig_InitDefaults(config);
 
-    config->_config_init = (int)_PyCoreConfig_INIT_PYTHON;
+    config->_config_init = (int)_PyConfig_INIT_PYTHON;
     config->configure_c_stdio = 1;
     config->parse_argv = 1;
 
@@ -626,7 +626,7 @@ _PyCoreConfig_InitIsolatedConfig(_PyCoreConfig *config)
 {
     _PyCoreConfig_InitDefaults(config);
 
-    config->_config_init = (int)_PyCoreConfig_INIT_ISOLATED;
+    config->_config_init = (int)_PyConfig_INIT_ISOLATED;
     config->isolated = 1;
     config->use_environment = 0;
     config->user_site_directory = 0;
@@ -962,6 +962,11 @@ _PyCoreConfig_GetEnvDup(_PyCoreConfig *config,
 static void
 _PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config)
 {
+    if (config->_config_init != _PyConfig_INIT_COMPAT) {
+        /* Python and Isolated configuration ignore global variables */
+        return;
+    }
+
 #define COPY_FLAG(ATTR, VALUE) \
         if (config->ATTR == -1) { \
             config->ATTR = VALUE; \
index a51fb5800127d83eaa33b6f861e9fe4abd0cb8f8..c3af080401e9b96243918fd53a7655814b552339 100644 (file)
@@ -40,7 +40,11 @@ Py_FrozenMain(int argc, char **argv)
     }
 
     _PyCoreConfig config;
-    _PyCoreConfig_InitPythonConfig(&config);
+    err = _PyCoreConfig_InitPythonConfig(&config);
+    if (_PyInitError_Failed(err)) {
+        _PyCoreConfig_Clear(&config);
+        _Py_ExitInitError(err);
+    }
     config.pathconfig_warnings = 0;   /* Suppress errors from getpath.c */
 
     if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
@@ -82,8 +86,7 @@ Py_FrozenMain(int argc, char **argv)
         Py_SetProgramName(argv_copy[0]);
 
     err = _Py_InitializeFromConfig(&config);
-    /* No need to call _PyCoreConfig_Clear() since we didn't allocate any
-       memory: program_name is a constant string. */
+    _PyCoreConfig_Clear(&config);
     if (_PyInitError_Failed(err)) {
         _Py_ExitInitError(err);
     }
index 3d9d3b1b205fc9f9fb8b3663cc61a734474a72db..bbf29b2fa598193919c668ed56ebe5cda6ce7a52 100644 (file)
@@ -383,7 +383,7 @@ pathconfig_global_init(void)
 
     _PyInitError err;
     _PyCoreConfig config;
-    _PyCoreConfig_Init(&config);
+    _PyCoreConfig_InitCompatConfig(&config);
 
     err = _PyCoreConfig_Read(&config);
     if (_Py_INIT_FAILED(err)) {
index 4df6208cadb8410d954cf8cd03e4c1ff63b50327..392324ff201a338ef1dcda9cfc4afaf98dea2674 100644 (file)
@@ -262,16 +262,17 @@ _PyPreCmdline_Read(_PyPreCmdline *cmdline, const _PyPreConfig *preconfig)
 
 
 void
-_PyPreConfig_Init(_PyPreConfig *config)
+_PyPreConfig_InitCompatConfig(_PyPreConfig *config)
 {
     memset(config, 0, sizeof(*config));
 
     config->_config_version = _Py_CONFIG_VERSION;
+    config->_config_init = (int)_PyConfig_INIT_COMPAT;
     config->parse_argv = 0;
     config->isolated = -1;
     config->use_environment = -1;
     config->configure_locale = 1;
-    config->utf8_mode = -2;
+    config->utf8_mode = -1;
     config->dev_mode = -1;
     config->allocator = PYMEM_ALLOCATOR_NOT_SET;
 #ifdef MS_WINDOWS
@@ -283,23 +284,30 @@ _PyPreConfig_Init(_PyPreConfig *config)
 void
 _PyPreConfig_InitPythonConfig(_PyPreConfig *config)
 {
-    _PyPreConfig_Init(config);
+    _PyPreConfig_InitCompatConfig(config);
 
+    config->_config_init = (int)_PyConfig_INIT_PYTHON;
+    config->isolated = 0;
     config->parse_argv = 1;
+    config->use_environment = 1;
     /* Set to -1 to enable C locale coercion (PEP 538) and UTF-8 Mode (PEP 540)
        depending on the LC_CTYPE locale, PYTHONUTF8 and PYTHONCOERCECLOCALE
        environment variables. */
     config->coerce_c_locale = -1;
     config->coerce_c_locale_warn = -1;
     config->utf8_mode = -1;
+#ifdef MS_WINDOWS
+    config->legacy_windows_fs_encoding = 0;
+#endif
 }
 
 
 void
 _PyPreConfig_InitIsolatedConfig(_PyPreConfig *config)
 {
-    _PyPreConfig_Init(config);
+    _PyPreConfig_InitCompatConfig(config);
 
+    config->_config_init = (int)_PyConfig_INIT_ISOLATED;
     config->configure_locale = 0;
     config->isolated = 1;
     config->use_environment = 0;
@@ -315,7 +323,7 @@ void
 _PyPreConfig_InitFromPreConfig(_PyPreConfig *config,
                                const _PyPreConfig *config2)
 {
-    _PyPreConfig_Init(config);
+    _PyPreConfig_InitCompatConfig(config);
     _PyPreConfig_Copy(config, config2);
 }
 
@@ -324,17 +332,17 @@ void
 _PyPreConfig_InitFromCoreConfig(_PyPreConfig *config,
                                 const _PyCoreConfig *coreconfig)
 {
-    _PyCoreConfigInitEnum config_init = (_PyCoreConfigInitEnum)coreconfig->_config_init;
+    _PyConfigInitEnum config_init = (_PyConfigInitEnum)coreconfig->_config_init;
     switch (config_init) {
-    case _PyCoreConfig_INIT_PYTHON:
+    case _PyConfig_INIT_PYTHON:
         _PyPreConfig_InitPythonConfig(config);
         break;
-    case _PyCoreConfig_INIT_ISOLATED:
+    case _PyConfig_INIT_ISOLATED:
         _PyPreConfig_InitIsolatedConfig(config);
         break;
-    case _PyCoreConfig_INIT:
+    case _PyConfig_INIT_COMPAT:
     default:
-        _PyPreConfig_Init(config);
+        _PyPreConfig_InitCompatConfig(config);
     }
     _PyPreConfig_GetCoreConfig(config, coreconfig);
 }
@@ -428,6 +436,11 @@ _PyPreConfig_GetCoreConfig(_PyPreConfig *config,
 static void
 _PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
 {
+    if (config->_config_init != _PyConfig_INIT_COMPAT) {
+        /* Python and Isolated configuration ignore global variables */
+        return;
+    }
+
 #define COPY_FLAG(ATTR, VALUE) \
     if (config->ATTR < 0) { \
         config->ATTR = VALUE; \
@@ -439,12 +452,10 @@ _PyPreConfig_GetGlobalConfig(_PyPreConfig *config)
 
     COPY_FLAG(isolated, Py_IsolatedFlag);
     COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag);
+    COPY_FLAG(utf8_mode, Py_UTF8Mode);
 #ifdef MS_WINDOWS
     COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag);
 #endif
-    if (config->utf8_mode == -2) {
-        config->utf8_mode = Py_UTF8Mode;
-    }
 
 #undef COPY_FLAG
 #undef COPY_NOT_FLAG
@@ -565,12 +576,7 @@ preconfig_init_utf8_mode(_PyPreConfig *config, const _PyPreCmdline *cmdline)
     }
 
     const wchar_t *xopt;
-    if (cmdline) {
-        xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
-    }
-    else {
-        xopt = NULL;
-    }
+    xopt = _Py_get_xoption(&cmdline->xoptions, L"utf8");
     if (xopt) {
         wchar_t *sep = wcschr(xopt, L'=');
         if (sep) {
index 6dc684bfcebb84ce67516504ebe110f2a7ffd1be..21c386bb4a3eddc08377fddff33c9b5457d3cbca 100644 (file)
@@ -867,7 +867,7 @@ _Py_InitializeCore(_PyRuntimeState *runtime,
     }
 
     _PyCoreConfig local_config;
-    _PyCoreConfig_Init(&local_config);
+    _PyCoreConfig_InitCompatConfig(&local_config);
     err = pyinit_coreconfig(runtime, &local_config, src_config, args, interp_p);
     _PyCoreConfig_Clear(&local_config);
     return err;
@@ -1096,7 +1096,7 @@ Py_InitializeEx(int install_sigs)
     }
 
     _PyCoreConfig config;
-    _PyCoreConfig_Init(&config);
+    _PyCoreConfig_InitCompatConfig(&config);
     config.install_signal_handlers = install_sigs;
 
     err = _Py_InitializeFromConfig(&config);
index 2f80aa253b5aae754a16a475084c4fbdfaceba5f..879a5a91f8a3b09d9fb0a34b18aad9d6f6f43944 100644 (file)
@@ -49,7 +49,7 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime)
 
     _PyGC_Initialize(&runtime->gc);
     _PyEval_Initialize(&runtime->ceval);
-    _PyPreConfig_Init(&runtime->preconfig);
+    _PyPreConfig_InitPythonConfig(&runtime->preconfig);
 
     runtime->gilstate.check_enabled = 1;
 
@@ -189,7 +189,13 @@ PyInterpreterState_New(void)
     memset(interp, 0, sizeof(*interp));
     interp->id_refcount = -1;
     interp->check_interval = 100;
-    _PyCoreConfig_Init(&interp->core_config);
+
+    _PyInitError err = _PyCoreConfig_InitPythonConfig(&interp->core_config);
+    if (_Py_INIT_FAILED(err)) {
+        PyMem_RawFree(interp);
+        return NULL;
+    }
+
     interp->eval_frame = _PyEval_EvalFrameDefault;
 #ifdef HAVE_DLOPEN
 #if HAVE_DECL_RTLD_NOW