mirror of
https://github.com/python/cpython.git
synced 2025-10-10 00:43:41 +00:00
gh-129033: Remove _PyInterpreterState_SetConfig() function (#129048)
Remove _PyInterpreterState_GetConfigCopy() and _PyInterpreterState_SetConfig() private functions. PEP 741 "Python Configuration C API" added a better public C API: PyConfig_Get() and PyConfig_Set().
This commit is contained in:
parent
573c181502
commit
8ceb6cb117
11 changed files with 22 additions and 500 deletions
|
@ -341,43 +341,6 @@ extern void _PyInterpreterState_SetWhence(
|
||||||
|
|
||||||
extern const PyConfig* _PyInterpreterState_GetConfig(PyInterpreterState *interp);
|
extern const PyConfig* _PyInterpreterState_GetConfig(PyInterpreterState *interp);
|
||||||
|
|
||||||
// Get a copy of the current interpreter configuration.
|
|
||||||
//
|
|
||||||
// Return 0 on success. Raise an exception and return -1 on error.
|
|
||||||
//
|
|
||||||
// The caller must initialize 'config', using PyConfig_InitPythonConfig()
|
|
||||||
// for example.
|
|
||||||
//
|
|
||||||
// Python must be preinitialized to call this method.
|
|
||||||
// The caller must hold the GIL.
|
|
||||||
//
|
|
||||||
// Once done with the configuration, PyConfig_Clear() must be called to clear
|
|
||||||
// it.
|
|
||||||
//
|
|
||||||
// Export for '_testinternalcapi' shared extension.
|
|
||||||
PyAPI_FUNC(int) _PyInterpreterState_GetConfigCopy(
|
|
||||||
struct PyConfig *config);
|
|
||||||
|
|
||||||
// Set the configuration of the current interpreter.
|
|
||||||
//
|
|
||||||
// This function should be called during or just after the Python
|
|
||||||
// initialization.
|
|
||||||
//
|
|
||||||
// Update the sys module with the new configuration. If the sys module was
|
|
||||||
// modified directly after the Python initialization, these changes are lost.
|
|
||||||
//
|
|
||||||
// Some configuration like faulthandler or warnoptions can be updated in the
|
|
||||||
// configuration, but don't reconfigure Python (don't enable/disable
|
|
||||||
// faulthandler and don't reconfigure warnings filters).
|
|
||||||
//
|
|
||||||
// Return 0 on success. Raise an exception and return -1 on error.
|
|
||||||
//
|
|
||||||
// The configuration should come from _PyInterpreterState_GetConfigCopy().
|
|
||||||
//
|
|
||||||
// Export for '_testinternalcapi' shared extension.
|
|
||||||
PyAPI_FUNC(int) _PyInterpreterState_SetConfig(
|
|
||||||
const struct PyConfig *config);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Runtime Feature Flags
|
Runtime Feature Flags
|
||||||
|
|
|
@ -1,291 +0,0 @@
|
||||||
# bpo-42260: Test _PyInterpreterState_GetConfigCopy()
|
|
||||||
# and _PyInterpreterState_SetConfig().
|
|
||||||
#
|
|
||||||
# Test run in a subprocess since set_config(get_config())
|
|
||||||
# does reset sys attributes to their state of the Python startup
|
|
||||||
# (before the site module is run).
|
|
||||||
|
|
||||||
import _testinternalcapi
|
|
||||||
import sys
|
|
||||||
import unittest
|
|
||||||
from test import support
|
|
||||||
from test.support import MS_WINDOWS
|
|
||||||
|
|
||||||
|
|
||||||
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):
|
|
||||||
def setUp(self):
|
|
||||||
self.old_config = _testinternalcapi.get_config()
|
|
||||||
self.sys_copy = dict(sys.__dict__)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
_testinternalcapi.reset_path_config()
|
|
||||||
_testinternalcapi.set_config(self.old_config)
|
|
||||||
sys.__dict__.clear()
|
|
||||||
sys.__dict__.update(self.sys_copy)
|
|
||||||
|
|
||||||
def set_config(self, **kwargs):
|
|
||||||
_testinternalcapi.set_config(self.old_config | kwargs)
|
|
||||||
|
|
||||||
def check(self, **kwargs):
|
|
||||||
self.set_config(**kwargs)
|
|
||||||
for key, value in kwargs.items():
|
|
||||||
self.assertEqual(getattr(sys, key), value,
|
|
||||||
(key, value))
|
|
||||||
|
|
||||||
def test_set_invalid(self):
|
|
||||||
invalid_uint = -1
|
|
||||||
NULL = None
|
|
||||||
invalid_wstr = NULL
|
|
||||||
# PyWideStringList strings must be non-NULL
|
|
||||||
invalid_wstrlist = ["abc", NULL, "def"]
|
|
||||||
|
|
||||||
type_tests = []
|
|
||||||
value_tests = [
|
|
||||||
# enum
|
|
||||||
('_config_init', 0),
|
|
||||||
('_config_init', 4),
|
|
||||||
# unsigned long
|
|
||||||
("hash_seed", -1),
|
|
||||||
("hash_seed", MAX_HASH_SEED + 1),
|
|
||||||
]
|
|
||||||
|
|
||||||
# int (unsigned)
|
|
||||||
int_options = [
|
|
||||||
'_config_init',
|
|
||||||
'bytes_warning',
|
|
||||||
'optimization_level',
|
|
||||||
'tracemalloc',
|
|
||||||
'verbose',
|
|
||||||
]
|
|
||||||
int_options.extend(BOOL_OPTIONS)
|
|
||||||
for key in int_options:
|
|
||||||
value_tests.append((key, invalid_uint))
|
|
||||||
type_tests.append((key, "abc"))
|
|
||||||
type_tests.append((key, 2.0))
|
|
||||||
|
|
||||||
# wchar_t*
|
|
||||||
for key in (
|
|
||||||
'filesystem_encoding',
|
|
||||||
'filesystem_errors',
|
|
||||||
'stdio_encoding',
|
|
||||||
'stdio_errors',
|
|
||||||
'check_hash_pycs_mode',
|
|
||||||
'program_name',
|
|
||||||
'platlibdir',
|
|
||||||
# optional wstr:
|
|
||||||
# 'pythonpath_env'
|
|
||||||
# 'home'
|
|
||||||
# 'pycache_prefix'
|
|
||||||
# 'run_command'
|
|
||||||
# 'run_module'
|
|
||||||
# 'run_filename'
|
|
||||||
# 'executable'
|
|
||||||
# 'prefix'
|
|
||||||
# 'exec_prefix'
|
|
||||||
# 'base_executable'
|
|
||||||
# 'base_prefix'
|
|
||||||
# 'base_exec_prefix'
|
|
||||||
):
|
|
||||||
value_tests.append((key, invalid_wstr))
|
|
||||||
type_tests.append((key, b'bytes'))
|
|
||||||
type_tests.append((key, 123))
|
|
||||||
|
|
||||||
# PyWideStringList
|
|
||||||
for key in (
|
|
||||||
'orig_argv',
|
|
||||||
'argv',
|
|
||||||
'xoptions',
|
|
||||||
'warnoptions',
|
|
||||||
'module_search_paths',
|
|
||||||
):
|
|
||||||
if key != 'xoptions':
|
|
||||||
value_tests.append((key, invalid_wstrlist))
|
|
||||||
type_tests.append((key, 123))
|
|
||||||
type_tests.append((key, "abc"))
|
|
||||||
type_tests.append((key, [123]))
|
|
||||||
type_tests.append((key, [b"bytes"]))
|
|
||||||
|
|
||||||
|
|
||||||
if MS_WINDOWS:
|
|
||||||
value_tests.append(('legacy_windows_stdio', invalid_uint))
|
|
||||||
|
|
||||||
for exc_type, tests in (
|
|
||||||
(ValueError, value_tests),
|
|
||||||
(TypeError, type_tests),
|
|
||||||
):
|
|
||||||
for key, value in tests:
|
|
||||||
config = self.old_config | {key: value}
|
|
||||||
with self.subTest(key=key, value=value, exc_type=exc_type):
|
|
||||||
with self.assertRaises(exc_type):
|
|
||||||
_testinternalcapi.set_config(config)
|
|
||||||
|
|
||||||
def test_flags(self):
|
|
||||||
bool_options = set(BOOL_OPTIONS)
|
|
||||||
for sys_attr, key, value in (
|
|
||||||
("debug", "parser_debug", 2),
|
|
||||||
("inspect", "inspect", 3),
|
|
||||||
("interactive", "interactive", 4),
|
|
||||||
("optimize", "optimization_level", 5),
|
|
||||||
("verbose", "verbose", 6),
|
|
||||||
("bytes_warning", "bytes_warning", 7),
|
|
||||||
("quiet", "quiet", 8),
|
|
||||||
("isolated", "isolated", 9),
|
|
||||||
):
|
|
||||||
with self.subTest(sys=sys_attr, key=key, value=value):
|
|
||||||
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.set_config(write_bytecode=0)
|
|
||||||
self.assertEqual(sys.flags.dont_write_bytecode, True)
|
|
||||||
self.assertEqual(sys.dont_write_bytecode, True)
|
|
||||||
|
|
||||||
self.set_config(write_bytecode=1)
|
|
||||||
self.assertEqual(sys.flags.dont_write_bytecode, False)
|
|
||||||
self.assertEqual(sys.dont_write_bytecode, False)
|
|
||||||
|
|
||||||
self.set_config(user_site_directory=0, isolated=0)
|
|
||||||
self.assertEqual(sys.flags.no_user_site, 1)
|
|
||||||
self.set_config(user_site_directory=1, isolated=0)
|
|
||||||
self.assertEqual(sys.flags.no_user_site, 0)
|
|
||||||
|
|
||||||
self.set_config(site_import=0)
|
|
||||||
self.assertEqual(sys.flags.no_site, 1)
|
|
||||||
self.set_config(site_import=1)
|
|
||||||
self.assertEqual(sys.flags.no_site, 0)
|
|
||||||
|
|
||||||
self.set_config(dev_mode=0)
|
|
||||||
self.assertEqual(sys.flags.dev_mode, False)
|
|
||||||
self.set_config(dev_mode=1)
|
|
||||||
self.assertEqual(sys.flags.dev_mode, True)
|
|
||||||
|
|
||||||
self.set_config(use_environment=0, isolated=0)
|
|
||||||
self.assertEqual(sys.flags.ignore_environment, 1)
|
|
||||||
self.set_config(use_environment=1, isolated=0)
|
|
||||||
self.assertEqual(sys.flags.ignore_environment, 0)
|
|
||||||
|
|
||||||
self.set_config(use_hash_seed=1, hash_seed=0)
|
|
||||||
self.assertEqual(sys.flags.hash_randomization, 0)
|
|
||||||
self.set_config(use_hash_seed=0, hash_seed=0)
|
|
||||||
self.assertEqual(sys.flags.hash_randomization, 1)
|
|
||||||
self.set_config(use_hash_seed=1, hash_seed=123)
|
|
||||||
self.assertEqual(sys.flags.hash_randomization, 1)
|
|
||||||
|
|
||||||
if support.Py_GIL_DISABLED:
|
|
||||||
self.set_config(enable_gil=-1)
|
|
||||||
self.assertEqual(sys.flags.gil, None)
|
|
||||||
self.set_config(enable_gil=0)
|
|
||||||
self.assertEqual(sys.flags.gil, 0)
|
|
||||||
self.set_config(enable_gil=1)
|
|
||||||
self.assertEqual(sys.flags.gil, 1)
|
|
||||||
else:
|
|
||||||
# Builds without Py_GIL_DISABLED don't have
|
|
||||||
# PyConfig.enable_gil. sys.flags.gil is always defined to 1, for
|
|
||||||
# consistency.
|
|
||||||
self.assertEqual(sys.flags.gil, 1)
|
|
||||||
|
|
||||||
def test_options(self):
|
|
||||||
self.check(warnoptions=[])
|
|
||||||
self.check(warnoptions=["default", "ignore"])
|
|
||||||
|
|
||||||
self.set_config(xoptions={})
|
|
||||||
self.assertEqual(sys._xoptions, {})
|
|
||||||
self.set_config(xoptions={"dev": True, "tracemalloc": "5"})
|
|
||||||
self.assertEqual(sys._xoptions, {"dev": True, "tracemalloc": "5"})
|
|
||||||
|
|
||||||
def test_pathconfig(self):
|
|
||||||
self.check(
|
|
||||||
executable='executable',
|
|
||||||
prefix="prefix",
|
|
||||||
base_prefix="base_prefix",
|
|
||||||
exec_prefix="exec_prefix",
|
|
||||||
base_exec_prefix="base_exec_prefix",
|
|
||||||
platlibdir="platlibdir")
|
|
||||||
|
|
||||||
self.set_config(base_executable="base_executable")
|
|
||||||
self.assertEqual(sys._base_executable, "base_executable")
|
|
||||||
|
|
||||||
# When base_xxx is NULL, value is copied from xxxx
|
|
||||||
self.set_config(
|
|
||||||
executable='executable',
|
|
||||||
prefix="prefix",
|
|
||||||
exec_prefix="exec_prefix",
|
|
||||||
base_executable=None,
|
|
||||||
base_prefix=None,
|
|
||||||
base_exec_prefix=None)
|
|
||||||
self.assertEqual(sys._base_executable, "executable")
|
|
||||||
self.assertEqual(sys.base_prefix, "prefix")
|
|
||||||
self.assertEqual(sys.base_exec_prefix, "exec_prefix")
|
|
||||||
|
|
||||||
def test_path(self):
|
|
||||||
self.set_config(module_search_paths_set=1,
|
|
||||||
module_search_paths=['a', 'b', 'c'])
|
|
||||||
self.assertEqual(sys.path, ['a', 'b', 'c'])
|
|
||||||
|
|
||||||
# sys.path is reset if module_search_paths_set=0
|
|
||||||
self.set_config(module_search_paths_set=0,
|
|
||||||
module_search_paths=['new_path'])
|
|
||||||
self.assertNotEqual(sys.path, ['a', 'b', 'c'])
|
|
||||||
self.assertNotEqual(sys.path, ['new_path'])
|
|
||||||
|
|
||||||
def test_argv(self):
|
|
||||||
self.set_config(parse_argv=0,
|
|
||||||
argv=['python_program', 'args'],
|
|
||||||
orig_argv=['orig', 'orig_args'])
|
|
||||||
self.assertEqual(sys.argv, ['python_program', 'args'])
|
|
||||||
self.assertEqual(sys.orig_argv, ['orig', 'orig_args'])
|
|
||||||
|
|
||||||
self.set_config(parse_argv=0,
|
|
||||||
argv=[],
|
|
||||||
orig_argv=[])
|
|
||||||
self.assertEqual(sys.argv, [''])
|
|
||||||
self.assertEqual(sys.orig_argv, [])
|
|
||||||
|
|
||||||
def test_pycache_prefix(self):
|
|
||||||
self.check(pycache_prefix=None)
|
|
||||||
self.check(pycache_prefix="pycache_prefix")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
unittest.main()
|
|
|
@ -505,10 +505,10 @@ def requires_lzma(reason='requires lzma'):
|
||||||
|
|
||||||
def has_no_debug_ranges():
|
def has_no_debug_ranges():
|
||||||
try:
|
try:
|
||||||
import _testinternalcapi
|
import _testcapi
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise unittest.SkipTest("_testinternalcapi required")
|
raise unittest.SkipTest("_testinternalcapi required")
|
||||||
config = _testinternalcapi.get_config()
|
return not _testcapi.config_get('code_debug_ranges')
|
||||||
return not bool(config['code_debug_ranges'])
|
return not bool(config['code_debug_ranges'])
|
||||||
|
|
||||||
def requires_debug_ranges(reason='requires co_positions / debug_ranges'):
|
def requires_debug_ranges(reason='requires co_positions / debug_ranges'):
|
||||||
|
|
|
@ -2141,28 +2141,27 @@ class SubinterpreterTest(unittest.TestCase):
|
||||||
self.assertEqual(ret, 0)
|
self.assertEqual(ret, 0)
|
||||||
self.assertEqual(pickle.load(f), {'a': '123x', 'b': '123'})
|
self.assertEqual(pickle.load(f), {'a': '123x', 'b': '123'})
|
||||||
|
|
||||||
|
# _testcapi cannot be imported in a subinterpreter on a Free Threaded build
|
||||||
|
@support.requires_gil_enabled()
|
||||||
def test_py_config_isoloated_per_interpreter(self):
|
def test_py_config_isoloated_per_interpreter(self):
|
||||||
# A config change in one interpreter must not leak to out to others.
|
# A config change in one interpreter must not leak to out to others.
|
||||||
#
|
#
|
||||||
# This test could verify ANY config value, it just happens to have been
|
# This test could verify ANY config value, it just happens to have been
|
||||||
# written around the time of int_max_str_digits. Refactoring is okay.
|
# written around the time of int_max_str_digits. Refactoring is okay.
|
||||||
code = """if 1:
|
code = """if 1:
|
||||||
import sys, _testinternalcapi
|
import sys, _testcapi
|
||||||
|
|
||||||
# Any config value would do, this happens to be the one being
|
# Any config value would do, this happens to be the one being
|
||||||
# double checked at the time this test was written.
|
# double checked at the time this test was written.
|
||||||
config = _testinternalcapi.get_config()
|
_testcapi.config_set('int_max_str_digits', 55555)
|
||||||
config['int_max_str_digits'] = 55555
|
sub_value = _testcapi.config_get('int_max_str_digits')
|
||||||
config['parse_argv'] = 0
|
|
||||||
_testinternalcapi.set_config(config)
|
|
||||||
sub_value = _testinternalcapi.get_config()['int_max_str_digits']
|
|
||||||
assert sub_value == 55555, sub_value
|
assert sub_value == 55555, sub_value
|
||||||
"""
|
"""
|
||||||
before_config = _testinternalcapi.get_config()
|
before_config = _testcapi.config_get('int_max_str_digits')
|
||||||
assert before_config['int_max_str_digits'] != 55555
|
assert before_config != 55555
|
||||||
self.assertEqual(support.run_in_subinterp(code), 0,
|
self.assertEqual(support.run_in_subinterp(code), 0,
|
||||||
'subinterp code failure, check stderr.')
|
'subinterp code failure, check stderr.')
|
||||||
after_config = _testinternalcapi.get_config()
|
after_config = _testcapi.config_get('int_max_str_digits')
|
||||||
self.assertIsNot(
|
self.assertIsNot(
|
||||||
before_config, after_config,
|
before_config, after_config,
|
||||||
"Expected get_config() to return a new dict on each call")
|
"Expected get_config() to return a new dict on each call")
|
||||||
|
|
|
@ -1746,14 +1746,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
self.check_all_configs("test_init_warnoptions", config, preconfig,
|
self.check_all_configs("test_init_warnoptions", config, preconfig,
|
||||||
api=API_PYTHON)
|
api=API_PYTHON)
|
||||||
|
|
||||||
def test_init_set_config(self):
|
|
||||||
config = {
|
|
||||||
'bytes_warning': 2,
|
|
||||||
'warnoptions': ['error::BytesWarning'],
|
|
||||||
}
|
|
||||||
self.check_all_configs("test_init_set_config", config,
|
|
||||||
api=API_ISOLATED)
|
|
||||||
|
|
||||||
@unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
|
@unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
|
||||||
def test_initconfig_api(self):
|
def test_initconfig_api(self):
|
||||||
preconfig = {
|
preconfig = {
|
||||||
|
@ -1845,22 +1837,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
self.assertEqual(err, "")
|
self.assertEqual(err, "")
|
||||||
|
|
||||||
|
|
||||||
class SetConfigTests(unittest.TestCase):
|
|
||||||
def test_set_config(self):
|
|
||||||
# bpo-42260: Test _PyInterpreterState_SetConfig()
|
|
||||||
import_helper.import_module('_testcapi')
|
|
||||||
cmd = [sys.executable, '-X', 'utf8', '-I', '-m', 'test._test_embed_set_config']
|
|
||||||
proc = subprocess.run(cmd,
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
encoding='utf-8', errors='backslashreplace')
|
|
||||||
if proc.returncode and support.verbose:
|
|
||||||
print(proc.stdout)
|
|
||||||
print(proc.stderr)
|
|
||||||
self.assertEqual(proc.returncode, 0,
|
|
||||||
(proc.returncode, proc.stdout, proc.stderr))
|
|
||||||
|
|
||||||
|
|
||||||
class AuditingTests(EmbeddingTestsMixin, unittest.TestCase):
|
class AuditingTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
def test_open_code_hook(self):
|
def test_open_code_hook(self):
|
||||||
self.run_embedded_interpreter("test_open_code_hook")
|
self.run_embedded_interpreter("test_open_code_hook")
|
||||||
|
|
|
@ -2145,25 +2145,25 @@ class ArgsTestCase(BaseTestCase):
|
||||||
import unittest
|
import unittest
|
||||||
from test import support
|
from test import support
|
||||||
try:
|
try:
|
||||||
from _testinternalcapi import get_config
|
from _testcapi import config_get
|
||||||
except ImportError:
|
except ImportError:
|
||||||
get_config = None
|
config_get = None
|
||||||
|
|
||||||
# WASI/WASM buildbots don't use -E option
|
# WASI/WASM buildbots don't use -E option
|
||||||
use_environment = (support.is_emscripten or support.is_wasi)
|
use_environment = (support.is_emscripten or support.is_wasi)
|
||||||
|
|
||||||
class WorkerTests(unittest.TestCase):
|
class WorkerTests(unittest.TestCase):
|
||||||
@unittest.skipUnless(get_config is None, 'need get_config()')
|
@unittest.skipUnless(config_get is None, 'need config_get()')
|
||||||
def test_config(self):
|
def test_config(self):
|
||||||
config = get_config()['config']
|
config = config_get()
|
||||||
# -u option
|
# -u option
|
||||||
self.assertEqual(config['buffered_stdio'], 0)
|
self.assertEqual(config_get('buffered_stdio'), 0)
|
||||||
# -W default option
|
# -W default option
|
||||||
self.assertTrue(config['warnoptions'], ['default'])
|
self.assertTrue(config_get('warnoptions'), ['default'])
|
||||||
# -bb option
|
# -bb option
|
||||||
self.assertTrue(config['bytes_warning'], 2)
|
self.assertTrue(config_get('bytes_warning'), 2)
|
||||||
# -E option
|
# -E option
|
||||||
self.assertTrue(config['use_environment'], use_environment)
|
self.assertTrue(config_get('use_environment'), use_environment)
|
||||||
|
|
||||||
def test_python_opts(self):
|
def test_python_opts(self):
|
||||||
# -u option
|
# -u option
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Remove ``_PyInterpreterState_GetConfigCopy()`` and
|
||||||
|
``_PyInterpreterState_SetConfig()`` private functions. Use instead
|
||||||
|
:c:func:`PyConfig_Get` and :c:func:`PyConfig_Set`, public C API added by
|
||||||
|
:pep:`741` "Python Configuration C API". Patch by Victor Stinner.
|
|
@ -25,7 +25,6 @@
|
||||||
#include "pycore_hashtable.h" // _Py_hashtable_new()
|
#include "pycore_hashtable.h" // _Py_hashtable_new()
|
||||||
#include "pycore_initconfig.h" // _Py_GetConfigsAsDict()
|
#include "pycore_initconfig.h" // _Py_GetConfigsAsDict()
|
||||||
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_New()
|
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_New()
|
||||||
#include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy()
|
|
||||||
#include "pycore_long.h" // _PyLong_Sign()
|
#include "pycore_long.h" // _PyLong_Sign()
|
||||||
#include "pycore_object.h" // _PyObject_IsFreed()
|
#include "pycore_object.h" // _PyObject_IsFreed()
|
||||||
#include "pycore_optimizer.h" // _Py_UopsSymbol, etc.
|
#include "pycore_optimizer.h" // _Py_UopsSymbol, etc.
|
||||||
|
@ -318,41 +317,6 @@ test_hashtable(PyObject *self, PyObject *Py_UNUSED(args))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
test_get_config(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
|
|
||||||
{
|
|
||||||
PyConfig config;
|
|
||||||
PyConfig_InitIsolatedConfig(&config);
|
|
||||||
if (_PyInterpreterState_GetConfigCopy(&config) < 0) {
|
|
||||||
PyConfig_Clear(&config);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
PyObject *dict = _PyConfig_AsDict(&config);
|
|
||||||
PyConfig_Clear(&config);
|
|
||||||
return dict;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
test_set_config(PyObject *Py_UNUSED(self), PyObject *dict)
|
|
||||||
{
|
|
||||||
PyConfig config;
|
|
||||||
PyConfig_InitIsolatedConfig(&config);
|
|
||||||
if (_PyConfig_FromDict(&config, dict) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (_PyInterpreterState_SetConfig(&config) < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
PyConfig_Clear(&config);
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
|
|
||||||
error:
|
|
||||||
PyConfig_Clear(&config);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
test_reset_path_config(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(arg))
|
test_reset_path_config(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(arg))
|
||||||
{
|
{
|
||||||
|
@ -2062,8 +2026,6 @@ static PyMethodDef module_functions[] = {
|
||||||
{"test_popcount", test_popcount, METH_NOARGS},
|
{"test_popcount", test_popcount, METH_NOARGS},
|
||||||
{"test_bit_length", test_bit_length, METH_NOARGS},
|
{"test_bit_length", test_bit_length, METH_NOARGS},
|
||||||
{"test_hashtable", test_hashtable, METH_NOARGS},
|
{"test_hashtable", test_hashtable, METH_NOARGS},
|
||||||
{"get_config", test_get_config, METH_NOARGS},
|
|
||||||
{"set_config", test_set_config, METH_O},
|
|
||||||
{"reset_path_config", test_reset_path_config, METH_NOARGS},
|
{"reset_path_config", test_reset_path_config, METH_NOARGS},
|
||||||
{"test_edit_cost", test_edit_cost, METH_NOARGS},
|
{"test_edit_cost", test_edit_cost, METH_NOARGS},
|
||||||
{"test_bytes_find", test_bytes_find, METH_NOARGS},
|
{"test_bytes_find", test_bytes_find, METH_NOARGS},
|
||||||
|
|
|
@ -1791,48 +1791,6 @@ static int test_init_warnoptions(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int tune_config(void)
|
|
||||||
{
|
|
||||||
PyConfig config;
|
|
||||||
PyConfig_InitPythonConfig(&config);
|
|
||||||
if (_PyInterpreterState_GetConfigCopy(&config) < 0) {
|
|
||||||
PyConfig_Clear(&config);
|
|
||||||
PyErr_Print();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
config.bytes_warning = 2;
|
|
||||||
|
|
||||||
if (_PyInterpreterState_SetConfig(&config) < 0) {
|
|
||||||
PyConfig_Clear(&config);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
PyConfig_Clear(&config);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int test_init_set_config(void)
|
|
||||||
{
|
|
||||||
// Initialize core
|
|
||||||
PyConfig config;
|
|
||||||
PyConfig_InitIsolatedConfig(&config);
|
|
||||||
config_set_string(&config, &config.program_name, PROGRAM_NAME);
|
|
||||||
config.bytes_warning = 0;
|
|
||||||
init_from_config_clear(&config);
|
|
||||||
|
|
||||||
// Tune the configuration using _PyInterpreterState_SetConfig()
|
|
||||||
if (tune_config() < 0) {
|
|
||||||
PyErr_Print();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_config();
|
|
||||||
Py_Finalize();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int initconfig_getint(PyInitConfig *config, const char *name)
|
static int initconfig_getint(PyInitConfig *config, const char *name)
|
||||||
{
|
{
|
||||||
int64_t value;
|
int64_t value;
|
||||||
|
@ -2445,7 +2403,6 @@ static struct TestCase TestCases[] = {
|
||||||
{"test_init_setpythonhome", test_init_setpythonhome},
|
{"test_init_setpythonhome", test_init_setpythonhome},
|
||||||
{"test_init_is_python_build", test_init_is_python_build},
|
{"test_init_is_python_build", test_init_is_python_build},
|
||||||
{"test_init_warnoptions", test_init_warnoptions},
|
{"test_init_warnoptions", test_init_warnoptions},
|
||||||
{"test_init_set_config", test_init_set_config},
|
|
||||||
{"test_initconfig_api", test_initconfig_api},
|
{"test_initconfig_api", test_initconfig_api},
|
||||||
{"test_initconfig_get_api", test_initconfig_get_api},
|
{"test_initconfig_get_api", test_initconfig_get_api},
|
||||||
{"test_initconfig_exit", test_initconfig_exit},
|
{"test_initconfig_exit", test_initconfig_exit},
|
||||||
|
|
|
@ -444,40 +444,6 @@ interpreter_update_config(PyThreadState *tstate, int only_update_path_config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
_PyInterpreterState_SetConfig(const PyConfig *src_config)
|
|
||||||
{
|
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
|
||||||
int res = -1;
|
|
||||||
|
|
||||||
PyConfig config;
|
|
||||||
PyConfig_InitPythonConfig(&config);
|
|
||||||
PyStatus status = _PyConfig_Copy(&config, src_config);
|
|
||||||
if (_PyStatus_EXCEPTION(status)) {
|
|
||||||
_PyErr_SetFromPyStatus(status);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = _PyConfig_Read(&config, 1);
|
|
||||||
if (_PyStatus_EXCEPTION(status)) {
|
|
||||||
_PyErr_SetFromPyStatus(status);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = _PyConfig_Copy(&tstate->interp->config, &config);
|
|
||||||
if (_PyStatus_EXCEPTION(status)) {
|
|
||||||
_PyErr_SetFromPyStatus(status);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = interpreter_update_config(tstate, 0);
|
|
||||||
|
|
||||||
done:
|
|
||||||
PyConfig_Clear(&config);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Global initializations. Can be undone by Py_Finalize(). Don't
|
/* Global initializations. Can be undone by Py_Finalize(). Don't
|
||||||
call this twice without an intervening Py_Finalize() call.
|
call this twice without an intervening Py_Finalize() call.
|
||||||
|
|
||||||
|
|
|
@ -2880,20 +2880,6 @@ _PyInterpreterState_GetConfig(PyInterpreterState *interp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
_PyInterpreterState_GetConfigCopy(PyConfig *config)
|
|
||||||
{
|
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
|
||||||
|
|
||||||
PyStatus status = _PyConfig_Copy(config, &interp->config);
|
|
||||||
if (PyStatus_Exception(status)) {
|
|
||||||
_PyErr_SetFromPyStatus(status);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const PyConfig*
|
const PyConfig*
|
||||||
_Py_GetConfig(void)
|
_Py_GetConfig(void)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue