From eb053c3103dffd157d867fe8baabba25b8f80be4 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Sep 2026 19:16:17 +0200 Subject: [PATCH 1/9] gh-158001: Remove global configuration variables from C API Keep 4 variables in the stable ABI: * Py_FileSystemDefaultEncodeErrors * Py_FileSystemDefaultEncoding * Py_HasFileSystemDefaultEncoding * Py_UTF8Mode --- Doc/c-api/interp-lifecycle.rst | 274 +---------------- Doc/whatsnew/3.16.rst | 70 +++++ Include/cpython/pydebug.h | 21 -- Include/fileobject.h | 13 - Include/internal/pycore_fileutils.h | 2 - Lib/test/test_embed.py | 41 +-- ...-09-23-19-37-53.gh-issue-158001.X_Xamm.rst | 25 ++ Programs/_testembed.c | 3 + Python/initconfig.c | 275 ++++++------------ Python/preconfig.c | 43 +-- 10 files changed, 203 insertions(+), 564 deletions(-) create mode 100644 Misc/NEWS.d/next/C_API/2026-09-23-19-37-53.gh-issue-158001.X_Xamm.rst diff --git a/Doc/c-api/interp-lifecycle.rst b/Doc/c-api/interp-lifecycle.rst index 46f5b1dd33963c..7515baa18a1f03 100644 --- a/Doc/c-api/interp-lifecycle.rst +++ b/Doc/c-api/interp-lifecycle.rst @@ -15,8 +15,7 @@ Before Python initialization In an application embedding Python, the :c:func:`Py_Initialize` function must be called before using any other Python/C API functions; with the exception of -a few functions and the :ref:`global configuration variables -`. +a few functions. The following functions can be safely called before Python is initialized: @@ -78,277 +77,6 @@ The following functions can be safely called before Python is initialized: :c:func:`Py_RunMain`. -.. _global-conf-vars: - -Global configuration variables ------------------------------- - -Python has variables for the global configuration to control different features -and options. By default, these flags are controlled by :ref:`command line -options `. - -When a flag is set by an option, the value of the flag is the number of times -that the option was set. For example, ``-b`` sets :c:data:`Py_BytesWarningFlag` -to 1 and ``-bb`` sets :c:data:`Py_BytesWarningFlag` to 2. - - -.. c:var:: int Py_BytesWarningFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.bytes_warning` should be used instead, see :ref:`Python - Initialization Configuration `. - - Issue a warning when comparing :class:`bytes` or :class:`bytearray` with - :class:`str` or :class:`bytes` with :class:`int`. Issue an error if greater - or equal to ``2``. - - Set by the :option:`-b` option. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_DebugFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.parser_debug` should be used instead, see :ref:`Python - Initialization Configuration `. - - Turn on parser debugging output (for expert only, depending on compilation - options). - - Set by the :option:`-d` option and the :envvar:`PYTHONDEBUG` environment - variable. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_DontWriteBytecodeFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.write_bytecode` should be used instead, see :ref:`Python - Initialization Configuration `. - - If set to non-zero, Python won't try to write ``.pyc`` files on the - import of source modules. - - Set by the :option:`-B` option and the :envvar:`PYTHONDONTWRITEBYTECODE` - environment variable. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_FrozenFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.pathconfig_warnings` should be used instead, see - :ref:`Python Initialization Configuration `. - - Private flag used by ``_freeze_module`` and ``frozenmain`` programs. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_HashRandomizationFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.hash_seed` and :c:member:`PyConfig.use_hash_seed` should - be used instead, see :ref:`Python Initialization Configuration - `. - - Set to ``1`` if the :envvar:`PYTHONHASHSEED` environment variable is set to - a non-empty string. - - If the flag is non-zero, read the :envvar:`PYTHONHASHSEED` environment - variable to initialize the secret hash seed. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_IgnoreEnvironmentFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.use_environment` should be used instead, see - :ref:`Python Initialization Configuration `. - - Ignore all :envvar:`!PYTHON*` environment variables, e.g. - :envvar:`PYTHONPATH` and :envvar:`PYTHONHOME`, that might be set. - - Set by the :option:`-E` and :option:`-I` options. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_InspectFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.inspect` should be used instead, see - :ref:`Python Initialization Configuration `. - - When a script is passed as first argument or the :option:`-c` option is used, - enter interactive mode after executing the script or the command, even when - :data:`sys.stdin` does not appear to be a terminal. - - Set by the :option:`-i` option and the :envvar:`PYTHONINSPECT` environment - variable. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_InteractiveFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.interactive` should be used instead, see - :ref:`Python Initialization Configuration `. - - Set by the :option:`-i` option. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_IsolatedFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.isolated` should be used instead, see - :ref:`Python Initialization Configuration `. - - Run Python in isolated mode. In isolated mode :data:`sys.path` contains - neither the script's directory nor the user's site-packages directory. - - Set by the :option:`-I` option. - - .. versionadded:: 3.4 - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_LegacyWindowsFSEncodingFlag - - This API is kept for backward compatibility: setting - :c:member:`PyPreConfig.legacy_windows_fs_encoding` should be used instead, see - :ref:`Python Initialization Configuration `. - - If the flag is non-zero, use the ``mbcs`` encoding with ``replace`` error - handler, instead of the UTF-8 encoding with ``surrogatepass`` error handler, - for the :term:`filesystem encoding and error handler`. - - Set to ``1`` if the :envvar:`PYTHONLEGACYWINDOWSFSENCODING` environment - variable is set to a non-empty string. - - See :pep:`529` for more details. - - .. availability:: Windows. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_LegacyWindowsStdioFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.legacy_windows_stdio` should be used instead, see - :ref:`Python Initialization Configuration `. - - If the flag is non-zero, use :class:`io.FileIO` instead of - :class:`!io._WindowsConsoleIO` for :mod:`sys` standard streams. - - Set to ``1`` if the :envvar:`PYTHONLEGACYWINDOWSSTDIO` environment - variable is set to a non-empty string. - - See :pep:`528` for more details. - - .. availability:: Windows. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_NoSiteFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.site_import` should be used instead, see - :ref:`Python Initialization Configuration `. - - Disable the import of the module :mod:`site` and the site-dependent - manipulations of :data:`sys.path` that it entails. Also disable these - manipulations if :mod:`site` is explicitly imported later (call - :func:`site.main` if you want them to be triggered). - - Set by the :option:`-S` option. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_NoUserSiteDirectory - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.user_site_directory` should be used instead, see - :ref:`Python Initialization Configuration `. - - Don't add the :data:`user site-packages directory ` to - :data:`sys.path`. - - Set by the :option:`-s` and :option:`-I` options, and the - :envvar:`PYTHONNOUSERSITE` environment variable. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_OptimizeFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.optimization_level` should be used instead, see - :ref:`Python Initialization Configuration `. - - Set by the :option:`-O` option and the :envvar:`PYTHONOPTIMIZE` environment - variable. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_QuietFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.quiet` should be used instead, see :ref:`Python - Initialization Configuration `. - - Don't display the copyright and version messages even in interactive mode. - - Set by the :option:`-q` option. - - .. versionadded:: 3.2 - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_UnbufferedStdioFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.buffered_stdio` should be used instead, see :ref:`Python - Initialization Configuration `. - - Force the stdout and stderr streams to be unbuffered. - - Set by the :option:`-u` option and the :envvar:`PYTHONUNBUFFERED` - environment variable. - - .. deprecated-removed:: 3.12 3.16 - - -.. c:var:: int Py_VerboseFlag - - This API is kept for backward compatibility: setting - :c:member:`PyConfig.verbose` should be used instead, see :ref:`Python - Initialization Configuration `. - - Print a message each time a module is initialized, showing the place - (filename or built-in module) from which it is loaded. If greater or equal - to ``2``, print a message for each file that is checked for when - searching for a module. Also provides information on module cleanup at exit. - - Set by the :option:`-v` option and the :envvar:`PYTHONVERBOSE` environment - variable. - - .. deprecated-removed:: 3.12 3.16 - - Initializing and finalizing the interpreter ------------------------------------------- diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 8362b1ef7e312b..1b2bfe59c1962b 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -1131,6 +1131,76 @@ Deprecated C APIs Removed C APIs -------------- +* Remove global configuration variables: + + * :c:var:`!Py_DebugFlag`: + Use :c:member:`PyConfig.parser_debug` or + :c:func:`PyConfig_Get("parser_debug") ` instead. + * :c:var:`!Py_VerboseFlag`: + Use :c:member:`PyConfig.verbose` or + :c:func:`PyConfig_Get("verbose") ` instead. + * :c:var:`!Py_QuietFlag`: + Use :c:member:`PyConfig.quiet` or + :c:func:`PyConfig_Get("quiet") ` instead. + * :c:var:`!Py_InteractiveFlag`: + Use :c:member:`PyConfig.interactive` or + :c:func:`PyConfig_Get("interactive") ` instead. + * :c:var:`!Py_InspectFlag`: + Use :c:member:`PyConfig.inspect` or + :c:func:`PyConfig_Get("inspect") ` instead. + * :c:var:`!Py_OptimizeFlag`: + Use :c:member:`PyConfig.optimization_level` or + :c:func:`PyConfig_Get("optimization_level") ` instead. + * :c:var:`!Py_NoSiteFlag`: + Use :c:member:`PyConfig.site_import` or + :c:func:`PyConfig_Get("site_import") ` instead. + * :c:var:`!Py_BytesWarningFlag`: + Use :c:member:`PyConfig.bytes_warning` or + :c:func:`PyConfig_Get("bytes_warning") ` instead. + * :c:var:`!Py_FrozenFlag`: + Use :c:member:`PyConfig.pathconfig_warnings` or + :c:func:`PyConfig_Get("pathconfig_warnings") ` instead. + * :c:var:`!Py_IgnoreEnvironmentFlag`: + Use :c:member:`PyConfig.use_environment` or + :c:func:`PyConfig_Get("use_environment") ` instead. + * :c:var:`!Py_DontWriteBytecodeFlag`: + Use :c:member:`PyConfig.write_bytecode` or + :c:func:`PyConfig_Get("write_bytecode") ` instead. + * :c:var:`!Py_NoUserSiteDirectory`: + Use :c:member:`PyConfig.user_site_directory` or + :c:func:`PyConfig_Get("user_site_directory") ` instead. + * :c:var:`!Py_UnbufferedStdioFlag`: + Use :c:member:`PyConfig.buffered_stdio` or + :c:func:`PyConfig_Get("buffered_stdio") ` instead. + * :c:var:`!Py_HashRandomizationFlag`: + Use :c:member:`PyConfig.use_hash_seed` + and :c:member:`PyConfig.hash_seed` or + :c:func:`PyConfig_Get("hash_seed") ` instead. + * :c:var:`!Py_IsolatedFlag`: + Use :c:member:`PyConfig.isolated` or + :c:func:`PyConfig_Get("isolated") ` instead. + * :c:var:`!Py_LegacyWindowsFSEncodingFlag`: + Use :c:member:`PyPreConfig.legacy_windows_fs_encoding` or + :c:func:`PyConfig_Get("legacy_windows_fs_encoding") ` instead. + * :c:var:`!Py_LegacyWindowsStdioFlag`: + Use :c:member:`PyConfig.legacy_windows_stdio` or + :c:func:`PyConfig_Get("legacy_windows_stdio") ` instead. + * :c:var:`!Py_FileSystemDefaultEncoding`, :c:var:`!Py_HasFileSystemDefaultEncoding`: + Use :c:member:`PyConfig.filesystem_encoding` or + :c:func:`PyConfig_Get("filesystem_encoding") ` instead. + * :c:var:`!Py_FileSystemDefaultEncodeErrors`: + Use :c:member:`PyConfig.filesystem_errors` or + :c:func:`PyConfig_Get("filesystem_errors") ` instead. + * :c:var:`!Py_UTF8Mode`: + Use :c:member:`PyPreConfig.utf8_mode` or + :c:func:`PyConfig_Get("utf8_mode") ` instead. + (see :c:func:`Py_PreInitialize`) + + The :c:func:`Py_InitializeFromConfig` API should be used with + :c:type:`PyConfig` to set these options. Or :c:func:`PyConfig_Get` can be + used to get these options at runtime. + (Contributed by Victor Stinner in :gh:`158001`.) + * The :c:var:`!PyUnstable_ExecutableKinds` array, as well as the macros :c:macro:`!PyUnstable_EXECUTABLE_KIND_SKIP`, :c:macro:`!PyUnstable_EXECUTABLE_KIND_PY_FUNCTION`, diff --git a/Include/cpython/pydebug.h b/Include/cpython/pydebug.h index f6ebd99ed7e2ff..d27f992f460109 100644 --- a/Include/cpython/pydebug.h +++ b/Include/cpython/pydebug.h @@ -5,27 +5,6 @@ extern "C" { #endif -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_DebugFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_VerboseFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_QuietFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_InteractiveFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_InspectFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_OptimizeFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_NoSiteFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_BytesWarningFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_FrozenFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_IgnoreEnvironmentFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_DontWriteBytecodeFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_NoUserSiteDirectory; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_UnbufferedStdioFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_HashRandomizationFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_IsolatedFlag; - -#ifdef MS_WINDOWS -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_LegacyWindowsFSEncodingFlag; -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_LegacyWindowsStdioFlag; -#endif - /* this is a wrapper around getenv() that pays attention to Py_IgnoreEnvironmentFlag. It should be used for getting variables like PYTHONPATH and PYTHONHOME from the environment */ diff --git a/Include/fileobject.h b/Include/fileobject.h index 6a6d11409497fa..464bc3b29f483a 100644 --- a/Include/fileobject.h +++ b/Include/fileobject.h @@ -16,19 +16,6 @@ PyAPI_FUNC(int) PyFile_WriteObject(PyObject *, PyObject *, int); PyAPI_FUNC(int) PyFile_WriteString(const char *, PyObject *); PyAPI_FUNC(int) PyObject_AsFileDescriptor(PyObject *); -/* The default encoding used by the platform file system APIs - If non-NULL, this is different than the default encoding for strings -*/ -Py_DEPRECATED(3.12) PyAPI_DATA(const char *) Py_FileSystemDefaultEncoding; -#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03060000 -Py_DEPRECATED(3.12) PyAPI_DATA(const char *) Py_FileSystemDefaultEncodeErrors; -#endif -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_HasFileSystemDefaultEncoding; - -#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000 -Py_DEPRECATED(3.12) PyAPI_DATA(int) Py_UTF8Mode; -#endif - #ifndef Py_LIMITED_API # define Py_CPYTHON_FILEOBJECT_H # include "cpython/fileobject.h" diff --git a/Include/internal/pycore_fileutils.h b/Include/internal/pycore_fileutils.h index 83cdc4f3dfdd44..128790823aa879 100644 --- a/Include/internal/pycore_fileutils.h +++ b/Include/internal/pycore_fileutils.h @@ -190,8 +190,6 @@ extern int _Py_open_osfhandle(void *handle, int flags); ? _PyStatus_ERR("cannot decode " NAME) \ : _PyStatus_NO_MEMORY() -extern int _Py_HasFileSystemDefaultEncodeErrors; - extern int _Py_DecodeUTF8Ex( const char *arg, Py_ssize_t arglen, diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 81241ea1f33733..77b231323cc275 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -823,7 +823,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): # global config DEFAULT_GLOBAL_CONFIG = { 'Py_HasFileSystemDefaultEncoding': 0, - 'Py_HashRandomizationFlag': 1, '_Py_HasFileSystemDefaultEncodeErrors': 0, } COPY_GLOBAL_PRE_CONFIG = [ @@ -831,31 +830,9 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): ] COPY_GLOBAL_CONFIG = [ # Copy core config to global config for expected values - # True means that the core config value is inverted (0 => 1 and 1 => 0) - ('Py_BytesWarningFlag', 'bytes_warning'), - ('Py_DebugFlag', 'parser_debug'), - ('Py_DontWriteBytecodeFlag', 'write_bytecode', True), ('Py_FileSystemDefaultEncodeErrors', 'filesystem_errors'), ('Py_FileSystemDefaultEncoding', 'filesystem_encoding'), - ('Py_FrozenFlag', 'pathconfig_warnings', True), - ('Py_IgnoreEnvironmentFlag', 'use_environment', True), - ('Py_InspectFlag', 'inspect'), - ('Py_InteractiveFlag', 'interactive'), - ('Py_IsolatedFlag', 'isolated'), - ('Py_NoSiteFlag', 'site_import', True), - ('Py_NoUserSiteDirectory', 'user_site_directory', True), - ('Py_OptimizeFlag', 'optimization_level'), - ('Py_QuietFlag', 'quiet'), - ('Py_UnbufferedStdioFlag', 'buffered_stdio', True), - ('Py_VerboseFlag', 'verbose'), ] - if MS_WINDOWS: - COPY_GLOBAL_PRE_CONFIG.extend(( - ('Py_LegacyWindowsFSEncodingFlag', 'legacy_windows_fs_encoding'), - )) - COPY_GLOBAL_CONFIG.extend(( - ('Py_LegacyWindowsStdioFlag', 'legacy_windows_stdio'), - )) EXPECTED_CONFIG = None @@ -1013,20 +990,10 @@ def check_global_config(self, configs): config = configs['config'] expected = dict(self.DEFAULT_GLOBAL_CONFIG) - for item in self.COPY_GLOBAL_CONFIG: - if len(item) == 3: - global_key, core_key, opposite = item - expected[global_key] = 0 if config[core_key] else 1 - else: - global_key, core_key = item - expected[global_key] = config[core_key] - for item in self.COPY_GLOBAL_PRE_CONFIG: - if len(item) == 3: - global_key, core_key, opposite = item - expected[global_key] = 0 if pre_config[core_key] else 1 - else: - global_key, core_key = item - expected[global_key] = pre_config[core_key] + for global_key, core_key in self.COPY_GLOBAL_CONFIG: + expected[global_key] = config[core_key] + for global_key, core_key in self.COPY_GLOBAL_PRE_CONFIG: + expected[global_key] = pre_config[core_key] self.assertEqual(configs['global_config'], expected) diff --git a/Misc/NEWS.d/next/C_API/2026-09-23-19-37-53.gh-issue-158001.X_Xamm.rst b/Misc/NEWS.d/next/C_API/2026-09-23-19-37-53.gh-issue-158001.X_Xamm.rst new file mode 100644 index 00000000000000..1b81be97e283ea --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-09-23-19-37-53.gh-issue-158001.X_Xamm.rst @@ -0,0 +1,25 @@ +Remove 21 global configuration variables: + +* :c:var:`!Py_BytesWarningFlag`, +* :c:var:`!Py_DebugFlag`, +* :c:var:`!Py_DontWriteBytecodeFlag`, +* :c:var:`!Py_FileSystemDefaultEncodeErrors`, +* :c:var:`!Py_FileSystemDefaultEncoding`, +* :c:var:`!Py_FrozenFlag`, +* :c:var:`!Py_HasFileSystemDefaultEncoding`, +* :c:var:`!Py_HashRandomizationFlag`, +* :c:var:`!Py_IgnoreEnvironmentFlag`, +* :c:var:`!Py_InspectFlag`, +* :c:var:`!Py_InteractiveFlag`, +* :c:var:`!Py_IsolatedFlag`, +* :c:var:`!Py_LegacyWindowsFSEncodingFlag`, +* :c:var:`!Py_LegacyWindowsStdioFlag`, +* :c:var:`!Py_NoSiteFlag`, +* :c:var:`!Py_NoUserSiteDirectory`, +* :c:var:`!Py_OptimizeFlag`, +* :c:var:`!Py_QuietFlag`, +* :c:var:`!Py_UTF8Mode`, +* :c:var:`!Py_UnbufferedStdioFlag`, +* :c:var:`!Py_VerboseFlag`. + +Patch by Victor Stinner. diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 17b93ba47caac4..b364d8c44573b3 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -27,6 +27,9 @@ extern void Py_SetPath(const wchar_t *path); // for the stable ABI. We want to test them in this program. extern void PySys_ResetWarnOptions(void); +// Variable removed from Python 3.16 limited C API, but kept in the stable ABI +extern int Py_UTF8Mode; + int main_argc; char **main_argv; diff --git a/Python/initconfig.c b/Python/initconfig.c index 464c76f9e3df2f..d683fdd6abc6e1 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -95,128 +95,115 @@ typedef struct { PyConfigMemberType type; PyConfigMemberVisibility visibility; PyConfigSysSpec sys; - PyConfigGlobalVar global_var; } PyConfigSpec; -#define SPEC(MEMBER, TYPE, VISIBILITY, sys, global_var) \ +#define SPEC(MEMBER, TYPE, VISIBILITY, sys) \ {#MEMBER, offsetof(PyConfig, MEMBER), \ - PyConfig_MEMBER_##TYPE, PyConfig_MEMBER_##VISIBILITY, sys, global_var} + PyConfig_MEMBER_##TYPE, PyConfig_MEMBER_##VISIBILITY, sys} #define SYS_ATTR(name) {name, -1, NULL} #define SYS_FLAG_SETTER(index, setter) {NULL, index, setter} #define SYS_FLAG(index) SYS_FLAG_SETTER(index, NULL) #define NO_SYS SYS_ATTR(NULL) -#define GLOBAL(ptr, not) {ptr, not} -#define NO_GLOBAL GLOBAL(NULL, 0) - -// Ignore deprecations on global variables such as Py_IsolatedFlag -_Py_COMP_DIAG_PUSH -_Py_COMP_DIAG_IGNORE_DEPR_DECLS - // Update _test_embed_set_config when adding new members static const PyConfigSpec PYCONFIG_SPEC[] = { // --- Public options ----------- - SPEC(argv, WSTR_LIST, PUBLIC, SYS_ATTR("argv"), NO_GLOBAL), - SPEC(base_exec_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("base_exec_prefix"), NO_GLOBAL), - SPEC(base_executable, WSTR_OPT, PUBLIC, SYS_ATTR("_base_executable"), NO_GLOBAL), - SPEC(base_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("base_prefix"), NO_GLOBAL), - SPEC(bytes_warning, UINT, PUBLIC, SYS_FLAG(9), GLOBAL(&Py_BytesWarningFlag, 0)), - SPEC(cpu_count, INT, PUBLIC, NO_SYS, NO_GLOBAL), - SPEC(lazy_imports, INT, PUBLIC, NO_SYS, NO_GLOBAL), - SPEC(exec_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("exec_prefix"), NO_GLOBAL), - SPEC(executable, WSTR_OPT, PUBLIC, SYS_ATTR("executable"), NO_GLOBAL), - SPEC(inspect, BOOL, PUBLIC, SYS_FLAG(1), GLOBAL(&Py_InspectFlag, 0)), - SPEC(int_max_str_digits, UINT, PUBLIC, NO_SYS, NO_GLOBAL), - SPEC(interactive, BOOL, PUBLIC, SYS_FLAG(2), GLOBAL(&Py_InteractiveFlag, 0)), - SPEC(module_search_paths, WSTR_LIST, PUBLIC, SYS_ATTR("path"), NO_GLOBAL), - SPEC(optimization_level, UINT, PUBLIC, SYS_FLAG(3), GLOBAL(&Py_OptimizeFlag, 0)), - SPEC(parser_debug, BOOL, PUBLIC, SYS_FLAG(0), GLOBAL(&Py_DebugFlag, 0)), - SPEC(platlibdir, WSTR, PUBLIC, SYS_ATTR("platlibdir"), NO_GLOBAL), - SPEC(prefix, WSTR_OPT, PUBLIC, SYS_ATTR("prefix"), NO_GLOBAL), - SPEC(pycache_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("pycache_prefix"), NO_GLOBAL), - SPEC(quiet, BOOL, PUBLIC, SYS_FLAG(10), GLOBAL(&Py_QuietFlag, 0)), - SPEC(stdlib_dir, WSTR_OPT, PUBLIC, SYS_ATTR("_stdlib_dir"), NO_GLOBAL), + SPEC(argv, WSTR_LIST, PUBLIC, SYS_ATTR("argv")), + SPEC(base_exec_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("base_exec_prefix")), + SPEC(base_executable, WSTR_OPT, PUBLIC, SYS_ATTR("_base_executable")), + SPEC(base_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("base_prefix")), + SPEC(bytes_warning, UINT, PUBLIC, SYS_FLAG(9)), + SPEC(cpu_count, INT, PUBLIC, NO_SYS), + SPEC(lazy_imports, INT, PUBLIC, NO_SYS), + SPEC(exec_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("exec_prefix")), + SPEC(executable, WSTR_OPT, PUBLIC, SYS_ATTR("executable")), + SPEC(inspect, BOOL, PUBLIC, SYS_FLAG(1)), + SPEC(int_max_str_digits, UINT, PUBLIC, NO_SYS), + SPEC(interactive, BOOL, PUBLIC, SYS_FLAG(2)), + SPEC(module_search_paths, WSTR_LIST, PUBLIC, SYS_ATTR("path")), + SPEC(optimization_level, UINT, PUBLIC, SYS_FLAG(3)), + SPEC(parser_debug, BOOL, PUBLIC, SYS_FLAG(0)), + SPEC(platlibdir, WSTR, PUBLIC, SYS_ATTR("platlibdir")), + SPEC(prefix, WSTR_OPT, PUBLIC, SYS_ATTR("prefix")), + SPEC(pycache_prefix, WSTR_OPT, PUBLIC, SYS_ATTR("pycache_prefix")), + SPEC(quiet, BOOL, PUBLIC, SYS_FLAG(10)), + SPEC(stdlib_dir, WSTR_OPT, PUBLIC, SYS_ATTR("_stdlib_dir")), SPEC(use_environment, BOOL, PUBLIC, - SYS_FLAG_SETTER(7, config_sys_flag_not), GLOBAL(&Py_IgnoreEnvironmentFlag, 1)), - SPEC(verbose, UINT, PUBLIC, SYS_FLAG(8), GLOBAL(&Py_VerboseFlag, 0)), - SPEC(warnoptions, WSTR_LIST, PUBLIC, SYS_ATTR("warnoptions"), NO_GLOBAL), - SPEC(write_bytecode, BOOL, PUBLIC, SYS_FLAG_SETTER(4, config_sys_flag_not), - GLOBAL(&Py_DontWriteBytecodeFlag, 1)), - SPEC(xoptions, WSTR_LIST, PUBLIC, SYS_ATTR("_xoptions"), NO_GLOBAL), + SYS_FLAG_SETTER(7, config_sys_flag_not)), + SPEC(verbose, UINT, PUBLIC, SYS_FLAG(8)), + SPEC(warnoptions, WSTR_LIST, PUBLIC, SYS_ATTR("warnoptions")), + SPEC(write_bytecode, BOOL, PUBLIC, SYS_FLAG_SETTER(4, config_sys_flag_not)), + SPEC(xoptions, WSTR_LIST, PUBLIC, SYS_ATTR("_xoptions")), // --- Read-only options ----------- #ifdef Py_STATS - SPEC(_pystats, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), + SPEC(_pystats, BOOL, READ_ONLY, NO_SYS), #endif - SPEC(buffered_stdio, BOOL, READ_ONLY, NO_SYS, - GLOBAL(&Py_UnbufferedStdioFlag, 1)), - SPEC(check_hash_pycs_mode, WSTR, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(code_debug_ranges, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(configure_c_stdio, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(dev_mode, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), // sys.flags.dev_mode - SPEC(dump_refs, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(dump_refs_file, WSTR_OPT, READ_ONLY, NO_SYS, NO_GLOBAL), + SPEC(buffered_stdio, BOOL, READ_ONLY, NO_SYS), + SPEC(check_hash_pycs_mode, WSTR, READ_ONLY, NO_SYS), + SPEC(code_debug_ranges, BOOL, READ_ONLY, NO_SYS), + SPEC(configure_c_stdio, BOOL, READ_ONLY, NO_SYS), + SPEC(dev_mode, BOOL, READ_ONLY, NO_SYS), // sys.flags.dev_mode + SPEC(dump_refs, BOOL, READ_ONLY, NO_SYS), + SPEC(dump_refs_file, WSTR_OPT, READ_ONLY, NO_SYS), #ifdef Py_GIL_DISABLED - SPEC(enable_gil, INT, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(tlbc_enabled, INT, READ_ONLY, NO_SYS, NO_GLOBAL), + SPEC(enable_gil, INT, READ_ONLY, NO_SYS), + SPEC(tlbc_enabled, INT, READ_ONLY, NO_SYS), #endif - SPEC(faulthandler, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(filesystem_encoding, WSTR, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(filesystem_errors, WSTR, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(hash_seed, ULONG, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(home, WSTR_OPT, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(thread_inherit_context, INT, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(context_aware_warnings, INT, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(import_time, UINT, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(install_signal_handlers, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(isolated, BOOL, READ_ONLY, NO_SYS, GLOBAL(&Py_IsolatedFlag, 0)), // sys.flags.isolated + SPEC(faulthandler, BOOL, READ_ONLY, NO_SYS), + SPEC(filesystem_encoding, WSTR, READ_ONLY, NO_SYS), + SPEC(filesystem_errors, WSTR, READ_ONLY, NO_SYS), + SPEC(hash_seed, ULONG, READ_ONLY, NO_SYS), + SPEC(home, WSTR_OPT, READ_ONLY, NO_SYS), + SPEC(thread_inherit_context, INT, READ_ONLY, NO_SYS), + SPEC(context_aware_warnings, INT, READ_ONLY, NO_SYS), + SPEC(import_time, UINT, READ_ONLY, NO_SYS), + SPEC(install_signal_handlers, BOOL, READ_ONLY, NO_SYS), + SPEC(isolated, BOOL, READ_ONLY, NO_SYS), // sys.flags.isolated #ifdef MS_WINDOWS - SPEC(legacy_windows_stdio, BOOL, READ_ONLY, NO_SYS, - GLOBAL(&Py_LegacyWindowsStdioFlag, 0)), + SPEC(legacy_windows_stdio, BOOL, READ_ONLY, NO_SYS), #endif - SPEC(malloc_stats, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(pymalloc_hugepages, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(orig_argv, WSTR_LIST, READ_ONLY, SYS_ATTR("orig_argv"), NO_GLOBAL), - SPEC(parse_argv, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(pathconfig_warnings, BOOL, READ_ONLY, NO_SYS, - GLOBAL(&Py_FrozenFlag, 1)), - SPEC(perf_profiling, UINT, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(remote_debug, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(program_name, WSTR, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(run_command, WSTR_OPT, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(run_filename, WSTR_OPT, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(run_module, WSTR_OPT, READ_ONLY, NO_SYS, NO_GLOBAL), + SPEC(malloc_stats, BOOL, READ_ONLY, NO_SYS), + SPEC(pymalloc_hugepages, BOOL, READ_ONLY, NO_SYS), + SPEC(orig_argv, WSTR_LIST, READ_ONLY, SYS_ATTR("orig_argv")), + SPEC(parse_argv, BOOL, READ_ONLY, NO_SYS), + SPEC(pathconfig_warnings, BOOL, READ_ONLY, NO_SYS), + SPEC(perf_profiling, UINT, READ_ONLY, NO_SYS), + SPEC(remote_debug, BOOL, READ_ONLY, NO_SYS), + SPEC(program_name, WSTR, READ_ONLY, NO_SYS), + SPEC(run_command, WSTR_OPT, READ_ONLY, NO_SYS), + SPEC(run_filename, WSTR_OPT, READ_ONLY, NO_SYS), + SPEC(run_module, WSTR_OPT, READ_ONLY, NO_SYS), #ifdef Py_DEBUG - SPEC(run_presite, WSTR_OPT, READ_ONLY, NO_SYS, NO_GLOBAL), + SPEC(run_presite, WSTR_OPT, READ_ONLY, NO_SYS), #endif - SPEC(safe_path, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(show_ref_count, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(site_import, BOOL, READ_ONLY, NO_SYS, GLOBAL(&Py_NoSiteFlag, 1)), // sys.flags.no_site - SPEC(skip_source_first_line, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(stdio_encoding, WSTR_OPT, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(stdio_errors, WSTR, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(tracemalloc, UINT, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(use_frozen_modules, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), - SPEC(use_hash_seed, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), + SPEC(safe_path, BOOL, READ_ONLY, NO_SYS), + SPEC(show_ref_count, BOOL, READ_ONLY, NO_SYS), + SPEC(site_import, BOOL, READ_ONLY, NO_SYS), // sys.flags.no_site + SPEC(skip_source_first_line, BOOL, READ_ONLY, NO_SYS), + SPEC(stdio_encoding, WSTR_OPT, READ_ONLY, NO_SYS), + SPEC(stdio_errors, WSTR, READ_ONLY, NO_SYS), + SPEC(tracemalloc, UINT, READ_ONLY, NO_SYS), + SPEC(use_frozen_modules, BOOL, READ_ONLY, NO_SYS), + SPEC(use_hash_seed, BOOL, READ_ONLY, NO_SYS), #ifdef __APPLE__ - SPEC(use_system_logger, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), + SPEC(use_system_logger, BOOL, READ_ONLY, NO_SYS), #endif - SPEC(user_site_directory, BOOL, READ_ONLY, NO_SYS, - GLOBAL(&Py_NoUserSiteDirectory, 1)), // sys.flags.no_user_site - SPEC(warn_default_encoding, BOOL, READ_ONLY, NO_SYS, NO_GLOBAL), + SPEC(user_site_directory, BOOL, READ_ONLY, NO_SYS), // sys.flags.no_user_site + SPEC(warn_default_encoding, BOOL, READ_ONLY, NO_SYS), // --- Init-only options ----------- - SPEC(_config_init, UINT, INIT_ONLY, NO_SYS, NO_GLOBAL), - SPEC(_init_main, BOOL, INIT_ONLY, NO_SYS, NO_GLOBAL), - SPEC(_install_importlib, BOOL, INIT_ONLY, NO_SYS, NO_GLOBAL), - SPEC(_is_python_build, BOOL, INIT_ONLY, NO_SYS, NO_GLOBAL), - SPEC(module_search_paths_set, BOOL, INIT_ONLY, NO_SYS, NO_GLOBAL), - SPEC(pythonpath_env, WSTR_OPT, INIT_ONLY, NO_SYS, NO_GLOBAL), - SPEC(sys_path_0, WSTR_OPT, INIT_ONLY, NO_SYS, NO_GLOBAL), + SPEC(_config_init, UINT, INIT_ONLY, NO_SYS), + SPEC(_init_main, BOOL, INIT_ONLY, NO_SYS), + SPEC(_install_importlib, BOOL, INIT_ONLY, NO_SYS), + SPEC(_is_python_build, BOOL, INIT_ONLY, NO_SYS), + SPEC(module_search_paths_set, BOOL, INIT_ONLY, NO_SYS), + SPEC(pythonpath_env, WSTR_OPT, INIT_ONLY, NO_SYS), + SPEC(sys_path_0, WSTR_OPT, INIT_ONLY, NO_SYS), // Array terminator {NULL, 0, 0, 0, NO_SYS}, @@ -252,16 +239,11 @@ static const PyConfigSpec PYPRECONFIG_SPEC[] = { {NULL, 0, 0, 0, NO_SYS}, }; -// End of ignoring deprecations on global variables -_Py_COMP_DIAG_POP - #undef SPEC #undef SYS_ATTR #undef SYS_FLAG_SETTER #undef SYS_FLAG #undef NO_SYS -#undef GLOBAL -#undef NO_GLOBAL // Forward declarations @@ -611,45 +593,30 @@ static const char usage_envvars[] = /* --- Global configuration variables ----------------------------- */ +// Variable removed from Python limited C API 3.16, but kept in the stable ABI +PyAPI_DATA(int) Py_UTF8Mode; + /* UTF-8 mode (PEP 540): if equal to 1, use the UTF-8 encoding, and change stdin and stdout error handler to "surrogateescape". */ int Py_UTF8Mode = 0; -int Py_DebugFlag = 0; /* Needed by parser.c */ -int Py_VerboseFlag = 0; /* Needed by import.c */ -int Py_QuietFlag = 0; /* Needed by sysmodule.c */ -int Py_InteractiveFlag = 0; /* Previously, was used by Py_FdIsInteractive() */ -int Py_InspectFlag = 0; /* Needed to determine whether to exit at SystemExit */ -int Py_OptimizeFlag = 0; /* Needed by compile.c */ -int Py_NoSiteFlag = 0; /* Suppress 'import site' */ -int Py_BytesWarningFlag = 0; /* Warn on str(bytes) and str(buffer) */ -int Py_FrozenFlag = 0; /* Needed by getpath.c */ -int Py_IgnoreEnvironmentFlag = 0; /* e.g. PYTHONPATH, PYTHONHOME */ -int Py_DontWriteBytecodeFlag = 0; /* Suppress writing bytecode files (*.pyc) */ -int Py_NoUserSiteDirectory = 0; /* for -s and site.py */ -int Py_UnbufferedStdioFlag = 0; /* Unbuffered binary std{in,out,err} */ -int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */ -int Py_IsolatedFlag = 0; /* for -I, isolate from user's env */ -#ifdef MS_WINDOWS -int Py_LegacyWindowsFSEncodingFlag = 0; /* Uses mbcs instead of utf-8 */ -int Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */ -#endif static PyObject * _Py_GetGlobalVariablesAsDict(void) { -_Py_COMP_DIAG_PUSH -_Py_COMP_DIAG_IGNORE_DEPR_DECLS - PyObject *dict, *obj; + extern const char *Py_FileSystemDefaultEncoding; + extern const char *Py_FileSystemDefaultEncodeErrors; + extern int Py_HasFileSystemDefaultEncoding; + extern int _Py_HasFileSystemDefaultEncodeErrors; - dict = PyDict_New(); + PyObject *dict = PyDict_New(); if (dict == NULL) { return NULL; } #define SET_ITEM(KEY, EXPR) \ do { \ - obj = (EXPR); \ + PyObject *obj = (EXPR); \ if (obj == NULL) { \ goto fail; \ } \ @@ -674,27 +641,6 @@ _Py_COMP_DIAG_IGNORE_DEPR_DECLS SET_ITEM_INT(_Py_HasFileSystemDefaultEncodeErrors); SET_ITEM_INT(Py_UTF8Mode); - SET_ITEM_INT(Py_DebugFlag); - SET_ITEM_INT(Py_VerboseFlag); - SET_ITEM_INT(Py_QuietFlag); - SET_ITEM_INT(Py_InteractiveFlag); - SET_ITEM_INT(Py_InspectFlag); - - SET_ITEM_INT(Py_OptimizeFlag); - SET_ITEM_INT(Py_NoSiteFlag); - SET_ITEM_INT(Py_BytesWarningFlag); - SET_ITEM_INT(Py_FrozenFlag); - SET_ITEM_INT(Py_IgnoreEnvironmentFlag); - SET_ITEM_INT(Py_DontWriteBytecodeFlag); - SET_ITEM_INT(Py_NoUserSiteDirectory); - SET_ITEM_INT(Py_UnbufferedStdioFlag); - SET_ITEM_INT(Py_HashRandomizationFlag); - SET_ITEM_INT(Py_IsolatedFlag); - -#ifdef MS_WINDOWS - SET_ITEM_INT(Py_LegacyWindowsFSEncodingFlag); - SET_ITEM_INT(Py_LegacyWindowsStdioFlag); -#endif return dict; @@ -706,7 +652,6 @@ _Py_COMP_DIAG_IGNORE_DEPR_DECLS #undef SET_ITEM #undef SET_ITEM_INT #undef SET_ITEM_STR -_Py_COMP_DIAG_POP } char* @@ -1834,38 +1779,6 @@ config_read_preconfig(PyConfig *config) } -/* Set Py_xxx global configuration variables from 'config' configuration. */ -static void -config_set_global_vars(const PyConfig *config) -{ - const PyConfigSpec *spec = PYCONFIG_SPEC; - for (; spec->name != NULL; spec++) { - if (spec->global_var.ptr == NULL) { - continue; - } - assert(spec->type == PyConfig_MEMBER_INT - || spec->type == PyConfig_MEMBER_UINT - || spec->type == PyConfig_MEMBER_BOOL); - int *member = config_get_spec_member(config, spec); - int value = *member; - if (value == -1) { - continue; - } - if (spec->global_var.not) { - value = !value; - } - *spec->global_var.ptr = value; - } - -_Py_COMP_DIAG_PUSH -_Py_COMP_DIAG_IGNORE_DEPR_DECLS - /* Random or non-zero hash seed */ - Py_HashRandomizationFlag = (config->use_hash_seed == 0 || - config->hash_seed != 0); -_Py_COMP_DIAG_POP -} - - static const wchar_t* config_get_xoption(const PyConfig *config, wchar_t *name) { @@ -3012,8 +2925,6 @@ config_init_stdio(const PyConfig *config) PyStatus _PyConfig_Write(const PyConfig *config, _PyRuntimeState *runtime) { - config_set_global_vars(config); - if (config->configure_c_stdio) { config_init_stdio(config); } @@ -5043,16 +4954,6 @@ PyConfig_Set(const char *name, PyObject *value) Py_UNREACHABLE(); } - // Set the global variable - if (spec->global_var.ptr != NULL) { - assert(has_int_value); - int value = int_value; - if (spec->global_var.not) { - value = !value; - } - *spec->global_var.ptr = value; - } - if (spec->sys.attr != NULL) { // Set the sys attribute, but don't set PyInterpreterState.config // to keep the code simple. diff --git a/Python/preconfig.c b/Python/preconfig.c index 16594e545abaed..844ac8e6372fc5 100644 --- a/Python/preconfig.c +++ b/Python/preconfig.c @@ -13,10 +13,18 @@ /* Forward declarations */ static void preconfig_copy(PyPreConfig *config, const PyPreConfig *config2); +extern int Py_UTF8Mode; /* --- File system encoding/errors -------------------------------- */ +// Variables removed from Python limited C API 3.16, but kept in the stable ABI +PyAPI_DATA(const char *) Py_FileSystemDefaultEncoding; +PyAPI_DATA(const char *) Py_FileSystemDefaultEncodeErrors; +PyAPI_DATA(int) Py_HasFileSystemDefaultEncoding; + +// The default encoding used by the platform file system APIs. +// If non-NULL, this is different than the default encoding for strings. const char *Py_FileSystemDefaultEncoding = NULL; int Py_HasFileSystemDefaultEncoding = 0; const char *Py_FileSystemDefaultEncodeErrors = NULL; @@ -25,8 +33,6 @@ int _Py_HasFileSystemDefaultEncodeErrors = 0; void _Py_ClearFileSystemEncoding(void) { -_Py_COMP_DIAG_PUSH -_Py_COMP_DIAG_IGNORE_DEPR_DECLS if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) { PyMem_RawFree((char*)Py_FileSystemDefaultEncoding); Py_FileSystemDefaultEncoding = NULL; @@ -35,7 +41,6 @@ _Py_COMP_DIAG_IGNORE_DEPR_DECLS PyMem_RawFree((char*)Py_FileSystemDefaultEncodeErrors); Py_FileSystemDefaultEncodeErrors = NULL; } -_Py_COMP_DIAG_POP } @@ -60,14 +65,11 @@ _Py_SetFileSystemEncoding(const char *encoding, const char *errors) _Py_ClearFileSystemEncoding(); -_Py_COMP_DIAG_PUSH -_Py_COMP_DIAG_IGNORE_DEPR_DECLS Py_FileSystemDefaultEncoding = encoding2; Py_HasFileSystemDefaultEncoding = 0; Py_FileSystemDefaultEncodeErrors = errors2; _Py_HasFileSystemDefaultEncodeErrors = 0; -_Py_COMP_DIAG_POP return 0; } @@ -470,39 +472,18 @@ preconfig_get_global_var(PyPreConfig *config) return; } -_Py_COMP_DIAG_PUSH -_Py_COMP_DIAG_IGNORE_DEPR_DECLS if (Py_UTF8Mode > 0) { config->utf8_mode = Py_UTF8Mode; } -_Py_COMP_DIAG_POP } static void -preconfig_set_global_vars(const PyPreConfig *config) +preconfig_set_global_var(const PyPreConfig *config) { -#define COPY_FLAG(ATTR, VAR) \ - if (config->ATTR >= 0) { \ - VAR = config->ATTR; \ - } -#define COPY_NOT_FLAG(ATTR, VAR) \ - if (config->ATTR >= 0) { \ - VAR = !config->ATTR; \ + if (config->utf8_mode >= 0) { + Py_UTF8Mode = config->utf8_mode; } - -_Py_COMP_DIAG_PUSH -_Py_COMP_DIAG_IGNORE_DEPR_DECLS - COPY_FLAG(isolated, Py_IsolatedFlag); - COPY_NOT_FLAG(use_environment, Py_IgnoreEnvironmentFlag); -#ifdef MS_WINDOWS - COPY_FLAG(legacy_windows_fs_encoding, Py_LegacyWindowsFSEncodingFlag); -#endif - COPY_FLAG(utf8_mode, Py_UTF8Mode); -_Py_COMP_DIAG_POP - -#undef COPY_FLAG -#undef COPY_NOT_FLAG } @@ -935,7 +916,7 @@ _PyPreConfig_Write(const PyPreConfig *src_config) } } - preconfig_set_global_vars(&config); + preconfig_set_global_var(&config); if (config.configure_locale) { if (config.coerce_c_locale) { From dbe5caef1ba613498ac2013c41fbc204a78e2c4d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Sep 2026 21:49:52 +0200 Subject: [PATCH 2/9] Update tests * test_capi.test_config: Remove test_config_set_global_vars(). * test_ctypes: Get Py_Version variable instead of Py_OptimizeFlag. --- Lib/test/test_capi/test_config.py | 40 ----------------------------- Lib/test/test_ctypes/test_values.py | 8 +++--- 2 files changed, 4 insertions(+), 44 deletions(-) diff --git a/Lib/test/test_capi/test_config.py b/Lib/test/test_capi/test_config.py index 29012634361838..789f652b004bff 100644 --- a/Lib/test/test_capi/test_config.py +++ b/Lib/test/test_capi/test_config.py @@ -379,46 +379,6 @@ def expect_bool_not(value): finally: config_set(name, old_value) - def test_config_set_global_vars(self): - # Test PyConfig_Set() with global configuration variables - config_get = _testcapi.config_get - config_set = _testcapi.config_set - get_configs = _testinternalcapi.get_configs - new_values = (0, 1, 5) - - for name, global_name, not_value in ( - ('bytes_warning', 'Py_BytesWarningFlag', False), - ('inspect', 'Py_InspectFlag', False), - ('interactive', 'Py_InteractiveFlag', False), - ('optimization_level', 'Py_OptimizeFlag', False), - ('parser_debug', 'Py_DebugFlag', False), - ('quiet', 'Py_QuietFlag', False), - ('use_environment', 'Py_IgnoreEnvironmentFlag', True), - ('verbose', 'Py_VerboseFlag', False), - ('write_bytecode', 'Py_DontWriteBytecodeFlag', True), - - # Read-only variables - #('buffered_stdio', 'Py_UnbufferedStdioFlag', True), - #('isolated', 'Py_IsolatedFlag', False), - #('pathconfig_warnings', 'Py_FrozenFlag', True), - #('site_import', 'Py_NoSiteFlag', True), - #('user_site_directory', 'Py_NoUserSiteDirectory', True), - # Windows only - #('legacy_windows_stdio', 'Py_LegacyWindowsStdioFlag', False) - ): - with self.subTest(name=name): - old_value = config_get(name) - try: - for value in new_values: - config_set(name, value) - global_config = get_configs()['global_config'] - expected = value - if not_value: - expected = int(not value) - self.assertEqual(global_config[global_name], expected) - finally: - config_set(name, old_value) - def test_config_set_cpu_count(self): config_get = _testcapi.config_get config_set = _testcapi.config_set diff --git a/Lib/test/test_ctypes/test_values.py b/Lib/test/test_ctypes/test_values.py index 82c928c9f6406c..08aabe8088db72 100644 --- a/Lib/test/test_ctypes/test_values.py +++ b/Lib/test/test_ctypes/test_values.py @@ -73,12 +73,12 @@ def test_undefined(self): class PythonValuesTestCase(unittest.TestCase): """This test only works when python itself is a dll/shared library""" - def test_optimizeflag(self): - # This test accesses the Py_OptimizeFlag integer, which is + def test_version_var(self): + # This test accesses the Py_Version integer, which is # exported by the Python dll and should match the sys.flags value - opt = c_int.in_dll(pythonapi, "Py_OptimizeFlag").value - self.assertEqual(opt, sys.flags.optimize) + version = c_int.in_dll(pythonapi, "Py_Version").value + self.assertEqual(version, sys.hexversion) @thread_unsafe('overrides frozen modules') def test_frozentable(self): From 42963a7213d9bd15204f3bced233b52b2c228917 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Sep 2026 22:40:33 +0200 Subject: [PATCH 3/9] Update make check-limited-abi Mark the 4 variables as abi_only in Misc/stable_abi.toml. --- Doc/data/stable_abi.dat | 4 ---- Misc/stable_abi.toml | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 3fbff9a0d65362..62b88f80f5f9b3 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -954,8 +954,6 @@ func,Py_EndInterpreter,3.2,, func,Py_EnterRecursiveCall,3.9,, func,Py_Exit,3.2,, func,Py_FatalError,3.2,, -data,Py_FileSystemDefaultEncodeErrors,3.10,, -data,Py_FileSystemDefaultEncoding,3.2,, func,Py_Finalize,3.2,, func,Py_FinalizeEx,3.6,, func,Py_GenericAlias,3.9,, @@ -968,7 +966,6 @@ func,Py_GetCopyright,3.2,, func,Py_GetPlatform,3.2,, func,Py_GetRecursionLimit,3.2,, func,Py_GetVersion,3.2,, -data,Py_HasFileSystemDefaultEncoding,3.2,, func,Py_HashBuffer,3.16,, func,Py_IS_TYPE,3.15,, func,Py_IncRef,3.2,, @@ -1025,7 +1022,6 @@ macro,Py_T_ULONGLONG,3.12,, macro,Py_T_USHORT,3.12,, type,Py_UCS4,3.2,, macro,Py_UNBLOCK_THREADS,3.2,, -data,Py_UTF8Mode,3.8,, func,Py_VaBuildValue,3.2,, data,Py_Version,3.11,, func,Py_XNewRef,3.10,, diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index 8ae17142dcc67a..611e50403a3e54 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -1640,6 +1640,7 @@ added = '3.2' [data.Py_FileSystemDefaultEncoding] added = '3.2' + abi_only = true [function.Py_Finalize] added = '3.2' [function.Py_GetBuildInfo] @@ -1674,6 +1675,7 @@ added = '3.2' [data.Py_HasFileSystemDefaultEncoding] added = '3.2' + abi_only = true [function.Py_IncRef] added = '3.2' [function.Py_Initialize] @@ -2173,6 +2175,7 @@ added = '3.8' [data.Py_UTF8Mode] added = '3.8' + abi_only = true [function.PyExceptionClass_Name] added = '3.8' [function.PyIndex_Check] @@ -2259,6 +2262,7 @@ added = '3.10' [data.Py_FileSystemDefaultEncodeErrors] added = '3.10' + abi_only = true [function.PyCodec_Unregister] added = '3.10' [function.PyErr_SetInterruptEx] From 316cb16a2b1470617cbae898dc17a891e8fc73d5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Sep 2026 22:47:16 +0200 Subject: [PATCH 4/9] doc: Remove links to removed variables --- .../c-api-pending-removal-in-3.16.rst | 34 +++++++++---------- Doc/whatsnew/3.12.rst | 34 +++++++++---------- Doc/whatsnew/3.7.rst | 4 +-- ...-07-08-00-38-32.gh-issue-153300.lVoWyR.rst | 2 +- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/Doc/deprecations/c-api-pending-removal-in-3.16.rst b/Doc/deprecations/c-api-pending-removal-in-3.16.rst index fe2d91cf316b18..dd840fac9b151b 100644 --- a/Doc/deprecations/c-api-pending-removal-in-3.16.rst +++ b/Doc/deprecations/c-api-pending-removal-in-3.16.rst @@ -17,56 +17,56 @@ Pending removal in Python 3.16 * Global configuration variables: - * :c:var:`Py_DebugFlag`: + * :c:var:`!Py_DebugFlag`: Use :c:member:`PyConfig.parser_debug` or :c:func:`PyConfig_Get("parser_debug") ` instead. - * :c:var:`Py_VerboseFlag`: + * :c:var:`!Py_VerboseFlag`: Use :c:member:`PyConfig.verbose` or :c:func:`PyConfig_Get("verbose") ` instead. - * :c:var:`Py_QuietFlag`: + * :c:var:`!Py_QuietFlag`: Use :c:member:`PyConfig.quiet` or :c:func:`PyConfig_Get("quiet") ` instead. - * :c:var:`Py_InteractiveFlag`: + * :c:var:`!Py_InteractiveFlag`: Use :c:member:`PyConfig.interactive` or :c:func:`PyConfig_Get("interactive") ` instead. - * :c:var:`Py_InspectFlag`: + * :c:var:`!Py_InspectFlag`: Use :c:member:`PyConfig.inspect` or :c:func:`PyConfig_Get("inspect") ` instead. - * :c:var:`Py_OptimizeFlag`: + * :c:var:`!Py_OptimizeFlag`: Use :c:member:`PyConfig.optimization_level` or :c:func:`PyConfig_Get("optimization_level") ` instead. - * :c:var:`Py_NoSiteFlag`: + * :c:var:`!Py_NoSiteFlag`: Use :c:member:`PyConfig.site_import` or :c:func:`PyConfig_Get("site_import") ` instead. - * :c:var:`Py_BytesWarningFlag`: + * :c:var:`!Py_BytesWarningFlag`: Use :c:member:`PyConfig.bytes_warning` or :c:func:`PyConfig_Get("bytes_warning") ` instead. - * :c:var:`Py_FrozenFlag`: + * :c:var:`!Py_FrozenFlag`: Use :c:member:`PyConfig.pathconfig_warnings` or :c:func:`PyConfig_Get("pathconfig_warnings") ` instead. - * :c:var:`Py_IgnoreEnvironmentFlag`: + * :c:var:`!Py_IgnoreEnvironmentFlag`: Use :c:member:`PyConfig.use_environment` or :c:func:`PyConfig_Get("use_environment") ` instead. - * :c:var:`Py_DontWriteBytecodeFlag`: + * :c:var:`!Py_DontWriteBytecodeFlag`: Use :c:member:`PyConfig.write_bytecode` or :c:func:`PyConfig_Get("write_bytecode") ` instead. - * :c:var:`Py_NoUserSiteDirectory`: + * :c:var:`!Py_NoUserSiteDirectory`: Use :c:member:`PyConfig.user_site_directory` or :c:func:`PyConfig_Get("user_site_directory") ` instead. - * :c:var:`Py_UnbufferedStdioFlag`: + * :c:var:`!Py_UnbufferedStdioFlag`: Use :c:member:`PyConfig.buffered_stdio` or :c:func:`PyConfig_Get("buffered_stdio") ` instead. - * :c:var:`Py_HashRandomizationFlag`: + * :c:var:`!Py_HashRandomizationFlag`: Use :c:member:`PyConfig.use_hash_seed` and :c:member:`PyConfig.hash_seed` or :c:func:`PyConfig_Get("hash_seed") ` instead. - * :c:var:`Py_IsolatedFlag`: + * :c:var:`!Py_IsolatedFlag`: Use :c:member:`PyConfig.isolated` or :c:func:`PyConfig_Get("isolated") ` instead. - * :c:var:`Py_LegacyWindowsFSEncodingFlag`: + * :c:var:`!Py_LegacyWindowsFSEncodingFlag`: Use :c:member:`PyPreConfig.legacy_windows_fs_encoding` or :c:func:`PyConfig_Get("legacy_windows_fs_encoding") ` instead. - * :c:var:`Py_LegacyWindowsStdioFlag`: + * :c:var:`!Py_LegacyWindowsStdioFlag`: Use :c:member:`PyConfig.legacy_windows_stdio` or :c:func:`PyConfig_Get("legacy_windows_stdio") ` instead. * :c:var:`!Py_FileSystemDefaultEncoding`, :c:var:`!Py_HasFileSystemDefaultEncoding`: diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index 9e48b3ab7393c8..78ddc627fcf4d7 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -2170,24 +2170,24 @@ Deprecated * Deprecate global configuration variable: - * :c:var:`Py_DebugFlag`: use :c:member:`PyConfig.parser_debug` - * :c:var:`Py_VerboseFlag`: use :c:member:`PyConfig.verbose` - * :c:var:`Py_QuietFlag`: use :c:member:`PyConfig.quiet` - * :c:var:`Py_InteractiveFlag`: use :c:member:`PyConfig.interactive` - * :c:var:`Py_InspectFlag`: use :c:member:`PyConfig.inspect` - * :c:var:`Py_OptimizeFlag`: use :c:member:`PyConfig.optimization_level` - * :c:var:`Py_NoSiteFlag`: use :c:member:`PyConfig.site_import` - * :c:var:`Py_BytesWarningFlag`: use :c:member:`PyConfig.bytes_warning` - * :c:var:`Py_FrozenFlag`: use :c:member:`PyConfig.pathconfig_warnings` - * :c:var:`Py_IgnoreEnvironmentFlag`: use :c:member:`PyConfig.use_environment` - * :c:var:`Py_DontWriteBytecodeFlag`: use :c:member:`PyConfig.write_bytecode` - * :c:var:`Py_NoUserSiteDirectory`: use :c:member:`PyConfig.user_site_directory` - * :c:var:`Py_UnbufferedStdioFlag`: use :c:member:`PyConfig.buffered_stdio` - * :c:var:`Py_HashRandomizationFlag`: use :c:member:`PyConfig.use_hash_seed` + * :c:var:`!Py_DebugFlag`: use :c:member:`PyConfig.parser_debug` + * :c:var:`!Py_VerboseFlag`: use :c:member:`PyConfig.verbose` + * :c:var:`!Py_QuietFlag`: use :c:member:`PyConfig.quiet` + * :c:var:`!Py_InteractiveFlag`: use :c:member:`PyConfig.interactive` + * :c:var:`!Py_InspectFlag`: use :c:member:`PyConfig.inspect` + * :c:var:`!Py_OptimizeFlag`: use :c:member:`PyConfig.optimization_level` + * :c:var:`!Py_NoSiteFlag`: use :c:member:`PyConfig.site_import` + * :c:var:`!Py_BytesWarningFlag`: use :c:member:`PyConfig.bytes_warning` + * :c:var:`!Py_FrozenFlag`: use :c:member:`PyConfig.pathconfig_warnings` + * :c:var:`!Py_IgnoreEnvironmentFlag`: use :c:member:`PyConfig.use_environment` + * :c:var:`!Py_DontWriteBytecodeFlag`: use :c:member:`PyConfig.write_bytecode` + * :c:var:`!Py_NoUserSiteDirectory`: use :c:member:`PyConfig.user_site_directory` + * :c:var:`!Py_UnbufferedStdioFlag`: use :c:member:`PyConfig.buffered_stdio` + * :c:var:`!Py_HashRandomizationFlag`: use :c:member:`PyConfig.use_hash_seed` and :c:member:`PyConfig.hash_seed` - * :c:var:`Py_IsolatedFlag`: use :c:member:`PyConfig.isolated` - * :c:var:`Py_LegacyWindowsFSEncodingFlag`: use :c:member:`PyPreConfig.legacy_windows_fs_encoding` - * :c:var:`Py_LegacyWindowsStdioFlag`: use :c:member:`PyConfig.legacy_windows_stdio` + * :c:var:`!Py_IsolatedFlag`: use :c:member:`PyConfig.isolated` + * :c:var:`!Py_LegacyWindowsFSEncodingFlag`: use :c:member:`PyPreConfig.legacy_windows_fs_encoding` + * :c:var:`!Py_LegacyWindowsStdioFlag`: use :c:member:`PyConfig.legacy_windows_stdio` * :c:var:`!Py_FileSystemDefaultEncoding`: use :c:member:`PyConfig.filesystem_encoding` * :c:var:`!Py_HasFileSystemDefaultEncoding`: use :c:member:`PyConfig.filesystem_encoding` * :c:var:`!Py_FileSystemDefaultEncodeErrors`: use :c:member:`PyConfig.filesystem_errors` diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 3af3e6ec9cac08..6900c97e9546c9 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -2524,7 +2524,7 @@ number of other issues). Some known details affected: over the default filters set by the interpreter Due to changes in the way the default warnings filters are configured, -setting :c:data:`Py_BytesWarningFlag` to a value greater than one is no longer +setting :c:data:`!Py_BytesWarningFlag` to a value greater than one is no longer sufficient to both emit :exc:`BytesWarning` messages and have them converted to exceptions. Instead, the flag must be set (to cause the warnings to be emitted in the first place), and an explicit ``error::BytesWarning`` @@ -2547,7 +2547,7 @@ Starting in 3.7.1, :c:func:`Py_Initialize` now consistently reads and respects all of the same environment settings as :c:func:`Py_Main` (in earlier Python versions, it respected an ill-defined subset of those environment variables, while in Python 3.7.0 it didn't read any of them due to :issue:`34247`). If -this behavior is unwanted, set :c:data:`Py_IgnoreEnvironmentFlag` to 1 before +this behavior is unwanted, set :c:data:`!Py_IgnoreEnvironmentFlag` to 1 before calling :c:func:`Py_Initialize`. In 3.7.1 the C API for Context Variables diff --git a/Misc/NEWS.d/next/C_API/2026-07-08-00-38-32.gh-issue-153300.lVoWyR.rst b/Misc/NEWS.d/next/C_API/2026-07-08-00-38-32.gh-issue-153300.lVoWyR.rst index 3c19c0e15d2bc6..bb85114220bbe6 100644 --- a/Misc/NEWS.d/next/C_API/2026-07-08-00-38-32.gh-issue-153300.lVoWyR.rst +++ b/Misc/NEWS.d/next/C_API/2026-07-08-00-38-32.gh-issue-153300.lVoWyR.rst @@ -1,3 +1,3 @@ :c:func:`PyConfig_Set()` now also set global configuration variables. For example, ``PyConfig_Set("inspect", value)`` now also sets -:c:var:`Py_InspectFlag`. Patch by Victor Stinner. +:c:var:`!Py_InspectFlag`. Patch by Victor Stinner. From 27cbdd6055e15828b43f1df757b01b896d039ea4 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Sep 2026 22:48:24 +0200 Subject: [PATCH 5/9] Try to fix build on Windows --- Programs/_testembed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Programs/_testembed.c b/Programs/_testembed.c index b364d8c44573b3..330bdc3dcea102 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -28,7 +28,7 @@ extern void Py_SetPath(const wchar_t *path); extern void PySys_ResetWarnOptions(void); // Variable removed from Python 3.16 limited C API, but kept in the stable ABI -extern int Py_UTF8Mode; +PyAPI_DATA(int) Py_UTF8Mode; int main_argc; From 8b1af46112e772bc630013000a61abe9136385b5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Sep 2026 22:58:49 +0200 Subject: [PATCH 6/9] Update Doc/tools/removed-ids.txt --- Doc/tools/removed-ids.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Doc/tools/removed-ids.txt b/Doc/tools/removed-ids.txt index be3c2f38f194ec..ae6b11de824bb9 100644 --- a/Doc/tools/removed-ids.txt +++ b/Doc/tools/removed-ids.txt @@ -3,6 +3,25 @@ # Remove from here in 3.16 c-api/allocation.html: deprecated-aliases c-api/file.html: deprecated-api +c-api/interp-lifecycle.html: c.Py_BytesWarningFlag +c-api/interp-lifecycle.html: c.Py_DebugFlag +c-api/interp-lifecycle.html: c.Py_DontWriteBytecodeFlag +c-api/interp-lifecycle.html: c.Py_FrozenFlag +c-api/interp-lifecycle.html: c.Py_HashRandomizationFlag +c-api/interp-lifecycle.html: c.Py_IgnoreEnvironmentFlag +c-api/interp-lifecycle.html: c.Py_InspectFlag +c-api/interp-lifecycle.html: c.Py_InteractiveFlag +c-api/interp-lifecycle.html: c.Py_IsolatedFlag +c-api/interp-lifecycle.html: c.Py_LegacyWindowsFSEncodingFlag +c-api/interp-lifecycle.html: c.Py_LegacyWindowsStdioFlag +c-api/interp-lifecycle.html: c.Py_NoSiteFlag +c-api/interp-lifecycle.html: c.Py_NoUserSiteDirectory +c-api/interp-lifecycle.html: c.Py_OptimizeFlag +c-api/interp-lifecycle.html: c.Py_QuietFlag +c-api/interp-lifecycle.html: c.Py_UnbufferedStdioFlag +c-api/interp-lifecycle.html: c.Py_VerboseFlag +c-api/interp-lifecycle.html: global-conf-vars +c-api/interp-lifecycle.html: global-configuration-variables # Removed sections library/asyncio-task.html: terminating-a-task-group From 301c87ce1c9a1f8f88a86257c468adeb83c8bffa Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Sep 2026 23:00:08 +0200 Subject: [PATCH 7/9] Fix make check-c-globals --- Tools/c-analyzer/cpython/ignored.tsv | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv index 60ff561776b76d..2ad801c671855c 100644 --- a/Tools/c-analyzer/cpython/ignored.tsv +++ b/Tools/c-analyzer/cpython/ignored.tsv @@ -778,6 +778,7 @@ Modules/expat/xmlrole.c - condSect1 - Modules/expat/xmlrole.c - condSect2 - Modules/expat/xmlrole.c - declClose - Modules/expat/xmlrole.c - error - +Python/preconfig.c - Py_UTF8Mode - ## other Modules/_io/_iomodule.c - _PyIO_Module - From 46fa56372e0b274a2fe11c8e24143af008b7424a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 24 Sep 2026 13:01:52 +0200 Subject: [PATCH 8/9] Update doc to point to PyInitConfig --- Doc/whatsnew/3.16.rst | 97 +++++++++++++------------------------------ 1 file changed, 29 insertions(+), 68 deletions(-) diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index e804304608274d..fe9f3028eab2b1 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -1141,74 +1141,35 @@ Deprecated C APIs Removed C APIs -------------- -* Remove global configuration variables: - - * :c:var:`!Py_DebugFlag`: - Use :c:member:`PyConfig.parser_debug` or - :c:func:`PyConfig_Get("parser_debug") ` instead. - * :c:var:`!Py_VerboseFlag`: - Use :c:member:`PyConfig.verbose` or - :c:func:`PyConfig_Get("verbose") ` instead. - * :c:var:`!Py_QuietFlag`: - Use :c:member:`PyConfig.quiet` or - :c:func:`PyConfig_Get("quiet") ` instead. - * :c:var:`!Py_InteractiveFlag`: - Use :c:member:`PyConfig.interactive` or - :c:func:`PyConfig_Get("interactive") ` instead. - * :c:var:`!Py_InspectFlag`: - Use :c:member:`PyConfig.inspect` or - :c:func:`PyConfig_Get("inspect") ` instead. - * :c:var:`!Py_OptimizeFlag`: - Use :c:member:`PyConfig.optimization_level` or - :c:func:`PyConfig_Get("optimization_level") ` instead. - * :c:var:`!Py_NoSiteFlag`: - Use :c:member:`PyConfig.site_import` or - :c:func:`PyConfig_Get("site_import") ` instead. - * :c:var:`!Py_BytesWarningFlag`: - Use :c:member:`PyConfig.bytes_warning` or - :c:func:`PyConfig_Get("bytes_warning") ` instead. - * :c:var:`!Py_FrozenFlag`: - Use :c:member:`PyConfig.pathconfig_warnings` or - :c:func:`PyConfig_Get("pathconfig_warnings") ` instead. - * :c:var:`!Py_IgnoreEnvironmentFlag`: - Use :c:member:`PyConfig.use_environment` or - :c:func:`PyConfig_Get("use_environment") ` instead. - * :c:var:`!Py_DontWriteBytecodeFlag`: - Use :c:member:`PyConfig.write_bytecode` or - :c:func:`PyConfig_Get("write_bytecode") ` instead. - * :c:var:`!Py_NoUserSiteDirectory`: - Use :c:member:`PyConfig.user_site_directory` or - :c:func:`PyConfig_Get("user_site_directory") ` instead. - * :c:var:`!Py_UnbufferedStdioFlag`: - Use :c:member:`PyConfig.buffered_stdio` or - :c:func:`PyConfig_Get("buffered_stdio") ` instead. - * :c:var:`!Py_HashRandomizationFlag`: - Use :c:member:`PyConfig.use_hash_seed` - and :c:member:`PyConfig.hash_seed` or - :c:func:`PyConfig_Get("hash_seed") ` instead. - * :c:var:`!Py_IsolatedFlag`: - Use :c:member:`PyConfig.isolated` or - :c:func:`PyConfig_Get("isolated") ` instead. - * :c:var:`!Py_LegacyWindowsFSEncodingFlag`: - Use :c:member:`PyPreConfig.legacy_windows_fs_encoding` or - :c:func:`PyConfig_Get("legacy_windows_fs_encoding") ` instead. - * :c:var:`!Py_LegacyWindowsStdioFlag`: - Use :c:member:`PyConfig.legacy_windows_stdio` or - :c:func:`PyConfig_Get("legacy_windows_stdio") ` instead. - * :c:var:`!Py_FileSystemDefaultEncoding`, :c:var:`!Py_HasFileSystemDefaultEncoding`: - Use :c:member:`PyConfig.filesystem_encoding` or - :c:func:`PyConfig_Get("filesystem_encoding") ` instead. - * :c:var:`!Py_FileSystemDefaultEncodeErrors`: - Use :c:member:`PyConfig.filesystem_errors` or - :c:func:`PyConfig_Get("filesystem_errors") ` instead. - * :c:var:`!Py_UTF8Mode`: - Use :c:member:`PyPreConfig.utf8_mode` or - :c:func:`PyConfig_Get("utf8_mode") ` instead. - (see :c:func:`Py_PreInitialize`) - - The :c:func:`Py_InitializeFromConfig` API should be used with - :c:type:`PyConfig` to set these options. Or :c:func:`PyConfig_Get` can be - used to get these options at runtime. +* Remove 21 global configuration variables, deprecated in Python 3.12. + To initialize Python, the :ref:`PyInitConfig C API ` can be + used instead. + To read these variables at runtime, :c:func:`PyConfig_Get` can be used + instead. + Removed variables with their :ref:`PyInitConfig C API ` and + :c:func:`PyConfig_Get` replacement: + + * :c:var:`!Py_DebugFlag`: Use ``"parser_debug"`` instead. + * :c:var:`!Py_VerboseFlag`: Use ``"verbose"`` instead. + * :c:var:`!Py_QuietFlag`: Use ``"quiet"`` instead. + * :c:var:`!Py_InteractiveFlag`: Use ``"interactive"`` instead. + * :c:var:`!Py_InspectFlag`: Use ``"inspect"`` instead. + * :c:var:`!Py_OptimizeFlag`: Use ``"optimization_level"`` instead. + * :c:var:`!Py_NoSiteFlag`: Use ``"site_import"`` instead (opposite value). + * :c:var:`!Py_BytesWarningFlag`: Use ``"bytes_warning"`` instead. + * :c:var:`!Py_FrozenFlag`: Use ``"pathconfig_warnings"`` instead (opposite value). + * :c:var:`!Py_IgnoreEnvironmentFlag`: Use ``"use_environment"`` instead (opposite value). + * :c:var:`!Py_DontWriteBytecodeFlag`: Use ``"write_bytecode"`` instead (opposite value). + * :c:var:`!Py_NoUserSiteDirectory`: Use ``"user_site_directory"`` instead (opposite value). + * :c:var:`!Py_UnbufferedStdioFlag`: Use ``"buffered_stdio"`` instead (opposite value). + * :c:var:`!Py_HashRandomizationFlag`: Use ``"hash_seed"`` instead. + * :c:var:`!Py_IsolatedFlag`: Use ``"isolated"`` instead. + * :c:var:`!Py_LegacyWindowsFSEncodingFlag`: Use ``"legacy_windows_fs_encoding"`` instead. + * :c:var:`!Py_LegacyWindowsStdioFlag`: Use ``"legacy_windows_stdio"`` instead. + * :c:var:`!Py_FileSystemDefaultEncoding`, :c:var:`!Py_HasFileSystemDefaultEncoding`: Use ``"filesystem_encoding"`` instead. + * :c:var:`!Py_FileSystemDefaultEncodeErrors`: Use ``"filesystem_errors"`` instead. + * :c:var:`!Py_UTF8Mode`: Use ``"utf8_mode"`` instead. + (Contributed by Victor Stinner in :gh:`158001`.) * Remove :c:func:`!PyEval_InitThreads` function which did nothing since Python From dcfba0061e61088cdde509b2586a2f7f74ada7aa Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 24 Sep 2026 13:30:51 +0200 Subject: [PATCH 9/9] Update comment --- Lib/test/test_ctypes/test_values.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_ctypes/test_values.py b/Lib/test/test_ctypes/test_values.py index 08aabe8088db72..0d62702c0c0fd3 100644 --- a/Lib/test/test_ctypes/test_values.py +++ b/Lib/test/test_ctypes/test_values.py @@ -75,7 +75,7 @@ class PythonValuesTestCase(unittest.TestCase): def test_version_var(self): # This test accesses the Py_Version integer, which is - # exported by the Python dll and should match the sys.flags value + # exported by the Python dll and should match the sys.hexversion value version = c_int.in_dll(pythonapi, "Py_Version").value self.assertEqual(version, sys.hexversion)