gh-107954, PEP 741: Add PyConfig_Get()/Set() functions (#123472)

Add PyConfig_Get(), PyConfig_GetInt(), PyConfig_Set() and
PyConfig_Names() functions to get and set the current runtime Python
configuration.

Add visibility and "sys spec" to config and preconfig specifications.

_PyConfig_AsDict() now converts PyConfig.xoptions as a dictionary.

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
This commit is contained in:
Victor Stinner 2024-09-02 23:25:08 +02:00 committed by GitHub
parent db42934270
commit 33b790978d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 1468 additions and 259 deletions

View file

@ -508,30 +508,30 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
PRE_CONFIG_COMPAT = {
'_config_init': API_COMPAT,
'allocator': PYMEM_ALLOCATOR_NOT_SET,
'parse_argv': 0,
'configure_locale': 1,
'coerce_c_locale': 0,
'coerce_c_locale_warn': 0,
'utf8_mode': 0,
'parse_argv': False,
'configure_locale': True,
'coerce_c_locale': False,
'coerce_c_locale_warn': False,
'utf8_mode': False,
}
if MS_WINDOWS:
PRE_CONFIG_COMPAT.update({
'legacy_windows_fs_encoding': 0,
'legacy_windows_fs_encoding': False,
})
PRE_CONFIG_PYTHON = dict(PRE_CONFIG_COMPAT,
_config_init=API_PYTHON,
parse_argv=1,
parse_argv=True,
coerce_c_locale=GET_DEFAULT_CONFIG,
utf8_mode=GET_DEFAULT_CONFIG,
)
PRE_CONFIG_ISOLATED = dict(PRE_CONFIG_COMPAT,
_config_init=API_ISOLATED,
configure_locale=0,
isolated=1,
use_environment=0,
utf8_mode=0,
dev_mode=0,
coerce_c_locale=0,
configure_locale=False,
isolated=True,
use_environment=False,
utf8_mode=False,
dev_mode=False,
coerce_c_locale=False,
)
COPY_PRE_CONFIG = [
@ -570,7 +570,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'argv': [""],
'orig_argv': [],
'xoptions': [],
'xoptions': {},
'warnoptions': [],
'pythonpath_env': None,
@ -619,14 +619,14 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'_is_python_build': IGNORE_CONFIG,
}
if Py_STATS:
CONFIG_COMPAT['_pystats'] = 0
CONFIG_COMPAT['_pystats'] = False
if support.Py_DEBUG:
CONFIG_COMPAT['run_presite'] = None
if support.Py_GIL_DISABLED:
CONFIG_COMPAT['enable_gil'] = -1
if MS_WINDOWS:
CONFIG_COMPAT.update({
'legacy_windows_stdio': 0,
'legacy_windows_stdio': False,
})
CONFIG_PYTHON = dict(CONFIG_COMPAT,
@ -644,12 +644,12 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
install_signal_handlers=False,
use_hash_seed=False,
faulthandler=False,
tracemalloc=0,
tracemalloc=False,
perf_profiling=False,
pathconfig_warnings=False,
)
if MS_WINDOWS:
CONFIG_ISOLATED['legacy_windows_stdio'] = 0
CONFIG_ISOLATED['legacy_windows_stdio'] = False
# global config
DEFAULT_GLOBAL_CONFIG = {
@ -928,23 +928,23 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
def test_init_global_config(self):
preconfig = {
'utf8_mode': 1,
'utf8_mode': True,
}
config = {
'program_name': './globalvar',
'site_import': 0,
'bytes_warning': 1,
'site_import': False,
'bytes_warning': True,
'warnoptions': ['default::BytesWarning'],
'inspect': 1,
'interactive': 1,
'inspect': True,
'interactive': True,
'optimization_level': 2,
'write_bytecode': 0,
'verbose': 1,
'quiet': 1,
'buffered_stdio': 0,
'write_bytecode': False,
'verbose': True,
'quiet': True,
'buffered_stdio': False,
'user_site_directory': 0,
'pathconfig_warnings': 0,
'user_site_directory': False,
'pathconfig_warnings': False,
}
self.check_all_configs("test_init_global_config", config, preconfig,
api=API_COMPAT)
@ -952,7 +952,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
def test_init_from_config(self):
preconfig = {
'allocator': ALLOCATOR_FOR_CONFIG,
'utf8_mode': 1,
'utf8_mode': True,
}
config = {
'install_signal_handlers': False,
@ -977,12 +977,12 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'-c', 'pass',
'arg2'],
'parse_argv': True,
'xoptions': [
'config_xoption1=3',
'config_xoption2=',
'config_xoption3',
'cmdline_xoption',
],
'xoptions': {
'config_xoption1': '3',
'config_xoption2': '',
'config_xoption3': True,
'cmdline_xoption': True,
},
'warnoptions': [
'cmdline_warnoption',
'default::BytesWarning',
@ -1126,7 +1126,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'dev_mode': True,
'faulthandler': True,
'warnoptions': ['default'],
'xoptions': ['dev'],
'xoptions': {'dev': True},
'safe_path': True,
}
self.check_all_configs("test_preinit_parse_argv", config, preconfig,
@ -1135,7 +1135,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
def test_preinit_dont_parse_argv(self):
# -X dev must be ignored by isolated preconfiguration
preconfig = {
'isolated': 0,
'isolated': False,
}
argv = ["python3",
"-E", "-I", "-P",
@ -1145,7 +1145,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
config = {
'argv': argv,
'orig_argv': argv,
'isolated': 0,
'isolated': False,
}
self.check_all_configs("test_preinit_dont_parse_argv", config, preconfig,
api=API_ISOLATED)
@ -1218,12 +1218,12 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
def test_init_sys_add(self):
config = {
'faulthandler': 1,
'xoptions': [
'config_xoption',
'cmdline_xoption',
'sysadd_xoption',
'faulthandler',
],
'xoptions': {
'config_xoption': True,
'cmdline_xoption': True,
'sysadd_xoption': True,
'faulthandler': True,
},
'warnoptions': [
'ignore:::cmdline_warnoption',
'ignore:::sysadd_warnoption',
@ -1259,7 +1259,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'program_name': './python3',
'run_command': code + '\n',
'parse_argv': True,
'_init_main': 0,
'_init_main': False,
'sys_path_0': '',
}
self.check_all_configs("test_init_main", config,
@ -1637,12 +1637,12 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
config['base_prefix'] = pyvenv_home
config['prefix'] = pyvenv_home
config['stdlib_dir'] = os.path.join(pyvenv_home, 'Lib')
config['use_frozen_modules'] = int(not support.Py_DEBUG)
config['use_frozen_modules'] = bool(not support.Py_DEBUG)
else:
# cannot reliably assume stdlib_dir here because it
# depends too much on our build. But it ought to be found
config['stdlib_dir'] = self.IGNORE_CONFIG
config['use_frozen_modules'] = int(not support.Py_DEBUG)
config['use_frozen_modules'] = bool(not support.Py_DEBUG)
env = self.copy_paths_by_env(config)
self.check_all_configs("test_init_compat_config", config,
@ -1706,7 +1706,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
config = _testinternalcapi.get_configs()['config']
self.assertEqual(Py_GetPath().split(os.path.pathsep),
self.assertEqual(tuple(Py_GetPath().split(os.path.pathsep)),
config['module_search_paths'])
self.assertEqual(Py_GetPrefix(), config['prefix'])
self.assertEqual(Py_GetExecPrefix(), config['exec_prefix'])
@ -1763,6 +1763,10 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
}
for raw, expected in tests:
optval = f'frozen_modules{raw}'
if raw.startswith('='):
xoption_value = raw[1:]
else:
xoption_value = True
config = {
'parse_argv': True,
'argv': ['-c'],
@ -1770,7 +1774,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'program_name': './argv0',
'run_command': 'pass\n',
'use_environment': True,
'xoptions': [optval],
'xoptions': {'frozen_modules': xoption_value},
'use_frozen_modules': expected,
}
env = {'TESTFROZEN': raw[1:]} if raw else None