Skip to content

Commit bab0db6

Browse files
authored
bpo-36763: Use _PyCoreConfig_InitPythonConfig() (GH-13398)
_PyPreConfig_InitPythonConfig() and _PyCoreConfig_InitPythonConfig() no longer inherit their values from global configuration variables. Changes: * _PyPreCmdline_Read() now ignores -X dev and PYTHONDEVMODE if dev_mode is already set. * Inline _PyPreConfig_INIT macro into _PyPreConfig_Init() function. * Inline _PyCoreConfig_INIT macro into _PyCoreConfig_Init() function. * Replace _PyCoreConfig_Init() with _PyCoreConfig_InitPythonConfig() in most tests of _testembed.c. * Replace _PyCoreConfig_Init() with _PyCoreConfig_InitIsolatedConfig() in _freeze_importlib.c. * Move some initialization functions from the internal to the private API.
1 parent 27ee0f8 commit bab0db6

File tree

8 files changed

+240
-181
lines changed

8 files changed

+240
-181
lines changed

Include/cpython/coreconfig.h

Lines changed: 17 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -115,27 +115,8 @@ typedef struct {
115115
PyMemAllocatorName allocator;
116116
} _PyPreConfig;
117117

118-
#ifdef MS_WINDOWS
119-
# define _PyPreConfig_WINDOWS_INIT \
120-
.legacy_windows_fs_encoding = -1,
121-
#else
122-
# define _PyPreConfig_WINDOWS_INIT
123-
#endif
124-
125-
#define _PyPreConfig_INIT \
126-
(_PyPreConfig){ \
127-
_PyPreConfig_WINDOWS_INIT \
128-
._config_version = _Py_CONFIG_VERSION, \
129-
.isolated = -1, \
130-
.use_environment = -1, \
131-
.configure_locale = 1, \
132-
.utf8_mode = -2, \
133-
.dev_mode = -1, \
134-
.allocator = PYMEM_ALLOCATOR_NOT_SET}
135-
136-
PyAPI_FUNC(void) _PyPreConfig_Init(_PyPreConfig *config);
137118
PyAPI_FUNC(void) _PyPreConfig_InitPythonConfig(_PyPreConfig *config);
138-
PyAPI_FUNC(void) _PyPreConfig_InitIsolateConfig(_PyPreConfig *config);
119+
PyAPI_FUNC(void) _PyPreConfig_InitIsolatedConfig(_PyPreConfig *config);
139120

140121

141122
/* --- _PyCoreConfig ---------------------------------------------- */
@@ -419,47 +400,23 @@ typedef struct {
419400

420401
} _PyCoreConfig;
421402

422-
#ifdef MS_WINDOWS
423-
# define _PyCoreConfig_WINDOWS_INIT \
424-
.legacy_windows_stdio = -1,
425-
#else
426-
# define _PyCoreConfig_WINDOWS_INIT
427-
#endif
428-
429-
#define _PyCoreConfig_INIT \
430-
(_PyCoreConfig){ \
431-
_PyCoreConfig_WINDOWS_INIT \
432-
._config_version = _Py_CONFIG_VERSION, \
433-
.isolated = -1, \
434-
.use_environment = -1, \
435-
.dev_mode = -1, \
436-
.install_signal_handlers = 1, \
437-
.use_hash_seed = -1, \
438-
.faulthandler = -1, \
439-
.tracemalloc = -1, \
440-
.use_module_search_paths = 0, \
441-
.parse_argv = 0, \
442-
.site_import = -1, \
443-
.bytes_warning = -1, \
444-
.inspect = -1, \
445-
.interactive = -1, \
446-
.optimization_level = -1, \
447-
.parser_debug= -1, \
448-
.write_bytecode = -1, \
449-
.verbose = -1, \
450-
.quiet = -1, \
451-
.user_site_directory = -1, \
452-
.configure_c_stdio = 0, \
453-
.buffered_stdio = -1, \
454-
._install_importlib = 1, \
455-
.check_hash_pycs_mode = NULL, \
456-
.pathconfig_warnings = -1, \
457-
._init_main = 1}
458-
/* Note: _PyCoreConfig_INIT sets other fields to 0/NULL */
459-
460-
PyAPI_FUNC(void) _PyCoreConfig_Init(_PyCoreConfig *config);
461403
PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitPythonConfig(_PyCoreConfig *config);
462-
PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitIsolateConfig(_PyCoreConfig *config);
404+
PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitIsolatedConfig(_PyCoreConfig *config);
405+
PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *);
406+
PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetString(
407+
wchar_t **config_str,
408+
const wchar_t *str);
409+
PyAPI_FUNC(_PyInitError) _PyCoreConfig_DecodeLocale(
410+
wchar_t **config_str,
411+
const char *str);
412+
PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config);
413+
PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetArgv(
414+
_PyCoreConfig *config,
415+
Py_ssize_t argc,
416+
char **argv);
417+
PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetWideArgv(_PyCoreConfig *config,
418+
Py_ssize_t argc,
419+
wchar_t **argv);
463420

464421
#ifdef __cplusplus
465422
}

Include/internal/pycore_coreconfig.h

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,6 @@ PyAPI_FUNC(_PyInitError) _PyPreCmdline_Read(_PyPreCmdline *cmdline,
121121
/* --- _PyPreConfig ----------------------------------------------- */
122122

123123
PyAPI_FUNC(void) _PyPreConfig_Init(_PyPreConfig *config);
124-
PyAPI_FUNC(void) _PyPreConfig_InitPythonConfig(_PyPreConfig *config);
125-
PyAPI_FUNC(void) _PyPreConfig_InitIsolatedConfig(_PyPreConfig *config);
126124
PyAPI_FUNC(void) _PyPreConfig_Copy(_PyPreConfig *config,
127125
const _PyPreConfig *config2);
128126
PyAPI_FUNC(PyObject*) _PyPreConfig_AsDict(const _PyPreConfig *config);
@@ -135,34 +133,18 @@ PyAPI_FUNC(_PyInitError) _PyPreConfig_Write(const _PyPreConfig *config);
135133

136134
/* --- _PyCoreConfig ---------------------------------------------- */
137135

138-
PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *);
139-
PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitPythonConfig(_PyCoreConfig *config);
140-
PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitIsolatedConfig(_PyCoreConfig *config);
136+
PyAPI_FUNC(void) _PyCoreConfig_Init(_PyCoreConfig *config);
141137
PyAPI_FUNC(_PyInitError) _PyCoreConfig_Copy(
142138
_PyCoreConfig *config,
143139
const _PyCoreConfig *config2);
144-
PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetString(
145-
wchar_t **config_str,
146-
const wchar_t *str);
147-
PyAPI_FUNC(_PyInitError) _PyCoreConfig_DecodeLocale(
148-
wchar_t **config_str,
149-
const char *str);
150140
PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitPathConfig(_PyCoreConfig *config);
151141
PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPathConfig(
152142
const _PyCoreConfig *config);
153-
PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config);
154143
PyAPI_FUNC(void) _PyCoreConfig_Write(const _PyCoreConfig *config,
155144
_PyRuntimeState *runtime);
156145
PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetPyArgv(
157146
_PyCoreConfig *config,
158147
const _PyArgv *args);
159-
PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetArgv(
160-
_PyCoreConfig *config,
161-
Py_ssize_t argc,
162-
char **argv);
163-
PyAPI_FUNC(_PyInitError) _PyCoreConfig_SetWideArgv(_PyCoreConfig *config,
164-
Py_ssize_t argc,
165-
wchar_t **argv);
166148

167149

168150
/* --- Function used for testing ---------------------------------- */

Lib/test/test_embed.py

Lines changed: 65 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,16 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
285285
'coerce_c_locale_warn': 0,
286286
'utf8_mode': 0,
287287
}
288+
ISOLATED_PRE_CONFIG = dict(DEFAULT_PRE_CONFIG,
289+
configure_locale=0,
290+
isolated=1,
291+
use_environment=0,
292+
utf8_mode=0,
293+
dev_mode=0,
294+
)
295+
if MS_WINDOWS:
296+
ISOLATED_PRE_CONFIG['legacy_windows_fs_encoding'] = 0
297+
288298
COPY_PRE_CONFIG = [
289299
'dev_mode',
290300
'isolated',
@@ -363,6 +373,24 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
363373
'legacy_windows_stdio': 0,
364374
})
365375

376+
PYTHON_CORE_CONFIG = dict(DEFAULT_CORE_CONFIG,
377+
configure_c_stdio=1,
378+
parse_argv=1,
379+
)
380+
ISOLATED_CORE_CONFIG = dict(DEFAULT_CORE_CONFIG,
381+
isolated=1,
382+
use_environment=0,
383+
user_site_directory=0,
384+
dev_mode=0,
385+
install_signal_handlers=0,
386+
use_hash_seed=0,
387+
faulthandler=0,
388+
tracemalloc=0,
389+
pathconfig_warnings=0,
390+
)
391+
if MS_WINDOWS:
392+
ISOLATED_CORE_CONFIG['legacy_windows_stdio'] = 0
393+
366394
# global config
367395
DEFAULT_GLOBAL_CONFIG = {
368396
'Py_HasFileSystemDefaultEncoding': 0,
@@ -410,8 +438,15 @@ def main_xoptions(self, xoptions_list):
410438
xoptions[opt] = True
411439
return xoptions
412440

413-
def get_expected_config(self, expected_preconfig, expected, env, add_path=None):
414-
expected = dict(self.DEFAULT_CORE_CONFIG, **expected)
441+
def get_expected_config(self, expected_preconfig, expected, env, api,
442+
add_path=None):
443+
if api == "python":
444+
default_config = self.PYTHON_CORE_CONFIG
445+
elif api == "isolated":
446+
default_config = self.ISOLATED_CORE_CONFIG
447+
else:
448+
default_config = self.DEFAULT_CORE_CONFIG
449+
expected = dict(default_config, **expected)
415450

416451
code = textwrap.dedent('''
417452
import json
@@ -521,8 +556,8 @@ def check_global_config(self, config):
521556

522557
self.assertEqual(config['global_config'], expected)
523558

524-
def check_config(self, testname, expected_config, expected_preconfig,
525-
add_path=None, stderr=None):
559+
def check_config(self, testname, expected_config=None, expected_preconfig=None,
560+
add_path=None, stderr=None, api="default"):
526561
env = dict(os.environ)
527562
# Remove PYTHON* environment variables to get deterministic environment
528563
for key in list(env):
@@ -533,8 +568,18 @@ def check_config(self, testname, expected_config, expected_preconfig,
533568
env['PYTHONCOERCECLOCALE'] = '0'
534569
env['PYTHONUTF8'] = '0'
535570

536-
expected_preconfig = dict(self.DEFAULT_PRE_CONFIG, **expected_preconfig)
537-
expected_config = self.get_expected_config(expected_preconfig, expected_config, env, add_path)
571+
if api == "isolated":
572+
default_preconfig = self.ISOLATED_PRE_CONFIG
573+
else:
574+
default_preconfig = self.DEFAULT_PRE_CONFIG
575+
if expected_preconfig is None:
576+
expected_preconfig = {}
577+
expected_preconfig = dict(default_preconfig, **expected_preconfig)
578+
if expected_config is None:
579+
expected_config = {}
580+
expected_config = self.get_expected_config(expected_preconfig,
581+
expected_config, env,
582+
api, add_path)
538583
for key in self.COPY_PRE_CONFIG:
539584
if key not in expected_preconfig:
540585
expected_preconfig[key] = expected_config[key]
@@ -677,76 +722,56 @@ def test_init_dev_mode(self):
677722
'dev_mode': 1,
678723
'warnoptions': ['default'],
679724
}
680-
self.check_config("init_dev_mode", config, preconfig)
725+
self.check_config("init_dev_mode", config, preconfig, api="python")
681726

682727
def test_init_isolated_flag(self):
683-
preconfig = {}
684728
config = {
685729
'isolated': 1,
686730
'use_environment': 0,
687731
'user_site_directory': 0,
688732
}
689-
self.check_config("init_isolated_flag", config, preconfig)
733+
self.check_config("init_isolated_flag", config, api="python")
690734

691735
def test_preinit_isolated1(self):
692736
# _PyPreConfig.isolated=1, _PyCoreConfig.isolated not set
693-
preconfig = {}
694737
config = {
695738
'isolated': 1,
696739
'use_environment': 0,
697740
'user_site_directory': 0,
698741
}
699-
self.check_config("preinit_isolated1", config, preconfig)
742+
self.check_config("preinit_isolated1", config)
700743

701744
def test_preinit_isolated2(self):
702745
# _PyPreConfig.isolated=0, _PyCoreConfig.isolated=1
703-
preconfig = {}
704746
config = {
705747
'isolated': 1,
706748
'use_environment': 0,
707749
'user_site_directory': 0,
708750
}
709-
self.check_config("preinit_isolated2", config, preconfig)
751+
self.check_config("preinit_isolated2", config)
710752

711753
def test_init_isolated_config(self):
712-
preconfig = {
713-
'configure_locale': 0,
714-
}
715-
config = {
716-
'isolated': 1,
717-
'use_environment': 0,
718-
'user_site_directory': 0,
719-
'install_signal_handlers': 0,
720-
'pathconfig_warnings': 0,
721-
}
722-
self.check_config("init_isolated_config", config, preconfig)
754+
self.check_config("init_isolated_config", api="isolated")
723755

724756
def test_init_python_config(self):
725-
preconfig = {}
726-
config = {
727-
'configure_c_stdio': 1,
728-
'parse_argv': 1,
729-
}
730-
self.check_config("init_python_config", config, preconfig)
757+
self.check_config("init_python_config", api="python")
731758

732759
def test_init_dont_configure_locale(self):
733760
# _PyPreConfig.configure_locale=0
734761
preconfig = {
735762
'configure_locale': 0,
736763
}
737-
self.check_config("init_dont_configure_locale", {}, preconfig)
764+
self.check_config("init_dont_configure_locale", {}, preconfig, api="python")
738765

739766
def test_init_read_set(self):
740-
preconfig = {}
741767
core_config = {
742768
'program_name': './init_read_set',
743769
'executable': 'my_executable',
744770
}
745-
self.check_config("init_read_set", core_config, preconfig,
771+
self.check_config("init_read_set", core_config, api="python",
746772
add_path="init_read_set_path")
747773

748774
def test_init_run_main(self):
749-
preconfig = {}
750775
code = ('import _testinternalcapi, json; '
751776
'print(json.dumps(_testinternalcapi.get_configs()))')
752777
core_config = {
@@ -755,10 +780,9 @@ def test_init_run_main(self):
755780
'run_command': code + '\n',
756781
'parse_argv': 1,
757782
}
758-
self.check_config("init_run_main", core_config, preconfig)
783+
self.check_config("init_run_main", core_config, api="python")
759784

760785
def test_init_main(self):
761-
preconfig = {}
762786
code = ('import _testinternalcapi, json; '
763787
'print(json.dumps(_testinternalcapi.get_configs()))')
764788
core_config = {
@@ -768,25 +792,26 @@ def test_init_main(self):
768792
'parse_argv': 1,
769793
'_init_main': 0,
770794
}
771-
self.check_config("init_main", core_config, preconfig,
795+
self.check_config("init_main", core_config, api="python",
772796
stderr="Run Python code before _Py_InitializeMain")
773797

774798
def test_init_parse_argv(self):
775799
core_config = {
800+
'parse_argv': 1,
776801
'argv': ['-c', 'arg1', '-v', 'arg3'],
777802
'program_name': './argv0',
778-
'parse_argv': 1,
779803
'run_command': 'pass\n',
780804
'use_environment': 0,
781805
}
782-
self.check_config("init_parse_argv", core_config, {})
806+
self.check_config("init_parse_argv", core_config, api="python")
783807

784808
def test_init_dont_parse_argv(self):
785809
core_config = {
810+
'parse_argv': 0,
786811
'argv': ['./argv0', '-E', '-c', 'pass', 'arg1', '-v', 'arg3'],
787812
'program_name': './argv0',
788813
}
789-
self.check_config("init_dont_parse_argv", core_config, {})
814+
self.check_config("init_dont_parse_argv", core_config, api="python")
790815

791816

792817
if __name__ == "__main__":

Programs/_freeze_importlib.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,12 @@ main(int argc, char *argv[])
7777
text[text_size] = '\0';
7878

7979
_PyCoreConfig config;
80-
_PyCoreConfig_Init(&config);
81-
config.use_environment = 0;
82-
config.user_site_directory = 0;
80+
_PyCoreConfig_InitIsolatedConfig(&config);
81+
8382
config.site_import = 0;
8483
config.program_name = L"./_freeze_importlib";
8584
/* Don't install importlib, since it could execute outdated bytecode. */
8685
config._install_importlib = 0;
87-
config.pathconfig_warnings = 0;
8886
config._init_main = 0;
8987

9088
_PyInitError err = _Py_InitializeFromConfig(&config);

0 commit comments

Comments
 (0)