Skip to content

Commit 2000495

Browse files
authored
bpo-36301: Remove _PyCoreConfig.preconfig (GH-12546)
* Replace _PyCoreConfig.preconfig with 3 new fields in _PyCoreConfig: isolated, use_environment, dev_mode. * Add _PyPreCmdline.dev_mode. * Add _Py_PreInitializeFromPreConfigInPlace().
1 parent f78a5e9 commit 2000495

File tree

13 files changed

+179
-145
lines changed

13 files changed

+179
-145
lines changed

Include/cpython/coreconfig.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ typedef struct {
123123
/* --- _PyCoreConfig ---------------------------------------------- */
124124

125125
typedef struct {
126-
_PyPreConfig preconfig;
126+
int isolated;
127+
int use_environment;
128+
int dev_mode;
127129

128130
/* Install signal handlers? Yes by default. */
129131
int install_signal_handlers;
@@ -375,7 +377,9 @@ typedef struct {
375377
#define _PyCoreConfig_INIT \
376378
(_PyCoreConfig){ \
377379
_PyCoreConfig_WINDOWS_INIT \
378-
.preconfig = _PyPreConfig_INIT, \
380+
.isolated = -1, \
381+
.use_environment = -1, \
382+
.dev_mode = -1, \
379383
.install_signal_handlers = 1, \
380384
.use_hash_seed = -1, \
381385
.faulthandler = -1, \

Include/cpython/pylifecycle.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding,
1616

1717
PyAPI_FUNC(_PyInitError) _Py_PreInitialize(void);
1818
PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromPreConfig(
19-
_PyPreConfig *preconfig);
19+
const _PyPreConfig *preconfig);
2020
PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromConfig(
2121
const _PyCoreConfig *coreconfig);
2222

Include/internal/pycore_coreconfig.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ typedef struct {
1616
_PyWstrList xoptions; /* "-X value" option */
1717
int use_environment; /* -E option */
1818
int isolated; /* -I option */
19+
int dev_mode; /* -X dev and PYTHONDEVMODE */
1920
} _PyPreCmdline;
2021

2122
#define _PyPreCmdline_INIT \
2223
(_PyPreCmdline){ \
2324
.use_environment = -1, \
24-
.isolated = -1}
25+
.isolated = -1, \
26+
.dev_mode = -1}
2527
/* Note: _PyPreCmdline_INIT sets other fields to 0/NULL */
2628

2729
PyAPI_FUNC(void) _PyPreCmdline_Clear(_PyPreCmdline *cmdline);
@@ -112,7 +114,7 @@ PyAPI_FUNC(void) _PyCoreConfig_SetGlobalConfig(const _PyCoreConfig *config);
112114
PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config);
113115
PyAPI_FUNC(_PyInitError) _PyCoreConfig_ReadFromArgv(_PyCoreConfig *config,
114116
const _PyArgv *args);
115-
PyAPI_FUNC(_PyInitError) _PyCoreConfig_Write(const _PyCoreConfig *config);
117+
PyAPI_FUNC(void) _PyCoreConfig_Write(const _PyCoreConfig *config);
116118

117119
/* --- _PyMainInterpreterConfig ----------------------------------- */
118120

Include/internal/pycore_pylifecycle.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ extern void _PyGILState_Fini(void);
7777

7878
PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void);
7979

80+
PyAPI_FUNC(_PyInitError) _Py_PreInitializeInPlace(
81+
_PyPreConfig *config);
82+
8083
#ifdef __cplusplus
8184
}
8285
#endif

Lib/test/test_embed.py

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -272,12 +272,19 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
272272
'allocator': None,
273273
'coerce_c_locale': 0,
274274
'coerce_c_locale_warn': 0,
275-
'dev_mode': 0,
276-
'isolated': 0,
277-
'use_environment': 1,
278275
'utf8_mode': 0,
279276
}
277+
COPY_PRE_CONFIG = [
278+
'dev_mode',
279+
'isolated',
280+
'use_environment',
281+
]
282+
280283
DEFAULT_CORE_CONFIG = {
284+
'isolated': 0,
285+
'use_environment': 1,
286+
'dev_mode': 0,
287+
281288
'install_signal_handlers': 1,
282289
'use_hash_seed': 0,
283290
'hash_seed': 0,
@@ -363,8 +370,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
363370
'_Py_HasFileSystemDefaultEncodeErrors': 0,
364371
}
365372
COPY_GLOBAL_PRE_CONFIG = [
366-
('Py_IgnoreEnvironmentFlag', 'use_environment', True),
367-
('Py_IsolatedFlag', 'isolated'),
368373
('Py_UTF8Mode', 'utf8_mode'),
369374
]
370375
COPY_GLOBAL_CONFIG = [
@@ -376,8 +381,10 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
376381
('Py_FileSystemDefaultEncodeErrors', 'filesystem_errors'),
377382
('Py_FileSystemDefaultEncoding', 'filesystem_encoding'),
378383
('Py_FrozenFlag', '_frozen'),
384+
('Py_IgnoreEnvironmentFlag', 'use_environment', True),
379385
('Py_InspectFlag', 'inspect'),
380386
('Py_InteractiveFlag', 'interactive'),
387+
('Py_IsolatedFlag', 'isolated'),
381388
('Py_NoSiteFlag', 'site_import', True),
382389
('Py_NoUserSiteDirectory', 'user_site_directory', True),
383390
('Py_OptimizeFlag', 'optimization_level'),
@@ -415,7 +422,7 @@ def check_main_config(self, config):
415422
expected['xoptions'] = self.main_xoptions(core_config['xoptions'])
416423
self.assertEqual(main_config, expected)
417424

418-
def get_expected_config(self, expected, expected_preconfig, env):
425+
def get_expected_config(self, expected, env):
419426
expected = dict(self.DEFAULT_CORE_CONFIG, **expected)
420427

421428
code = textwrap.dedent('''
@@ -443,7 +450,7 @@ def get_expected_config(self, expected, expected_preconfig, env):
443450
# when test_embed is run from a venv (bpo-35313)
444451
args = (sys.executable, '-S', '-c', code)
445452
env = dict(env)
446-
if not expected_preconfig['isolated']:
453+
if not expected['isolated']:
447454
env['PYTHONCOERCECLOCALE'] = '0'
448455
env['PYTHONUTF8'] = '0'
449456
proc = subprocess.run(args, env=env,
@@ -509,7 +516,10 @@ def check_config(self, testname, expected_config, expected_preconfig):
509516
config = json.loads(out)
510517

511518
expected_preconfig = dict(self.DEFAULT_PRE_CONFIG, **expected_preconfig)
512-
expected_config = self.get_expected_config(expected_config, expected_preconfig, env)
519+
expected_config = self.get_expected_config(expected_config, env)
520+
for key in self.COPY_PRE_CONFIG:
521+
if key not in expected_preconfig:
522+
expected_preconfig[key] = expected_config[key]
513523

514524
self.check_core_config(config, expected_config)
515525
self.check_pre_config(config, expected_preconfig)
@@ -617,35 +627,36 @@ def test_init_env(self):
617627

618628
def test_init_env_dev_mode(self):
619629
preconfig = dict(self.INIT_ENV_PRECONFIG,
620-
allocator='debug',
621-
dev_mode=1)
630+
allocator='debug')
622631
config = dict(self.INIT_ENV_CONFIG,
623632
dev_mode=1)
624633
self.check_config("init_env_dev_mode", config, preconfig)
625634

626-
def test_init_env_dev_mode(self):
635+
def test_init_env_dev_mode_alloc(self):
627636
preconfig = dict(self.INIT_ENV_PRECONFIG,
628-
allocator='malloc',
629-
dev_mode=1)
630-
config = dict(self.INIT_ENV_CONFIG)
637+
allocator='malloc')
638+
config = dict(self.INIT_ENV_CONFIG,
639+
dev_mode=1)
631640
self.check_config("init_env_dev_mode_alloc", config, preconfig)
632641

633642
def test_init_dev_mode(self):
634643
preconfig = {
635644
'allocator': 'debug',
636-
'dev_mode': 1,
637645
}
638646
config = {
639647
'faulthandler': 1,
648+
'dev_mode': 1,
640649
}
641650
self.check_config("init_dev_mode", config, preconfig)
642651

643652
def test_init_isolated(self):
644653
preconfig = {
645-
'isolated': 1,
646-
'use_environment': 0,
654+
'isolated': 0,
655+
'use_environment': 1,
647656
}
648657
config = {
658+
'isolated': 1,
659+
'use_environment': 0,
649660
'user_site_directory': 0,
650661
}
651662
self.check_config("init_isolated", config, preconfig)

Modules/main.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ pymain_init_preconfig(const _PyArgv *args)
294294
goto done;
295295
}
296296

297-
err = _Py_PreInitializeFromPreConfig(&config);
297+
err = _Py_PreInitializeInPlace(&config);
298298

299299
done:
300300
_PyPreConfig_Clear(&config);
@@ -311,11 +311,6 @@ pymain_init_coreconfig(_PyCoreConfig *config, const _PyArgv *args,
311311
return err;
312312
}
313313

314-
err = _PyCoreConfig_Write(config);
315-
if (_Py_INIT_FAILED(err)) {
316-
return err;
317-
}
318-
319314
return _Py_InitializeCore(interp_p, config);
320315
}
321316

@@ -483,7 +478,7 @@ pymain_header(const _PyCoreConfig *config)
483478
static void
484479
pymain_import_readline(const _PyCoreConfig *config)
485480
{
486-
if (config->preconfig.isolated) {
481+
if (config->isolated) {
487482
return;
488483
}
489484
if (!config->inspect && RUN_CODE(config)) {
@@ -655,7 +650,7 @@ pymain_run_file(_PyCoreConfig *config, PyCompilerFlags *cf)
655650
static void
656651
pymain_run_startup(_PyCoreConfig *config, PyCompilerFlags *cf)
657652
{
658-
const char *startup = _Py_GetEnv(config->preconfig.use_environment, "PYTHONSTARTUP");
653+
const char *startup = _Py_GetEnv(config->use_environment, "PYTHONSTARTUP");
659654
if (startup == NULL) {
660655
return;
661656
}
@@ -735,7 +730,7 @@ pymain_repl(_PyCoreConfig *config, PyCompilerFlags *cf, int *exitcode)
735730
{
736731
/* Check this environment variable at the end, to give programs the
737732
opportunity to set it from Python. */
738-
if (!Py_InspectFlag && _Py_GetEnv(config->preconfig.use_environment, "PYTHONINSPECT")) {
733+
if (!Py_InspectFlag && _Py_GetEnv(config->use_environment, "PYTHONINSPECT")) {
739734
Py_InspectFlag = 1;
740735
config->inspect = 1;
741736
}
@@ -775,7 +770,7 @@ pymain_run_python(PyInterpreterState *interp, int *exitcode)
775770
goto done;
776771
}
777772
}
778-
else if (!config->preconfig.isolated) {
773+
else if (!config->isolated) {
779774
PyObject *path0 = NULL;
780775
if (_PyPathConfig_ComputeSysPath0(&config->argv, &path0)) {
781776
if (path0 == NULL) {

Programs/_freeze_importlib.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ main(int argc, char *argv[])
7777
text[text_size] = '\0';
7878

7979
_PyCoreConfig config = _PyCoreConfig_INIT;
80-
config.preconfig.use_environment = 0;
80+
config.use_environment = 0;
8181
config.user_site_directory = 0;
8282
config.site_import = 0;
8383
config.program_name = L"./_freeze_importlib";

Programs/_testembed.c

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,22 @@ static int test_init_global_config(void)
397397

398398
static int test_init_from_config(void)
399399
{
400+
_PyInitError err;
401+
402+
_PyPreConfig preconfig = _PyPreConfig_INIT;
403+
404+
putenv("PYTHONMALLOC=malloc_debug");
405+
preconfig.allocator = "malloc";
406+
407+
putenv("PYTHONUTF8=0");
408+
Py_UTF8Mode = 0;
409+
preconfig.utf8_mode = 1;
410+
411+
err = _Py_PreInitializeFromPreConfig(&preconfig);
412+
if (_Py_INIT_FAILED(err)) {
413+
_Py_ExitInitError(err);
414+
}
415+
400416
/* Test _Py_InitializeFromConfig() */
401417
_PyCoreConfig config = _PyCoreConfig_INIT;
402418
config.install_signal_handlers = 0;
@@ -407,9 +423,6 @@ static int test_init_from_config(void)
407423
config.use_hash_seed = 1;
408424
config.hash_seed = 123;
409425

410-
putenv("PYTHONMALLOC=malloc_debug");
411-
config.preconfig.allocator = "malloc";
412-
413426
/* dev_mode=1 is tested in test_init_dev_mode() */
414427

415428
putenv("PYTHONFAULTHANDLER=");
@@ -430,10 +443,6 @@ static int test_init_from_config(void)
430443

431444
/* FIXME: test coerce_c_locale and coerce_c_locale_warn */
432445

433-
putenv("PYTHONUTF8=0");
434-
Py_UTF8Mode = 0;
435-
config.preconfig.utf8_mode = 1;
436-
437446
putenv("PYTHONPYCACHEPREFIX=env_pycache_prefix");
438447
config.pycache_prefix = L"conf_pycache_prefix";
439448

@@ -521,7 +530,7 @@ static int test_init_from_config(void)
521530
Py_FrozenFlag = 0;
522531
config._frozen = 1;
523532

524-
_PyInitError err = _Py_InitializeFromConfig(&config);
533+
err = _Py_InitializeFromConfig(&config);
525534
/* Don't call _PyCoreConfig_Clear() since all strings are static */
526535
if (_Py_INIT_FAILED(err)) {
527536
_Py_ExitInitError(err);
@@ -607,20 +616,30 @@ static int test_init_env_dev_mode_alloc(void)
607616

608617
static int test_init_isolated(void)
609618
{
619+
_PyInitError err;
620+
621+
_PyPreConfig preconfig = _PyPreConfig_INIT;
622+
623+
/* Set coerce_c_locale and utf8_mode to not depend on the locale */
624+
preconfig.coerce_c_locale = 0;
625+
preconfig.utf8_mode = 0;
626+
627+
err = _Py_PreInitializeFromPreConfig(&preconfig);
628+
if (_Py_INIT_FAILED(err)) {
629+
_Py_ExitInitError(err);
630+
}
631+
610632
/* Test _PyCoreConfig.isolated=1 */
611633
_PyCoreConfig config = _PyCoreConfig_INIT;
612634

613635
Py_IsolatedFlag = 0;
614-
config.preconfig.isolated = 1;
636+
config.isolated = 1;
615637

616-
/* Set coerce_c_locale and utf8_mode to not depend on the locale */
617-
config.preconfig.coerce_c_locale = 0;
618-
config.preconfig.utf8_mode = 0;
619638
/* Use path starting with "./" avoids a search along the PATH */
620639
config.program_name = L"./_testembed";
621640

622641
test_init_env_dev_mode_putenvs();
623-
_PyInitError err = _Py_InitializeFromConfig(&config);
642+
err = _Py_InitializeFromConfig(&config);
624643
if (_Py_INIT_FAILED(err)) {
625644
_Py_ExitInitError(err);
626645
}
@@ -635,7 +654,7 @@ static int test_init_dev_mode(void)
635654
_PyCoreConfig config = _PyCoreConfig_INIT;
636655
putenv("PYTHONFAULTHANDLER=");
637656
putenv("PYTHONMALLOC=");
638-
config.preconfig.dev_mode = 1;
657+
config.dev_mode = 1;
639658
config.program_name = L"./_testembed";
640659
_PyInitError err = _Py_InitializeFromConfig(&config);
641660
if (_Py_INIT_FAILED(err)) {

0 commit comments

Comments
 (0)