]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-129033: Remove _PyInterpreterState_SetConfig() function (#129048)
authorVictor Stinner <vstinner@python.org>
Mon, 20 Jan 2025 15:31:33 +0000 (16:31 +0100)
committerGitHub <noreply@github.com>
Mon, 20 Jan 2025 15:31:33 +0000 (16:31 +0100)
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().

Include/internal/pycore_interp.h
Lib/test/_test_embed_set_config.py [deleted file]
Lib/test/support/__init__.py
Lib/test/test_capi/test_misc.py
Lib/test/test_embed.py
Lib/test/test_regrtest.py
Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst [new file with mode: 0644]
Modules/_testinternalcapi.c
Programs/_testembed.c
Python/pylifecycle.c
Python/pystate.c

index a3c14dceffd7a0c21201978ff842927ff98a69bb..f745b09796753b727c2b94ab721bc2587ca3e1ae 100644 (file)
@@ -341,43 +341,6 @@ extern void _PyInterpreterState_SetWhence(
 
 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
diff --git a/Lib/test/_test_embed_set_config.py b/Lib/test/_test_embed_set_config.py
deleted file mode 100644 (file)
index 7edb35d..0000000
+++ /dev/null
@@ -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()
index e05e91babc2499aeaf3b9cf25fb129e7c941fce1..084b2411e799f47db3de0309aea719f50612fbf9 100644 (file)
@@ -505,10 +505,10 @@ def requires_lzma(reason='requires lzma'):
 
 def has_no_debug_ranges():
     try:
-        import _testinternalcapi
+        import _testcapi
     except ImportError:
         raise unittest.SkipTest("_testinternalcapi required")
-    config = _testinternalcapi.get_config()
+    return not _testcapi.config_get('code_debug_ranges')
     return not bool(config['code_debug_ranges'])
 
 def requires_debug_ranges(reason='requires co_positions / debug_ranges'):
index ac09d72c7741c95b056b19a565ee753220a153b4..31a4a224ec8f8873e76b998bcfde97db4407de7a 100644 (file)
@@ -2141,28 +2141,27 @@ class SubinterpreterTest(unittest.TestCase):
             self.assertEqual(ret, 0)
             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):
         # 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
         # written around the time of int_max_str_digits. Refactoring is okay.
         code = """if 1:
-        import sys, _testinternalcapi
+        import sys, _testcapi
 
         # Any config value would do, this happens to be the one being
         # double checked at the time this test was written.
-        config = _testinternalcapi.get_config()
-        config['int_max_str_digits'] = 55555
-        config['parse_argv'] = 0
-        _testinternalcapi.set_config(config)
-        sub_value = _testinternalcapi.get_config()['int_max_str_digits']
+        _testcapi.config_set('int_max_str_digits', 55555)
+        sub_value = _testcapi.config_get('int_max_str_digits')
         assert sub_value == 55555, sub_value
         """
-        before_config = _testinternalcapi.get_config()
-        assert before_config['int_max_str_digits'] != 55555
+        before_config = _testcapi.config_get('int_max_str_digits')
+        assert before_config != 55555
         self.assertEqual(support.run_in_subinterp(code), 0,
                          'subinterp code failure, check stderr.')
-        after_config = _testinternalcapi.get_config()
+        after_config = _testcapi.config_get('int_max_str_digits')
         self.assertIsNot(
                 before_config, after_config,
                 "Expected get_config() to return a new dict on each call")
index 6d1b4cce498276a4b973494a03f8acde9f35111b..bd01913e49d170a8f31e613f804c09cc8230d7d9 100644 (file)
@@ -1746,14 +1746,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
         self.check_all_configs("test_init_warnoptions", config, preconfig,
                                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")
     def test_initconfig_api(self):
         preconfig = {
@@ -1845,22 +1837,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
         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):
     def test_open_code_hook(self):
         self.run_embedded_interpreter("test_open_code_hook")
index ab46ccbf004a3ac4e15f219e2dd8018459ee6215..5707b355e94337a8e5f196490a8171f884ab2754 100644 (file)
@@ -2145,25 +2145,25 @@ class ArgsTestCase(BaseTestCase):
             import unittest
             from test import support
             try:
-                from _testinternalcapi import get_config
+                from _testcapi import config_get
             except ImportError:
-                get_config = None
+                config_get = None
 
             # WASI/WASM buildbots don't use -E option
             use_environment = (support.is_emscripten or support.is_wasi)
 
             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):
-                    config = get_config()['config']
+                    config = config_get()
                     # -u option
-                    self.assertEqual(config['buffered_stdio'], 0)
+                    self.assertEqual(config_get('buffered_stdio'), 0)
                     # -W default option
-                    self.assertTrue(config['warnoptions'], ['default'])
+                    self.assertTrue(config_get('warnoptions'), ['default'])
                     # -bb option
-                    self.assertTrue(config['bytes_warning'], 2)
+                    self.assertTrue(config_get('bytes_warning'), 2)
                     # -E option
-                    self.assertTrue(config['use_environment'], use_environment)
+                    self.assertTrue(config_get('use_environment'), use_environment)
 
                 def test_python_opts(self):
                     # -u option
diff --git a/Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst b/Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst
new file mode 100644 (file)
index 0000000..c0c109d
--- /dev/null
@@ -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.
index 98aea5b596e9208f0db5d1bb49e87f9f5052dc63..aae09f620b8898e9110ddf5b91ec162567e9dad5 100644 (file)
@@ -25,7 +25,6 @@
 #include "pycore_hashtable.h"     // _Py_hashtable_new()
 #include "pycore_initconfig.h"    // _Py_GetConfigsAsDict()
 #include "pycore_instruction_sequence.h"  // _PyInstructionSequence_New()
-#include "pycore_interp.h"        // _PyInterpreterState_GetConfigCopy()
 #include "pycore_long.h"          // _PyLong_Sign()
 #include "pycore_object.h"        // _PyObject_IsFreed()
 #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 *
 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_bit_length", test_bit_length, 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},
     {"test_edit_cost", test_edit_cost, METH_NOARGS},
     {"test_bytes_find", test_bytes_find, METH_NOARGS},
index 3681a89376638ab24e42937c8d538d62b9ec7b79..6f6d0cae58010e1780ed99b20967ff6a16f07969 100644 (file)
@@ -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)
 {
     int64_t value;
@@ -2445,7 +2403,6 @@ static struct TestCase TestCases[] = {
     {"test_init_setpythonhome", test_init_setpythonhome},
     {"test_init_is_python_build", test_init_is_python_build},
     {"test_init_warnoptions", test_init_warnoptions},
-    {"test_init_set_config", test_init_set_config},
     {"test_initconfig_api", test_initconfig_api},
     {"test_initconfig_get_api", test_initconfig_get_api},
     {"test_initconfig_exit", test_initconfig_exit},
index 8ec12b437f82982ba2dd65e69d2d26c436147a48..ea8a291a8e5eb4db13340f2c18b7c1b0475cd94d 100644 (file)
@@ -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
    call this twice without an intervening Py_Finalize() call.
 
index 52703b048d6022951a0342ab0bbe5ff7164fc29d..e5003021b83f00c22f940bdaf68ddce4d1be201b 100644 (file)
@@ -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*
 _Py_GetConfig(void)
 {