diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2017-12-15 00:46:02 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-15 00:46:02 (GMT) |
commit | da273412c4374de07a500e7f23f89a6bb7527398 (patch) | |
tree | 86f8e89fa317de8ab4d8f06166a934e6810cc3d3 /Modules/main.c | |
parent | 358e5e17a51ba00742bfaee4557a94c3c4179c22 (diff) | |
download | cpython-da273412c4374de07a500e7f23f89a6bb7527398.zip cpython-da273412c4374de07a500e7f23f89a6bb7527398.tar.gz cpython-da273412c4374de07a500e7f23f89a6bb7527398.tar.bz2 |
bpo-32030: Add _PyCoreConfig_Copy() (#4874)
Each interpreter now has its core_config and main_config copy:
* Add _PyCoreConfig_Copy() and _PyMainInterpreterConfig_Copy()
* Move _PyCoreConfig_Read(), _PyCoreConfig_Clear() and
_PyMainInterpreterConfig_Clear() from Python/pylifecycle.c to
Modules/main.c
* Fix _Py_InitializeEx_Private(): call _PyCoreConfig_ReadEnv() before
_Py_InitializeCore()
Diffstat (limited to 'Modules/main.c')
-rw-r--r-- | Modules/main.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/Modules/main.c b/Modules/main.c index e1a2f98..8c4219c 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1914,6 +1914,154 @@ pymain_parse_cmdline_envvars(_PyMain *pymain) } +/* Read configuration settings from standard locations + * + * This function doesn't make any changes to the interpreter state - it + * merely populates any missing configuration settings. This allows an + * embedding application to completely override a config option by + * setting it before calling this function, or else modify the default + * setting before passing the fully populated config to Py_EndInitialization. + * + * More advanced selective initialization tricks are possible by calling + * this function multiple times with various preconfigured settings. + */ + +_PyInitError +_PyCoreConfig_Read(_PyCoreConfig *config) +{ + if (config->program_name == NULL) { +#ifdef MS_WINDOWS + const wchar_t *program_name = L"python"; +#else + const wchar_t *program_name = L"python3"; +#endif + config->program_name = _PyMem_RawWcsdup(program_name); + if (config->program_name == NULL) { + return _Py_INIT_NO_MEMORY(); + } + } + + return _Py_INIT_OK(); +} + + +void +_PyCoreConfig_Clear(_PyCoreConfig *config) +{ +#define CLEAR(ATTR) \ + do { \ + PyMem_RawFree(ATTR); \ + ATTR = NULL; \ + } while (0) + + CLEAR(config->module_search_path_env); + CLEAR(config->home); + CLEAR(config->program_name); +#undef CLEAR +} + + +int +_PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) +{ + _PyCoreConfig_Clear(config); + +#define COPY_ATTR(ATTR) config->ATTR = config2->ATTR + COPY_ATTR(ignore_environment); + COPY_ATTR(use_hash_seed); + COPY_ATTR(hash_seed); + COPY_ATTR(_disable_importlib); + COPY_ATTR(allocator); + COPY_ATTR(dev_mode); + COPY_ATTR(faulthandler); + COPY_ATTR(tracemalloc); + COPY_ATTR(import_time); + COPY_ATTR(show_ref_count); + COPY_ATTR(show_alloc_count); + COPY_ATTR(dump_refs); + COPY_ATTR(malloc_stats); + COPY_ATTR(utf8_mode); +#undef COPY_ATTR + +#define COPY_STR_ATTR(ATTR) \ + do { \ + if (config2->ATTR != NULL) { \ + config->ATTR = _PyMem_RawWcsdup(config2->ATTR); \ + if (config->ATTR == NULL) { \ + return -1; \ + } \ + } \ + } while (0) + + COPY_STR_ATTR(module_search_path_env); + COPY_STR_ATTR(home); + COPY_STR_ATTR(program_name); +#undef COPY_STR_ATTR + return 0; +} + + +void +_PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config) +{ + Py_CLEAR(config->argv); + Py_CLEAR(config->module_search_path); + Py_CLEAR(config->warnoptions); + Py_CLEAR(config->xoptions); +} + + +static PyObject* +config_copy_attr(PyObject *obj) +{ + if (PyUnicode_Check(obj)) { + Py_INCREF(obj); + return obj; + } + else if (PyList_Check(obj)) { + return PyList_GetSlice(obj, 0, Py_SIZE(obj)); + } + else if (PyDict_Check(obj)) { + /* The dict type is used for xoptions. Make the assumption that keys + and values are immutables */ + return PyDict_Copy(obj); + } + else { + PyErr_Format(PyExc_TypeError, + "cannot copy config attribute of type %.200s", + Py_TYPE(obj)->tp_name); + return NULL; + } +} + + +int +_PyMainInterpreterConfig_Copy(_PyMainInterpreterConfig *config, + const _PyMainInterpreterConfig *config2) +{ + _PyMainInterpreterConfig_Clear(config); + +#define COPY_ATTR(ATTR) \ + do { \ + if (config2->ATTR != NULL) { \ + config->ATTR = config_copy_attr(config2->ATTR); \ + if (config->ATTR == NULL) { \ + return -1; \ + } \ + } \ + } while (0) + + COPY_ATTR(argv); + COPY_ATTR(module_search_path); + COPY_ATTR(warnoptions); + COPY_ATTR(xoptions); +#undef COPY_ATTR + return 0; +} + + + + static PyObject * config_create_path_list(const wchar_t *path, wchar_t delim) { |