From 022be02dcfdfd9011415804bb4553a33fa7ec8f3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 22 May 2019 23:58:50 +0200 Subject: [PATCH] bpo-36763: Add _PyPreConfig._config_init (GH-13481) * _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 | 22 +++--- Include/internal/pycore_coreconfig.h | 4 +- Lib/test/test_embed.py | 113 +++++++++++++++------------ Programs/_freeze_importlib.c | 22 ++++-- Programs/_testembed.c | 61 +++++++++++++-- Python/coreconfig.c | 17 ++-- Python/frozenmain.c | 9 ++- Python/pathconfig.c | 2 +- Python/preconfig.c | 44 ++++++----- Python/pylifecycle.c | 4 +- Python/pystate.c | 10 ++- 11 files changed, 200 insertions(+), 108 deletions(-) diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h index decfb70e73..ef5fde20e8 100644 --- a/Include/cpython/coreconfig.h +++ b/Include/cpython/coreconfig.h @@ -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 */ diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h index 324e0b82b9..b17737a90b 100644 --- a/Include/internal/pycore_coreconfig.h +++ b/Include/internal/pycore_coreconfig.h @@ -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); diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 4fe005dfa1..8101e70f9b 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -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__": diff --git a/Programs/_freeze_importlib.c b/Programs/_freeze_importlib.c index 1a719e2f96..8cf44d33bc 100644 --- a/Programs/_freeze_importlib.c +++ b/Programs/_freeze_importlib.c @@ -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); } diff --git a/Programs/_testembed.c b/Programs/_testembed.c index bc54936939..a273930e10 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -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 }, diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 958845e488..40dba4ee5e 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -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; \ diff --git a/Python/frozenmain.c b/Python/frozenmain.c index a51fb58001..c3af080401 100644 --- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -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); } diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 3d9d3b1b20..bbf29b2fa5 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -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)) { diff --git a/Python/preconfig.c b/Python/preconfig.c index 4df6208cad..392324ff20 100644 --- a/Python/preconfig.c +++ b/Python/preconfig.c @@ -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) { diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 6dc684bfce..21c386bb4a 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -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); diff --git a/Python/pystate.c b/Python/pystate.c index 2f80aa253b..879a5a91f8 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -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 -- 2.40.0