Skip to content

Commit 2094c2b

Browse files
authored
bpo-34567: pythoninfo gets coreconfig (GH-9043)
* Add _testcapi.get_coreconfig() to get the _PyCoreConfig of the interpreter * test.pythoninfo now gets the core configuration using _testcapi.get_coreconfig()
1 parent 8ea0911 commit 2094c2b

File tree

4 files changed

+174
-3
lines changed

4 files changed

+174
-3
lines changed

Include/coreconfig.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,10 @@ PyAPI_FUNC(int) _Py_SetFileSystemEncoding(
366366
PyAPI_FUNC(void) _Py_ClearFileSystemEncoding(void);
367367
#endif
368368

369+
#ifndef Py_LIMITED_API
370+
PyAPI_FUNC(PyObject*) _Py_wstrlist_as_pylist(int len, wchar_t **list);
371+
#endif
372+
369373

370374
#ifdef __cplusplus
371375
}

Lib/test/pythoninfo.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,17 @@ def collect_gdbm(info_add):
534534
info_add('gdbm.GDBM_VERSION', '.'.join(map(str, _GDBM_VERSION)))
535535

536536

537+
def collect_get_coreconfig(info_add):
538+
try:
539+
from _testcapi import get_coreconfig
540+
except ImportError:
541+
return
542+
543+
config = get_coreconfig()
544+
for key in sorted(config):
545+
info_add('coreconfig[%s]' % key, repr(config[key]))
546+
547+
537548
def collect_info(info):
538549
error = False
539550
info_add = info.add
@@ -562,6 +573,7 @@ def collect_info(info):
562573
collect_resource,
563574
collect_cc,
564575
collect_gdbm,
576+
collect_get_coreconfig,
565577

566578
# Collecting from tests should be last as they have side effects.
567579
collect_test_socket,

Modules/_testcapimodule.c

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4642,6 +4642,160 @@ decode_locale_ex(PyObject *self, PyObject *args)
46424642
}
46434643

46444644

4645+
static PyObject *
4646+
get_coreconfig(PyObject *self, PyObject *Py_UNUSED(args))
4647+
{
4648+
PyInterpreterState *interp = _PyInterpreterState_Get();
4649+
const _PyCoreConfig *config = &interp->core_config;
4650+
PyObject *dict, *obj;
4651+
4652+
dict = PyDict_New();
4653+
if (dict == NULL) {
4654+
return NULL;
4655+
}
4656+
4657+
#define FROM_STRING(STR) \
4658+
((STR != NULL) ? \
4659+
PyUnicode_FromString(STR) \
4660+
: (Py_INCREF(Py_None), Py_None))
4661+
#define FROM_WSTRING(STR) \
4662+
((STR != NULL) ? \
4663+
PyUnicode_FromWideChar(STR, -1) \
4664+
: (Py_INCREF(Py_None), Py_None))
4665+
#define SET_ITEM(KEY, EXPR) \
4666+
do { \
4667+
obj = (EXPR); \
4668+
if (obj == NULL) { \
4669+
return NULL; \
4670+
} \
4671+
int res = PyDict_SetItemString(dict, (KEY), obj); \
4672+
Py_DECREF(obj); \
4673+
if (res < 0) { \
4674+
goto fail; \
4675+
} \
4676+
} while (0)
4677+
4678+
SET_ITEM("install_signal_handlers",
4679+
PyLong_FromLong(config->install_signal_handlers));
4680+
SET_ITEM("use_environment",
4681+
PyLong_FromLong(config->use_environment));
4682+
SET_ITEM("use_hash_seed",
4683+
PyLong_FromLong(config->use_hash_seed));
4684+
SET_ITEM("hash_seed",
4685+
PyLong_FromUnsignedLong(config->hash_seed));
4686+
SET_ITEM("allocator",
4687+
FROM_STRING(config->allocator));
4688+
SET_ITEM("dev_mode",
4689+
PyLong_FromLong(config->dev_mode));
4690+
SET_ITEM("faulthandler",
4691+
PyLong_FromLong(config->faulthandler));
4692+
SET_ITEM("tracemalloc",
4693+
PyLong_FromLong(config->tracemalloc));
4694+
SET_ITEM("import_time",
4695+
PyLong_FromLong(config->import_time));
4696+
SET_ITEM("show_ref_count",
4697+
PyLong_FromLong(config->show_ref_count));
4698+
SET_ITEM("show_alloc_count",
4699+
PyLong_FromLong(config->show_alloc_count));
4700+
SET_ITEM("dump_refs",
4701+
PyLong_FromLong(config->dump_refs));
4702+
SET_ITEM("malloc_stats",
4703+
PyLong_FromLong(config->malloc_stats));
4704+
SET_ITEM("coerce_c_locale",
4705+
PyLong_FromLong(config->coerce_c_locale));
4706+
SET_ITEM("coerce_c_locale_warn",
4707+
PyLong_FromLong(config->coerce_c_locale_warn));
4708+
SET_ITEM("filesystem_encoding",
4709+
FROM_STRING(config->filesystem_encoding));
4710+
SET_ITEM("filesystem_errors",
4711+
FROM_STRING(config->filesystem_errors));
4712+
SET_ITEM("stdio_encoding",
4713+
FROM_STRING(config->stdio_encoding));
4714+
SET_ITEM("utf8_mode",
4715+
PyLong_FromLong(config->utf8_mode));
4716+
SET_ITEM("pycache_prefix",
4717+
FROM_WSTRING(config->pycache_prefix));
4718+
SET_ITEM("program_name",
4719+
FROM_WSTRING(config->program_name));
4720+
SET_ITEM("argv",
4721+
_Py_wstrlist_as_pylist(config->argc, config->argv));
4722+
SET_ITEM("program",
4723+
FROM_WSTRING(config->program));
4724+
SET_ITEM("warnoptions",
4725+
_Py_wstrlist_as_pylist(config->nwarnoption, config->warnoptions));
4726+
SET_ITEM("module_search_path_env",
4727+
FROM_WSTRING(config->module_search_path_env));
4728+
SET_ITEM("home",
4729+
FROM_WSTRING(config->home));
4730+
SET_ITEM("module_search_paths",
4731+
_Py_wstrlist_as_pylist(config->nmodule_search_path, config->module_search_paths));
4732+
SET_ITEM("executable",
4733+
FROM_WSTRING(config->executable));
4734+
SET_ITEM("prefix",
4735+
FROM_WSTRING(config->prefix));
4736+
SET_ITEM("base_prefix",
4737+
FROM_WSTRING(config->base_prefix));
4738+
SET_ITEM("exec_prefix",
4739+
FROM_WSTRING(config->exec_prefix));
4740+
SET_ITEM("base_exec_prefix",
4741+
FROM_WSTRING(config->base_exec_prefix));
4742+
#ifdef MS_WINDOWS
4743+
SET_ITEM("dll_path",
4744+
FROM_WSTRING(config->dll_path));
4745+
#endif
4746+
SET_ITEM("isolated",
4747+
PyLong_FromLong(config->isolated));
4748+
SET_ITEM("site_import",
4749+
PyLong_FromLong(config->site_import));
4750+
SET_ITEM("bytes_warning",
4751+
PyLong_FromLong(config->bytes_warning));
4752+
SET_ITEM("inspect",
4753+
PyLong_FromLong(config->inspect));
4754+
SET_ITEM("interactive",
4755+
PyLong_FromLong(config->interactive));
4756+
SET_ITEM("optimization_level",
4757+
PyLong_FromLong(config->optimization_level));
4758+
SET_ITEM("parser_debug",
4759+
PyLong_FromLong(config->parser_debug));
4760+
SET_ITEM("write_bytecode",
4761+
PyLong_FromLong(config->write_bytecode));
4762+
SET_ITEM("verbose",
4763+
PyLong_FromLong(config->verbose));
4764+
SET_ITEM("quiet",
4765+
PyLong_FromLong(config->quiet));
4766+
SET_ITEM("user_site_directory",
4767+
PyLong_FromLong(config->user_site_directory));
4768+
SET_ITEM("buffered_stdio",
4769+
PyLong_FromLong(config->buffered_stdio));
4770+
SET_ITEM("stdio_encoding",
4771+
FROM_STRING(config->stdio_encoding));
4772+
SET_ITEM("stdio_errors",
4773+
FROM_STRING(config->stdio_errors));
4774+
#ifdef MS_WINDOWS
4775+
SET_ITEM("legacy_windows_fs_encoding",
4776+
PyLong_FromLong(config->legacy_windows_fs_encoding));
4777+
SET_ITEM("legacy_windows_stdio",
4778+
PyLong_FromLong(config->legacy_windows_stdio));
4779+
#endif
4780+
SET_ITEM("_install_importlib",
4781+
PyLong_FromLong(config->_install_importlib));
4782+
SET_ITEM("_check_hash_pycs_mode",
4783+
FROM_STRING(config->_check_hash_pycs_mode));
4784+
SET_ITEM("_frozen",
4785+
PyLong_FromLong(config->_frozen));
4786+
4787+
return dict;
4788+
4789+
fail:
4790+
Py_DECREF(dict);
4791+
return NULL;
4792+
4793+
#undef FROM_STRING
4794+
#undef FROM_WSTRING
4795+
#undef SET_ITEM
4796+
}
4797+
4798+
46454799
static PyMethodDef TestMethods[] = {
46464800
{"raise_exception", raise_exception, METH_VARARGS},
46474801
{"raise_memoryerror", raise_memoryerror, METH_NOARGS},
@@ -4865,6 +5019,7 @@ static PyMethodDef TestMethods[] = {
48655019
{"hamt", new_hamt, METH_NOARGS},
48665020
{"EncodeLocaleEx", encode_locale_ex, METH_VARARGS},
48675021
{"DecodeLocaleEx", decode_locale_ex, METH_VARARGS},
5022+
{"get_coreconfig", get_coreconfig, METH_NOARGS},
48685023
{NULL, NULL} /* sentinel */
48695024
};
48705025

Modules/main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,8 +1018,8 @@ pymain_init_core_argv(_PyMain *pymain, _PyCoreConfig *config, _PyCmdline *cmdlin
10181018
}
10191019

10201020

1021-
static PyObject*
1022-
wstrlist_as_pylist(int len, wchar_t **list)
1021+
PyObject*
1022+
_Py_wstrlist_as_pylist(int len, wchar_t **list)
10231023
{
10241024
assert(list != NULL || len < 1);
10251025

@@ -1502,7 +1502,7 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *main_config,
15021502
#define COPY_WSTRLIST(ATTR, LEN, LIST) \
15031503
do { \
15041504
if (ATTR == NULL) { \
1505-
ATTR = wstrlist_as_pylist(LEN, LIST); \
1505+
ATTR = _Py_wstrlist_as_pylist(LEN, LIST); \
15061506
if (ATTR == NULL) { \
15071507
return _Py_INIT_NO_MEMORY(); \
15081508
} \

0 commit comments

Comments
 (0)