Skip to content

Commit cab5d07

Browse files
authored
bpo-36763: Add _PyCoreConfig_InitPythonConfig() (pythonGH-13388)
Add new functions to get the Python interpreter behavior: * _PyPreConfig_InitPythonConfig() * _PyCoreConfig_InitPythonConfig() Add new functions to get an isolated configuration: * _PyPreConfig_InitIsolatedConfig() * _PyCoreConfig_InitIsolatedConfig() Replace _PyPreConfig_INIT and _PyCoreConfig_INIT with new functions _PyPreConfig_Init() and _PyCoreConfig_Init(). _PyCoreConfig: set configure_c_stdio and parse_argv to 0 by default to behave as Python 3.6 in the default configuration. _PyCoreConfig_Read() no longer sets coerce_c_locale_warn to 1 if it's equal to 0. coerce_c_locale_warn must now be set to -1 (ex: using _PyCoreConfig_InitPythonConfig()) to enable C locale coercion warning. Add unit tests for _PyCoreConfig_InitPythonConfig() and _PyCoreConfig_InitIsolatedConfig(). Changes: * Rename _PyCoreConfig_GetCoreConfig() to _PyPreConfig_GetCoreConfig() * Fix core_read_precmdline(): handle parse_argv=0 * Fix _Py_PreInitializeFromCoreConfig(): pass coreconfig.argv to _Py_PreInitializeFromPyArgv(), except if parse_argv=0
1 parent b16b4e4 commit cab5d07

File tree

12 files changed

+362
-91
lines changed

12 files changed

+362
-91
lines changed

Include/cpython/coreconfig.h

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,18 @@ typedef struct {
8686
8787
If it is equal to 1, LC_CTYPE locale is read to decide it it should be
8888
coerced or not (ex: PYTHONCOERCECLOCALE=1). Internally, it is set to 2
89-
if the LC_CTYPE locale must be coerced. */
89+
if the LC_CTYPE locale must be coerced.
90+
91+
Disable by default (set to 0). Set it to -1 to let Python decides if it
92+
should be enabled or not. */
9093
int coerce_c_locale;
9194

9295
/* Emit a warning if the LC_CTYPE locale is coerced?
9396
94-
Disabled by default. Set to 1 by PYTHONCOERCECLOCALE=warn. */
97+
Set to 1 by PYTHONCOERCECLOCALE=warn.
98+
99+
Disable by default (set to 0). Set it to -1 to let Python decides if it
100+
should be enabled or not. */
95101
int coerce_c_locale_warn;
96102

97103
#ifdef MS_WINDOWS
@@ -116,7 +122,10 @@ typedef struct {
116122
Set to 0 by "-X utf8=0" and PYTHONUTF8=0.
117123
118124
If equals to -1, it is set to 1 if the LC_CTYPE locale is "C" or
119-
"POSIX", otherwise inherit Py_UTF8Mode value. */
125+
"POSIX", otherwise it is set to 0.
126+
127+
If equals to -2, inherit Py_UTF8Mode value value (which is equal to 0
128+
by default). */
120129
int utf8_mode;
121130

122131
int dev_mode; /* Development mode. PYTHONDEVMODE, -X dev */
@@ -138,9 +147,14 @@ typedef struct {
138147
._config_version = _Py_CONFIG_VERSION, \
139148
.isolated = -1, \
140149
.use_environment = -1, \
150+
.utf8_mode = -2, \
141151
.dev_mode = -1, \
142152
.allocator = PYMEM_ALLOCATOR_NOT_SET}
143153

154+
PyAPI_FUNC(void) _PyPreConfig_Init(_PyPreConfig *config);
155+
PyAPI_FUNC(void) _PyPreConfig_InitPythonConfig(_PyPreConfig *config);
156+
PyAPI_FUNC(void) _PyPreConfig_InitIsolateConfig(_PyPreConfig *config);
157+
144158

145159
/* --- _PyCoreConfig ---------------------------------------------- */
146160

@@ -213,8 +227,8 @@ typedef struct {
213227

214228
/* Command line arguments (sys.argv).
215229
216-
By default, Python command line arguments are parsed and then stripped
217-
from argv. Set parse_argv to 0 to avoid that.
230+
Set parse_argv to 1 to parse argv as Python command line arguments
231+
and then strip Python arguments from argv.
218232
219233
If argv is empty, an empty string is added to ensure that sys.argv
220234
always exists and is never empty. */
@@ -442,7 +456,7 @@ typedef struct {
442456
.faulthandler = -1, \
443457
.tracemalloc = -1, \
444458
.use_module_search_paths = 0, \
445-
.parse_argv = 1, \
459+
.parse_argv = 0, \
446460
.site_import = -1, \
447461
.bytes_warning = -1, \
448462
.inspect = -1, \
@@ -453,14 +467,18 @@ typedef struct {
453467
.verbose = -1, \
454468
.quiet = -1, \
455469
.user_site_directory = -1, \
456-
.configure_c_stdio = 1, \
470+
.configure_c_stdio = 0, \
457471
.buffered_stdio = -1, \
458472
._install_importlib = 1, \
459473
.check_hash_pycs_mode = NULL, \
460474
.pathconfig_warnings = -1, \
461475
._init_main = 1}
462476
/* Note: _PyCoreConfig_INIT sets other fields to 0/NULL */
463477

478+
PyAPI_FUNC(void) _PyCoreConfig_Init(_PyCoreConfig *config);
479+
PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitPythonConfig(_PyCoreConfig *config);
480+
PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitIsolateConfig(_PyCoreConfig *config);
481+
464482
#ifdef __cplusplus
465483
}
466484
#endif

Include/internal/pycore_coreconfig.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,13 @@ PyAPI_FUNC(_PyInitError) _PyPreCmdline_Read(_PyPreCmdline *cmdline,
8888

8989
/* --- _PyPreConfig ----------------------------------------------- */
9090

91+
PyAPI_FUNC(void) _PyPreConfig_Init(_PyPreConfig *config);
92+
PyAPI_FUNC(void) _PyPreConfig_InitPythonConfig(_PyPreConfig *config);
93+
PyAPI_FUNC(void) _PyPreConfig_InitIsolatedConfig(_PyPreConfig *config);
9194
PyAPI_FUNC(int) _PyPreConfig_Copy(_PyPreConfig *config,
9295
const _PyPreConfig *config2);
9396
PyAPI_FUNC(PyObject*) _PyPreConfig_AsDict(const _PyPreConfig *config);
94-
PyAPI_FUNC(void) _PyCoreConfig_GetCoreConfig(_PyPreConfig *config,
97+
PyAPI_FUNC(void) _PyPreConfig_GetCoreConfig(_PyPreConfig *config,
9598
const _PyCoreConfig *core_config);
9699
PyAPI_FUNC(_PyInitError) _PyPreConfig_Read(_PyPreConfig *config,
97100
const _PyArgv *args);
@@ -101,6 +104,8 @@ PyAPI_FUNC(_PyInitError) _PyPreConfig_Write(const _PyPreConfig *config);
101104
/* --- _PyCoreConfig ---------------------------------------------- */
102105

103106
PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *);
107+
PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitPythonConfig(_PyCoreConfig *config);
108+
PyAPI_FUNC(_PyInitError) _PyCoreConfig_InitIsolatedConfig(_PyCoreConfig *config);
104109
PyAPI_FUNC(_PyInitError) _PyCoreConfig_Copy(
105110
_PyCoreConfig *config,
106111
const _PyCoreConfig *config2);

Lib/test/test_embed.py

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
307307

308308
'pycache_prefix': None,
309309
'program_name': GET_DEFAULT_CONFIG,
310-
'parse_argv': 1,
310+
'parse_argv': 0,
311311
'argv': [""],
312312

313313
'xoptions': [],
@@ -333,7 +333,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
333333
'verbose': 0,
334334
'quiet': 0,
335335
'user_site_directory': 1,
336-
'configure_c_stdio': 1,
336+
'configure_c_stdio': 0,
337337
'buffered_stdio': 1,
338338

339339
'stdio_encoding': GET_DEFAULT_CONFIG,
@@ -588,6 +588,7 @@ def test_init_from_config(self):
588588
'pycache_prefix': 'conf_pycache_prefix',
589589
'program_name': './conf_program_name',
590590
'argv': ['-c', 'arg2'],
591+
'parse_argv': 1,
591592
'xoptions': ['core_xoption1=3', 'core_xoption2=', 'core_xoption3'],
592593
'warnoptions': ['error::ResourceWarning', 'default::BytesWarning'],
593594
'run_command': 'pass\n',
@@ -600,7 +601,7 @@ def test_init_from_config(self):
600601
'write_bytecode': 0,
601602
'verbose': 1,
602603
'quiet': 1,
603-
'configure_c_stdio': 0,
604+
'configure_c_stdio': 1,
604605
'buffered_stdio': 0,
605606
'user_site_directory': 0,
606607
'faulthandler': 1,
@@ -661,14 +662,14 @@ def test_init_dev_mode(self):
661662
}
662663
self.check_config("init_dev_mode", config, preconfig)
663664

664-
def test_init_isolated(self):
665+
def test_init_isolated_flag(self):
665666
preconfig = {}
666667
config = {
667668
'isolated': 1,
668669
'use_environment': 0,
669670
'user_site_directory': 0,
670671
}
671-
self.check_config("init_isolated", config, preconfig)
672+
self.check_config("init_isolated_flag", config, preconfig)
672673

673674
def test_preinit_isolated1(self):
674675
# _PyPreConfig.isolated=1, _PyCoreConfig.isolated not set
@@ -690,6 +691,25 @@ def test_preinit_isolated2(self):
690691
}
691692
self.check_config("preinit_isolated2", config, preconfig)
692693

694+
def test_init_isolated_config(self):
695+
preconfig = {}
696+
config = {
697+
'isolated': 1,
698+
'use_environment': 0,
699+
'user_site_directory': 0,
700+
'install_signal_handlers': 0,
701+
'pathconfig_warnings': 0,
702+
}
703+
self.check_config("init_isolated_config", config, preconfig)
704+
705+
def test_init_python_config(self):
706+
preconfig = {}
707+
config = {
708+
'configure_c_stdio': 1,
709+
'parse_argv': 1,
710+
}
711+
self.check_config("init_python_config", config, preconfig)
712+
693713
def test_init_read_set(self):
694714
preconfig = {}
695715
core_config = {
@@ -707,6 +727,7 @@ def test_init_run_main(self):
707727
'argv': ['-c', 'arg2'],
708728
'program_name': './python3',
709729
'run_command': code + '\n',
730+
'parse_argv': 1,
710731
}
711732
self.check_config("init_run_main", core_config, preconfig)
712733

@@ -718,15 +739,26 @@ def test_init_main(self):
718739
'argv': ['-c', 'arg2'],
719740
'program_name': './python3',
720741
'run_command': code + '\n',
742+
'parse_argv': 1,
721743
'_init_main': 0,
722744
}
723745
self.check_config("init_main", core_config, preconfig,
724746
stderr="Run Python code before _Py_InitializeMain")
725747

748+
def test_init_parse_argv(self):
749+
core_config = {
750+
'argv': ['-c', 'arg1', '-v', 'arg3'],
751+
'program_name': './argv0',
752+
'parse_argv': 1,
753+
'run_command': 'pass\n',
754+
'use_environment': 0,
755+
}
756+
self.check_config("init_parse_argv", core_config, {})
757+
726758
def test_init_dont_parse_argv(self):
727759
core_config = {
728-
'argv': ['-v', '-c', 'arg1', '-W', 'arg2'],
729-
'parse_argv': 0,
760+
'argv': ['./argv0', '-E', '-c', 'pass', 'arg1', '-v', 'arg3'],
761+
'program_name': './argv0',
730762
}
731763
self.check_config("init_dont_parse_argv", core_config, {})
732764

Modules/main.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,28 @@ pymain_init(const _PyArgv *args)
5252
fedisableexcept(FE_OVERFLOW);
5353
#endif
5454

55-
_PyPreConfig preconfig = _PyPreConfig_INIT;
56-
/* Set to -1 to enable them depending on the LC_CTYPE locale and the
57-
environment variables (PYTHONUTF8 and PYTHONCOERCECLOCALE) */
58-
preconfig.coerce_c_locale = -1;
59-
preconfig.utf8_mode = -1;
55+
_PyPreConfig preconfig;
56+
_PyPreConfig_InitPythonConfig(&preconfig);
6057
err = _Py_PreInitializeFromPyArgv(&preconfig, args);
6158
if (_Py_INIT_FAILED(err)) {
6259
return err;
6360
}
6461

62+
_PyCoreConfig config;
63+
err = _PyCoreConfig_InitPythonConfig(&config);
64+
if (_Py_INIT_FAILED(err)) {
65+
return err;
66+
}
67+
6568
/* pass NULL as the config: config is read from command line arguments,
6669
environment variables, configuration files */
6770
if (args->use_bytes_argv) {
68-
return _Py_InitializeFromArgs(NULL, args->argc, args->bytes_argv);
71+
return _Py_InitializeFromArgs(&config,
72+
args->argc, args->bytes_argv);
6973
}
7074
else {
71-
return _Py_InitializeFromWideArgs(NULL, args->argc, args->wchar_argv);
75+
return _Py_InitializeFromWideArgs(&config,
76+
args->argc, args->wchar_argv);
7277
}
7378
}
7479

Programs/_freeze_importlib.c

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

79-
_PyCoreConfig config = _PyCoreConfig_INIT;
79+
_PyCoreConfig config;
80+
_PyCoreConfig_Init(&config);
8081
config.use_environment = 0;
8182
config.user_site_directory = 0;
8283
config.site_import = 0;

0 commit comments

Comments
 (0)