From 8b9dbc017a190d13f717e714630d620adb7c7ac2 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 27 Mar 2019 01:36:16 +0100 Subject: [PATCH] bpo-36444: Remove _PyMainInterpreterConfig (GH-12571) --- Include/cpython/pylifecycle.h | 11 +- Include/cpython/pystate.h | 23 --- Include/internal/pycore_coreconfig.h | 5 - Include/internal/pycore_pystate.h | 1 - Lib/test/test_embed.py | 29 --- Modules/main.c | 270 +-------------------------- Python/coreconfig.c | 11 -- Python/pylifecycle.c | 43 ++--- Python/pystate.c | 8 - Python/sysmodule.c | 119 ++++++++---- 10 files changed, 103 insertions(+), 417 deletions(-) diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h index 0c5f74e4f2b..1db1d2167cb 100644 --- a/Include/cpython/pylifecycle.h +++ b/Include/cpython/pylifecycle.h @@ -26,17 +26,8 @@ PyAPI_FUNC(_PyInitError) _Py_InitializeCore( PyAPI_FUNC(int) _Py_IsCoreInitialized(void); -PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read( - _PyMainInterpreterConfig *config, - const _PyCoreConfig *core_config); -PyAPI_FUNC(void) _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *); -PyAPI_FUNC(int) _PyMainInterpreterConfig_Copy( - _PyMainInterpreterConfig *config, - const _PyMainInterpreterConfig *config2); - PyAPI_FUNC(_PyInitError) _Py_InitializeMainInterpreter( - PyInterpreterState *interp, - const _PyMainInterpreterConfig *); + PyInterpreterState *interp); /* Initialization and finalization */ diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 5439d07e6af..a0953f03261 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -8,33 +8,10 @@ extern "C" { #include "cpython/coreconfig.h" -/* Placeholders while working on the new configuration API - * - * See PEP 432 for final anticipated contents - */ -typedef struct { - int install_signal_handlers; /* Install signal handlers? -1 means unset */ - PyObject *argv; /* sys.argv list, can be NULL */ - PyObject *executable; /* sys.executable str */ - PyObject *prefix; /* sys.prefix str */ - PyObject *base_prefix; /* sys.base_prefix str, can be NULL */ - PyObject *exec_prefix; /* sys.exec_prefix str */ - PyObject *base_exec_prefix; /* sys.base_exec_prefix str, can be NULL */ - PyObject *warnoptions; /* sys.warnoptions list, can be NULL */ - PyObject *xoptions; /* sys._xoptions dict, can be NULL */ - PyObject *module_search_path; /* sys.path list */ - PyObject *pycache_prefix; /* sys.pycache_prefix str, can be NULL */ -} _PyMainInterpreterConfig; - -#define _PyMainInterpreterConfig_INIT \ - (_PyMainInterpreterConfig){.install_signal_handlers = -1} -/* Note: _PyMainInterpreterConfig_INIT sets other fields to 0/NULL */ - PyAPI_FUNC(int) _PyInterpreterState_RequiresIDRef(PyInterpreterState *); PyAPI_FUNC(void) _PyInterpreterState_RequireIDRef(PyInterpreterState *, int); PyAPI_FUNC(_PyCoreConfig *) _PyInterpreterState_GetCoreConfig(PyInterpreterState *); -PyAPI_FUNC(_PyMainInterpreterConfig *) _PyInterpreterState_GetMainConfig(PyInterpreterState *); PyAPI_FUNC(PyObject *) _PyInterpreterState_GetMainModule(PyInterpreterState *); diff --git a/Include/internal/pycore_coreconfig.h b/Include/internal/pycore_coreconfig.h index dad5d3f3ec8..c5f39bac9f8 100644 --- a/Include/internal/pycore_coreconfig.h +++ b/Include/internal/pycore_coreconfig.h @@ -104,11 +104,6 @@ PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *config, const _PyArgv *args); PyAPI_FUNC(void) _PyCoreConfig_Write(const _PyCoreConfig *config); -/* --- _PyMainInterpreterConfig ----------------------------------- */ - -PyAPI_FUNC(PyObject*) _PyMainInterpreterConfig_AsDict( - const _PyMainInterpreterConfig *config); - #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 27c6eea6aa8..df3730f8014 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -59,7 +59,6 @@ struct _is { int fscodec_initialized; _PyCoreConfig core_config; - _PyMainInterpreterConfig config; #ifdef HAVE_DLOPEN int dlopenflags; #endif diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index c44d24ecfdd..f5e3cef68a5 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -347,22 +347,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 'legacy_windows_stdio': 0, }) - # main config - COPY_MAIN_CONFIG = ( - # Copy core config to main config for expected values - 'argv', - 'base_exec_prefix', - 'base_prefix', - 'exec_prefix', - 'executable', - 'install_signal_handlers', - 'prefix', - 'pycache_prefix', - 'warnoptions', - # xoptions is created from core_config in check_main_config(). - # 'module_search_paths' is copied to 'module_search_path'. - ) - # global config DEFAULT_GLOBAL_CONFIG = { 'Py_HasFileSystemDefaultEncoding': 0, @@ -410,18 +394,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): xoptions[opt] = True return xoptions - def check_main_config(self, config): - core_config = config['core_config'] - main_config = config['main_config'] - - # main config - expected = {} - for key in self.COPY_MAIN_CONFIG: - expected[key] = core_config[key] - expected['module_search_path'] = core_config['module_search_paths'] - expected['xoptions'] = self.main_xoptions(core_config['xoptions']) - self.assertEqual(main_config, expected) - def get_expected_config(self, expected, env): expected = dict(self.DEFAULT_CORE_CONFIG, **expected) @@ -523,7 +495,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): self.check_core_config(config, expected_config) self.check_pre_config(config, expected_preconfig) - self.check_main_config(config) self.check_global_config(config) def test_init_default_config(self): diff --git a/Modules/main.c b/Modules/main.c index 98a886125ca..05b42cbc6c8 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -31,255 +31,6 @@ extern "C" { #endif -/* --- PyMainInterpreter ------------------------------------------ */ - -void -_PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config) -{ - Py_CLEAR(config->argv); - Py_CLEAR(config->executable); - Py_CLEAR(config->prefix); - Py_CLEAR(config->base_prefix); - Py_CLEAR(config->exec_prefix); - Py_CLEAR(config->base_exec_prefix); - Py_CLEAR(config->warnoptions); - Py_CLEAR(config->xoptions); - Py_CLEAR(config->module_search_path); - Py_CLEAR(config->pycache_prefix); -} - - -static int -mainconfig_add_xoption(PyObject *opts, const wchar_t *s) -{ - PyObject *name, *value; - - const wchar_t *name_end = wcschr(s, L'='); - if (!name_end) { - name = PyUnicode_FromWideChar(s, -1); - value = Py_True; - Py_INCREF(value); - } - else { - name = PyUnicode_FromWideChar(s, name_end - s); - value = PyUnicode_FromWideChar(name_end + 1, -1); - } - if (name == NULL || value == NULL) { - goto error; - } - if (PyDict_SetItem(opts, name, value) < 0) { - goto error; - } - Py_DECREF(name); - Py_DECREF(value); - return 0; - -error: - Py_XDECREF(name); - Py_XDECREF(value); - return -1; -} - - -static PyObject* -mainconfig_create_xoptions_dict(const _PyCoreConfig *config) -{ - Py_ssize_t nxoption = config->xoptions.length; - wchar_t * const * xoptions = config->xoptions.items; - PyObject *dict = PyDict_New(); - if (dict == NULL) { - return NULL; - } - - for (Py_ssize_t i=0; i < nxoption; i++) { - const wchar_t *option = xoptions[i]; - if (mainconfig_add_xoption(dict, option) < 0) { - Py_DECREF(dict); - return NULL; - } - } - - return dict; -} - - -static PyObject* -mainconfig_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) config->ATTR = config2->ATTR -#define COPY_OBJ_ATTR(ATTR) \ - do { \ - if (config2->ATTR != NULL) { \ - config->ATTR = mainconfig_copy_attr(config2->ATTR); \ - if (config->ATTR == NULL) { \ - return -1; \ - } \ - } \ - } while (0) - - COPY_ATTR(install_signal_handlers); - COPY_OBJ_ATTR(argv); - COPY_OBJ_ATTR(executable); - COPY_OBJ_ATTR(prefix); - COPY_OBJ_ATTR(base_prefix); - COPY_OBJ_ATTR(exec_prefix); - COPY_OBJ_ATTR(base_exec_prefix); - COPY_OBJ_ATTR(warnoptions); - COPY_OBJ_ATTR(xoptions); - COPY_OBJ_ATTR(module_search_path); - COPY_OBJ_ATTR(pycache_prefix); -#undef COPY_ATTR -#undef COPY_OBJ_ATTR - return 0; -} - - -PyObject* -_PyMainInterpreterConfig_AsDict(const _PyMainInterpreterConfig *config) -{ - PyObject *dict, *obj; - int res; - - dict = PyDict_New(); - if (dict == NULL) { - return NULL; - } - -#define SET_ITEM_INT(ATTR) \ - do { \ - obj = PyLong_FromLong(config->ATTR); \ - if (obj == NULL) { \ - goto fail; \ - } \ - res = PyDict_SetItemString(dict, #ATTR, obj); \ - Py_DECREF(obj); \ - if (res < 0) { \ - goto fail; \ - } \ - } while (0) - -#define SET_ITEM_OBJ(ATTR) \ - do { \ - obj = config->ATTR; \ - if (obj == NULL) { \ - obj = Py_None; \ - } \ - res = PyDict_SetItemString(dict, #ATTR, obj); \ - if (res < 0) { \ - goto fail; \ - } \ - } while (0) - - SET_ITEM_INT(install_signal_handlers); - SET_ITEM_OBJ(argv); - SET_ITEM_OBJ(executable); - SET_ITEM_OBJ(prefix); - SET_ITEM_OBJ(base_prefix); - SET_ITEM_OBJ(exec_prefix); - SET_ITEM_OBJ(base_exec_prefix); - SET_ITEM_OBJ(warnoptions); - SET_ITEM_OBJ(xoptions); - SET_ITEM_OBJ(module_search_path); - SET_ITEM_OBJ(pycache_prefix); - - return dict; - -fail: - Py_DECREF(dict); - return NULL; - -#undef SET_ITEM_OBJ -} - - -_PyInitError -_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *main_config, - const _PyCoreConfig *config) -{ - if (main_config->install_signal_handlers < 0) { - main_config->install_signal_handlers = config->install_signal_handlers; - } - - if (main_config->xoptions == NULL) { - main_config->xoptions = mainconfig_create_xoptions_dict(config); - if (main_config->xoptions == NULL) { - return _Py_INIT_NO_MEMORY(); - } - } - -#define COPY_WSTR(ATTR) \ - do { \ - if (main_config->ATTR == NULL && config->ATTR != NULL) { \ - main_config->ATTR = PyUnicode_FromWideChar(config->ATTR, -1); \ - if (main_config->ATTR == NULL) { \ - return _Py_INIT_NO_MEMORY(); \ - } \ - } \ - } while (0) -#define COPY_WSTRLIST(ATTR, LIST) \ - do { \ - if (ATTR == NULL) { \ - ATTR = _PyWstrList_AsList(LIST); \ - if (ATTR == NULL) { \ - return _Py_INIT_NO_MEMORY(); \ - } \ - } \ - } while (0) - - COPY_WSTRLIST(main_config->warnoptions, &config->warnoptions); - COPY_WSTRLIST(main_config->argv, &config->argv); - - if (config->_install_importlib) { - COPY_WSTR(executable); - COPY_WSTR(prefix); - COPY_WSTR(base_prefix); - COPY_WSTR(exec_prefix); - COPY_WSTR(base_exec_prefix); - - COPY_WSTRLIST(main_config->module_search_path, - &config->module_search_paths); - - if (config->pycache_prefix != NULL) { - COPY_WSTR(pycache_prefix); - } else { - main_config->pycache_prefix = NULL; - } - - } - - return _Py_INIT_OK(); -#undef COPY_WSTR -#undef COPY_WSTRLIST -} - - /* --- pymain_init() ---------------------------------------------- */ static _PyInitError @@ -315,25 +66,6 @@ pymain_init_coreconfig(_PyCoreConfig *config, const _PyArgv *args, } -static _PyInitError -pymain_init_python_main(PyInterpreterState *interp) -{ - _PyInitError err; - - _PyMainInterpreterConfig main_config = _PyMainInterpreterConfig_INIT; - err = _PyMainInterpreterConfig_Read(&main_config, &interp->core_config); - if (!_Py_INIT_FAILED(err)) { - err = _Py_InitializeMainInterpreter(interp, &main_config); - } - _PyMainInterpreterConfig_Clear(&main_config); - - if (_Py_INIT_FAILED(err)) { - return err; - } - return _Py_INIT_OK(); -} - - static _PyInitError pymain_init(const _PyArgv *args, PyInterpreterState **interp_p) { @@ -365,7 +97,7 @@ pymain_init(const _PyArgv *args, PyInterpreterState **interp_p) return err; } - err = pymain_init_python_main(*interp_p); + err = _Py_InitializeMainInterpreter(*interp_p); if (_Py_INIT_FAILED(err)) { return err; } diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 2f54e79081f..944a9e22ca1 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -2208,17 +2208,6 @@ _Py_GetConfigsAsDict(void) } Py_CLEAR(dict); - /* main config */ - const _PyMainInterpreterConfig *main_config = _PyInterpreterState_GetMainConfig(interp); - dict = _PyMainInterpreterConfig_AsDict(main_config); - if (dict == NULL) { - goto error; - } - if (PyDict_SetItemString(config, "main_config", dict) < 0) { - goto error; - } - Py_CLEAR(dict); - return config; error: diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 57b0c3215b7..ca90e7238b6 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -853,14 +853,19 @@ _Py_InitializeCore(const _PyCoreConfig *src_config, configuration. Example of bpo-34008: Py_Main() called after Py_Initialize(). */ static _PyInitError -_Py_ReconfigureMainInterpreter(PyInterpreterState *interp, - const _PyMainInterpreterConfig *config) +_Py_ReconfigureMainInterpreter(PyInterpreterState *interp) { - if (config->argv != NULL) { - int res = PyDict_SetItemString(interp->sysdict, "argv", config->argv); - if (res < 0) { - return _Py_INIT_ERR("fail to set sys.argv"); - } + _PyCoreConfig *core_config = &interp->core_config; + + PyObject *argv = _PyWstrList_AsList(&core_config->argv); + if (argv == NULL) { + return _Py_INIT_NO_MEMORY(); \ + } + + int res = PyDict_SetItemString(interp->sysdict, "argv", argv); + Py_DECREF(argv); + if (res < 0) { + return _Py_INIT_ERR("fail to set sys.argv"); } return _Py_INIT_OK(); } @@ -877,22 +882,17 @@ _Py_ReconfigureMainInterpreter(PyInterpreterState *interp, * non-zero return code. */ _PyInitError -_Py_InitializeMainInterpreter(PyInterpreterState *interp, - const _PyMainInterpreterConfig *config) +_Py_InitializeMainInterpreter(PyInterpreterState *interp) { if (!_PyRuntime.core_initialized) { return _Py_INIT_ERR("runtime core not initialized"); } /* Configure the main interpreter */ - if (_PyMainInterpreterConfig_Copy(&interp->config, config) < 0) { - return _Py_INIT_ERR("failed to copy main interpreter config"); - } - config = &interp->config; _PyCoreConfig *core_config = &interp->core_config; if (_PyRuntime.initialized) { - return _Py_ReconfigureMainInterpreter(interp, config); + return _Py_ReconfigureMainInterpreter(interp); } if (!core_config->_install_importlib) { @@ -929,7 +929,7 @@ _Py_InitializeMainInterpreter(PyInterpreterState *interp, return err; } - if (interp->config.install_signal_handlers) { + if (core_config->install_signal_handlers) { err = initsigs(); /* Signal handling stuff, including initintr() */ if (_Py_INIT_FAILED(err)) { return err; @@ -991,12 +991,7 @@ _Py_InitializeFromConfig(const _PyCoreConfig *config) } config = &interp->core_config; - _PyMainInterpreterConfig main_config = _PyMainInterpreterConfig_INIT; - err = _PyMainInterpreterConfig_Read(&main_config, config); - if (!_Py_INIT_FAILED(err)) { - err = _Py_InitializeMainInterpreter(interp, &main_config); - } - _PyMainInterpreterConfig_Clear(&main_config); + err = _Py_InitializeMainInterpreter(interp); if (_Py_INIT_FAILED(err)) { return err; } @@ -1364,24 +1359,18 @@ new_interpreter(PyThreadState **tstate_p) /* Copy the current interpreter config into the new interpreter */ _PyCoreConfig *core_config; - _PyMainInterpreterConfig *config; if (save_tstate != NULL) { core_config = &save_tstate->interp->core_config; - config = &save_tstate->interp->config; } else { /* No current thread state, copy from the main interpreter */ PyInterpreterState *main_interp = PyInterpreterState_Main(); core_config = &main_interp->core_config; - config = &main_interp->config; } if (_PyCoreConfig_Copy(&interp->core_config, core_config) < 0) { return _Py_INIT_ERR("failed to copy core config"); } core_config = &interp->core_config; - if (_PyMainInterpreterConfig_Copy(&interp->config, config) < 0) { - return _Py_INIT_ERR("failed to copy main interpreter config"); - } err = _PyExc_Init(); if (_Py_INIT_FAILED(err)) { diff --git a/Python/pystate.c b/Python/pystate.c index 6fe3dd1ff3f..a2464b6cf55 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -174,7 +174,6 @@ PyInterpreterState_New(void) interp->id_refcount = -1; interp->check_interval = 100; interp->core_config = _PyCoreConfig_INIT; - interp->config = _PyMainInterpreterConfig_INIT; interp->eval_frame = _PyEval_EvalFrameDefault; #ifdef HAVE_DLOPEN #if HAVE_DECL_RTLD_NOW @@ -221,7 +220,6 @@ PyInterpreterState_Clear(PyInterpreterState *interp) PyThreadState_Clear(p); HEAD_UNLOCK(); _PyCoreConfig_Clear(&interp->core_config); - _PyMainInterpreterConfig_Clear(&interp->config); Py_CLEAR(interp->codec_search_path); Py_CLEAR(interp->codec_search_cache); Py_CLEAR(interp->codec_error_registry); @@ -455,12 +453,6 @@ _PyInterpreterState_GetCoreConfig(PyInterpreterState *interp) return &interp->core_config; } -_PyMainInterpreterConfig * -_PyInterpreterState_GetMainConfig(PyInterpreterState *interp) -{ - return &interp->config; -} - PyObject * _PyInterpreterState_GetMainModule(PyInterpreterState *interp) { diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 12ec7d5918e..1af11c4ab97 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -17,6 +17,7 @@ Data members: #include "Python.h" #include "code.h" #include "frameobject.h" +#include "pycore_coreconfig.h" #include "pycore_pylifecycle.h" #include "pycore_pymem.h" #include "pycore_pathconfig.h" @@ -2530,26 +2531,71 @@ err_occurred: } \ } while (0) + +static int +sys_add_xoption(PyObject *opts, const wchar_t *s) +{ + PyObject *name, *value; + + const wchar_t *name_end = wcschr(s, L'='); + if (!name_end) { + name = PyUnicode_FromWideChar(s, -1); + value = Py_True; + Py_INCREF(value); + } + else { + name = PyUnicode_FromWideChar(s, name_end - s); + value = PyUnicode_FromWideChar(name_end + 1, -1); + } + if (name == NULL || value == NULL) { + goto error; + } + if (PyDict_SetItem(opts, name, value) < 0) { + goto error; + } + Py_DECREF(name); + Py_DECREF(value); + return 0; + +error: + Py_XDECREF(name); + Py_XDECREF(value); + return -1; +} + + +static PyObject* +sys_create_xoptions_dict(const _PyCoreConfig *config) +{ + Py_ssize_t nxoption = config->xoptions.length; + wchar_t * const * xoptions = config->xoptions.items; + PyObject *dict = PyDict_New(); + if (dict == NULL) { + return NULL; + } + + for (Py_ssize_t i=0; i < nxoption; i++) { + const wchar_t *option = xoptions[i]; + if (sys_add_xoption(dict, option) < 0) { + Py_DECREF(dict); + return NULL; + } + } + + return dict; +} + + int _PySys_InitMain(PyInterpreterState *interp) { PyObject *sysdict = interp->sysdict; - const _PyCoreConfig *core_config = &interp->core_config; - const _PyMainInterpreterConfig *config = &interp->config; + const _PyCoreConfig *config = &interp->core_config; int res; - /* _PyMainInterpreterConfig_Read() must set all these variables */ - assert(config->module_search_path != NULL); - assert(config->executable != NULL); - assert(config->prefix != NULL); - assert(config->base_prefix != NULL); - assert(config->exec_prefix != NULL); - assert(config->base_exec_prefix != NULL); - -#define COPY_LIST(KEY, ATTR) \ +#define COPY_LIST(KEY, VALUE) \ do { \ - assert(PyList_Check(ATTR)); \ - PyObject *list = PyList_GetSlice(ATTR, 0, PyList_GET_SIZE(ATTR)); \ + PyObject *list = _PyWstrList_AsList(&(VALUE)); \ if (list == NULL) { \ return -1; \ } \ @@ -2557,36 +2603,41 @@ _PySys_InitMain(PyInterpreterState *interp) Py_DECREF(list); \ } while (0) - COPY_LIST("path", config->module_search_path); +#define SET_SYS_FROM_WSTR(KEY, VALUE) \ + do { \ + PyObject *str = PyUnicode_FromWideChar(VALUE, -1); \ + if (str == NULL) { \ + return -1; \ + } \ + SET_SYS_FROM_STRING_BORROW(KEY, str); \ + Py_DECREF(str); \ + } while (0) - SET_SYS_FROM_STRING_BORROW("executable", config->executable); - SET_SYS_FROM_STRING_BORROW("prefix", config->prefix); - SET_SYS_FROM_STRING_BORROW("base_prefix", config->base_prefix); - SET_SYS_FROM_STRING_BORROW("exec_prefix", config->exec_prefix); - SET_SYS_FROM_STRING_BORROW("base_exec_prefix", config->base_exec_prefix); + COPY_LIST("path", config->module_search_paths); + + SET_SYS_FROM_WSTR("executable", config->executable); + SET_SYS_FROM_WSTR("prefix", config->prefix); + SET_SYS_FROM_WSTR("base_prefix", config->base_prefix); + SET_SYS_FROM_WSTR("exec_prefix", config->exec_prefix); + SET_SYS_FROM_WSTR("base_exec_prefix", config->base_exec_prefix); if (config->pycache_prefix != NULL) { - SET_SYS_FROM_STRING_BORROW("pycache_prefix", config->pycache_prefix); + SET_SYS_FROM_WSTR("pycache_prefix", config->pycache_prefix); } else { PyDict_SetItemString(sysdict, "pycache_prefix", Py_None); } - if (config->argv != NULL) { - SET_SYS_FROM_STRING_BORROW("argv", config->argv); - } - if (config->warnoptions != NULL) { - COPY_LIST("warnoptions", config->warnoptions); - } - if (config->xoptions != NULL) { - PyObject *dict = PyDict_Copy(config->xoptions); - if (dict == NULL) { - return -1; - } - SET_SYS_FROM_STRING_BORROW("_xoptions", dict); - Py_DECREF(dict); + COPY_LIST("argv", config->argv); + COPY_LIST("warnoptions", config->warnoptions); + + PyObject *xoptions = sys_create_xoptions_dict(config); + if (xoptions == NULL) { + return -1; } + SET_SYS_FROM_STRING_BORROW("_xoptions", xoptions); #undef COPY_LIST +#undef SET_SYS_FROM_WSTR /* Set flags to their final values */ SET_SYS_FROM_STRING_INT_RESULT("flags", make_flags()); @@ -2602,7 +2653,7 @@ _PySys_InitMain(PyInterpreterState *interp) } SET_SYS_FROM_STRING_INT_RESULT("dont_write_bytecode", - PyBool_FromLong(!core_config->write_bytecode)); + PyBool_FromLong(!config->write_bytecode)); if (get_warnoptions() == NULL) return -1;