From cad1f747da47849ab5d8b0b881f7a0b94564d290 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 5 Mar 2019 02:01:27 +0100 Subject: bpo-36142: Add _PyPreConfig structure (GH-12172) * Add _PyPreConfig structure * Move 'ignored' and 'use_environment' fields from _PyCoreConfig to _PyPreConfig * Add a new "_PyPreConfig preconfig;" field to _PyCoreConfig --- Include/cpython/coreconfig.h | 35 +++++++---- Include/internal/pycore_coreconfig.h | 13 ++++ Modules/main.c | 4 +- Programs/_freeze_importlib.c | 2 +- Programs/_testembed.c | 6 +- Python/coreconfig.c | 66 ++++++++++---------- Python/pathconfig.c | 2 +- Python/preconfig.c | 113 +++++++++++++++++++++++++++++++++++ Python/sysmodule.c | 4 +- 9 files changed, 193 insertions(+), 52 deletions(-) diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h index 8ad3b23..7997d59 100644 --- a/Include/cpython/coreconfig.h +++ b/Include/cpython/coreconfig.h @@ -46,16 +46,35 @@ typedef struct { #define _Py_INIT_FAILED(err) \ (err.msg != NULL || err.exitcode != -1) -/* --- _PyCoreConfig ---------------------------------------------- */ +/* --- _PyPreConfig ----------------------------------------------- */ typedef struct { - /* Install signal handlers? Yes by default. */ - int install_signal_handlers; + /* If greater than 0, enable isolated mode: sys.path contains + neither the script's directory nor the user's site-packages directory. + + Set to 1 by the -I command line option. If set to -1 (default), inherit + Py_IsolatedFlag value. */ + int isolated; /* If greater than 0: use environment variables. Set to 0 by -E command line option. If set to -1 (default), it is set to !Py_IgnoreEnvironmentFlag. */ int use_environment; +} _PyPreConfig; + +#define _PyPreConfig_INIT \ + (_PyPreConfig){ \ + .isolated = -1, \ + .use_environment = -1} + + +/* --- _PyCoreConfig ---------------------------------------------- */ + +typedef struct { + _PyPreConfig preconfig; + + /* Install signal handlers? Yes by default. */ + int install_signal_handlers; int use_hash_seed; /* PYTHONHASHSEED=x */ unsigned long hash_seed; @@ -152,13 +171,6 @@ typedef struct { wchar_t *dll_path; /* Windows DLL path */ #endif - /* If greater than 0, enable isolated mode: sys.path contains - neither the script's directory nor the user's site-packages directory. - - Set to 1 by the -I command line option. If set to -1 (default), inherit - Py_IsolatedFlag value. */ - int isolated; - /* If equal to zero, disable the import of the module site and the site-dependent manipulations of sys.path that it entails. Also disable these manipulations if site is explicitly imported later (call @@ -336,8 +348,8 @@ typedef struct { #define _PyCoreConfig_INIT \ (_PyCoreConfig){ \ + .preconfig = _PyPreConfig_INIT, \ .install_signal_handlers = 1, \ - .use_environment = -1, \ .use_hash_seed = -1, \ .faulthandler = -1, \ .tracemalloc = -1, \ @@ -345,7 +357,6 @@ typedef struct { .utf8_mode = -1, \ .argc = -1, \ .nmodule_search_path = -1, \ - .isolated = -1, \ .site_import = -1, \ .bytes_warning = -1, \ .inspect = -1, \ diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h index 9f3a4c7..6469fca 100644 --- a/Include/internal/pycore_coreconfig.h +++ b/Include/internal/pycore_coreconfig.h @@ -34,6 +34,19 @@ PyAPI_FUNC(_PyInitError) _PyArgv_Decode(const _PyArgv *args, PyAPI_FUNC(void) _Py_ClearArgcArgv(void); PyAPI_FUNC(int) _Py_SetArgcArgv(int argc, wchar_t * const *argv); +/* --- _PyPreConfig ----------------------------------------------- */ + +PyAPI_FUNC(void) _PyPreConfig_Clear(_PyPreConfig *config); +PyAPI_FUNC(int) _PyPreConfig_Copy(_PyPreConfig *config, + const _PyPreConfig *config2); +PyAPI_FUNC(void) _PyPreConfig_GetGlobalConfig(_PyPreConfig *config); +PyAPI_FUNC(void) _PyPreConfig_SetGlobalConfig(const _PyPreConfig *config); +PyAPI_FUNC(_PyInitError) _PyPreConfig_Read(_PyPreConfig *config); +PyAPI_FUNC(int) _PyPreConfig_AsDict(const _PyPreConfig *config, + PyObject *dict); + + + /* --- _PyCoreConfig ---------------------------------------------- */ PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config); diff --git a/Modules/main.c b/Modules/main.c index fdeaf1d..ff2e2f0 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -487,7 +487,7 @@ pymain_header(const _PyCoreConfig *config) static void pymain_import_readline(const _PyCoreConfig *config) { - if (config->isolated) { + if (config->preconfig.isolated) { return; } if (!config->inspect && RUN_CODE(config)) { @@ -779,7 +779,7 @@ pymain_run_python(PyInterpreterState *interp, int *exitcode) goto done; } } - else if (!config->isolated) { + else if (!config->preconfig.isolated) { PyObject *path0 = _PyPathConfig_ComputeArgv0(config->argc, config->argv); if (path0 == NULL) { diff --git a/Programs/_freeze_importlib.c b/Programs/_freeze_importlib.c index d0e40c9..e6c51a4 100644 --- a/Programs/_freeze_importlib.c +++ b/Programs/_freeze_importlib.c @@ -77,9 +77,9 @@ main(int argc, char *argv[]) text[text_size] = '\0'; _PyCoreConfig config = _PyCoreConfig_INIT; + config.preconfig.use_environment = 0; config.user_site_directory = 0; config.site_import = 0; - config.use_environment = 0; config.program_name = L"./_freeze_importlib"; /* Don't install importlib, since it could execute outdated bytecode. */ config._install_importlib = 0; diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 6b5311b..7b4d8c2 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -606,15 +606,15 @@ static int test_init_isolated(void) /* Test _PyCoreConfig.isolated=1 */ _PyCoreConfig config = _PyCoreConfig_INIT; + Py_IsolatedFlag = 0; + config.preconfig.isolated = 1; + /* Set coerce_c_locale and utf8_mode to not depend on the locale */ config.coerce_c_locale = 0; config.utf8_mode = 0; /* Use path starting with "./" avoids a search along the PATH */ config.program_name = L"./_testembed"; - Py_IsolatedFlag = 0; - config.isolated = 1; - test_init_env_putenvs(); _PyInitError err = _Py_InitializeFromConfig(&config); if (_Py_INIT_FAILED(err)) { diff --git a/Python/coreconfig.c b/Python/coreconfig.c index c3eccb3..3486da4 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -439,6 +439,8 @@ Py_GetArgcArgv(int *argc, wchar_t ***argv) void _PyCoreConfig_Clear(_PyCoreConfig *config) { + _PyPreConfig_Clear(&config->preconfig); + #define CLEAR(ATTR) \ do { \ PyMem_RawFree(ATTR); \ @@ -488,6 +490,10 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) { _PyCoreConfig_Clear(config); + if (_PyPreConfig_Copy(&config->preconfig, &config2->preconfig) < 0) { + return -1; + } + #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR #define COPY_STR_ATTR(ATTR) \ do { \ @@ -519,7 +525,6 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) } while (0) COPY_ATTR(install_signal_handlers); - COPY_ATTR(use_environment); COPY_ATTR(use_hash_seed); COPY_ATTR(hash_seed); COPY_ATTR(_install_importlib); @@ -557,7 +562,6 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) #endif COPY_WSTR_ATTR(base_exec_prefix); - COPY_ATTR(isolated); COPY_ATTR(site_import); COPY_ATTR(bytes_warning); COPY_ATTR(inspect); @@ -595,9 +599,9 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) const char* _PyCoreConfig_GetEnv(const _PyCoreConfig *config, const char *name) { - assert(config->use_environment >= 0); + assert(config->preconfig.use_environment >= 0); - if (!config->use_environment) { + if (!config->preconfig.use_environment) { return NULL; } @@ -616,9 +620,9 @@ _PyCoreConfig_GetEnvDup(const _PyCoreConfig *config, wchar_t **dest, wchar_t *wname, char *name) { - assert(config->use_environment >= 0); + assert(config->preconfig.use_environment >= 0); - if (!config->use_environment) { + if (!config->preconfig.use_environment) { *dest = NULL; return 0; } @@ -662,6 +666,8 @@ _PyCoreConfig_GetEnvDup(const _PyCoreConfig *config, void _PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config) { + _PyPreConfig_GetGlobalConfig(&config->preconfig); + #define COPY_FLAG(ATTR, VALUE) \ if (config->ATTR == -1) { \ config->ATTR = VALUE; \ @@ -672,7 +678,6 @@ _PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config) } COPY_FLAG(utf8_mode, Py_UTF8Mode); - COPY_FLAG(isolated, Py_IsolatedFlag); COPY_FLAG(bytes_warning, Py_BytesWarningFlag); COPY_FLAG(inspect, Py_InspectFlag); COPY_FLAG(interactive, Py_InteractiveFlag); @@ -686,7 +691,6 @@ _PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config) #endif COPY_FLAG(_frozen, Py_FrozenFlag); - COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag); COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag); COPY_NOT_FLAG(site_import, Py_NoSiteFlag); COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag); @@ -701,6 +705,8 @@ _PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config) void _PyCoreConfig_SetGlobalConfig(const _PyCoreConfig *config) { + _PyPreConfig_SetGlobalConfig(&config->preconfig); + #define COPY_FLAG(ATTR, VAR) \ if (config->ATTR != -1) { \ VAR = config->ATTR; \ @@ -711,7 +717,6 @@ _PyCoreConfig_SetGlobalConfig(const _PyCoreConfig *config) } COPY_FLAG(utf8_mode, Py_UTF8Mode); - COPY_FLAG(isolated, Py_IsolatedFlag); COPY_FLAG(bytes_warning, Py_BytesWarningFlag); COPY_FLAG(inspect, Py_InspectFlag); COPY_FLAG(interactive, Py_InteractiveFlag); @@ -725,7 +730,6 @@ _PyCoreConfig_SetGlobalConfig(const _PyCoreConfig *config) #endif COPY_FLAG(_frozen, Py_FrozenFlag); - COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag); COPY_NOT_FLAG(buffered_stdio, Py_UnbufferedStdioFlag); COPY_NOT_FLAG(site_import, Py_NoSiteFlag); COPY_NOT_FLAG(write_bytecode, Py_DontWriteBytecodeFlag); @@ -1497,10 +1501,15 @@ _PyCoreConfig_Read(_PyCoreConfig *config) _PyInitError err; _PyCoreConfig_GetGlobalConfig(config); - assert(config->use_environment >= 0); - if (config->isolated > 0) { - config->use_environment = 0; + err = _PyPreConfig_Read(&config->preconfig); + if (_Py_INIT_FAILED(err)) { + return err; + } + + assert(config->preconfig.use_environment >= 0); + + if (config->preconfig.isolated > 0) { config->user_site_directory = 0; } @@ -1510,7 +1519,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config) } #endif - if (config->use_environment) { + if (config->preconfig.use_environment) { err = config_read_env_vars(config); if (_Py_INIT_FAILED(err)) { return err; @@ -1611,7 +1620,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config) } assert(config->coerce_c_locale >= 0); - assert(config->use_environment >= 0); + assert(config->preconfig.use_environment >= 0); assert(config->filesystem_encoding != NULL); assert(config->filesystem_errors != NULL); assert(config->stdio_encoding != NULL); @@ -1679,18 +1688,23 @@ _PyCoreConfig_Write(const _PyCoreConfig *config) PyObject * _PyCoreConfig_AsDict(const _PyCoreConfig *config) { - PyObject *dict, *obj; + PyObject *dict; dict = PyDict_New(); if (dict == NULL) { return NULL; } + if (_PyPreConfig_AsDict(&config->preconfig, dict) < 0) { + Py_DECREF(dict); + return NULL; + } + #define SET_ITEM(KEY, EXPR) \ do { \ - obj = (EXPR); \ + PyObject *obj = (EXPR); \ if (obj == NULL) { \ - return NULL; \ + goto fail; \ } \ int res = PyDict_SetItemString(dict, (KEY), obj); \ Py_DECREF(obj); \ @@ -1718,7 +1732,6 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) SET_ITEM(#OPTIONS, _Py_wstrlist_as_pylist(config->NOPTION, config->OPTIONS)) SET_ITEM_INT(install_signal_handlers); - SET_ITEM_INT(use_environment); SET_ITEM_INT(use_hash_seed); SET_ITEM_UINT(hash_seed); SET_ITEM_STR(allocator); @@ -1752,7 +1765,6 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) #ifdef MS_WINDOWS SET_ITEM_WSTR(dll_path); #endif - SET_ITEM_INT(isolated); SET_ITEM_INT(site_import); SET_ITEM_INT(bytes_warning); SET_ITEM_INT(inspect); @@ -1828,14 +1840,6 @@ cmdline_clear(_PyCmdline *cmdline) } -static _PyInitError -cmdline_decode_argv(_PyCmdline *cmdline) -{ - assert(cmdline->argv == NULL); - return _PyArgv_Decode(cmdline->args, &cmdline->argv); -} - - /* --- _PyCoreConfig command line parser -------------------------- */ /* Parse the command line arguments */ @@ -1912,7 +1916,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, break; case 'I': - config->isolated++; + config->preconfig.isolated++; break; /* case 'J': reserved for Jython */ @@ -1934,7 +1938,7 @@ config_parse_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, break; case 'E': - config->use_environment = 0; + config->preconfig.use_environment = 0; break; case 't': @@ -2272,7 +2276,7 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline) return err; } - if (config->use_environment) { + if (config->preconfig.use_environment) { err = cmdline_init_env_warnoptions(cmdline, config); if (_Py_INIT_FAILED(err)) { return err; diff --git a/Python/pathconfig.c b/Python/pathconfig.c index f96f015..41fc9e2 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -330,7 +330,7 @@ _PyCoreConfig_CalculatePathConfig(_PyCoreConfig *config) #endif if (path_config.isolated != -1) { - config->isolated = path_config.isolated; + config->preconfig.isolated = path_config.isolated; } if (path_config.site_import != -1) { config->site_import = path_config.site_import; diff --git a/Python/preconfig.c b/Python/preconfig.c index 8102924..bb1e830 100644 --- a/Python/preconfig.c +++ b/Python/preconfig.c @@ -90,3 +90,116 @@ _PyArgv_Decode(const _PyArgv *args, wchar_t*** argv_p) *argv_p = argv; return _Py_INIT_OK(); } + + +/* --- _PyPreConfig ----------------------------------------------- */ + +void +_PyPreConfig_Clear(_PyPreConfig *config) +{ +} + + +int +_PyPreConfig_Copy(_PyPreConfig *config, const _PyPreConfig *config2) +{ + _PyPreConfig_Clear(config); + +#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR + + COPY_ATTR(isolated); + COPY_ATTR(use_environment); + +#undef COPY_ATTR + return 0; +} + + +void +_PyPreConfig_GetGlobalConfig(_PyPreConfig *config) +{ +#define COPY_FLAG(ATTR, VALUE) \ + if (config->ATTR == -1) { \ + config->ATTR = VALUE; \ + } +#define COPY_NOT_FLAG(ATTR, VALUE) \ + if (config->ATTR == -1) { \ + config->ATTR = !(VALUE); \ + } + + COPY_FLAG(isolated, Py_IsolatedFlag); + COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag); + +#undef COPY_FLAG +#undef COPY_NOT_FLAG +} + + +void +_PyPreConfig_SetGlobalConfig(const _PyPreConfig *config) +{ +#define COPY_FLAG(ATTR, VAR) \ + if (config->ATTR != -1) { \ + VAR = config->ATTR; \ + } +#define COPY_NOT_FLAG(ATTR, VAR) \ + if (config->ATTR != -1) { \ + VAR = !config->ATTR; \ + } + + COPY_FLAG(isolated, Py_IsolatedFlag); + COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag); + +#undef COPY_FLAG +#undef COPY_NOT_FLAG +} + + +_PyInitError +_PyPreConfig_Read(_PyPreConfig *config) +{ + _PyPreConfig_GetGlobalConfig(config); + + if (config->isolated > 0) { + config->use_environment = 0; + } + + /* Default values */ + if (config->use_environment < 0) { + config->use_environment = 0; + } + + assert(config->use_environment >= 0); + + return _Py_INIT_OK(); +} + + +int +_PyPreConfig_AsDict(const _PyPreConfig *config, PyObject *dict) +{ +#define SET_ITEM(KEY, EXPR) \ + do { \ + PyObject *obj = (EXPR); \ + if (obj == NULL) { \ + goto fail; \ + } \ + int res = PyDict_SetItemString(dict, (KEY), obj); \ + Py_DECREF(obj); \ + if (res < 0) { \ + goto fail; \ + } \ + } while (0) +#define SET_ITEM_INT(ATTR) \ + SET_ITEM(#ATTR, PyLong_FromLong(config->ATTR)) + + SET_ITEM_INT(isolated); + SET_ITEM_INT(use_environment); + return 0; + +fail: + return -1; + +#undef SET_ITEM +#undef SET_ITEM_INT +} diff --git a/Python/sysmodule.c b/Python/sysmodule.c index dd39305..4b12280 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2172,14 +2172,14 @@ make_flags(void) SetFlag(!config->write_bytecode); SetFlag(!config->user_site_directory); SetFlag(!config->site_import); - SetFlag(!config->use_environment); + SetFlag(!config->preconfig.use_environment); SetFlag(config->verbose); /* SetFlag(saw_unbuffered_flag); */ /* SetFlag(skipfirstline); */ SetFlag(config->bytes_warning); SetFlag(config->quiet); SetFlag(config->use_hash_seed == 0 || config->hash_seed != 0); - SetFlag(config->isolated); + SetFlag(config->preconfig.isolated); PyStructSequence_SET_ITEM(seq, pos++, PyBool_FromLong(config->dev_mode)); SetFlag(config->utf8_mode); #undef SetFlag -- cgit v0.12