gh-107954: Add PyConfig_MEMBER_BOOL type to PyConfigSpec (#116359)

_PyConfig_AsDict() now returns bool objects for options using the new
PyConfig_MEMBER_BOOL type.

Update tests for these changes.
This commit is contained in:
Victor Stinner 2024-03-06 10:29:27 +01:00 committed by GitHub
parent 22ccf13b33
commit 2b379968e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 213 additions and 191 deletions

View file

@ -14,6 +14,43 @@ from test.support import MS_WINDOWS
MAX_HASH_SEED = 4294967295 MAX_HASH_SEED = 4294967295
BOOL_OPTIONS = [
'isolated',
'use_environment',
'dev_mode',
'install_signal_handlers',
'use_hash_seed',
'faulthandler',
'import_time',
'code_debug_ranges',
'show_ref_count',
'dump_refs',
'malloc_stats',
'parse_argv',
'site_import',
'warn_default_encoding',
'inspect',
'interactive',
'parser_debug',
'write_bytecode',
'quiet',
'user_site_directory',
'configure_c_stdio',
'buffered_stdio',
'use_frozen_modules',
'safe_path',
'pathconfig_warnings',
'module_search_paths_set',
'skip_source_first_line',
'_install_importlib',
'_init_main',
'_is_python_build',
]
if MS_WINDOWS:
BOOL_OPTIONS.append('legacy_windows_stdio')
class SetConfigTests(unittest.TestCase): class SetConfigTests(unittest.TestCase):
def setUp(self): def setUp(self):
self.old_config = _testinternalcapi.get_config() self.old_config = _testinternalcapi.get_config()
@ -52,42 +89,15 @@ class SetConfigTests(unittest.TestCase):
] ]
# int (unsigned) # int (unsigned)
options = [ int_options = [
'_config_init', '_config_init',
'isolated',
'use_environment',
'dev_mode',
'install_signal_handlers',
'use_hash_seed',
'faulthandler',
'tracemalloc',
'import_time',
'code_debug_ranges',
'show_ref_count',
'dump_refs',
'malloc_stats',
'parse_argv',
'site_import',
'bytes_warning', 'bytes_warning',
'inspect',
'interactive',
'optimization_level', 'optimization_level',
'parser_debug', 'tracemalloc',
'write_bytecode',
'verbose', 'verbose',
'quiet',
'user_site_directory',
'configure_c_stdio',
'buffered_stdio',
'pathconfig_warnings',
'module_search_paths_set',
'skip_source_first_line',
'_install_importlib',
'_init_main',
] ]
if MS_WINDOWS: int_options.extend(BOOL_OPTIONS)
options.append('legacy_windows_stdio') for key in int_options:
for key in options:
value_tests.append((key, invalid_uint)) value_tests.append((key, invalid_uint))
type_tests.append((key, "abc")) type_tests.append((key, "abc"))
type_tests.append((key, 2.0)) type_tests.append((key, 2.0))
@ -148,6 +158,7 @@ class SetConfigTests(unittest.TestCase):
_testinternalcapi.set_config(config) _testinternalcapi.set_config(config)
def test_flags(self): def test_flags(self):
bool_options = set(BOOL_OPTIONS)
for sys_attr, key, value in ( for sys_attr, key, value in (
("debug", "parser_debug", 1), ("debug", "parser_debug", 1),
("inspect", "inspect", 2), ("inspect", "inspect", 2),
@ -160,6 +171,9 @@ class SetConfigTests(unittest.TestCase):
): ):
with self.subTest(sys=sys_attr, key=key, value=value): with self.subTest(sys=sys_attr, key=key, value=value):
self.set_config(**{key: value, 'parse_argv': 0}) self.set_config(**{key: value, 'parse_argv': 0})
if key in bool_options:
self.assertEqual(getattr(sys.flags, sys_attr), int(bool(value)))
else:
self.assertEqual(getattr(sys.flags, sys_attr), value) self.assertEqual(getattr(sys.flags, sys_attr), value)
self.set_config(write_bytecode=0) self.set_config(write_bytecode=0)

View file

@ -634,15 +634,13 @@ class CmdLineTest(unittest.TestCase):
PYTHONDONTWRITEBYTECODE=value, PYTHONDONTWRITEBYTECODE=value,
PYTHONVERBOSE=value, PYTHONVERBOSE=value,
) )
dont_write_bytecode = int(bool(value)) expected_bool = int(bool(value))
code = ( code = (
"import sys; " "import sys; "
"sys.stderr.write(str(sys.flags)); " "sys.stderr.write(str(sys.flags)); "
f"""sys.exit(not ( f"""sys.exit(not (
sys.flags.debug == sys.flags.optimize == sys.flags.optimize == sys.flags.verbose == {expected}
sys.flags.verbose == and sys.flags.debug == sys.flags.dont_write_bytecode == {expected_bool}
{expected}
and sys.flags.dont_write_bytecode == {dont_write_bytecode}
))""" ))"""
) )
with self.subTest(envar_value=value): with self.subTest(envar_value=value):

View file

@ -443,31 +443,31 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
CONFIG_COMPAT = { CONFIG_COMPAT = {
'_config_init': API_COMPAT, '_config_init': API_COMPAT,
'isolated': 0, 'isolated': False,
'use_environment': 1, 'use_environment': True,
'dev_mode': 0, 'dev_mode': False,
'install_signal_handlers': 1, 'install_signal_handlers': True,
'use_hash_seed': 0, 'use_hash_seed': False,
'hash_seed': 0, 'hash_seed': 0,
'int_max_str_digits': sys.int_info.default_max_str_digits, 'int_max_str_digits': sys.int_info.default_max_str_digits,
'cpu_count': -1, 'cpu_count': -1,
'faulthandler': 0, 'faulthandler': False,
'tracemalloc': 0, 'tracemalloc': 0,
'perf_profiling': 0, 'perf_profiling': False,
'import_time': 0, 'import_time': False,
'code_debug_ranges': 1, 'code_debug_ranges': True,
'show_ref_count': 0, 'show_ref_count': False,
'dump_refs': 0, 'dump_refs': False,
'dump_refs_file': None, 'dump_refs_file': None,
'malloc_stats': 0, 'malloc_stats': False,
'filesystem_encoding': GET_DEFAULT_CONFIG, 'filesystem_encoding': GET_DEFAULT_CONFIG,
'filesystem_errors': GET_DEFAULT_CONFIG, 'filesystem_errors': GET_DEFAULT_CONFIG,
'pycache_prefix': None, 'pycache_prefix': None,
'program_name': GET_DEFAULT_CONFIG, 'program_name': GET_DEFAULT_CONFIG,
'parse_argv': 0, 'parse_argv': False,
'argv': [""], 'argv': [""],
'orig_argv': [], 'orig_argv': [],
@ -484,39 +484,39 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'exec_prefix': GET_DEFAULT_CONFIG, 'exec_prefix': GET_DEFAULT_CONFIG,
'base_exec_prefix': GET_DEFAULT_CONFIG, 'base_exec_prefix': GET_DEFAULT_CONFIG,
'module_search_paths': GET_DEFAULT_CONFIG, 'module_search_paths': GET_DEFAULT_CONFIG,
'module_search_paths_set': 1, 'module_search_paths_set': True,
'platlibdir': sys.platlibdir, 'platlibdir': sys.platlibdir,
'stdlib_dir': GET_DEFAULT_CONFIG, 'stdlib_dir': GET_DEFAULT_CONFIG,
'site_import': 1, 'site_import': True,
'bytes_warning': 0, 'bytes_warning': 0,
'warn_default_encoding': 0, 'warn_default_encoding': False,
'inspect': 0, 'inspect': False,
'interactive': 0, 'interactive': False,
'optimization_level': 0, 'optimization_level': 0,
'parser_debug': 0, 'parser_debug': False,
'write_bytecode': 1, 'write_bytecode': True,
'verbose': 0, 'verbose': 0,
'quiet': 0, 'quiet': False,
'user_site_directory': 1, 'user_site_directory': True,
'configure_c_stdio': 0, 'configure_c_stdio': False,
'buffered_stdio': 1, 'buffered_stdio': True,
'stdio_encoding': GET_DEFAULT_CONFIG, 'stdio_encoding': GET_DEFAULT_CONFIG,
'stdio_errors': GET_DEFAULT_CONFIG, 'stdio_errors': GET_DEFAULT_CONFIG,
'skip_source_first_line': 0, 'skip_source_first_line': False,
'run_command': None, 'run_command': None,
'run_module': None, 'run_module': None,
'run_filename': None, 'run_filename': None,
'sys_path_0': None, 'sys_path_0': None,
'_install_importlib': 1, '_install_importlib': True,
'check_hash_pycs_mode': 'default', 'check_hash_pycs_mode': 'default',
'pathconfig_warnings': 1, 'pathconfig_warnings': True,
'_init_main': 1, '_init_main': True,
'use_frozen_modules': not support.Py_DEBUG, 'use_frozen_modules': not support.Py_DEBUG,
'safe_path': 0, 'safe_path': False,
'_is_python_build': IGNORE_CONFIG, '_is_python_build': IGNORE_CONFIG,
} }
if Py_STATS: if Py_STATS:
@ -530,22 +530,22 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
CONFIG_PYTHON = dict(CONFIG_COMPAT, CONFIG_PYTHON = dict(CONFIG_COMPAT,
_config_init=API_PYTHON, _config_init=API_PYTHON,
configure_c_stdio=1, configure_c_stdio=True,
parse_argv=2, parse_argv=True,
) )
CONFIG_ISOLATED = dict(CONFIG_COMPAT, CONFIG_ISOLATED = dict(CONFIG_COMPAT,
_config_init=API_ISOLATED, _config_init=API_ISOLATED,
isolated=1, isolated=True,
use_environment=0, use_environment=False,
user_site_directory=0, user_site_directory=False,
safe_path=1, safe_path=True,
dev_mode=0, dev_mode=False,
install_signal_handlers=0, install_signal_handlers=False,
use_hash_seed=0, use_hash_seed=False,
faulthandler=0, faulthandler=False,
tracemalloc=0, tracemalloc=0,
perf_profiling=0, perf_profiling=False,
pathconfig_warnings=0, pathconfig_warnings=False,
) )
if MS_WINDOWS: if MS_WINDOWS:
CONFIG_ISOLATED['legacy_windows_stdio'] = 0 CONFIG_ISOLATED['legacy_windows_stdio'] = 0
@ -851,15 +851,15 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'utf8_mode': 1, 'utf8_mode': 1,
} }
config = { config = {
'install_signal_handlers': 0, 'install_signal_handlers': False,
'use_hash_seed': 1, 'use_hash_seed': True,
'hash_seed': 123, 'hash_seed': 123,
'tracemalloc': 2, 'tracemalloc': 2,
'perf_profiling': 0, 'perf_profiling': False,
'import_time': 1, 'import_time': True,
'code_debug_ranges': 0, 'code_debug_ranges': False,
'show_ref_count': 1, 'show_ref_count': True,
'malloc_stats': 1, 'malloc_stats': True,
'stdio_encoding': 'iso8859-1', 'stdio_encoding': 'iso8859-1',
'stdio_errors': 'replace', 'stdio_errors': 'replace',
@ -872,7 +872,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'-X', 'cmdline_xoption', '-X', 'cmdline_xoption',
'-c', 'pass', '-c', 'pass',
'arg2'], 'arg2'],
'parse_argv': 2, 'parse_argv': True,
'xoptions': [ 'xoptions': [
'config_xoption1=3', 'config_xoption1=3',
'config_xoption2=', 'config_xoption2=',
@ -886,26 +886,26 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
], ],
'run_command': 'pass\n', 'run_command': 'pass\n',
'site_import': 0, 'site_import': False,
'bytes_warning': 1, 'bytes_warning': 1,
'inspect': 1, 'inspect': True,
'interactive': 1, 'interactive': True,
'optimization_level': 2, 'optimization_level': 2,
'write_bytecode': 0, 'write_bytecode': False,
'verbose': 1, 'verbose': 1,
'quiet': 1, 'quiet': True,
'configure_c_stdio': 1, 'configure_c_stdio': True,
'buffered_stdio': 0, 'buffered_stdio': False,
'user_site_directory': 0, 'user_site_directory': False,
'faulthandler': 1, 'faulthandler': True,
'platlibdir': 'my_platlibdir', 'platlibdir': 'my_platlibdir',
'module_search_paths': self.IGNORE_CONFIG, 'module_search_paths': self.IGNORE_CONFIG,
'safe_path': 1, 'safe_path': True,
'int_max_str_digits': 31337, 'int_max_str_digits': 31337,
'cpu_count': 4321, 'cpu_count': 4321,
'check_hash_pycs_mode': 'always', 'check_hash_pycs_mode': 'always',
'pathconfig_warnings': 0, 'pathconfig_warnings': False,
} }
if Py_STATS: if Py_STATS:
config['_pystats'] = 1 config['_pystats'] = 1
@ -917,28 +917,28 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'allocator': ALLOCATOR_FOR_CONFIG, 'allocator': ALLOCATOR_FOR_CONFIG,
} }
config = { config = {
'use_hash_seed': 1, 'use_hash_seed': True,
'hash_seed': 42, 'hash_seed': 42,
'tracemalloc': 2, 'tracemalloc': 2,
'perf_profiling': 0, 'perf_profiling': False,
'import_time': 1, 'import_time': True,
'code_debug_ranges': 0, 'code_debug_ranges': False,
'malloc_stats': 1, 'malloc_stats': True,
'inspect': 1, 'inspect': True,
'optimization_level': 2, 'optimization_level': 2,
'pythonpath_env': '/my/path', 'pythonpath_env': '/my/path',
'pycache_prefix': 'env_pycache_prefix', 'pycache_prefix': 'env_pycache_prefix',
'write_bytecode': 0, 'write_bytecode': False,
'verbose': 1, 'verbose': 1,
'buffered_stdio': 0, 'buffered_stdio': False,
'stdio_encoding': 'iso8859-1', 'stdio_encoding': 'iso8859-1',
'stdio_errors': 'replace', 'stdio_errors': 'replace',
'user_site_directory': 0, 'user_site_directory': False,
'faulthandler': 1, 'faulthandler': True,
'warnoptions': ['EnvVar'], 'warnoptions': ['EnvVar'],
'platlibdir': 'env_platlibdir', 'platlibdir': 'env_platlibdir',
'module_search_paths': self.IGNORE_CONFIG, 'module_search_paths': self.IGNORE_CONFIG,
'safe_path': 1, 'safe_path': True,
'int_max_str_digits': 4567, 'int_max_str_digits': 4567,
} }
if Py_STATS: if Py_STATS:
@ -952,32 +952,32 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'utf8_mode': 1, 'utf8_mode': 1,
} }
config = { config = {
'use_hash_seed': 1, 'use_hash_seed': True,
'hash_seed': 42, 'hash_seed': 42,
'tracemalloc': 2, 'tracemalloc': 2,
'perf_profiling': 0, 'perf_profiling': False,
'import_time': 1, 'import_time': True,
'code_debug_ranges': 0, 'code_debug_ranges': False,
'malloc_stats': 1, 'malloc_stats': True,
'inspect': 1, 'inspect': True,
'optimization_level': 2, 'optimization_level': 2,
'pythonpath_env': '/my/path', 'pythonpath_env': '/my/path',
'pycache_prefix': 'env_pycache_prefix', 'pycache_prefix': 'env_pycache_prefix',
'write_bytecode': 0, 'write_bytecode': False,
'verbose': 1, 'verbose': 1,
'buffered_stdio': 0, 'buffered_stdio': False,
'stdio_encoding': 'iso8859-1', 'stdio_encoding': 'iso8859-1',
'stdio_errors': 'replace', 'stdio_errors': 'replace',
'user_site_directory': 0, 'user_site_directory': False,
'faulthandler': 1, 'faulthandler': True,
'warnoptions': ['EnvVar'], 'warnoptions': ['EnvVar'],
'platlibdir': 'env_platlibdir', 'platlibdir': 'env_platlibdir',
'module_search_paths': self.IGNORE_CONFIG, 'module_search_paths': self.IGNORE_CONFIG,
'safe_path': 1, 'safe_path': True,
'int_max_str_digits': 4567, 'int_max_str_digits': 4567,
} }
if Py_STATS: if Py_STATS:
config['_pystats'] = 1 config['_pystats'] = True
self.check_all_configs("test_init_python_env", config, preconfig, self.check_all_configs("test_init_python_env", config, preconfig,
api=API_PYTHON) api=API_PYTHON)
@ -1002,8 +1002,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'allocator': PYMEM_ALLOCATOR_DEBUG, 'allocator': PYMEM_ALLOCATOR_DEBUG,
} }
config = { config = {
'faulthandler': 1, 'faulthandler': True,
'dev_mode': 1, 'dev_mode': True,
'warnoptions': ['default'], 'warnoptions': ['default'],
} }
self.check_all_configs("test_init_dev_mode", config, preconfig, self.check_all_configs("test_init_dev_mode", config, preconfig,
@ -1019,11 +1019,11 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'argv': ['script.py'], 'argv': ['script.py'],
'orig_argv': ['python3', '-X', 'dev', '-P', 'script.py'], 'orig_argv': ['python3', '-X', 'dev', '-P', 'script.py'],
'run_filename': os.path.abspath('script.py'), 'run_filename': os.path.abspath('script.py'),
'dev_mode': 1, 'dev_mode': True,
'faulthandler': 1, 'faulthandler': True,
'warnoptions': ['default'], 'warnoptions': ['default'],
'xoptions': ['dev'], 'xoptions': ['dev'],
'safe_path': 1, 'safe_path': True,
} }
self.check_all_configs("test_preinit_parse_argv", config, preconfig, self.check_all_configs("test_preinit_parse_argv", config, preconfig,
api=API_PYTHON) api=API_PYTHON)
@ -1048,30 +1048,30 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
def test_init_isolated_flag(self): def test_init_isolated_flag(self):
config = { config = {
'isolated': 1, 'isolated': True,
'safe_path': 1, 'safe_path': True,
'use_environment': 0, 'use_environment': False,
'user_site_directory': 0, 'user_site_directory': False,
} }
self.check_all_configs("test_init_isolated_flag", config, api=API_PYTHON) self.check_all_configs("test_init_isolated_flag", config, api=API_PYTHON)
def test_preinit_isolated1(self): def test_preinit_isolated1(self):
# _PyPreConfig.isolated=1, _PyCoreConfig.isolated not set # _PyPreConfig.isolated=1, _PyCoreConfig.isolated not set
config = { config = {
'isolated': 1, 'isolated': True,
'safe_path': 1, 'safe_path': True,
'use_environment': 0, 'use_environment': False,
'user_site_directory': 0, 'user_site_directory': False,
} }
self.check_all_configs("test_preinit_isolated1", config, api=API_COMPAT) self.check_all_configs("test_preinit_isolated1", config, api=API_COMPAT)
def test_preinit_isolated2(self): def test_preinit_isolated2(self):
# _PyPreConfig.isolated=0, _PyCoreConfig.isolated=1 # _PyPreConfig.isolated=0, _PyCoreConfig.isolated=1
config = { config = {
'isolated': 1, 'isolated': True,
'safe_path': 1, 'safe_path': True,
'use_environment': 0, 'use_environment': False,
'user_site_directory': 0, 'user_site_directory': False,
} }
self.check_all_configs("test_preinit_isolated2", config, api=API_COMPAT) self.check_all_configs("test_preinit_isolated2", config, api=API_COMPAT)
@ -1139,7 +1139,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'orig_argv': ['python3', '-c', code, 'arg2'], 'orig_argv': ['python3', '-c', code, 'arg2'],
'program_name': './python3', 'program_name': './python3',
'run_command': code + '\n', 'run_command': code + '\n',
'parse_argv': 2, 'parse_argv': True,
'sys_path_0': '', 'sys_path_0': '',
} }
self.check_all_configs("test_init_run_main", config, api=API_PYTHON) self.check_all_configs("test_init_run_main", config, api=API_PYTHON)
@ -1154,7 +1154,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'arg2'], 'arg2'],
'program_name': './python3', 'program_name': './python3',
'run_command': code + '\n', 'run_command': code + '\n',
'parse_argv': 2, 'parse_argv': True,
'_init_main': 0, '_init_main': 0,
'sys_path_0': '', 'sys_path_0': '',
} }
@ -1164,12 +1164,12 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
def test_init_parse_argv(self): def test_init_parse_argv(self):
config = { config = {
'parse_argv': 2, 'parse_argv': True,
'argv': ['-c', 'arg1', '-v', 'arg3'], 'argv': ['-c', 'arg1', '-v', 'arg3'],
'orig_argv': ['./argv0', '-E', '-c', 'pass', 'arg1', '-v', 'arg3'], 'orig_argv': ['./argv0', '-E', '-c', 'pass', 'arg1', '-v', 'arg3'],
'program_name': './argv0', 'program_name': './argv0',
'run_command': 'pass\n', 'run_command': 'pass\n',
'use_environment': 0, 'use_environment': False,
} }
self.check_all_configs("test_init_parse_argv", config, api=API_PYTHON) self.check_all_configs("test_init_parse_argv", config, api=API_PYTHON)
@ -1178,7 +1178,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
'parse_argv': 0, 'parse_argv': 0,
} }
config = { config = {
'parse_argv': 0, 'parse_argv': False,
'argv': ['./argv0', '-E', '-c', 'pass', 'arg1', '-v', 'arg3'], 'argv': ['./argv0', '-E', '-c', 'pass', 'arg1', '-v', 'arg3'],
'orig_argv': ['./argv0', '-E', '-c', 'pass', 'arg1', '-v', 'arg3'], 'orig_argv': ['./argv0', '-E', '-c', 'pass', 'arg1', '-v', 'arg3'],
'program_name': './argv0', 'program_name': './argv0',
@ -1653,20 +1653,20 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
def test_init_use_frozen_modules(self): def test_init_use_frozen_modules(self):
tests = { tests = {
('=on', 1), ('=on', True),
('=off', 0), ('=off', False),
('=', 1), ('=', True),
('', 1), ('', True),
} }
for raw, expected in tests: for raw, expected in tests:
optval = f'frozen_modules{raw}' optval = f'frozen_modules{raw}'
config = { config = {
'parse_argv': 2, 'parse_argv': True,
'argv': ['-c'], 'argv': ['-c'],
'orig_argv': ['./argv0', '-X', optval, '-c', 'pass'], 'orig_argv': ['./argv0', '-X', optval, '-c', 'pass'],
'program_name': './argv0', 'program_name': './argv0',
'run_command': 'pass\n', 'run_command': 'pass\n',
'use_environment': 1, 'use_environment': True,
'xoptions': [optval], 'xoptions': [optval],
'use_frozen_modules': expected, 'use_frozen_modules': expected,
} }
@ -1792,9 +1792,9 @@ class MiscTests(EmbeddingTestsMixin, unittest.TestCase):
sys.argv ['./argv0', '-E', 'arg1', 'arg2'] sys.argv ['./argv0', '-E', 'arg1', 'arg2']
config program_name: ./argv0 config program_name: ./argv0
config executable: {executable} config executable: {executable}
config use_environment: 1 config use_environment: True
config configure_c_stdio: 1 config configure_c_stdio: True
config buffered_stdio: 0 config buffered_stdio: False
""").lstrip() """).lstrip()
self.assertEqual(out, expected) self.assertEqual(out, expected)

View file

@ -30,6 +30,7 @@ typedef enum {
PyConfig_MEMBER_INT = 0, PyConfig_MEMBER_INT = 0,
PyConfig_MEMBER_UINT = 1, PyConfig_MEMBER_UINT = 1,
PyConfig_MEMBER_ULONG = 2, PyConfig_MEMBER_ULONG = 2,
PyConfig_MEMBER_BOOL = 3,
PyConfig_MEMBER_WSTR = 10, PyConfig_MEMBER_WSTR = 10,
PyConfig_MEMBER_WSTR_OPT = 11, PyConfig_MEMBER_WSTR_OPT = 11,
@ -45,61 +46,62 @@ typedef struct {
#define SPEC(MEMBER, TYPE) \ #define SPEC(MEMBER, TYPE) \
{#MEMBER, offsetof(PyConfig, MEMBER), PyConfig_MEMBER_##TYPE} {#MEMBER, offsetof(PyConfig, MEMBER), PyConfig_MEMBER_##TYPE}
// Update _test_embed_set_config when adding new members
static const PyConfigSpec PYCONFIG_SPEC[] = { static const PyConfigSpec PYCONFIG_SPEC[] = {
SPEC(_config_init, UINT), SPEC(_config_init, UINT),
SPEC(isolated, UINT), SPEC(isolated, BOOL),
SPEC(use_environment, UINT), SPEC(use_environment, BOOL),
SPEC(dev_mode, UINT), SPEC(dev_mode, BOOL),
SPEC(install_signal_handlers, UINT), SPEC(install_signal_handlers, BOOL),
SPEC(use_hash_seed, UINT), SPEC(use_hash_seed, BOOL),
SPEC(hash_seed, ULONG), SPEC(hash_seed, ULONG),
SPEC(faulthandler, UINT), SPEC(faulthandler, BOOL),
SPEC(tracemalloc, UINT), SPEC(tracemalloc, UINT),
SPEC(perf_profiling, UINT), SPEC(perf_profiling, BOOL),
SPEC(import_time, UINT), SPEC(import_time, BOOL),
SPEC(code_debug_ranges, UINT), SPEC(code_debug_ranges, BOOL),
SPEC(show_ref_count, UINT), SPEC(show_ref_count, BOOL),
SPEC(dump_refs, UINT), SPEC(dump_refs, BOOL),
SPEC(dump_refs_file, WSTR_OPT), SPEC(dump_refs_file, WSTR_OPT),
SPEC(malloc_stats, UINT), SPEC(malloc_stats, BOOL),
SPEC(filesystem_encoding, WSTR), SPEC(filesystem_encoding, WSTR),
SPEC(filesystem_errors, WSTR), SPEC(filesystem_errors, WSTR),
SPEC(pycache_prefix, WSTR_OPT), SPEC(pycache_prefix, WSTR_OPT),
SPEC(parse_argv, UINT), SPEC(parse_argv, BOOL),
SPEC(orig_argv, WSTR_LIST), SPEC(orig_argv, WSTR_LIST),
SPEC(argv, WSTR_LIST), SPEC(argv, WSTR_LIST),
SPEC(xoptions, WSTR_LIST), SPEC(xoptions, WSTR_LIST),
SPEC(warnoptions, WSTR_LIST), SPEC(warnoptions, WSTR_LIST),
SPEC(site_import, UINT), SPEC(site_import, BOOL),
SPEC(bytes_warning, UINT), SPEC(bytes_warning, UINT),
SPEC(warn_default_encoding, UINT), SPEC(warn_default_encoding, BOOL),
SPEC(inspect, UINT), SPEC(inspect, BOOL),
SPEC(interactive, UINT), SPEC(interactive, BOOL),
SPEC(optimization_level, UINT), SPEC(optimization_level, UINT),
SPEC(parser_debug, UINT), SPEC(parser_debug, BOOL),
SPEC(write_bytecode, UINT), SPEC(write_bytecode, BOOL),
SPEC(verbose, UINT), SPEC(verbose, UINT),
SPEC(quiet, UINT), SPEC(quiet, BOOL),
SPEC(user_site_directory, UINT), SPEC(user_site_directory, BOOL),
SPEC(configure_c_stdio, UINT), SPEC(configure_c_stdio, BOOL),
SPEC(buffered_stdio, UINT), SPEC(buffered_stdio, BOOL),
SPEC(stdio_encoding, WSTR), SPEC(stdio_encoding, WSTR),
SPEC(stdio_errors, WSTR), SPEC(stdio_errors, WSTR),
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
SPEC(legacy_windows_stdio, UINT), SPEC(legacy_windows_stdio, BOOL),
#endif #endif
SPEC(check_hash_pycs_mode, WSTR), SPEC(check_hash_pycs_mode, WSTR),
SPEC(use_frozen_modules, UINT), SPEC(use_frozen_modules, BOOL),
SPEC(safe_path, UINT), SPEC(safe_path, BOOL),
SPEC(int_max_str_digits, INT), SPEC(int_max_str_digits, INT),
SPEC(cpu_count, INT), SPEC(cpu_count, INT),
SPEC(pathconfig_warnings, UINT), SPEC(pathconfig_warnings, BOOL),
SPEC(program_name, WSTR), SPEC(program_name, WSTR),
SPEC(pythonpath_env, WSTR_OPT), SPEC(pythonpath_env, WSTR_OPT),
SPEC(home, WSTR_OPT), SPEC(home, WSTR_OPT),
SPEC(platlibdir, WSTR), SPEC(platlibdir, WSTR),
SPEC(sys_path_0, WSTR_OPT), SPEC(sys_path_0, WSTR_OPT),
SPEC(module_search_paths_set, UINT), SPEC(module_search_paths_set, BOOL),
SPEC(module_search_paths, WSTR_LIST), SPEC(module_search_paths, WSTR_LIST),
SPEC(stdlib_dir, WSTR_OPT), SPEC(stdlib_dir, WSTR_OPT),
SPEC(executable, WSTR_OPT), SPEC(executable, WSTR_OPT),
@ -108,15 +110,15 @@ static const PyConfigSpec PYCONFIG_SPEC[] = {
SPEC(base_prefix, WSTR_OPT), SPEC(base_prefix, WSTR_OPT),
SPEC(exec_prefix, WSTR_OPT), SPEC(exec_prefix, WSTR_OPT),
SPEC(base_exec_prefix, WSTR_OPT), SPEC(base_exec_prefix, WSTR_OPT),
SPEC(skip_source_first_line, UINT), SPEC(skip_source_first_line, BOOL),
SPEC(run_command, WSTR_OPT), SPEC(run_command, WSTR_OPT),
SPEC(run_module, WSTR_OPT), SPEC(run_module, WSTR_OPT),
SPEC(run_filename, WSTR_OPT), SPEC(run_filename, WSTR_OPT),
SPEC(_install_importlib, UINT), SPEC(_install_importlib, BOOL),
SPEC(_init_main, UINT), SPEC(_init_main, BOOL),
SPEC(_is_python_build, UINT), SPEC(_is_python_build, BOOL),
#ifdef Py_STATS #ifdef Py_STATS
SPEC(_pystats, UINT), SPEC(_pystats, BOOL),
#endif #endif
#ifdef Py_DEBUG #ifdef Py_DEBUG
SPEC(run_presite, WSTR_OPT), SPEC(run_presite, WSTR_OPT),
@ -1007,6 +1009,7 @@ _PyConfig_Copy(PyConfig *config, const PyConfig *config2)
switch (spec->type) { switch (spec->type) {
case PyConfig_MEMBER_INT: case PyConfig_MEMBER_INT:
case PyConfig_MEMBER_UINT: case PyConfig_MEMBER_UINT:
case PyConfig_MEMBER_BOOL:
{ {
*(int*)member = *(int*)member2; *(int*)member = *(int*)member2;
break; break;
@ -1062,6 +1065,12 @@ _PyConfig_AsDict(const PyConfig *config)
obj = PyLong_FromLong(value); obj = PyLong_FromLong(value);
break; break;
} }
case PyConfig_MEMBER_BOOL:
{
int value = *(int*)member;
obj = PyBool_FromLong(value);
break;
}
case PyConfig_MEMBER_ULONG: case PyConfig_MEMBER_ULONG:
{ {
unsigned long value = *(unsigned long*)member; unsigned long value = *(unsigned long*)member;
@ -1285,20 +1294,21 @@ _PyConfig_FromDict(PyConfig *config, PyObject *dict)
char *member = (char *)config + spec->offset; char *member = (char *)config + spec->offset;
switch (spec->type) { switch (spec->type) {
case PyConfig_MEMBER_INT: case PyConfig_MEMBER_INT:
if (config_dict_get_int(dict, spec->name, (int*)member) < 0) {
return -1;
}
break;
case PyConfig_MEMBER_UINT: case PyConfig_MEMBER_UINT:
case PyConfig_MEMBER_BOOL:
{ {
int value; int value;
if (config_dict_get_int(dict, spec->name, &value) < 0) { if (config_dict_get_int(dict, spec->name, &value) < 0) {
return -1; return -1;
} }
if (spec->type == PyConfig_MEMBER_BOOL
|| spec->type == PyConfig_MEMBER_UINT)
{
if (value < 0) { if (value < 0) {
config_dict_invalid_value(spec->name); config_dict_invalid_value(spec->name);
return -1; return -1;
} }
}
*(int*)member = value; *(int*)member = value;
break; break;
} }