mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-36763: Add _PyCoreConfig_InitPythonConfig() (GH-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
This commit is contained in:
		
							parent
							
								
									b16b4e4592
								
							
						
					
					
						commit
						cab5d0741e
					
				
					 12 changed files with 362 additions and 91 deletions
				
			
		|  | @ -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 = -1; | ||||
| int Py_UTF8Mode = 0; | ||||
| int Py_DebugFlag = 0; /* Needed by parser.c */ | ||||
| int Py_VerboseFlag = 0; /* Needed by import.c */ | ||||
| int Py_QuietFlag = 0; /* Needed by sysmodule.c */ | ||||
|  | @ -520,6 +520,61 @@ _PyCoreConfig_Clear(_PyCoreConfig *config) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| _PyCoreConfig_Init(_PyCoreConfig *config) | ||||
| { | ||||
|     *config = _PyCoreConfig_INIT; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| _PyInitError | ||||
| _PyCoreConfig_InitPythonConfig(_PyCoreConfig *config) | ||||
| { | ||||
|     _PyCoreConfig_Init(config); | ||||
| 
 | ||||
|     config->configure_c_stdio = 1; | ||||
|     config->parse_argv = 1; | ||||
| 
 | ||||
|     return _Py_INIT_OK(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| _PyInitError | ||||
| _PyCoreConfig_InitIsolatedConfig(_PyCoreConfig *config) | ||||
| { | ||||
|     _PyCoreConfig_Init(config); | ||||
| 
 | ||||
|     /* set to 1 */ | ||||
|     config->isolated = 1; | ||||
|     config->site_import = 1; | ||||
|     config->write_bytecode = 1; | ||||
|     config->buffered_stdio = 1; | ||||
| 
 | ||||
|     /* set to 0 */ | ||||
|     config->use_environment = 0; | ||||
|     config->dev_mode = 0; | ||||
|     config->install_signal_handlers = 0; | ||||
|     config->use_hash_seed = 0; | ||||
|     config->faulthandler = 0; | ||||
|     config->tracemalloc = 0; | ||||
|     config->bytes_warning = 0; | ||||
|     config->inspect = 0; | ||||
|     config->interactive = 0; | ||||
|     config->optimization_level = 0; | ||||
|     config->parser_debug = 0; | ||||
|     config->verbose = 0; | ||||
|     config->quiet = 0; | ||||
|     config->user_site_directory = 0; | ||||
|     config->configure_c_stdio = 0; | ||||
|     config->pathconfig_warnings = 0; | ||||
| #ifdef MS_WINDOWS | ||||
|     config->legacy_windows_stdio = 0; | ||||
| #endif | ||||
| 
 | ||||
|     return _Py_INIT_OK(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Copy str into *config_str (duplicate the string) */ | ||||
| _PyInitError | ||||
| _PyCoreConfig_SetString(wchar_t **config_str, const wchar_t *str) | ||||
|  | @ -2014,17 +2069,20 @@ core_read_precmdline(_PyCoreConfig *config, _PyPreCmdline *precmdline) | |||
| { | ||||
|     _PyInitError err; | ||||
| 
 | ||||
|     if (_PyWstrList_Copy(&precmdline->argv, &config->argv) < 0) { | ||||
|         return _Py_INIT_NO_MEMORY(); | ||||
|     if (config->parse_argv) { | ||||
|         if (_PyWstrList_Copy(&precmdline->argv, &config->argv) < 0) { | ||||
|             return _Py_INIT_NO_MEMORY(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     _PyPreConfig preconfig = _PyPreConfig_INIT; | ||||
|     _PyPreConfig preconfig; | ||||
|     _PyPreConfig_Init(&preconfig); | ||||
|     if (_PyPreConfig_Copy(&preconfig, &_PyRuntime.preconfig) < 0) { | ||||
|         err = _Py_INIT_NO_MEMORY(); | ||||
|         return err; | ||||
|     } | ||||
| 
 | ||||
|     _PyCoreConfig_GetCoreConfig(&preconfig, config); | ||||
|     _PyPreConfig_GetCoreConfig(&preconfig, config); | ||||
| 
 | ||||
|     err = _PyPreCmdline_Read(precmdline, &preconfig); | ||||
|     if (_Py_INIT_FAILED(err)) { | ||||
|  | @ -2155,6 +2213,7 @@ _PyInitError | |||
| _PyCoreConfig_Read(_PyCoreConfig *config) | ||||
| { | ||||
|     _PyInitError err; | ||||
|     _PyWstrList orig_argv = _PyWstrList_INIT; | ||||
| 
 | ||||
|     err = _Py_PreInitializeFromCoreConfig(config, NULL); | ||||
|     if (_Py_INIT_FAILED(err)) { | ||||
|  | @ -2163,6 +2222,10 @@ _PyCoreConfig_Read(_PyCoreConfig *config) | |||
| 
 | ||||
|     _PyCoreConfig_GetGlobalConfig(config); | ||||
| 
 | ||||
|     if (_PyWstrList_Copy(&orig_argv, &config->argv) < 0) { | ||||
|         return _Py_INIT_NO_MEMORY(); | ||||
|     } | ||||
| 
 | ||||
|     _PyPreCmdline precmdline = _PyPreCmdline_INIT; | ||||
|     err = core_read_precmdline(config, &precmdline); | ||||
|     if (_Py_INIT_FAILED(err)) { | ||||
|  | @ -2185,10 +2248,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config) | |||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
|     /* precmdline.argv is a copy of config.argv which is modified
 | ||||
|        by config_read_cmdline() */ | ||||
|     const _PyWstrList *argv = &precmdline.argv; | ||||
|     if (_Py_SetArgcArgv(argv->length, argv->items) < 0) { | ||||
|     if (_Py_SetArgcArgv(orig_argv.length, orig_argv.items) < 0) { | ||||
|         err = _Py_INIT_NO_MEMORY(); | ||||
|         goto done; | ||||
|     } | ||||
|  | @ -2249,6 +2309,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config) | |||
|     err = _Py_INIT_OK(); | ||||
| 
 | ||||
| done: | ||||
|     _PyWstrList_Clear(&orig_argv); | ||||
|     _PyPreCmdline_Clear(&precmdline); | ||||
|     return err; | ||||
| } | ||||
|  |  | |||
|  | @ -39,7 +39,8 @@ Py_FrozenMain(int argc, char **argv) | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     _PyCoreConfig config = _PyCoreConfig_INIT; | ||||
|     _PyCoreConfig config; | ||||
|     _PyCoreConfig_Init(&config); | ||||
|     config.pathconfig_warnings = 0;   /* Suppress errors from getpath.c */ | ||||
| 
 | ||||
|     if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') | ||||
|  |  | |||
|  | @ -392,7 +392,8 @@ pathconfig_global_init(void) | |||
|     } | ||||
| 
 | ||||
|     _PyInitError err; | ||||
|     _PyCoreConfig config = _PyCoreConfig_INIT; | ||||
|     _PyCoreConfig config; | ||||
|     _PyCoreConfig_Init(&config); | ||||
| 
 | ||||
|     err = _PyCoreConfig_Read(&config); | ||||
|     if (_Py_INIT_FAILED(err)) { | ||||
|  |  | |||
|  | @ -260,6 +260,42 @@ _PyPreCmdline_Read(_PyPreCmdline *cmdline, | |||
| 
 | ||||
| /* --- _PyPreConfig ----------------------------------------------- */ | ||||
| 
 | ||||
| void | ||||
| _PyPreConfig_Init(_PyPreConfig *config) | ||||
| { | ||||
|     *config = _PyPreConfig_INIT; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| _PyPreConfig_InitPythonConfig(_PyPreConfig *config) | ||||
| { | ||||
|     _PyPreConfig_Init(config); | ||||
| 
 | ||||
|     /* 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; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| _PyPreConfig_InitIsolatedConfig(_PyPreConfig *config) | ||||
| { | ||||
|     _PyPreConfig_Init(config); | ||||
| 
 | ||||
|     config->isolated = 1; | ||||
|     config->use_environment = 0; | ||||
| #ifdef MS_WINDOWS | ||||
|     config->legacy_windows_fs_encoding = 0; | ||||
| #endif | ||||
|     config->utf8_mode = 0; | ||||
|     config->dev_mode = 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| _PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2) | ||||
| { | ||||
|  | @ -346,7 +382,7 @@ _PyPreConfig_AsDict(const _PyPreConfig *config) | |||
| 
 | ||||
| 
 | ||||
| void | ||||
| _PyCoreConfig_GetCoreConfig(_PyPreConfig *config, | ||||
| _PyPreConfig_GetCoreConfig(_PyPreConfig *config, | ||||
|                             const _PyCoreConfig *core_config) | ||||
| { | ||||
| #define COPY_ATTR(ATTR) \ | ||||
|  | @ -366,11 +402,11 @@ static void | |||
| _PyPreConfig_GetGlobalConfig(_PyPreConfig *config) | ||||
| { | ||||
| #define COPY_FLAG(ATTR, VALUE) \ | ||||
|     if (config->ATTR == -1) { \ | ||||
|     if (config->ATTR < 0) { \ | ||||
|         config->ATTR = VALUE; \ | ||||
|     } | ||||
| #define COPY_NOT_FLAG(ATTR, VALUE) \ | ||||
|     if (config->ATTR == -1) { \ | ||||
|     if (config->ATTR < 0) { \ | ||||
|         config->ATTR = !(VALUE); \ | ||||
|     } | ||||
| 
 | ||||
|  | @ -379,8 +415,8 @@ _PyPreConfig_GetGlobalConfig(_PyPreConfig *config) | |||
| #ifdef MS_WINDOWS | ||||
|     COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag); | ||||
| #endif | ||||
|     if (Py_UTF8Mode > 0) { | ||||
|         config->utf8_mode = 1; | ||||
|     if (config->utf8_mode == -2) { | ||||
|         config->utf8_mode = Py_UTF8Mode; | ||||
|     } | ||||
| 
 | ||||
| #undef COPY_FLAG | ||||
|  | @ -392,11 +428,11 @@ static void | |||
| _PyPreConfig_SetGlobalConfig(const _PyPreConfig *config) | ||||
| { | ||||
| #define COPY_FLAG(ATTR, VAR) \ | ||||
|     if (config->ATTR != -1) { \ | ||||
|     if (config->ATTR >= 0) { \ | ||||
|         VAR = config->ATTR; \ | ||||
|     } | ||||
| #define COPY_NOT_FLAG(ATTR, VAR) \ | ||||
|     if (config->ATTR != -1) { \ | ||||
|     if (config->ATTR >= 0) { \ | ||||
|         VAR = !config->ATTR; \ | ||||
|     } | ||||
| 
 | ||||
|  | @ -575,7 +611,9 @@ preconfig_init_coerce_c_locale(_PyPreConfig *config) | |||
|             } | ||||
|         } | ||||
|         else if (strcmp(env, "warn") == 0) { | ||||
|             config->coerce_c_locale_warn = 1; | ||||
|             if (config->coerce_c_locale_warn < 0) { | ||||
|                 config->coerce_c_locale_warn = 1; | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             if (config->coerce_c_locale < 0) { | ||||
|  | @ -587,19 +625,19 @@ preconfig_init_coerce_c_locale(_PyPreConfig *config) | |||
|     /* Test if coerce_c_locale equals to -1 or equals to 1:
 | ||||
|        PYTHONCOERCECLOCALE=1 doesn't imply that the C locale is always coerced. | ||||
|        It is only coerced if if the LC_CTYPE locale is "C". */ | ||||
|     if (config->coerce_c_locale == 0 || config->coerce_c_locale == 2) { | ||||
|         return; | ||||
|     if (config->coerce_c_locale < 0 || config->coerce_c_locale == 1) { | ||||
|         /* The C locale enables the C locale coercion (PEP 538) */ | ||||
|         if (_Py_LegacyLocaleDetected()) { | ||||
|             config->coerce_c_locale = 2; | ||||
|         } | ||||
|         else { | ||||
|             config->coerce_c_locale = 0; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /* The C locale enables the C locale coercion (PEP 538) */ | ||||
|     if (_Py_LegacyLocaleDetected()) { | ||||
|         config->coerce_c_locale = 2; | ||||
|     if (config->coerce_c_locale_warn < 0) { | ||||
|         config->coerce_c_locale_warn = 0; | ||||
|     } | ||||
|     else { | ||||
|         config->coerce_c_locale = 0; | ||||
|     } | ||||
| 
 | ||||
|     assert(config->coerce_c_locale >= 0); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -659,6 +697,7 @@ preconfig_read(_PyPreConfig *config, _PyPreCmdline *cmdline) | |||
|     } | ||||
| 
 | ||||
|     assert(config->coerce_c_locale >= 0); | ||||
|     assert(config->coerce_c_locale_warn >= 0); | ||||
| #ifdef MS_WINDOWS | ||||
|     assert(config->legacy_windows_fs_encoding >= 0); | ||||
| #endif | ||||
|  | @ -700,7 +739,8 @@ _PyPreConfig_Read(_PyPreConfig *config, const _PyArgv *args) | |||
|     } | ||||
| 
 | ||||
|     /* Save the config to be able to restore it if encodings change */ | ||||
|     _PyPreConfig save_config = _PyPreConfig_INIT; | ||||
|     _PyPreConfig save_config; | ||||
|     _PyPreConfig_Init(&save_config); | ||||
|     if (_PyPreConfig_Copy(&save_config, config) < 0) { | ||||
|         return _Py_INIT_NO_MEMORY(); | ||||
|     } | ||||
|  |  | |||
|  | @ -701,7 +701,8 @@ _Py_PreInitializeFromPyArgv(const _PyPreConfig *src_config, const _PyArgv *args) | |||
|         return _Py_INIT_OK(); | ||||
|     } | ||||
| 
 | ||||
|     _PyPreConfig config = _PyPreConfig_INIT; | ||||
|     _PyPreConfig config; | ||||
|     _PyPreConfig_Init(&config); | ||||
| 
 | ||||
|     if (src_config) { | ||||
|         if (_PyPreConfig_Copy(&config, src_config) < 0) { | ||||
|  | @ -752,13 +753,22 @@ _PyInitError | |||
| _Py_PreInitializeFromCoreConfig(const _PyCoreConfig *coreconfig, | ||||
|                                 const _PyArgv *args) | ||||
| { | ||||
|     _PyPreConfig config = _PyPreConfig_INIT; | ||||
|     _PyPreConfig config; | ||||
|     _PyPreConfig_Init(&config); | ||||
|     if (coreconfig != NULL) { | ||||
|         _PyCoreConfig_GetCoreConfig(&config, coreconfig); | ||||
|         _PyPreConfig_GetCoreConfig(&config, coreconfig); | ||||
|     } | ||||
| 
 | ||||
|     if (args == NULL && coreconfig != NULL && coreconfig->parse_argv) { | ||||
|         _PyArgv config_args = { | ||||
|             .use_bytes_argv = 0, | ||||
|             .argc = coreconfig->argv.length, | ||||
|             .wchar_argv = coreconfig->argv.items}; | ||||
|         return _Py_PreInitializeFromPyArgv(&config, &config_args); | ||||
|     } | ||||
|     else { | ||||
|         return _Py_PreInitializeFromPyArgv(&config, args); | ||||
|     } | ||||
|     return _Py_PreInitializeFromPyArgv(&config, args); | ||||
|     /* No need to clear config:
 | ||||
|        _PyCoreConfig_GetCoreConfig() doesn't allocate memory */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -829,7 +839,8 @@ _Py_InitializeCore(_PyRuntimeState *runtime, | |||
|         return err; | ||||
|     } | ||||
| 
 | ||||
|     _PyCoreConfig local_config = _PyCoreConfig_INIT; | ||||
|     _PyCoreConfig local_config; | ||||
|     _PyCoreConfig_Init(&local_config); | ||||
|     err = pyinit_coreconfig(runtime, &local_config, src_config, args, interp_p); | ||||
|     _PyCoreConfig_Clear(&local_config); | ||||
|     return err; | ||||
|  | @ -1051,7 +1062,8 @@ Py_InitializeEx(int install_sigs) | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     _PyCoreConfig config = _PyCoreConfig_INIT; | ||||
|     _PyCoreConfig config; | ||||
|     _PyCoreConfig_Init(&config); | ||||
|     config.install_signal_handlers = install_sigs; | ||||
| 
 | ||||
|     err = _Py_InitializeFromConfig(&config); | ||||
|  |  | |||
|  | @ -49,7 +49,7 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) | |||
| 
 | ||||
|     _PyGC_Initialize(&runtime->gc); | ||||
|     _PyEval_Initialize(&runtime->ceval); | ||||
|     runtime->preconfig = _PyPreConfig_INIT; | ||||
|     _PyPreConfig_Init(&runtime->preconfig); | ||||
| 
 | ||||
|     runtime->gilstate.check_enabled = 1; | ||||
| 
 | ||||
|  | @ -189,7 +189,7 @@ PyInterpreterState_New(void) | |||
|     memset(interp, 0, sizeof(*interp)); | ||||
|     interp->id_refcount = -1; | ||||
|     interp->check_interval = 100; | ||||
|     interp->core_config = _PyCoreConfig_INIT; | ||||
|     _PyCoreConfig_Init(&interp->core_config); | ||||
|     interp->eval_frame = _PyEval_EvalFrameDefault; | ||||
| #ifdef HAVE_DLOPEN | ||||
| #if HAVE_DECL_RTLD_NOW | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Victor Stinner
						Victor Stinner