[Python-checkins] gh-105145: Remove old functions to config Python init (#105154)

vstinner webhook-mailer at python.org
Thu Jun 1 03:14:09 EDT 2023


https://github.com/python/cpython/commit/424049cc1117d66dfa86196ee5f694c15b46ac6c
commit: 424049cc1117d66dfa86196ee5f694c15b46ac6c
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2023-06-01T09:14:02+02:00
summary:

gh-105145: Remove old functions to config Python init (#105154)

Remove the following old functions to configure the Python
initialization, deprecated in Python 3.11:

* PySys_AddWarnOptionUnicode()
* PySys_AddWarnOption()
* PySys_AddXOption()
* PySys_HasWarnOptions()
* PySys_SetArgvEx()
* PySys_SetArgv()
* PySys_SetPath()
* Py_SetPath()
* Py_SetProgramName()
* Py_SetPythonHome()
* Py_SetStandardStreamEncoding()
* _Py_SetProgramFullPath()

Most of these functions are kept in the stable ABI, except:

* Py_SetStandardStreamEncoding()
* _Py_SetProgramFullPath()

Update Doc/extending/embedding.rst and Doc/extending/extending.rst to
use the new PyConfig API.

_testembed.c:

* check_stdio_details() now sets stdio_encoding and stdio_errors
  of PyConfig.
* Add definitions of functions removed from the API but kept in the
  stable ABI.
* test_init_from_config() and test_init_read_set() now use
  PyConfig_SetString() instead of PyConfig_SetBytesString().

Remove _Py_ClearStandardStreamEncoding() internal function.

files:
A Misc/NEWS.d/next/C API/2023-05-31-16-51-18.gh-issue-105145.b3B6lJ.rst
M Doc/c-api/init.rst
M Doc/c-api/init_config.rst
M Doc/c-api/intro.rst
M Doc/c-api/sys.rst
M Doc/data/stable_abi.dat
M Doc/extending/embedding.rst
M Doc/extending/extending.rst
M Doc/library/sys_path_init.rst
M Doc/using/windows.rst
M Doc/whatsnew/3.13.rst
M Include/cpython/pylifecycle.h
M Include/internal/pycore_pylifecycle.h
M Include/pylifecycle.h
M Include/sysmodule.h
M Misc/stable_abi.toml
M Modules/main.c
M Programs/_testembed.c
M Python/initconfig.c
M Python/pathconfig.c
M Python/pylifecycle.c
M Python/sysmodule.c

diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst
index 26762969ef8eb..f3690ebfab282 100644
--- a/Doc/c-api/init.rst
+++ b/Doc/c-api/init.rst
@@ -29,12 +29,6 @@ The following functions can be safely called before Python is initialized:
   * :c:func:`PyMem_SetAllocator`
   * :c:func:`PyMem_SetupDebugHooks`
   * :c:func:`PyObject_SetArenaAllocator`
-  * :c:func:`Py_SetPath`
-  * :c:func:`Py_SetProgramName`
-  * :c:func:`Py_SetPythonHome`
-  * :c:func:`Py_SetStandardStreamEncoding`
-  * :c:func:`PySys_AddWarnOption`
-  * :c:func:`PySys_AddXOption`
   * :c:func:`PySys_ResetWarnOptions`
 
 * Informative functions:
@@ -332,7 +326,6 @@ Initializing and finalizing the interpreter
 .. c:function:: void Py_Initialize()
 
    .. index::
-      single: Py_SetProgramName()
       single: PyEval_InitThreads()
       single: modules (in module sys)
       single: path (in module sys)
@@ -340,8 +333,6 @@ Initializing and finalizing the interpreter
       pair: module; __main__
       pair: module; sys
       triple: module; search; path
-      single: PySys_SetArgv()
-      single: PySys_SetArgvEx()
       single: Py_FinalizeEx()
 
    Initialize the Python interpreter.  In an application embedding  Python,
@@ -352,7 +343,9 @@ Initializing and finalizing the interpreter
    the table of loaded modules (``sys.modules``), and creates the fundamental
    modules :mod:`builtins`, :mod:`__main__` and :mod:`sys`.  It also initializes
    the module search path (``sys.path``). It does not set ``sys.argv``; use
-   :c:func:`PySys_SetArgvEx` for that.  This is a no-op when called for a second time
+   the new :c:type:`PyConfig` API of the :ref:`Python Initialization
+   Configuration <init-config>` for that.  This is a no-op when called for a
+   second time
    (without calling :c:func:`Py_FinalizeEx` first).  There is no return value; it is a
    fatal error if the initialization fails.
 
@@ -425,76 +418,9 @@ Process-wide parameters
 =======================
 
 
-.. c:function:: int Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
-
-   .. index::
-      single: Py_Initialize()
-      single: main()
-      triple: stdin; stdout; sdterr
-
-   This API is kept for backward compatibility: setting
-   :c:member:`PyConfig.stdio_encoding` and :c:member:`PyConfig.stdio_errors`
-   should be used instead, see :ref:`Python Initialization Configuration
-   <init-config>`.
-
-   This function should be called before :c:func:`Py_Initialize`, if it is
-   called at all. It specifies which encoding and error handling to use
-   with standard IO, with the same meanings as in :func:`str.encode`.
-
-   It overrides :envvar:`PYTHONIOENCODING` values, and allows embedding code
-   to control IO encoding when the environment variable does not work.
-
-   *encoding* and/or *errors* may be ``NULL`` to use
-   :envvar:`PYTHONIOENCODING` and/or default values (depending on other
-   settings).
-
-   Note that :data:`sys.stderr` always uses the "backslashreplace" error
-   handler, regardless of this (or any other) setting.
-
-   If :c:func:`Py_FinalizeEx` is called, this function will need to be called
-   again in order to affect subsequent calls to :c:func:`Py_Initialize`.
-
-   Returns ``0`` if successful, a nonzero value on error (e.g. calling after the
-   interpreter has already been initialized).
-
-   .. versionadded:: 3.4
-
-   .. deprecated:: 3.11
-
-
-.. c:function:: void Py_SetProgramName(const wchar_t *name)
-
-   .. index::
-      single: Py_Initialize()
-      single: main()
-      single: Py_GetPath()
-
-   This API is kept for backward compatibility: setting
-   :c:member:`PyConfig.program_name` should be used instead, see :ref:`Python
-   Initialization Configuration <init-config>`.
-
-   This function should be called before :c:func:`Py_Initialize` is called for
-   the first time, if it is called at all.  It tells the interpreter the value
-   of the ``argv[0]`` argument to the :c:func:`main` function of the program
-   (converted to wide characters).
-   This is used by :c:func:`Py_GetPath` and some other functions below to find
-   the Python run-time libraries relative to the interpreter executable.  The
-   default value is ``'python'``.  The argument should point to a
-   zero-terminated wide character string in static storage whose contents will not
-   change for the duration of the program's execution.  No code in the Python
-   interpreter will change the contents of this storage.
-
-   Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a
-   :c:expr:`wchar_*` string.
-
-   .. deprecated:: 3.11
-
-
 .. c:function:: wchar* Py_GetProgramName()
 
-   .. index:: single: Py_SetProgramName()
-
-   Return the program name set with :c:func:`Py_SetProgramName`, or the default.
+   Return the program name set with :c:member:`PyConfig.program_name`, or the default.
    The returned string points into static storage; the caller should not modify its
    value.
 
@@ -509,7 +435,7 @@ Process-wide parameters
 
    Return the *prefix* for installed platform-independent files. This is derived
    through a number of complicated rules from the program name set with
-   :c:func:`Py_SetProgramName` and some environment variables; for example, if the
+   :c:member:`PyConfig.program_name` and some environment variables; for example, if the
    program name is ``'/usr/local/bin/python'``, the prefix is ``'/usr/local'``. The
    returned string points into static storage; the caller should not modify its
    value.  This corresponds to the :makevar:`prefix` variable in the top-level
@@ -528,7 +454,7 @@ Process-wide parameters
 
    Return the *exec-prefix* for installed platform-*dependent* files.  This is
    derived through a number of complicated rules from the program name set with
-   :c:func:`Py_SetProgramName` and some environment variables; for example, if the
+   :c:member:`PyConfig.program_name` and some environment variables; for example, if the
    program name is ``'/usr/local/bin/python'``, the exec-prefix is
    ``'/usr/local'``.  The returned string points into static storage; the caller
    should not modify its value.  This corresponds to the :makevar:`exec_prefix`
@@ -568,12 +494,11 @@ Process-wide parameters
 .. c:function:: wchar_t* Py_GetProgramFullPath()
 
    .. index::
-      single: Py_SetProgramName()
       single: executable (in module sys)
 
    Return the full program name of the Python executable; this is  computed as a
    side-effect of deriving the default module search path  from the program name
-   (set by :c:func:`Py_SetProgramName` above). The returned string points into
+   (set by :c:member:`PyConfig.program_name`). The returned string points into
    static storage; the caller should not modify its value.  The value is available
    to Python code as ``sys.executable``.
 
@@ -589,10 +514,9 @@ Process-wide parameters
    .. index::
       triple: module; search; path
       single: path (in module sys)
-      single: Py_SetPath()
 
    Return the default module search path; this is computed from the program name
-   (set by :c:func:`Py_SetProgramName` above) and some environment variables.
+   (set by :c:member:`PyConfig.program_name`) and some environment variables.
    The returned string consists of a series of directory names separated by a
    platform dependent delimiter character.  The delimiter character is ``':'``
    on Unix and macOS, ``';'`` on Windows.  The returned string points into
@@ -610,44 +534,6 @@ Process-wide parameters
       It now returns ``NULL`` if called before :c:func:`Py_Initialize`.
 
 
-.. c:function::  void Py_SetPath(const wchar_t *)
-
-   .. index::
-      triple: module; search; path
-      single: path (in module sys)
-      single: Py_GetPath()
-
-   This API is kept for backward compatibility: setting
-   :c:member:`PyConfig.module_search_paths` and
-   :c:member:`PyConfig.module_search_paths_set` should be used instead, see
-   :ref:`Python Initialization Configuration <init-config>`.
-
-   Set the default module search path.  If this function is called before
-   :c:func:`Py_Initialize`, then :c:func:`Py_GetPath` won't attempt to compute a
-   default search path but uses the one provided instead.  This is useful if
-   Python is embedded by an application that has full knowledge of the location
-   of all modules.  The path components should be separated by the platform
-   dependent delimiter character, which is ``':'`` on Unix and macOS, ``';'``
-   on Windows.
-
-   This also causes :data:`sys.executable` to be set to the program
-   full path (see :c:func:`Py_GetProgramFullPath`) and for :data:`sys.prefix` and
-   :data:`sys.exec_prefix` to be empty.  It is up to the caller to modify these
-   if required after calling :c:func:`Py_Initialize`.
-
-   Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a
-   :c:expr:`wchar_*` string.
-
-   The path argument is copied internally, so the caller may free it after the
-   call completes.
-
-   .. versionchanged:: 3.8
-      The program full path is now used for :data:`sys.executable`, instead
-      of the program name.
-
-   .. deprecated:: 3.11
-
-
 .. c:function:: const char* Py_GetVersion()
 
    Return the version of this Python interpreter.  This is a string that looks
@@ -718,110 +604,10 @@ Process-wide parameters
    ``sys.version``.
 
 
-.. c:function:: void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
-
-   .. index::
-      single: main()
-      single: Py_FatalError()
-      single: argv (in module sys)
-
-   This API is kept for backward compatibility: setting
-   :c:member:`PyConfig.argv`, :c:member:`PyConfig.parse_argv` and
-   :c:member:`PyConfig.safe_path` should be used instead, see :ref:`Python
-   Initialization Configuration <init-config>`.
-
-   Set :data:`sys.argv` based on *argc* and *argv*.  These parameters are
-   similar to those passed to the program's :c:func:`main` function with the
-   difference that the first entry should refer to the script file to be
-   executed rather than the executable hosting the Python interpreter.  If there
-   isn't a script that will be run, the first entry in *argv* can be an empty
-   string.  If this function fails to initialize :data:`sys.argv`, a fatal
-   condition is signalled using :c:func:`Py_FatalError`.
-
-   If *updatepath* is zero, this is all the function does.  If *updatepath*
-   is non-zero, the function also modifies :data:`sys.path` according to the
-   following algorithm:
-
-   - If the name of an existing script is passed in ``argv[0]``, the absolute
-     path of the directory where the script is located is prepended to
-     :data:`sys.path`.
-   - Otherwise (that is, if *argc* is ``0`` or ``argv[0]`` doesn't point
-     to an existing file name), an empty string is prepended to
-     :data:`sys.path`, which is the same as prepending the current working
-     directory (``"."``).
-
-   Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a
-   :c:expr:`wchar_*` string.
-
-   See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv`
-   members of the :ref:`Python Initialization Configuration <init-config>`.
-
-   .. note::
-      It is recommended that applications embedding the Python interpreter
-      for purposes other than executing a single script pass ``0`` as *updatepath*,
-      and update :data:`sys.path` themselves if desired.
-      See `CVE-2008-5983 <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5983>`_.
-
-      On versions before 3.1.3, you can achieve the same effect by manually
-      popping the first :data:`sys.path` element after having called
-      :c:func:`PySys_SetArgv`, for example using::
-
-         PyRun_SimpleString("import sys; sys.path.pop(0)\n");
-
-   .. versionadded:: 3.1.3
-
-   .. XXX impl. doesn't seem consistent in allowing ``0``/``NULL`` for the params;
-      check w/ Guido.
-
-   .. deprecated:: 3.11
-
-
-.. c:function:: void PySys_SetArgv(int argc, wchar_t **argv)
-
-   This API is kept for backward compatibility: setting
-   :c:member:`PyConfig.argv` and :c:member:`PyConfig.parse_argv` should be used
-   instead, see :ref:`Python Initialization Configuration <init-config>`.
-
-   This function works like :c:func:`PySys_SetArgvEx` with *updatepath* set
-   to ``1`` unless the :program:`python` interpreter was started with the
-   :option:`-I`.
-
-   Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a
-   :c:expr:`wchar_*` string.
-
-   See also :c:member:`PyConfig.orig_argv` and :c:member:`PyConfig.argv`
-   members of the :ref:`Python Initialization Configuration <init-config>`.
-
-   .. versionchanged:: 3.4 The *updatepath* value depends on :option:`-I`.
-
-   .. deprecated:: 3.11
-
-
-.. c:function:: void Py_SetPythonHome(const wchar_t *home)
-
-   This API is kept for backward compatibility: setting
-   :c:member:`PyConfig.home` should be used instead, see :ref:`Python
-   Initialization Configuration <init-config>`.
-
-   Set the default "home" directory, that is, the location of the standard
-   Python libraries.  See :envvar:`PYTHONHOME` for the meaning of the
-   argument string.
-
-   The argument should point to a zero-terminated character string in static
-   storage whose contents will not change for the duration of the program's
-   execution.  No code in the Python interpreter will change the contents of
-   this storage.
-
-   Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a
-   :c:expr:`wchar_*` string.
-
-   .. deprecated:: 3.11
-
-
 .. c:function:: wchar_t* Py_GetPythonHome()
 
-   Return the default "home", that is, the value set by a previous call to
-   :c:func:`Py_SetPythonHome`, or the value of the :envvar:`PYTHONHOME`
+   Return the default "home", that is, the value set by
+   :c:member:`PyConfig.home`, or the value of the :envvar:`PYTHONHOME`
    environment variable if it is set.
 
    This function should not be called before :c:func:`Py_Initialize`, otherwise
diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst
index 161def0b4baf3..5f70c45c54f75 100644
--- a/Doc/c-api/init_config.rst
+++ b/Doc/c-api/init_config.rst
@@ -531,7 +531,17 @@ PyConfig
 
    .. c:member:: PyWideStringList argv
 
-      Command line arguments: :data:`sys.argv`.
+      .. index::
+         single: main()
+         single: argv (in module sys)
+
+      Set :data:`sys.argv` command line arguments based on
+      :c:member:`~PyConfig.argv`.  These parameters are similar to those passed
+      to the program's :c:func:`main` function with the difference that the
+      first entry should refer to the script file to be executed rather than
+      the executable hosting the Python interpreter.  If there isn't a script
+      that will be run, the first entry in :c:member:`~PyConfig.argv` can be an
+      empty string.
 
       Set :c:member:`~PyConfig.parse_argv` to ``1`` to parse
       :c:member:`~PyConfig.argv` the same way the regular Python parses Python
@@ -572,6 +582,8 @@ PyConfig
 
       Part of the :ref:`Python Path Configuration <init-path-config>` output.
 
+      See also :c:member:`PyConfig.exec_prefix`.
+
    .. c:member:: wchar_t* base_executable
 
       Python base executable: :data:`sys._base_executable`.
@@ -584,6 +596,8 @@ PyConfig
 
       Part of the :ref:`Python Path Configuration <init-path-config>` output.
 
+      See also :c:member:`PyConfig.executable`.
+
    .. c:member:: wchar_t* base_prefix
 
       :data:`sys.base_prefix`.
@@ -592,6 +606,8 @@ PyConfig
 
       Part of the :ref:`Python Path Configuration <init-path-config>` output.
 
+      See also :c:member:`PyConfig.prefix`.
+
    .. c:member:: int buffered_stdio
 
       If equals to ``0`` and :c:member:`~PyConfig.configure_c_stdio` is non-zero,
@@ -700,6 +716,8 @@ PyConfig
 
       Part of the :ref:`Python Path Configuration <init-path-config>` output.
 
+      See also :c:member:`PyConfig.base_exec_prefix`.
+
    .. c:member:: wchar_t* executable
 
       The absolute path of the executable binary for the Python interpreter:
@@ -709,6 +727,8 @@ PyConfig
 
       Part of the :ref:`Python Path Configuration <init-path-config>` output.
 
+      See also :c:member:`PyConfig.base_executable`.
+
    .. c:member:: int faulthandler
 
       Enable faulthandler?
@@ -780,10 +800,8 @@ PyConfig
 
    .. c:member:: wchar_t* home
 
-      Python home directory.
-
-      If :c:func:`Py_SetPythonHome` has been called, use its argument if it is
-      not ``NULL``.
+      Set the default Python "home" directory, that is, the location of the
+      standard Python libraries (see :envvar:`PYTHONHOME`).
 
       Set by the :envvar:`PYTHONHOME` environment variable.
 
@@ -1029,12 +1047,13 @@ PyConfig
 
       Part of the :ref:`Python Path Configuration <init-path-config>` output.
 
+      See also :c:member:`PyConfig.base_prefix`.
+
    .. c:member:: wchar_t* program_name
 
       Program name used to initialize :c:member:`~PyConfig.executable` and in
       early error messages during Python initialization.
 
-      * If :func:`Py_SetProgramName` has been called, use its argument.
       * On macOS, use :envvar:`PYTHONEXECUTABLE` environment variable if set.
       * If the ``WITH_NEXT_FRAMEWORK`` macro is defined, use
         :envvar:`__PYVENV_LAUNCHER__` environment variable if set.
@@ -1144,9 +1163,6 @@ PyConfig
       :data:`sys.stderr` (but :data:`sys.stderr` always uses
       ``"backslashreplace"`` error handler).
 
-      If :c:func:`Py_SetStandardStreamEncoding` has been called, use its
-      *error* and *errors* arguments if they are not ``NULL``.
-
       Use the :envvar:`PYTHONIOENCODING` environment variable if it is
       non-empty.
 
@@ -1162,6 +1178,8 @@ PyConfig
         or if the LC_CTYPE locale is "C" or "POSIX".
       * ``"strict"`` otherwise.
 
+      See also :c:member:`PyConfig.legacy_windows_stdio`.
+
    .. c:member:: int tracemalloc
 
       Enable tracemalloc?
@@ -1509,7 +1527,7 @@ If a ``._pth`` file is present:
 * Set :c:member:`~PyConfig.safe_path` to ``1``.
 
 The ``__PYVENV_LAUNCHER__`` environment variable is used to set
-:c:member:`PyConfig.base_executable`
+:c:member:`PyConfig.base_executable`.
 
 
 Py_RunMain()
diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst
index 8de76e55cd058..9014f7e03b360 100644
--- a/Doc/c-api/intro.rst
+++ b/Doc/c-api/intro.rst
@@ -739,14 +739,14 @@ environment variable :envvar:`PYTHONHOME`, or insert additional directories in
 front of the standard path by setting :envvar:`PYTHONPATH`.
 
 .. index::
-   single: Py_SetProgramName()
    single: Py_GetPath()
    single: Py_GetPrefix()
    single: Py_GetExecPrefix()
    single: Py_GetProgramFullPath()
 
-The embedding application can steer the search by calling
-``Py_SetProgramName(file)`` *before* calling  :c:func:`Py_Initialize`.  Note that
+The embedding application can steer the search by setting
+:c:member:`PyConfig.program_name` *before* calling
+:c:func:`Py_InitializeFromConfig`. Note that
 :envvar:`PYTHONHOME` still overrides this and :envvar:`PYTHONPATH` is still
 inserted in front of the standard path.  An application that requires total
 control has to provide its own implementation of :c:func:`Py_GetPath`,
diff --git a/Doc/c-api/sys.rst b/Doc/c-api/sys.rst
index 6fc8a3aff9568..ad6005b7c7a87 100644
--- a/Doc/c-api/sys.rst
+++ b/Doc/c-api/sys.rst
@@ -237,46 +237,6 @@ accessible to C code.  They all work with the current interpreter thread's
    Reset :data:`sys.warnoptions` to an empty list. This function may be
    called prior to :c:func:`Py_Initialize`.
 
-.. c:function:: void PySys_AddWarnOption(const wchar_t *s)
-
-   This API is kept for backward compatibility: setting
-   :c:member:`PyConfig.warnoptions` should be used instead, see :ref:`Python
-   Initialization Configuration <init-config>`.
-
-   Append *s* to :data:`sys.warnoptions`. This function must be called prior
-   to :c:func:`Py_Initialize` in order to affect the warnings filter list.
-
-   .. deprecated:: 3.11
-
-.. c:function:: void PySys_AddWarnOptionUnicode(PyObject *unicode)
-
-   This API is kept for backward compatibility: setting
-   :c:member:`PyConfig.warnoptions` should be used instead, see :ref:`Python
-   Initialization Configuration <init-config>`.
-
-   Append *unicode* to :data:`sys.warnoptions`.
-
-   Note: this function is not currently usable from outside the CPython
-   implementation, as it must be called prior to the implicit import of
-   :mod:`warnings` in :c:func:`Py_Initialize` to be effective, but can't be
-   called until enough of the runtime has been initialized to permit the
-   creation of Unicode objects.
-
-   .. deprecated:: 3.11
-
-.. c:function:: void PySys_SetPath(const wchar_t *path)
-
-   This API is kept for backward compatibility: setting
-   :c:member:`PyConfig.module_search_paths` and
-   :c:member:`PyConfig.module_search_paths_set` should be used instead, see
-   :ref:`Python Initialization Configuration <init-config>`.
-
-   Set :data:`sys.path` to a list object of paths found in *path* which should
-   be a list of paths separated with the platform's search path delimiter
-   (``:`` on Unix, ``;`` on Windows).
-
-   .. deprecated:: 3.11
-
 .. c:function:: void PySys_WriteStdout(const char *format, ...)
 
    Write the output string described by *format* to :data:`sys.stdout`.  No
@@ -313,20 +273,6 @@ accessible to C code.  They all work with the current interpreter thread's
 
    .. versionadded:: 3.2
 
-.. c:function:: void PySys_AddXOption(const wchar_t *s)
-
-   This API is kept for backward compatibility: setting
-   :c:member:`PyConfig.xoptions` should be used instead, see :ref:`Python
-   Initialization Configuration <init-config>`.
-
-   Parse *s* as a set of :option:`-X` options and add them to the current
-   options mapping as returned by :c:func:`PySys_GetXOptions`. This function
-   may be called prior to :c:func:`Py_Initialize`.
-
-   .. versionadded:: 3.2
-
-   .. deprecated:: 3.11
-
 .. c:function:: PyObject *PySys_GetXOptions()
 
    Return the current dictionary of :option:`-X` options, similarly to
diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat
index f255d9586b9ba..17b291fd4d0fa 100644
--- a/Doc/data/stable_abi.dat
+++ b/Doc/data/stable_abi.dat
@@ -596,19 +596,12 @@ function,PyStructSequence_NewType,3.2,,
 function,PyStructSequence_SetItem,3.2,,
 var,PyStructSequence_UnnamedField,3.11,,
 var,PySuper_Type,3.2,,
-function,PySys_AddWarnOption,3.2,,
-function,PySys_AddWarnOptionUnicode,3.2,,
-function,PySys_AddXOption,3.7,,
 function,PySys_FormatStderr,3.2,,
 function,PySys_FormatStdout,3.2,,
 function,PySys_GetObject,3.2,,
 function,PySys_GetXOptions,3.7,,
-function,PySys_HasWarnOptions,3.2,,
 function,PySys_ResetWarnOptions,3.2,,
-function,PySys_SetArgv,3.2,,
-function,PySys_SetArgvEx,3.2,,
 function,PySys_SetObject,3.2,,
-function,PySys_SetPath,3.2,,
 function,PySys_WriteStderr,3.2,,
 function,PySys_WriteStdout,3.2,,
 type,PyThreadState,3.2,,opaque
@@ -850,9 +843,6 @@ function,Py_NewInterpreter,3.2,,
 function,Py_NewRef,3.10,,
 function,Py_ReprEnter,3.2,,
 function,Py_ReprLeave,3.2,,
-function,Py_SetPath,3.7,,
-function,Py_SetProgramName,3.2,,
-function,Py_SetPythonHome,3.2,,
 function,Py_SetRecursionLimit,3.2,,
 type,Py_UCS4,3.2,,
 macro,Py_UNBLOCK_THREADS,3.2,,
diff --git a/Doc/extending/embedding.rst b/Doc/extending/embedding.rst
index e64db37334403..1470029b80477 100644
--- a/Doc/extending/embedding.rst
+++ b/Doc/extending/embedding.rst
@@ -59,24 +59,36 @@ perform some operation on a file. ::
    int
    main(int argc, char *argv[])
    {
-       wchar_t *program = Py_DecodeLocale(argv[0], NULL);
-       if (program == NULL) {
-           fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
-           exit(1);
+       PyStatus status;
+       PyConfig config;
+       PyConfig_InitPythonConfig(&config);
+
+       /* optional but recommended */
+       status = PyConfig_SetBytesString(&config, &config.program_name, argv[0]);
+       if (PyStatus_Exception(status)) {
+           goto exception;
        }
-       Py_SetProgramName(program);  /* optional but recommended */
-       Py_Initialize();
+
+       status = Py_InitializeFromConfig(&config);
+       if (PyStatus_Exception(status)) {
+           goto exception;
+       }
+       PyConfig_Clear(&config);
+
        PyRun_SimpleString("from time import time,ctime\n"
                           "print('Today is', ctime(time()))\n");
        if (Py_FinalizeEx() < 0) {
            exit(120);
        }
-       PyMem_RawFree(program);
        return 0;
+
+     exception:
+        PyConfig_Clear(&config);
+        Py_ExitStatusException(status);
    }
 
-The :c:func:`Py_SetProgramName` function should be called before
-:c:func:`Py_Initialize` to inform the interpreter about paths to Python run-time
+Setting :c:member:`PyConfig.program_name` should be called before
+:c:func:`Py_InitializeFromConfig` to inform the interpreter about paths to Python run-time
 libraries.  Next, the Python interpreter is initialized with
 :c:func:`Py_Initialize`, followed by the execution of a hard-coded Python script
 that prints the date and time.  Afterwards, the :c:func:`Py_FinalizeEx` call shuts
diff --git a/Doc/extending/extending.rst b/Doc/extending/extending.rst
index c37b69f988a6b..ef93848840861 100644
--- a/Doc/extending/extending.rst
+++ b/Doc/extending/extending.rst
@@ -383,14 +383,15 @@ automatically unless there's an entry in the :c:data:`PyImport_Inittab` table.
 To add the module to the initialization table, use :c:func:`PyImport_AppendInittab`,
 optionally followed by an import of the module::
 
+   #define PY_SSIZE_T_CLEAN
+   #include <Python.h>
+
    int
    main(int argc, char *argv[])
    {
-       wchar_t *program = Py_DecodeLocale(argv[0], NULL);
-       if (program == NULL) {
-           fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
-           exit(1);
-       }
+       PyStatus status;
+       PyConfig config;
+       PyConfig_InitPythonConfig(&config);
 
        /* Add a built-in module, before Py_Initialize */
        if (PyImport_AppendInittab("spam", PyInit_spam) == -1) {
@@ -399,11 +400,18 @@ optionally followed by an import of the module::
        }
 
        /* Pass argv[0] to the Python interpreter */
-       Py_SetProgramName(program);
+       status = PyConfig_SetBytesString(&config, &config.program_name, argv[0]);
+       if (PyStatus_Exception(status)) {
+           goto exception;
+       }
 
        /* Initialize the Python interpreter.  Required.
           If this step fails, it will be a fatal error. */
-       Py_Initialize();
+       status = Py_InitializeFromConfig(&config);
+       if (PyStatus_Exception(status)) {
+           goto exception;
+       }
+       PyConfig_Clear(&config);
 
        /* Optionally import the module; alternatively,
           import can be deferred until the embedded script
@@ -414,10 +422,13 @@ optionally followed by an import of the module::
            fprintf(stderr, "Error: could not import module 'spam'\n");
        }
 
-       ...
+       // ... use Python C API here ...
 
-       PyMem_RawFree(program);
        return 0;
+
+     exception:
+        PyConfig_Clear(&config);
+        Py_ExitStatusException(status);
    }
 
 .. note::
diff --git a/Doc/library/sys_path_init.rst b/Doc/library/sys_path_init.rst
index 72c1387344c2a..a87a41cf829fa 100644
--- a/Doc/library/sys_path_init.rst
+++ b/Doc/library/sys_path_init.rst
@@ -99,8 +99,7 @@ Embedded Python
 
 If Python is embedded within another application :c:func:`Py_InitializeFromConfig` and
 the :c:type:`PyConfig` structure can be used to initialize Python. The path specific
-details are described at :ref:`init-path-config`. Alternatively the older :c:func:`Py_SetPath`
-can be used to bypass the initialization of the module search path.
+details are described at :ref:`init-path-config`.
 
 .. seealso::
 
diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst
index 43e3c72f3e1cd..ac1ba111e6d9b 100644
--- a/Doc/using/windows.rst
+++ b/Doc/using/windows.rst
@@ -1169,8 +1169,8 @@ following advice will prevent conflicts with other installations:
   listed.
 
 * If you are loading :file:`python3.dll` or :file:`python37.dll` in your own
-  executable, explicitly call :c:func:`Py_SetPath` or (at least)
-  :c:func:`Py_SetProgramName` before :c:func:`Py_Initialize`.
+  executable, explicitly set :c:member:`PyConfig.module_search_paths` before
+  :c:func:`Py_InitializeFromConfig`.
 
 * Clear and/or overwrite :envvar:`PYTHONPATH` and set :envvar:`PYTHONHOME`
   before launching :file:`python.exe` from your application.
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index e263d0bde484e..cdc48a547ce26 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -375,3 +375,23 @@ Removed
   * ``PyEval_CallMethod()``: use :c:func:`PyObject_CallMethod` instead.
 
   (Contributed by Victor Stinner in :gh:`105107`.)
+
+* Remove the following old functions to configure the Python initialization,
+  deprecated in Python 3.11:
+
+  * ``PySys_AddWarnOptionUnicode()``: use :c:member:`PyConfig.warnoptions` instead.
+  * ``PySys_AddWarnOption()``: use :c:member:`PyConfig.warnoptions` instead.
+  * ``PySys_AddXOption()``: use :c:member:`PyConfig.xoptions` instead.
+  * ``PySys_HasWarnOptions()``: use :c:member:`PyConfig.xoptions` instead.
+  * ``PySys_SetArgvEx()``: set :c:member:`PyConfig.argv` instead.
+  * ``PySys_SetArgv()``: set :c:member:`PyConfig.argv` instead.
+  * ``PySys_SetPath()``: set :c:member:`PyConfig.module_search_paths` instead.
+  * ``Py_SetPath()``: set :c:member:`PyConfig.module_search_paths` instead.
+  * ``Py_SetProgramName()``: set :c:member:`PyConfig.program_name` instead.
+  * ``Py_SetPythonHome()``: set :c:member:`PyConfig.home` instead.
+  * ``Py_SetStandardStreamEncoding()``: set :c:member:`PyConfig.stdio_encoding` instead.
+  * ``_Py_SetProgramFullPath()``: set :c:member:`PyConfig.executable` instead.
+
+  Use the new :c:type:`PyConfig` API of the :ref:`Python Initialization
+  Configuration <init-config>` instead (:pep:`587`), added to Python 3.8.
+  (Contributed by Victor Stinner in :gh:`105145`.)
diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h
index 314a5cc5b942a..1ca9ee91a72b1 100644
--- a/Include/cpython/pylifecycle.h
+++ b/Include/cpython/pylifecycle.h
@@ -6,13 +6,6 @@
    in all builds of Python */
 PyAPI_FUNC(int) Py_FrozenMain(int argc, char **argv);
 
-/* Only used by applications that embed the interpreter and need to
- * override the standard encoding determination mechanism
- */
-Py_DEPRECATED(3.11) PyAPI_FUNC(int) Py_SetStandardStreamEncoding(
-    const char *encoding,
-    const char *errors);
-
 /* PEP 432 Multi-phase initialization API (Private while provisional!) */
 
 PyAPI_FUNC(PyStatus) Py_PreInitialize(
@@ -46,8 +39,6 @@ PyAPI_FUNC(void) _Py_RestoreSignals(void);
 PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *);
 PyAPI_FUNC(int) _Py_FdIsInteractive(FILE *fp, PyObject *filename);
 
-Py_DEPRECATED(3.11) PyAPI_FUNC(void) _Py_SetProgramFullPath(const wchar_t *);
-
 PyAPI_FUNC(const char *) _Py_gitidentifier(void);
 PyAPI_FUNC(const char *) _Py_gitversion(void);
 
diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h
index 7cd998a704c88..b07c2dba8de84 100644
--- a/Include/internal/pycore_pylifecycle.h
+++ b/Include/internal/pycore_pylifecycle.h
@@ -23,8 +23,6 @@ extern PyStatus _PyUnicode_InitEncodings(PyThreadState *tstate);
 extern int _PyUnicode_EnableLegacyWindowsFSEncoding(void);
 #endif
 
-PyAPI_FUNC(void) _Py_ClearStandardStreamEncoding(void);
-
 PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc);
 
 /* Various one-time initializers */
diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h
index e4c3b09c963fe..0190b4c3f5ded 100644
--- a/Include/pylifecycle.h
+++ b/Include/pylifecycle.h
@@ -34,18 +34,12 @@ PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv);
 PyAPI_FUNC(int) Py_BytesMain(int argc, char **argv);
 
 /* In pathconfig.c */
-Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *);
 PyAPI_FUNC(wchar_t *) Py_GetProgramName(void);
-
-Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetPythonHome(const wchar_t *);
 PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void);
-
 PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void);
-
 PyAPI_FUNC(wchar_t *) Py_GetPrefix(void);
 PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
 PyAPI_FUNC(wchar_t *) Py_GetPath(void);
-Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetPath(const wchar_t *);
 #ifdef MS_WINDOWS
 int _Py_CheckPython3(void);
 #endif
diff --git a/Include/sysmodule.h b/Include/sysmodule.h
index 96f883870b34d..5fd21f5fa30a2 100644
--- a/Include/sysmodule.h
+++ b/Include/sysmodule.h
@@ -10,10 +10,6 @@ extern "C" {
 PyAPI_FUNC(PyObject *) PySys_GetObject(const char *);
 PyAPI_FUNC(int) PySys_SetObject(const char *, PyObject *);
 
-Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_SetArgv(int, wchar_t **);
-Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_SetArgvEx(int, wchar_t **, int);
-Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_SetPath(const wchar_t *);
-
 PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...)
                  Py_GCC_ATTRIBUTE((format(printf, 1, 2)));
 PyAPI_FUNC(void) PySys_WriteStderr(const char *format, ...)
@@ -22,11 +18,7 @@ PyAPI_FUNC(void) PySys_FormatStdout(const char *format, ...);
 PyAPI_FUNC(void) PySys_FormatStderr(const char *format, ...);
 
 PyAPI_FUNC(void) PySys_ResetWarnOptions(void);
-Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_AddWarnOption(const wchar_t *);
-Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_AddWarnOptionUnicode(PyObject *);
-Py_DEPRECATED(3.11) PyAPI_FUNC(int) PySys_HasWarnOptions(void);
 
-Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_AddXOption(const wchar_t *);
 PyAPI_FUNC(PyObject *) PySys_GetXOptions(void);
 
 #if !defined(Py_LIMITED_API)
diff --git a/Misc/NEWS.d/next/C API/2023-05-31-16-51-18.gh-issue-105145.b3B6lJ.rst b/Misc/NEWS.d/next/C API/2023-05-31-16-51-18.gh-issue-105145.b3B6lJ.rst
new file mode 100644
index 0000000000000..a3ad765b69623
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-05-31-16-51-18.gh-issue-105145.b3B6lJ.rst	
@@ -0,0 +1,17 @@
+Remove the following old functions to configure the Python initialization,
+deprecated in Python 3.11:
+
+* ``PySys_AddWarnOptionUnicode()``
+* ``PySys_AddWarnOption()``
+* ``PySys_AddXOption()``
+* ``PySys_HasWarnOptions()``
+* ``PySys_SetArgvEx()``
+* ``PySys_SetArgv()``
+* ``PySys_SetPath()``
+* ``Py_SetPath()``
+* ``Py_SetProgramName()``
+* ``Py_SetPythonHome()``
+* ``Py_SetStandardStreamEncoding()``
+* ``_Py_SetProgramFullPath()``
+
+Patch by Victor Stinner.
diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml
index ff3b09ca74c39..7ff4da9a1f7b6 100644
--- a/Misc/stable_abi.toml
+++ b/Misc/stable_abi.toml
@@ -1311,8 +1311,10 @@
     added = '3.2'
 [function.PySys_AddWarnOption]
     added = '3.2'
+    abi_only = true
 [function.PySys_AddWarnOptionUnicode]
     added = '3.2'
+    abi_only = true
 [function.PySys_FormatStderr]
     added = '3.2'
 [function.PySys_FormatStdout]
@@ -1321,16 +1323,20 @@
     added = '3.2'
 [function.PySys_HasWarnOptions]
     added = '3.2'
+    abi_only = true
 [function.PySys_ResetWarnOptions]
     added = '3.2'
 [function.PySys_SetArgv]
     added = '3.2'
+    abi_only = true
 [function.PySys_SetArgvEx]
     added = '3.2'
+    abi_only = true
 [function.PySys_SetObject]
     added = '3.2'
 [function.PySys_SetPath]
     added = '3.2'
+    abi_only = true
 [function.PySys_WriteStderr]
     added = '3.2'
 [function.PySys_WriteStdout]
@@ -1658,8 +1664,10 @@
     added = '3.2'
 [function.Py_SetProgramName]
     added = '3.2'
+    abi_only = true
 [function.Py_SetPythonHome]
     added = '3.2'
+    abi_only = true
 [function.Py_SetRecursionLimit]
     added = '3.2'
 [function.Py_VaBuildValue]
@@ -1990,6 +1998,7 @@
     added = '3.7'  # (and 3.6.1 and 3.5.3)
 [function.PySys_AddXOption]
     added = '3.7'  # (and 3.6.1 and 3.5.3)
+    abi_only = true
 [function.PySys_GetXOptions]
     added = '3.7'  # (and 3.6.1 and 3.5.3)
 [function.PyUnicode_AsUCS4]
@@ -2020,6 +2029,7 @@
     added = '3.7'  # (and 3.6.1 and 3.5.3)
 [function.Py_SetPath]
     added = '3.7'  # (and 3.6.1 and 3.5.3)
+    abi_only = true
 [function.PyErr_SetExcFromWindowsErr]
     added = '3.7'  # (and 3.6.1 and 3.5.3)
     ifdef = 'MS_WINDOWS'
diff --git a/Modules/main.c b/Modules/main.c
index 7edfeb3365b4c..a5c009321d607 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -636,7 +636,6 @@ pymain_free(void)
        remain valid after Py_Finalize(), since
        Py_Initialize()-Py_Finalize() can be called multiple times. */
     _PyPathConfig_ClearGlobal();
-    _Py_ClearStandardStreamEncoding();
     _Py_ClearArgcArgv();
     _PyRuntime_Finalize();
 }
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
index f78ba41fe7b4e..351cdc302e8cb 100644
--- a/Programs/_testembed.c
+++ b/Programs/_testembed.c
@@ -14,6 +14,15 @@
 #include <stdlib.h>               // putenv()
 #include <wchar.h>
 
+// These functions were removed from Python 3.13 API but are still exported
+// for the stable ABI. We want to test them in this program.
+extern void Py_SetProgramName(const wchar_t *program_name);
+extern void PySys_AddWarnOption(const wchar_t *s);
+extern void PySys_AddXOption(const wchar_t *s);
+extern void Py_SetPath(const wchar_t *path);
+extern void Py_SetPythonHome(const wchar_t *home);
+
+
 int main_argc;
 char **main_argv;
 
@@ -204,23 +213,34 @@ static int test_repeated_simple_init(void)
  * Test forcing a particular IO encoding
  *****************************************************/
 
-static void check_stdio_details(const char *encoding, const char * errors)
+static void check_stdio_details(const wchar_t *encoding, const wchar_t *errors)
 {
     /* Output info for the test case to check */
     if (encoding) {
-        printf("Expected encoding: %s\n", encoding);
+        printf("Expected encoding: %ls\n", encoding);
     } else {
         printf("Expected encoding: default\n");
     }
     if (errors) {
-        printf("Expected errors: %s\n", errors);
+        printf("Expected errors: %ls\n", errors);
     } else {
         printf("Expected errors: default\n");
     }
     fflush(stdout);
+
+    PyConfig config;
+    _PyConfig_InitCompatConfig(&config);
     /* Force the given IO encoding */
-    Py_SetStandardStreamEncoding(encoding, errors);
-    _testembed_Py_InitializeFromConfig();
+    if (encoding) {
+        config_set_string(&config, &config.stdio_encoding, encoding);
+    }
+    if (errors) {
+        config_set_string(&config, &config.stdio_errors, errors);
+    }
+    config_set_program_name(&config);
+    init_from_config_clear(&config);
+
+
     PyRun_SimpleString(
         "import sys;"
         "print('stdin: {0.encoding}:{0.errors}'.format(sys.stdin));"
@@ -237,19 +257,11 @@ static int test_forced_io_encoding(void)
     printf("--- Use defaults ---\n");
     check_stdio_details(NULL, NULL);
     printf("--- Set errors only ---\n");
-    check_stdio_details(NULL, "ignore");
+    check_stdio_details(NULL, L"ignore");
     printf("--- Set encoding only ---\n");
-    check_stdio_details("iso8859-1", NULL);
+    check_stdio_details(L"iso8859-1", NULL);
     printf("--- Set encoding and errors ---\n");
-    check_stdio_details("iso8859-1", "replace");
-
-    /* Check calling after initialization fails */
-    Py_Initialize();
-
-    if (Py_SetStandardStreamEncoding(NULL, NULL) == 0) {
-        printf("Unexpected success calling Py_SetStandardStreamEncoding");
-    }
-    Py_Finalize();
+    check_stdio_details(L"iso8859-1", L"replace");
     return 0;
 }
 
@@ -639,11 +651,7 @@ static int test_init_from_config(void)
     /* FIXME: test path config: module_search_path .. dll_path */
 
     putenv("PYTHONPLATLIBDIR=env_platlibdir");
-    status = PyConfig_SetBytesString(&config, &config.platlibdir, "my_platlibdir");
-    if (PyStatus_Exception(status)) {
-        PyConfig_Clear(&config);
-        Py_ExitStatusException(status);
-    }
+    config_set_string(&config, &config.platlibdir, L"my_platlibdir");
 
     putenv("PYTHONVERBOSE=0");
     Py_VerboseFlag = 0;
@@ -682,12 +690,6 @@ static int test_init_from_config(void)
     config.buffered_stdio = 0;
 
     putenv("PYTHONIOENCODING=cp424");
-    Py_SetStandardStreamEncoding("ascii", "ignore");
-#ifdef MS_WINDOWS
-    /* Py_SetStandardStreamEncoding() sets Py_LegacyWindowsStdioFlag to 1.
-       Force it to 0 through the config. */
-    config.legacy_windows_stdio = 0;
-#endif
     config_set_string(&config, &config.stdio_encoding, L"iso8859-1");
     config_set_string(&config, &config.stdio_errors, L"replace");
 
@@ -1410,11 +1412,7 @@ static int test_init_read_set(void)
     PyConfig config;
     PyConfig_InitPythonConfig(&config);
 
-    status = PyConfig_SetBytesString(&config, &config.program_name,
-                                     "./init_read_set");
-    if (PyStatus_Exception(status)) {
-        goto fail;
-    }
+    config_set_string(&config, &config.program_name, L"./init_read_set");
 
     status = PyConfig_Read(&config);
     if (PyStatus_Exception(status)) {
diff --git a/Python/initconfig.c b/Python/initconfig.c
index 0d42b7ea082d6..1dcefd478eefe 100644
--- a/Python/initconfig.c
+++ b/Python/initconfig.c
@@ -514,94 +514,6 @@ _PyWideStringList_AsList(const PyWideStringList *list)
 }
 
 
-/* --- Py_SetStandardStreamEncoding() ----------------------------- */
-
-/* Helper to allow an embedding application to override the normal
- * mechanism that attempts to figure out an appropriate IO encoding
- */
-
-static char *_Py_StandardStreamEncoding = NULL;
-static char *_Py_StandardStreamErrors = NULL;
-
-int
-Py_SetStandardStreamEncoding(const char *encoding, const char *errors)
-{
-    if (Py_IsInitialized()) {
-        /* This is too late to have any effect */
-        return -1;
-    }
-
-    int res = 0;
-
-    /* Py_SetStandardStreamEncoding() can be called before Py_Initialize(),
-       but Py_Initialize() can change the allocator. Use a known allocator
-       to be able to release the memory later. */
-    PyMemAllocatorEx old_alloc;
-    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
-
-    /* Can't call PyErr_NoMemory() on errors, as Python hasn't been
-     * initialised yet.
-     *
-     * However, the raw memory allocators are initialised appropriately
-     * as C static variables, so _PyMem_RawStrdup is OK even though
-     * Py_Initialize hasn't been called yet.
-     */
-    if (encoding) {
-        PyMem_RawFree(_Py_StandardStreamEncoding);
-        _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding);
-        if (!_Py_StandardStreamEncoding) {
-            res = -2;
-            goto done;
-        }
-    }
-    if (errors) {
-        PyMem_RawFree(_Py_StandardStreamErrors);
-        _Py_StandardStreamErrors = _PyMem_RawStrdup(errors);
-        if (!_Py_StandardStreamErrors) {
-            PyMem_RawFree(_Py_StandardStreamEncoding);
-            _Py_StandardStreamEncoding = NULL;
-            res = -3;
-            goto done;
-        }
-    }
-#ifdef MS_WINDOWS
-    if (_Py_StandardStreamEncoding) {
-_Py_COMP_DIAG_PUSH
-_Py_COMP_DIAG_IGNORE_DEPR_DECLS
-        /* Overriding the stream encoding implies legacy streams */
-        Py_LegacyWindowsStdioFlag = 1;
-_Py_COMP_DIAG_POP
-    }
-#endif
-
-done:
-    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
-
-    return res;
-}
-
-
-void
-_Py_ClearStandardStreamEncoding(void)
-{
-    /* Use the same allocator than Py_SetStandardStreamEncoding() */
-    PyMemAllocatorEx old_alloc;
-    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
-
-    /* We won't need them anymore. */
-    if (_Py_StandardStreamEncoding) {
-        PyMem_RawFree(_Py_StandardStreamEncoding);
-        _Py_StandardStreamEncoding = NULL;
-    }
-    if (_Py_StandardStreamErrors) {
-        PyMem_RawFree(_Py_StandardStreamErrors);
-        _Py_StandardStreamErrors = NULL;
-    }
-
-    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
-}
-
-
 /* --- Py_GetArgcArgv() ------------------------------------------- */
 
 void
@@ -1973,26 +1885,6 @@ config_init_stdio_encoding(PyConfig *config,
 {
     PyStatus status;
 
-    /* If Py_SetStandardStreamEncoding() has been called, use its
-        arguments if they are not NULL. */
-    if (config->stdio_encoding == NULL && _Py_StandardStreamEncoding != NULL) {
-        status = CONFIG_SET_BYTES_STR(config, &config->stdio_encoding,
-                                      _Py_StandardStreamEncoding,
-                                      "_Py_StandardStreamEncoding");
-        if (_PyStatus_EXCEPTION(status)) {
-            return status;
-        }
-    }
-
-    if (config->stdio_errors == NULL && _Py_StandardStreamErrors != NULL) {
-        status = CONFIG_SET_BYTES_STR(config, &config->stdio_errors,
-                                      _Py_StandardStreamErrors,
-                                      "_Py_StandardStreamErrors");
-        if (_PyStatus_EXCEPTION(status)) {
-            return status;
-        }
-    }
-
     // Exit if encoding and errors are defined
     if (config->stdio_encoding != NULL && config->stdio_errors != NULL) {
         return _PyStatus_OK();
diff --git a/Python/pathconfig.c b/Python/pathconfig.c
index be0f97c4b204a..afffa134e893b 100644
--- a/Python/pathconfig.c
+++ b/Python/pathconfig.c
@@ -211,7 +211,8 @@ path_out_of_memory(const char *func)
     _Py_FatalErrorFunc(func, "out of memory");
 }
 
-void
+// Removed in Python 3.13 API, but kept for the stable ABI
+PyAPI_FUNC(void)
 Py_SetPath(const wchar_t *path)
 {
     if (path == NULL) {
@@ -252,7 +253,8 @@ Py_SetPath(const wchar_t *path)
 }
 
 
-void
+// Removed in Python 3.13 API, but kept for the stable ABI
+PyAPI_FUNC(void)
 Py_SetPythonHome(const wchar_t *home)
 {
     int has_value = home && home[0];
@@ -275,7 +277,8 @@ Py_SetPythonHome(const wchar_t *home)
 }
 
 
-void
+// Removed in Python 3.13 API, but kept for the stable ABI
+PyAPI_FUNC(void)
 Py_SetProgramName(const wchar_t *program_name)
 {
     int has_value = program_name && program_name[0];
@@ -297,28 +300,6 @@ Py_SetProgramName(const wchar_t *program_name)
     }
 }
 
-void
-_Py_SetProgramFullPath(const wchar_t *program_full_path)
-{
-    int has_value = program_full_path && program_full_path[0];
-
-    PyMemAllocatorEx old_alloc;
-    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
-
-    PyMem_RawFree(_Py_path_config.program_full_path);
-    _Py_path_config.program_full_path = NULL;
-
-    if (has_value) {
-        _Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
-    }
-
-    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
-
-    if (has_value && _Py_path_config.program_full_path == NULL) {
-        path_out_of_memory(__func__);
-    }
-}
-
 
 wchar_t *
 Py_GetPath(void)
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 06c43459624c6..c6fbf1722ed9c 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -2556,7 +2556,6 @@ init_sys_streams(PyThreadState *tstate)
     res = _PyStatus_ERR("can't initialize sys standard streams");
 
 done:
-    _Py_ClearStandardStreamEncoding();
     Py_XDECREF(iomod);
     return res;
 }
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 32be7ec09ebfd..4427e73e584e3 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -2614,7 +2614,8 @@ _PySys_AddWarnOptionWithError(PyThreadState *tstate, PyObject *option)
     return 0;
 }
 
-void
+// Removed in Python 3.13 API, but kept for the stable ABI
+PyAPI_FUNC(void)
 PySys_AddWarnOptionUnicode(PyObject *option)
 {
     PyThreadState *tstate = _PyThreadState_GET();
@@ -2626,7 +2627,8 @@ PySys_AddWarnOptionUnicode(PyObject *option)
     }
 }
 
-void
+// Removed in Python 3.13 API, but kept for the stable ABI
+PyAPI_FUNC(void)
 PySys_AddWarnOption(const wchar_t *s)
 {
     PyThreadState *tstate = _PyThreadState_GET();
@@ -2645,7 +2647,8 @@ _Py_COMP_DIAG_POP
     Py_DECREF(unicode);
 }
 
-int
+// Removed in Python 3.13 API, but kept for the stable ABI
+PyAPI_FUNC(int)
 PySys_HasWarnOptions(void)
 {
     PyThreadState *tstate = _PyThreadState_GET();
@@ -2718,7 +2721,8 @@ _PySys_AddXOptionWithError(const wchar_t *s)
     return -1;
 }
 
-void
+// Removed in Python 3.13 API, but kept for the stable ABI
+PyAPI_FUNC(void)
 PySys_AddXOption(const wchar_t *s)
 {
     PyThreadState *tstate = _PyThreadState_GET();
@@ -3621,7 +3625,8 @@ makepathobject(const wchar_t *path, wchar_t delim)
     return v;
 }
 
-void
+// Removed in Python 3.13 API, but kept for the stable ABI
+PyAPI_FUNC(void)
 PySys_SetPath(const wchar_t *path)
 {
     PyObject *v;
@@ -3653,7 +3658,8 @@ make_sys_argv(int argc, wchar_t * const * argv)
     return list;
 }
 
-void
+// Removed in Python 3.13 API, but kept for the stable ABI
+PyAPI_FUNC(void)
 PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
 {
     wchar_t* empty_argv[1] = {L""};
@@ -3697,7 +3703,8 @@ PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
     }
 }
 
-void
+// Removed in Python 3.13 API, but kept for the stable ABI
+PyAPI_FUNC(void)
 PySys_SetArgv(int argc, wchar_t **argv)
 {
 _Py_COMP_DIAG_PUSH



More information about the Python-checkins mailing list