[Python-checkins] [3.7] bpo-35233: Rewrite test_embed.InitConfigTests (GH-10524) (GH-10529)
Victor Stinner
webhook-mailer at python.org
Tue Nov 13 20:01:57 EST 2018
https://github.com/python/cpython/commit/35c28d562ec7249f2a6aef8e326eadac130a1656
commit: 35c28d562ec7249f2a6aef8e326eadac130a1656
branch: 3.7
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2018-11-14T02:01:52+01:00
summary:
[3.7] bpo-35233: Rewrite test_embed.InitConfigTests (GH-10524) (GH-10529)
* Add C functions:
* _Py_GetGlobalVariablesAsDict()
* _PyCoreConfig_AsDict()
* _PyMainInterpreterConfig_AsDict()
* Add new _testcapi methods:
* get_global_config()
* get_core_config()
* get_main_config()
* test.pythoninfo: get global, core and main configuration
* _testembed now serializes global, core and main configurations
using JSON to reuse _Py_GetGlobalVariablesAsDict(),
_PyCoreConfig_AsDict() and _PyMainInterpreterConfig_AsDict(),
rather than duplicating code.
* test_embed.InitConfigTests now test much more configuration
variables
files:
M Include/pylifecycle.h
M Lib/test/pythoninfo.py
M Lib/test/test_embed.py
M Modules/_testcapimodule.c
M Modules/main.c
M Programs/_testembed.c
diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h
index 119296194934..41f7d14af9e4 100644
--- a/Include/pylifecycle.h
+++ b/Include/pylifecycle.h
@@ -61,11 +61,14 @@ PyAPI_FUNC(_PyInitError) _Py_InitializeFromConfig(
PyAPI_FUNC(void) _Py_Initialize_ReadEnvVarsNoAlloc(void);
#endif
+PyAPI_FUNC(PyObject *) _Py_GetGlobalVariablesAsDict(void);
+
PyAPI_FUNC(_PyInitError) _PyCoreConfig_Read(_PyCoreConfig *);
PyAPI_FUNC(void) _PyCoreConfig_Clear(_PyCoreConfig *);
PyAPI_FUNC(int) _PyCoreConfig_Copy(
_PyCoreConfig *config,
const _PyCoreConfig *config2);
+PyAPI_FUNC(PyObject *) _PyCoreConfig_AsDict(const _PyCoreConfig *config);
PyAPI_FUNC(void) _PyCoreConfig_SetGlobalConfig(
const _PyCoreConfig *config);
@@ -77,6 +80,8 @@ PyAPI_FUNC(void) _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *);
PyAPI_FUNC(int) _PyMainInterpreterConfig_Copy(
_PyMainInterpreterConfig *config,
const _PyMainInterpreterConfig *config2);
+PyAPI_FUNC(PyObject*) _PyMainInterpreterConfig_AsDict(
+ const _PyMainInterpreterConfig *config);
PyAPI_FUNC(_PyInitError) _Py_InitializeMainInterpreter(
PyInterpreterState *interp,
diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py
index 4a563e9baae2..9257fdf332a6 100644
--- a/Lib/test/pythoninfo.py
+++ b/Lib/test/pythoninfo.py
@@ -142,7 +142,7 @@ def collect_platform(info_add):
info_add('platform.python_implementation',
platform.python_implementation())
info_add('platform.platform',
- platform.platform(aliased=True, terse=True))
+ platform.platform(aliased=True))
def collect_locale(info_add):
@@ -525,6 +525,33 @@ def collect_cc(info_add):
info_add('CC.version', text)
+def collect_gdbm(info_add):
+ try:
+ from _gdbm import _GDBM_VERSION
+ except ImportError:
+ return
+
+ info_add('gdbm.GDBM_VERSION', '.'.join(map(str, _GDBM_VERSION)))
+
+
+def collect_get_config(info_add):
+ # Dump global configuration variables, _PyCoreConfig
+ # and _PyMainInterpreterConfig
+ try:
+ from _testcapi import get_global_config, get_core_config, get_main_config
+ except ImportError:
+ return
+
+ for prefix, get_config_func in (
+ ('global_config', get_global_config),
+ ('core_config', get_core_config),
+ ('main_config', get_main_config),
+ ):
+ config = get_config_func()
+ for key in sorted(config):
+ info_add('%s[%s]' % (prefix, key), repr(config[key]))
+
+
def collect_info(info):
error = False
info_add = info.add
@@ -552,6 +579,8 @@ def collect_info(info):
collect_testcapi,
collect_resource,
collect_cc,
+ collect_gdbm,
+ collect_get_config,
# Collecting from tests should be last as they have side effects.
collect_test_socket,
diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index 29274580339f..62a20abf0377 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -3,6 +3,7 @@
import unittest
from collections import namedtuple
+import json
import os
import re
import subprocess
@@ -251,12 +252,52 @@ def test_initialize_pymain(self):
class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
maxDiff = 4096
- DEFAULT_CONFIG = {
+ UTF8_MODE_ERRORS = ('surrogatepass' if sys.platform == 'win32'
+ else 'surrogateescape')
+ # FIXME: untested core configuration variables
+ UNTESTED_CORE_CONFIG = (
+ 'base_exec_prefix',
+ 'base_prefix',
+ 'exec_prefix',
+ 'executable',
+ 'home',
+ 'module_search_path_env',
+ 'module_search_paths',
+ 'prefix',
+ )
+ # FIXME: untested main configuration variables
+ UNTESTED_MAIN_CONFIG = (
+ 'install_signal_handlers',
+ 'module_search_path',
+ )
+ DEFAULT_GLOBAL_CONFIG = {
+ 'Py_BytesWarningFlag': 0,
+ 'Py_DebugFlag': 0,
+ 'Py_DontWriteBytecodeFlag': 0,
+ 'Py_FrozenFlag': 0,
+ 'Py_HasFileSystemDefaultEncoding': 0,
+ 'Py_HashRandomizationFlag': 1,
+ 'Py_InspectFlag': 0,
+ 'Py_InteractiveFlag': 0,
+ 'Py_IsolatedFlag': 0,
+ 'Py_NoSiteFlag': 0,
+ 'Py_NoUserSiteDirectory': 0,
+ 'Py_OptimizeFlag': 0,
+ 'Py_QuietFlag': 0,
+ 'Py_UnbufferedStdioFlag': 0,
+ 'Py_VerboseFlag': 0,
+ }
+ if os.name == 'nt':
+ DEFAULT_GLOBAL_CONFIG['Py_HasFileSystemDefaultEncoding'] = 1
+ DEFAULT_GLOBAL_CONFIG['Py_LegacyWindowsFSEncodingFlag'] = 0
+ DEFAULT_GLOBAL_CONFIG['Py_LegacyWindowsStdioFlag'] = 0
+
+ DEFAULT_CORE_CONFIG = {
'install_signal_handlers': 1,
- 'Py_IgnoreEnvironmentFlag': 0,
+ 'ignore_environment': 0,
'use_hash_seed': 0,
'hash_seed': 0,
- 'allocator': '(null)',
+ 'allocator': None,
'dev_mode': 0,
'faulthandler': 0,
'tracemalloc': 0,
@@ -265,34 +306,42 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'show_alloc_count': 0,
'dump_refs': 0,
'malloc_stats': 0,
- 'utf8_mode': 0,
+ 'utf8_mode': 0,
'coerce_c_locale': 0,
'coerce_c_locale_warn': 0,
'program_name': './_testembed',
- 'argc': 0,
- 'argv': '[]',
- 'program': '(null)',
+ 'argv': [],
+ 'program': None,
- 'Py_IsolatedFlag': 0,
- 'Py_NoSiteFlag': 0,
- 'Py_BytesWarningFlag': 0,
- 'Py_InspectFlag': 0,
- 'Py_InteractiveFlag': 0,
- 'Py_OptimizeFlag': 0,
- 'Py_DebugFlag': 0,
- 'Py_DontWriteBytecodeFlag': 0,
- 'Py_VerboseFlag': 0,
- 'Py_QuietFlag': 0,
- 'Py_NoUserSiteDirectory': 0,
- 'Py_UnbufferedStdioFlag': 0,
+ 'xoptions': [],
+ 'warnoptions': [],
'_disable_importlib': 0,
- 'Py_FrozenFlag': 0,
}
- def check_config(self, testname, expected):
+ def get_filesystem_encoding(self, isolated, env):
+ code = ('import codecs, locale, sys; '
+ 'print(sys.getfilesystemencoding(), '
+ 'sys.getfilesystemencodeerrors())')
+ args = (sys.executable, '-c', code)
+ env = dict(env)
+ if not isolated:
+ env['PYTHONCOERCECLOCALE'] = '0'
+ env['PYTHONUTF8'] = '0'
+ proc = subprocess.run(args, text=True, env=env,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ if proc.returncode:
+ raise Exception(f"failed to get the locale encoding: "
+ f"stdout={proc.stdout!r} stderr={proc.stderr!r}")
+ out = proc.stdout.rstrip()
+ return out.split()
+
+ def check_config(self, testname, expected, expected_global):
+ expected = dict(self.DEFAULT_CORE_CONFIG, **expected)
+
env = dict(os.environ)
for key in list(env):
if key.startswith('PYTHON'):
@@ -301,42 +350,78 @@ def check_config(self, testname, expected):
# on the current locale
env['PYTHONCOERCECLOCALE'] = '0'
env['PYTHONUTF8'] = '0'
+
out, err = self.run_embedded_interpreter(testname, env=env)
# Ignore err
- expected = dict(self.DEFAULT_CONFIG, **expected)
- for key, value in expected.items():
- expected[key] = str(value)
+ config = json.loads(out)
+ core_config = config['core_config']
+ executable = core_config['executable']
+ main_config = config['main_config']
+
+ for key in self.UNTESTED_MAIN_CONFIG:
+ del main_config[key]
+
+ expected_main = {
+ 'argv': [],
+ 'prefix': sys.prefix,
+ 'executable': core_config['executable'],
+ 'base_prefix': sys.base_prefix,
+ 'base_exec_prefix': sys.base_exec_prefix,
+ 'warnoptions': core_config['warnoptions'],
+ 'xoptions': {},
+ 'exec_prefix': core_config['exec_prefix'],
+ }
+ self.assertEqual(main_config, expected_main)
- config = {}
- for line in out.splitlines():
- key, value = line.split(' = ', 1)
- config[key] = value
- self.assertEqual(config, expected)
+ expected_global = dict(self.DEFAULT_GLOBAL_CONFIG, **expected_global)
+
+ if 'Py_FileSystemDefaultEncoding' not in expected_global:
+ isolated = expected_global['Py_IsolatedFlag']
+ fs_encoding, fs_errors = self.get_filesystem_encoding(isolated, env)
+ expected_global['Py_FileSystemDefaultEncodeErrors'] = fs_errors
+ expected_global['Py_FileSystemDefaultEncoding'] = fs_encoding
+
+ for global_key, core_key in (
+ ('Py_UTF8Mode', 'utf8_mode'),
+ ('Py_IgnoreEnvironmentFlag', 'ignore_environment'),
+ ):
+ expected_global[global_key] = core_config[core_key]
+
+ self.assertEqual(config['global_config'], expected_global)
+
+ for key in self.UNTESTED_CORE_CONFIG:
+ core_config.pop(key, None)
+ self.assertEqual(core_config, expected)
def test_init_default_config(self):
- self.check_config("init_default_config", {})
+ self.check_config("init_default_config", {}, {})
def test_init_global_config(self):
- config = {
+ core_config = {
'program_name': './globalvar',
- 'Py_NoSiteFlag': 1,
+ 'utf8_mode': 1,
+ }
+ global_config = {
'Py_BytesWarningFlag': 1,
+ 'Py_DontWriteBytecodeFlag': 1,
+ 'Py_HasFileSystemDefaultEncoding': 1,
+ 'Py_FileSystemDefaultEncodeErrors': self.UTF8_MODE_ERRORS,
+ 'Py_FileSystemDefaultEncoding': 'utf-8',
'Py_InspectFlag': 1,
'Py_InteractiveFlag': 1,
+ 'Py_NoSiteFlag': 1,
+ 'Py_NoUserSiteDirectory': 1,
'Py_OptimizeFlag': 2,
- 'Py_DontWriteBytecodeFlag': 1,
- 'Py_VerboseFlag': 1,
'Py_QuietFlag': 1,
- 'Py_UnbufferedStdioFlag': 1,
- 'utf8_mode': 1,
- 'Py_NoUserSiteDirectory': 1,
+ 'Py_VerboseFlag': 1,
'Py_FrozenFlag': 1,
+ 'Py_UnbufferedStdioFlag': 1,
}
- self.check_config("init_global_config", config)
+ self.check_config("init_global_config", core_config, global_config)
def test_init_from_config(self):
- config = {
+ core_config = {
'install_signal_handlers': 0,
'use_hash_seed': 1,
'hash_seed': 123,
@@ -354,10 +439,14 @@ def test_init_from_config(self):
'faulthandler': 1,
}
- self.check_config("init_from_config", config)
+ global_config = {
+ 'Py_HasFileSystemDefaultEncoding': 1,
+ 'Py_NoUserSiteDirectory': 0,
+ }
+ self.check_config("init_from_config", core_config, global_config)
def test_init_env(self):
- config = {
+ core_config = {
'use_hash_seed': 1,
'hash_seed': 42,
'allocator': 'malloc_debug',
@@ -365,32 +454,39 @@ def test_init_env(self):
'import_time': 1,
'malloc_stats': 1,
'utf8_mode': 1,
+ 'faulthandler': 1,
+ 'dev_mode': 1,
+ }
+ global_config = {
+ 'Py_DontWriteBytecodeFlag': 1,
+ 'Py_HasFileSystemDefaultEncoding': 1,
'Py_InspectFlag': 1,
+ 'Py_NoUserSiteDirectory': 1,
'Py_OptimizeFlag': 2,
- 'Py_DontWriteBytecodeFlag': 1,
- 'Py_VerboseFlag': 1,
'Py_UnbufferedStdioFlag': 1,
- 'Py_NoUserSiteDirectory': 1,
- 'faulthandler': 1,
- 'dev_mode': 1,
+ 'Py_VerboseFlag': 1,
+ 'Py_FileSystemDefaultEncoding': 'utf-8',
+ 'Py_FileSystemDefaultEncodeErrors': self.UTF8_MODE_ERRORS,
}
- self.check_config("init_env", config)
+ self.check_config("init_env", core_config, global_config)
def test_init_dev_mode(self):
- config = {
+ core_config = {
'dev_mode': 1,
'faulthandler': 1,
'allocator': 'debug',
}
- self.check_config("init_dev_mode", config)
+ self.check_config("init_dev_mode", core_config, {})
def test_init_isolated(self):
- config = {
+ core_config = {
+ 'ignore_environment': 1,
+ }
+ global_config = {
'Py_IsolatedFlag': 1,
- 'Py_IgnoreEnvironmentFlag': 1,
'Py_NoUserSiteDirectory': 1,
}
- self.check_config("init_isolated", config)
+ self.check_config("init_isolated", core_config, global_config)
if __name__ == "__main__":
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 174b767f2b90..eafe3477e447 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -4551,6 +4551,31 @@ new_hamt(PyObject *self, PyObject *args)
}
+static PyObject *
+get_global_config(PyObject *self, PyObject *Py_UNUSED(args))
+{
+ return _Py_GetGlobalVariablesAsDict();
+}
+
+
+static PyObject *
+get_core_config(PyObject *self, PyObject *Py_UNUSED(args))
+{
+ PyInterpreterState *interp = PyThreadState_GET()->interp;
+ const _PyCoreConfig *config = &interp->core_config;
+ return _PyCoreConfig_AsDict(config);
+}
+
+
+static PyObject *
+get_main_config(PyObject *self, PyObject *Py_UNUSED(args))
+{
+ PyInterpreterState *interp = PyThreadState_GET()->interp;
+ const _PyMainInterpreterConfig *config = &interp->config;
+ return _PyMainInterpreterConfig_AsDict(config);
+}
+
+
static PyMethodDef TestMethods[] = {
{"raise_exception", raise_exception, METH_VARARGS},
{"raise_memoryerror", (PyCFunction)raise_memoryerror, METH_NOARGS},
@@ -4777,6 +4802,9 @@ static PyMethodDef TestMethods[] = {
{"get_mapping_items", get_mapping_items, METH_O},
{"test_pythread_tss_key_state", test_pythread_tss_key_state, METH_VARARGS},
{"hamt", new_hamt, METH_NOARGS},
+ {"get_global_config", get_global_config, METH_NOARGS},
+ {"get_core_config", get_core_config, METH_NOARGS},
+ {"get_main_config", get_main_config, METH_NOARGS},
{NULL, NULL} /* sentinel */
};
diff --git a/Modules/main.c b/Modules/main.c
index 7771d2750097..ab7ac86bad91 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -1297,7 +1297,7 @@ pymain_init_core_argv(_PyMain *pymain, _PyCoreConfig *config,
static PyObject*
-wstrlist_as_pylist(int len, wchar_t **list)
+_Py_wstrlist_as_pylist(int len, wchar_t **list)
{
assert(list != NULL || len < 1);
@@ -1361,6 +1361,77 @@ pymain_update_sys_path(_PyMain *pymain, PyObject *path0)
}
+PyObject *
+_Py_GetGlobalVariablesAsDict(void)
+{
+ PyObject *dict, *obj;
+
+ dict = PyDict_New();
+ if (dict == NULL) {
+ return NULL;
+ }
+
+#define SET_ITEM(KEY, EXPR) \
+ do { \
+ obj = (EXPR); \
+ if (obj == NULL) { \
+ return NULL; \
+ } \
+ int res = PyDict_SetItemString(dict, (KEY), obj); \
+ Py_DECREF(obj); \
+ if (res < 0) { \
+ goto fail; \
+ } \
+ } while (0)
+#define SET_ITEM_INT(VAR) \
+ SET_ITEM(#VAR, PyLong_FromLong(VAR))
+#define FROM_STRING(STR) \
+ ((STR != NULL) ? \
+ PyUnicode_FromString(STR) \
+ : (Py_INCREF(Py_None), Py_None))
+#define SET_ITEM_STR(VAR) \
+ SET_ITEM(#VAR, FROM_STRING(VAR))
+
+ SET_ITEM_STR(Py_FileSystemDefaultEncoding);
+ SET_ITEM_INT(Py_HasFileSystemDefaultEncoding);
+ SET_ITEM_STR(Py_FileSystemDefaultEncodeErrors);
+
+ SET_ITEM_INT(Py_UTF8Mode);
+ SET_ITEM_INT(Py_DebugFlag);
+ SET_ITEM_INT(Py_VerboseFlag);
+ SET_ITEM_INT(Py_QuietFlag);
+ SET_ITEM_INT(Py_InteractiveFlag);
+ SET_ITEM_INT(Py_InspectFlag);
+
+ SET_ITEM_INT(Py_OptimizeFlag);
+ SET_ITEM_INT(Py_NoSiteFlag);
+ SET_ITEM_INT(Py_BytesWarningFlag);
+ SET_ITEM_INT(Py_FrozenFlag);
+ SET_ITEM_INT(Py_IgnoreEnvironmentFlag);
+ SET_ITEM_INT(Py_DontWriteBytecodeFlag);
+ SET_ITEM_INT(Py_NoUserSiteDirectory);
+ SET_ITEM_INT(Py_UnbufferedStdioFlag);
+ SET_ITEM_INT(Py_HashRandomizationFlag);
+ SET_ITEM_INT(Py_IsolatedFlag);
+
+#ifdef MS_WINDOWS
+ SET_ITEM_INT(Py_LegacyWindowsFSEncodingFlag);
+ SET_ITEM_INT(Py_LegacyWindowsStdioFlag);
+#endif
+
+ return dict;
+
+fail:
+ Py_DECREF(dict);
+ return NULL;
+
+#undef FROM_STRING
+#undef SET_ITEM
+#undef SET_ITEM_INT
+#undef SET_ITEM_STR
+}
+
+
void
_PyCoreConfig_GetGlobalConfig(_PyCoreConfig *config)
{
@@ -2432,6 +2503,110 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
}
+PyObject *
+_PyCoreConfig_AsDict(const _PyCoreConfig *config)
+{
+ PyObject *dict, *obj;
+
+ dict = PyDict_New();
+ if (dict == NULL) {
+ return NULL;
+ }
+
+#define FROM_STRING(STR) \
+ ((STR != NULL) ? \
+ PyUnicode_FromString(STR) \
+ : (Py_INCREF(Py_None), Py_None))
+#define FROM_WSTRING(STR) \
+ ((STR != NULL) ? \
+ PyUnicode_FromWideChar(STR, -1) \
+ : (Py_INCREF(Py_None), Py_None))
+#define SET_ITEM(KEY, EXPR) \
+ do { \
+ obj = (EXPR); \
+ if (obj == NULL) { \
+ return NULL; \
+ } \
+ int res = PyDict_SetItemString(dict, (KEY), obj); \
+ Py_DECREF(obj); \
+ if (res < 0) { \
+ goto fail; \
+ } \
+ } while (0)
+
+ SET_ITEM("install_signal_handlers",
+ PyLong_FromLong(config->install_signal_handlers));
+ SET_ITEM("ignore_environment",
+ PyLong_FromLong(config->ignore_environment));
+ SET_ITEM("use_hash_seed",
+ PyLong_FromLong(config->use_hash_seed));
+ SET_ITEM("hash_seed",
+ PyLong_FromUnsignedLong(config->hash_seed));
+ SET_ITEM("allocator",
+ FROM_STRING(config->allocator));
+ SET_ITEM("dev_mode",
+ PyLong_FromLong(config->dev_mode));
+ SET_ITEM("faulthandler",
+ PyLong_FromLong(config->faulthandler));
+ SET_ITEM("tracemalloc",
+ PyLong_FromLong(config->tracemalloc));
+ SET_ITEM("import_time",
+ PyLong_FromLong(config->import_time));
+ SET_ITEM("show_ref_count",
+ PyLong_FromLong(config->show_ref_count));
+ SET_ITEM("show_alloc_count",
+ PyLong_FromLong(config->show_alloc_count));
+ SET_ITEM("dump_refs",
+ PyLong_FromLong(config->dump_refs));
+ SET_ITEM("malloc_stats",
+ PyLong_FromLong(config->malloc_stats));
+ SET_ITEM("coerce_c_locale",
+ PyLong_FromLong(config->coerce_c_locale));
+ SET_ITEM("coerce_c_locale_warn",
+ PyLong_FromLong(config->coerce_c_locale_warn));
+ SET_ITEM("utf8_mode",
+ PyLong_FromLong(config->utf8_mode));
+ SET_ITEM("program_name",
+ FROM_WSTRING(config->program_name));
+ SET_ITEM("argv",
+ _Py_wstrlist_as_pylist(config->argc, config->argv));
+ SET_ITEM("program",
+ FROM_WSTRING(config->program));
+ SET_ITEM("xoptions",
+ _Py_wstrlist_as_pylist(config->nxoption, config->xoptions));
+ SET_ITEM("warnoptions",
+ _Py_wstrlist_as_pylist(config->nwarnoption, config->warnoptions));
+ SET_ITEM("module_search_path_env",
+ FROM_WSTRING(config->module_search_path_env));
+ SET_ITEM("home",
+ FROM_WSTRING(config->home));
+ SET_ITEM("module_search_paths",
+ _Py_wstrlist_as_pylist(config->nmodule_search_path, config->module_search_paths));
+ SET_ITEM("executable",
+ FROM_WSTRING(config->executable));
+ SET_ITEM("prefix",
+ FROM_WSTRING(config->prefix));
+ SET_ITEM("base_prefix",
+ FROM_WSTRING(config->base_prefix));
+ SET_ITEM("exec_prefix",
+ FROM_WSTRING(config->exec_prefix));
+ SET_ITEM("base_exec_prefix",
+ FROM_WSTRING(config->base_exec_prefix));
+ SET_ITEM("_disable_importlib",
+ PyLong_FromLong(config->_disable_importlib));
+
+ return dict;
+
+fail:
+ Py_DECREF(dict);
+ return NULL;
+
+#undef FROM_STRING
+#undef FROM_WSTRING
+#undef SET_ITEM
+}
+
+
void
_PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *config)
{
@@ -2501,6 +2676,57 @@ _PyMainInterpreterConfig_Copy(_PyMainInterpreterConfig *config,
}
+PyObject*
+_PyMainInterpreterConfig_AsDict(const _PyMainInterpreterConfig *config)
+{
+ PyObject *dict, *obj;
+ int res;
+
+ dict = PyDict_New();
+ if (dict == NULL) {
+ return NULL;
+ }
+
+#define SET_ITEM(KEY, ATTR) \
+ do { \
+ obj = config->ATTR; \
+ if (obj == NULL) { \
+ obj = Py_None; \
+ } \
+ res = PyDict_SetItemString(dict, (KEY), obj); \
+ if (res < 0) { \
+ goto fail; \
+ } \
+ } while (0)
+
+ obj = PyLong_FromLong(config->install_signal_handlers);
+ if (obj == NULL) {
+ goto fail;
+ }
+ res = PyDict_SetItemString(dict, "install_signal_handlers", obj);
+ Py_DECREF(obj);
+ if (res < 0) {
+ goto fail;
+ }
+
+ SET_ITEM("argv", argv);
+ SET_ITEM("executable", executable);
+ SET_ITEM("prefix", prefix);
+ SET_ITEM("base_prefix", base_prefix);
+ SET_ITEM("exec_prefix", exec_prefix);
+ SET_ITEM("base_exec_prefix", base_exec_prefix);
+ SET_ITEM("warnoptions", warnoptions);
+ SET_ITEM("xoptions", xoptions);
+ SET_ITEM("module_search_path", module_search_path);
+
+ return dict;
+
+fail:
+ Py_DECREF(dict);
+ return NULL;
+
+#undef SET_ITEM
+}
_PyInitError
@@ -2530,7 +2756,7 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *main_config,
#define COPY_WSTRLIST(ATTR, LEN, LIST) \
do { \
if (ATTR == NULL) { \
- ATTR = wstrlist_as_pylist(LEN, LIST); \
+ ATTR = _Py_wstrlist_as_pylist(LEN, LIST); \
if (ATTR == NULL) { \
return _Py_INIT_NO_MEMORY(); \
} \
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
index 6c35f9586bfe..b198962db3a4 100644
--- a/Programs/_testembed.c
+++ b/Programs/_testembed.c
@@ -293,92 +293,77 @@ static int test_initialize_pymain(void)
}
-static void
-dump_config(void)
+static int
+dump_config_impl(void)
{
-#define ASSERT_EQUAL(a, b) \
- if ((a) != (b)) { \
- printf("ERROR: %s != %s (%i != %i)\n", #a, #b, (a), (b)); \
- exit(1); \
+ PyObject *config = NULL;
+ PyObject *dict = NULL;
+
+ config = PyDict_New();
+ if (config == NULL) {
+ goto error;
}
-#define ASSERT_STR_EQUAL(a, b) \
- if ((a) == NULL || (b == NULL) || wcscmp((a), (b)) != 0) { \
- printf("ERROR: %s != %s ('%ls' != '%ls')\n", #a, #b, (a), (b)); \
- exit(1); \
+
+ /* global config */
+ dict = _Py_GetGlobalVariablesAsDict();
+ if (dict == NULL) {
+ goto error;
+ }
+ if (PyDict_SetItemString(config, "global_config", dict) < 0) {
+ goto error;
}
+ Py_CLEAR(dict);
+ /* core config */
PyInterpreterState *interp = PyThreadState_Get()->interp;
- _PyCoreConfig *config = &interp->core_config;
-
- printf("install_signal_handlers = %i\n", config->install_signal_handlers);
-
- printf("Py_IgnoreEnvironmentFlag = %i\n", Py_IgnoreEnvironmentFlag);
+ const _PyCoreConfig *core_config = &interp->core_config;
+ dict = _PyCoreConfig_AsDict(core_config);
+ if (dict == NULL) {
+ goto error;
+ }
+ if (PyDict_SetItemString(config, "core_config", dict) < 0) {
+ goto error;
+ }
+ Py_CLEAR(dict);
- printf("use_hash_seed = %i\n", config->use_hash_seed);
- printf("hash_seed = %lu\n", config->hash_seed);
+ /* main config */
+ const _PyMainInterpreterConfig *main_config = &interp->config;
+ dict = _PyMainInterpreterConfig_AsDict(main_config);
+ if (dict == NULL) {
+ goto error;
+ }
+ if (PyDict_SetItemString(config, "main_config", dict) < 0) {
+ goto error;
+ }
+ Py_CLEAR(dict);
+
+ PyObject *json = PyImport_ImportModule("json");
+ PyObject *res = PyObject_CallMethod(json, "dumps", "O", config);
+ Py_DECREF(json);
+ Py_CLEAR(config);
+ if (res == NULL) {
+ goto error;
+ }
- printf("allocator = %s\n", config->allocator);
+ PySys_FormatStdout("%S\n", res);
+ Py_DECREF(res);
- printf("dev_mode = %i\n", config->dev_mode);
- printf("faulthandler = %i\n", config->faulthandler);
- printf("tracemalloc = %i\n", config->tracemalloc);
- printf("import_time = %i\n", config->import_time);
- printf("show_ref_count = %i\n", config->show_ref_count);
- printf("show_alloc_count = %i\n", config->show_alloc_count);
- printf("dump_refs = %i\n", config->dump_refs);
- printf("malloc_stats = %i\n", config->malloc_stats);
+ return 0;
- printf("coerce_c_locale = %i\n", config->coerce_c_locale);
- printf("coerce_c_locale_warn = %i\n", config->coerce_c_locale_warn);
- printf("utf8_mode = %i\n", config->utf8_mode);
+error:
+ Py_XDECREF(config);
+ Py_XDECREF(dict);
+ return -1;
+}
- printf("program_name = %ls\n", config->program_name);
- ASSERT_STR_EQUAL(config->program_name, Py_GetProgramName());
- printf("argc = %i\n", config->argc);
- printf("argv = [");
- for (int i=0; i < config->argc; i++) {
- if (i) {
- printf(", ");
- }
- printf("\"%ls\"", config->argv[i]);
+static void
+dump_config(void)
+{
+ if (dump_config_impl() < 0) {
+ fprintf(stderr, "failed to dump the configuration:\n");
+ PyErr_Print();
}
- printf("]\n");
-
- printf("program = %ls\n", config->program);
- /* FIXME: test xoptions */
- /* FIXME: test warnoptions */
- /* FIXME: test module_search_path_env */
- /* FIXME: test home */
- /* FIXME: test module_search_paths */
- /* FIXME: test executable */
- /* FIXME: test prefix */
- /* FIXME: test base_prefix */
- /* FIXME: test exec_prefix */
- /* FIXME: test base_exec_prefix */
- /* FIXME: test dll_path */
-
- printf("Py_IsolatedFlag = %i\n", Py_IsolatedFlag);
- printf("Py_NoSiteFlag = %i\n", Py_NoSiteFlag);
- printf("Py_BytesWarningFlag = %i\n", Py_BytesWarningFlag);
- printf("Py_InspectFlag = %i\n", Py_InspectFlag);
- printf("Py_InteractiveFlag = %i\n", Py_InteractiveFlag);
- printf("Py_OptimizeFlag = %i\n", Py_OptimizeFlag);
- printf("Py_DebugFlag = %i\n", Py_DebugFlag);
- printf("Py_DontWriteBytecodeFlag = %i\n", Py_DontWriteBytecodeFlag);
- printf("Py_VerboseFlag = %i\n", Py_VerboseFlag);
- printf("Py_QuietFlag = %i\n", Py_QuietFlag);
- printf("Py_NoUserSiteDirectory = %i\n", Py_NoUserSiteDirectory);
- printf("Py_UnbufferedStdioFlag = %i\n", Py_UnbufferedStdioFlag);
- /* FIXME: test legacy_windows_fs_encoding */
- /* FIXME: test legacy_windows_stdio */
-
- printf("_disable_importlib = %i\n", config->_disable_importlib);
- /* cannot test _Py_CheckHashBasedPycsMode: the symbol is not exported */
- printf("Py_FrozenFlag = %i\n", Py_FrozenFlag);
-
-#undef ASSERT_EQUAL
-#undef ASSERT_STR_EQUAL
}
More information about the Python-checkins
mailing list