[Python-checkins] bpo-36444: Remove _PyMainInterpreterConfig (GH-12571)

Victor Stinner webhook-mailer at python.org
Tue Mar 26 20:36:20 EDT 2019


https://github.com/python/cpython/commit/8b9dbc017a190d13f717e714630d620adb7c7ac2
commit: 8b9dbc017a190d13f717e714630d620adb7c7ac2
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2019-03-27T01:36:16+01:00
summary:

bpo-36444: Remove _PyMainInterpreterConfig (GH-12571)

files:
M Include/cpython/pylifecycle.h
M Include/cpython/pystate.h
M Include/internal/pycore_coreconfig.h
M Include/internal/pycore_pystate.h
M Lib/test/test_embed.py
M Modules/main.c
M Python/coreconfig.c
M Python/pylifecycle.c
M Python/pystate.c
M Python/sysmodule.c

diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h
index 0c5f74e4f2b2..1db1d2167cb1 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 5439d07e6af3..a0953f03261d 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 dad5d3f3ec8d..c5f39bac9f83 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 27c6eea6aa8c..df3730f8014a 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 c44d24ecfdd3..f5e3cef68a54 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 @@ def main_xoptions(self, xoptions_list):
                 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 @@ def check_config(self, testname, expected_config, expected_preconfig):
 
         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 98a886125ca8..05b42cbc6c83 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 2f54e79081fd..944a9e22ca12 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 57b0c3215b7d..ca90e7238b66 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 6fe3dd1ff3fa..a2464b6cf551 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 12ec7d5918ed..1af11c4ab97c 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 @@ _PySys_InitCore(PyObject *sysdict)
         }                                                  \
     } 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;



More information about the Python-checkins mailing list