mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									8ed705c083
								
							
						
					
					
						commit
						424049cc11
					
				
					 22 changed files with 182 additions and 522 deletions
				
			
		|  | @ -29,12 +29,6 @@ The following functions can be safely called before Python is initialized: | ||||||
|   * :c:func:`PyMem_SetAllocator` |   * :c:func:`PyMem_SetAllocator` | ||||||
|   * :c:func:`PyMem_SetupDebugHooks` |   * :c:func:`PyMem_SetupDebugHooks` | ||||||
|   * :c:func:`PyObject_SetArenaAllocator` |   * :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` |   * :c:func:`PySys_ResetWarnOptions` | ||||||
| 
 | 
 | ||||||
| * Informative functions: | * Informative functions: | ||||||
|  | @ -332,7 +326,6 @@ Initializing and finalizing the interpreter | ||||||
| .. c:function:: void Py_Initialize() | .. c:function:: void Py_Initialize() | ||||||
| 
 | 
 | ||||||
|    .. index:: |    .. index:: | ||||||
|       single: Py_SetProgramName() |  | ||||||
|       single: PyEval_InitThreads() |       single: PyEval_InitThreads() | ||||||
|       single: modules (in module sys) |       single: modules (in module sys) | ||||||
|       single: path (in module sys) |       single: path (in module sys) | ||||||
|  | @ -340,8 +333,6 @@ Initializing and finalizing the interpreter | ||||||
|       pair: module; __main__ |       pair: module; __main__ | ||||||
|       pair: module; sys |       pair: module; sys | ||||||
|       triple: module; search; path |       triple: module; search; path | ||||||
|       single: PySys_SetArgv() |  | ||||||
|       single: PySys_SetArgvEx() |  | ||||||
|       single: Py_FinalizeEx() |       single: Py_FinalizeEx() | ||||||
| 
 | 
 | ||||||
|    Initialize the Python interpreter.  In an application embedding  Python, |    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 |    the table of loaded modules (``sys.modules``), and creates the fundamental | ||||||
|    modules :mod:`builtins`, :mod:`__main__` and :mod:`sys`.  It also initializes |    modules :mod:`builtins`, :mod:`__main__` and :mod:`sys`.  It also initializes | ||||||
|    the module search path (``sys.path``). It does not set ``sys.argv``; use |    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 |    (without calling :c:func:`Py_FinalizeEx` first).  There is no return value; it is a | ||||||
|    fatal error if the initialization fails. |    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() | .. c:function:: wchar* Py_GetProgramName() | ||||||
| 
 | 
 | ||||||
|    .. index:: single: Py_SetProgramName() |    Return the program name set with :c:member:`PyConfig.program_name`, or the default. | ||||||
| 
 |  | ||||||
|    Return the program name set with :c:func:`Py_SetProgramName`, or the default. |  | ||||||
|    The returned string points into static storage; the caller should not modify its |    The returned string points into static storage; the caller should not modify its | ||||||
|    value. |    value. | ||||||
| 
 | 
 | ||||||
|  | @ -509,7 +435,7 @@ Process-wide parameters | ||||||
| 
 | 
 | ||||||
|    Return the *prefix* for installed platform-independent files. This is derived |    Return the *prefix* for installed platform-independent files. This is derived | ||||||
|    through a number of complicated rules from the program name set with |    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 |    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 |    returned string points into static storage; the caller should not modify its | ||||||
|    value.  This corresponds to the :makevar:`prefix` variable in the top-level |    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 |    Return the *exec-prefix* for installed platform-*dependent* files.  This is | ||||||
|    derived through a number of complicated rules from the program name set with |    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 |    program name is ``'/usr/local/bin/python'``, the exec-prefix is | ||||||
|    ``'/usr/local'``.  The returned string points into static storage; the caller |    ``'/usr/local'``.  The returned string points into static storage; the caller | ||||||
|    should not modify its value.  This corresponds to the :makevar:`exec_prefix` |    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() | .. c:function:: wchar_t* Py_GetProgramFullPath() | ||||||
| 
 | 
 | ||||||
|    .. index:: |    .. index:: | ||||||
|       single: Py_SetProgramName() |  | ||||||
|       single: executable (in module sys) |       single: executable (in module sys) | ||||||
| 
 | 
 | ||||||
|    Return the full program name of the Python executable; this is  computed as a |    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 |    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 |    static storage; the caller should not modify its value.  The value is available | ||||||
|    to Python code as ``sys.executable``. |    to Python code as ``sys.executable``. | ||||||
| 
 | 
 | ||||||
|  | @ -589,10 +514,9 @@ Process-wide parameters | ||||||
|    .. index:: |    .. index:: | ||||||
|       triple: module; search; path |       triple: module; search; path | ||||||
|       single: path (in module sys) |       single: path (in module sys) | ||||||
|       single: Py_SetPath() |  | ||||||
| 
 | 
 | ||||||
|    Return the default module search path; this is computed from the program name |    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 |    The returned string consists of a series of directory names separated by a | ||||||
|    platform dependent delimiter character.  The delimiter character is ``':'`` |    platform dependent delimiter character.  The delimiter character is ``':'`` | ||||||
|    on Unix and macOS, ``';'`` on Windows.  The returned string points into |    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`. |       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() | .. c:function:: const char* Py_GetVersion() | ||||||
| 
 | 
 | ||||||
|    Return the version of this Python interpreter.  This is a string that looks |    Return the version of this Python interpreter.  This is a string that looks | ||||||
|  | @ -718,110 +604,10 @@ Process-wide parameters | ||||||
|    ``sys.version``. |    ``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() | .. c:function:: wchar_t* Py_GetPythonHome() | ||||||
| 
 | 
 | ||||||
|    Return the default "home", that is, the value set by a previous call to |    Return the default "home", that is, the value set by | ||||||
|    :c:func:`Py_SetPythonHome`, or the value of the :envvar:`PYTHONHOME` |    :c:member:`PyConfig.home`, or the value of the :envvar:`PYTHONHOME` | ||||||
|    environment variable if it is set. |    environment variable if it is set. | ||||||
| 
 | 
 | ||||||
|    This function should not be called before :c:func:`Py_Initialize`, otherwise |    This function should not be called before :c:func:`Py_Initialize`, otherwise | ||||||
|  |  | ||||||
|  | @ -531,7 +531,17 @@ PyConfig | ||||||
| 
 | 
 | ||||||
|    .. c:member:: PyWideStringList argv |    .. 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 |       Set :c:member:`~PyConfig.parse_argv` to ``1`` to parse | ||||||
|       :c:member:`~PyConfig.argv` the same way the regular Python parses Python |       :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. |       Part of the :ref:`Python Path Configuration <init-path-config>` output. | ||||||
| 
 | 
 | ||||||
|  |       See also :c:member:`PyConfig.exec_prefix`. | ||||||
|  | 
 | ||||||
|    .. c:member:: wchar_t* base_executable |    .. c:member:: wchar_t* base_executable | ||||||
| 
 | 
 | ||||||
|       Python base executable: :data:`sys._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. |       Part of the :ref:`Python Path Configuration <init-path-config>` output. | ||||||
| 
 | 
 | ||||||
|  |       See also :c:member:`PyConfig.executable`. | ||||||
|  | 
 | ||||||
|    .. c:member:: wchar_t* base_prefix |    .. c:member:: wchar_t* base_prefix | ||||||
| 
 | 
 | ||||||
|       :data:`sys.base_prefix`. |       :data:`sys.base_prefix`. | ||||||
|  | @ -592,6 +606,8 @@ PyConfig | ||||||
| 
 | 
 | ||||||
|       Part of the :ref:`Python Path Configuration <init-path-config>` output. |       Part of the :ref:`Python Path Configuration <init-path-config>` output. | ||||||
| 
 | 
 | ||||||
|  |       See also :c:member:`PyConfig.prefix`. | ||||||
|  | 
 | ||||||
|    .. c:member:: int buffered_stdio |    .. c:member:: int buffered_stdio | ||||||
| 
 | 
 | ||||||
|       If equals to ``0`` and :c:member:`~PyConfig.configure_c_stdio` is non-zero, |       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. |       Part of the :ref:`Python Path Configuration <init-path-config>` output. | ||||||
| 
 | 
 | ||||||
|  |       See also :c:member:`PyConfig.base_exec_prefix`. | ||||||
|  | 
 | ||||||
|    .. c:member:: wchar_t* executable |    .. c:member:: wchar_t* executable | ||||||
| 
 | 
 | ||||||
|       The absolute path of the executable binary for the Python interpreter: |       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. |       Part of the :ref:`Python Path Configuration <init-path-config>` output. | ||||||
| 
 | 
 | ||||||
|  |       See also :c:member:`PyConfig.base_executable`. | ||||||
|  | 
 | ||||||
|    .. c:member:: int faulthandler |    .. c:member:: int faulthandler | ||||||
| 
 | 
 | ||||||
|       Enable faulthandler? |       Enable faulthandler? | ||||||
|  | @ -780,10 +800,8 @@ PyConfig | ||||||
| 
 | 
 | ||||||
|    .. c:member:: wchar_t* home |    .. c:member:: wchar_t* home | ||||||
| 
 | 
 | ||||||
|       Python home directory. |       Set the default Python "home" directory, that is, the location of the | ||||||
| 
 |       standard Python libraries (see :envvar:`PYTHONHOME`). | ||||||
|       If :c:func:`Py_SetPythonHome` has been called, use its argument if it is |  | ||||||
|       not ``NULL``. |  | ||||||
| 
 | 
 | ||||||
|       Set by the :envvar:`PYTHONHOME` environment variable. |       Set by the :envvar:`PYTHONHOME` environment variable. | ||||||
| 
 | 
 | ||||||
|  | @ -1029,12 +1047,13 @@ PyConfig | ||||||
| 
 | 
 | ||||||
|       Part of the :ref:`Python Path Configuration <init-path-config>` output. |       Part of the :ref:`Python Path Configuration <init-path-config>` output. | ||||||
| 
 | 
 | ||||||
|  |       See also :c:member:`PyConfig.base_prefix`. | ||||||
|  | 
 | ||||||
|    .. c:member:: wchar_t* program_name |    .. c:member:: wchar_t* program_name | ||||||
| 
 | 
 | ||||||
|       Program name used to initialize :c:member:`~PyConfig.executable` and in |       Program name used to initialize :c:member:`~PyConfig.executable` and in | ||||||
|       early error messages during Python initialization. |       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. |       * On macOS, use :envvar:`PYTHONEXECUTABLE` environment variable if set. | ||||||
|       * If the ``WITH_NEXT_FRAMEWORK`` macro is defined, use |       * If the ``WITH_NEXT_FRAMEWORK`` macro is defined, use | ||||||
|         :envvar:`__PYVENV_LAUNCHER__` environment variable if set. |         :envvar:`__PYVENV_LAUNCHER__` environment variable if set. | ||||||
|  | @ -1144,9 +1163,6 @@ PyConfig | ||||||
|       :data:`sys.stderr` (but :data:`sys.stderr` always uses |       :data:`sys.stderr` (but :data:`sys.stderr` always uses | ||||||
|       ``"backslashreplace"`` error handler). |       ``"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 |       Use the :envvar:`PYTHONIOENCODING` environment variable if it is | ||||||
|       non-empty. |       non-empty. | ||||||
| 
 | 
 | ||||||
|  | @ -1162,6 +1178,8 @@ PyConfig | ||||||
|         or if the LC_CTYPE locale is "C" or "POSIX". |         or if the LC_CTYPE locale is "C" or "POSIX". | ||||||
|       * ``"strict"`` otherwise. |       * ``"strict"`` otherwise. | ||||||
| 
 | 
 | ||||||
|  |       See also :c:member:`PyConfig.legacy_windows_stdio`. | ||||||
|  | 
 | ||||||
|    .. c:member:: int tracemalloc |    .. c:member:: int tracemalloc | ||||||
| 
 | 
 | ||||||
|       Enable tracemalloc? |       Enable tracemalloc? | ||||||
|  | @ -1509,7 +1527,7 @@ If a ``._pth`` file is present: | ||||||
| * Set :c:member:`~PyConfig.safe_path` to ``1``. | * Set :c:member:`~PyConfig.safe_path` to ``1``. | ||||||
| 
 | 
 | ||||||
| The ``__PYVENV_LAUNCHER__`` environment variable is used to set | The ``__PYVENV_LAUNCHER__`` environment variable is used to set | ||||||
| :c:member:`PyConfig.base_executable` | :c:member:`PyConfig.base_executable`. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Py_RunMain() | Py_RunMain() | ||||||
|  |  | ||||||
|  | @ -739,14 +739,14 @@ environment variable :envvar:`PYTHONHOME`, or insert additional directories in | ||||||
| front of the standard path by setting :envvar:`PYTHONPATH`. | front of the standard path by setting :envvar:`PYTHONPATH`. | ||||||
| 
 | 
 | ||||||
| .. index:: | .. index:: | ||||||
|    single: Py_SetProgramName() |  | ||||||
|    single: Py_GetPath() |    single: Py_GetPath() | ||||||
|    single: Py_GetPrefix() |    single: Py_GetPrefix() | ||||||
|    single: Py_GetExecPrefix() |    single: Py_GetExecPrefix() | ||||||
|    single: Py_GetProgramFullPath() |    single: Py_GetProgramFullPath() | ||||||
| 
 | 
 | ||||||
| The embedding application can steer the search by calling | The embedding application can steer the search by setting | ||||||
| ``Py_SetProgramName(file)`` *before* calling  :c:func:`Py_Initialize`.  Note that | :c:member:`PyConfig.program_name` *before* calling | ||||||
|  | :c:func:`Py_InitializeFromConfig`. Note that | ||||||
| :envvar:`PYTHONHOME` still overrides this and :envvar:`PYTHONPATH` is still | :envvar:`PYTHONHOME` still overrides this and :envvar:`PYTHONPATH` is still | ||||||
| inserted in front of the standard path.  An application that requires total | inserted in front of the standard path.  An application that requires total | ||||||
| control has to provide its own implementation of :c:func:`Py_GetPath`, | control has to provide its own implementation of :c:func:`Py_GetPath`, | ||||||
|  |  | ||||||
|  | @ -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 |    Reset :data:`sys.warnoptions` to an empty list. This function may be | ||||||
|    called prior to :c:func:`Py_Initialize`. |    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, ...) | .. c:function:: void PySys_WriteStdout(const char *format, ...) | ||||||
| 
 | 
 | ||||||
|    Write the output string described by *format* to :data:`sys.stdout`.  No |    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 |    .. 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() | .. c:function:: PyObject *PySys_GetXOptions() | ||||||
| 
 | 
 | ||||||
|    Return the current dictionary of :option:`-X` options, similarly to |    Return the current dictionary of :option:`-X` options, similarly to | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								Doc/data/stable_abi.dat
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								Doc/data/stable_abi.dat
									
										
									
										generated
									
									
									
								
							|  | @ -596,19 +596,12 @@ function,PyStructSequence_NewType,3.2,, | ||||||
| function,PyStructSequence_SetItem,3.2,, | function,PyStructSequence_SetItem,3.2,, | ||||||
| var,PyStructSequence_UnnamedField,3.11,, | var,PyStructSequence_UnnamedField,3.11,, | ||||||
| var,PySuper_Type,3.2,, | 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_FormatStderr,3.2,, | ||||||
| function,PySys_FormatStdout,3.2,, | function,PySys_FormatStdout,3.2,, | ||||||
| function,PySys_GetObject,3.2,, | function,PySys_GetObject,3.2,, | ||||||
| function,PySys_GetXOptions,3.7,, | function,PySys_GetXOptions,3.7,, | ||||||
| function,PySys_HasWarnOptions,3.2,, |  | ||||||
| function,PySys_ResetWarnOptions,3.2,, | function,PySys_ResetWarnOptions,3.2,, | ||||||
| function,PySys_SetArgv,3.2,, |  | ||||||
| function,PySys_SetArgvEx,3.2,, |  | ||||||
| function,PySys_SetObject,3.2,, | function,PySys_SetObject,3.2,, | ||||||
| function,PySys_SetPath,3.2,, |  | ||||||
| function,PySys_WriteStderr,3.2,, | function,PySys_WriteStderr,3.2,, | ||||||
| function,PySys_WriteStdout,3.2,, | function,PySys_WriteStdout,3.2,, | ||||||
| type,PyThreadState,3.2,,opaque | type,PyThreadState,3.2,,opaque | ||||||
|  | @ -850,9 +843,6 @@ function,Py_NewInterpreter,3.2,, | ||||||
| function,Py_NewRef,3.10,, | function,Py_NewRef,3.10,, | ||||||
| function,Py_ReprEnter,3.2,, | function,Py_ReprEnter,3.2,, | ||||||
| function,Py_ReprLeave,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,, | function,Py_SetRecursionLimit,3.2,, | ||||||
| type,Py_UCS4,3.2,, | type,Py_UCS4,3.2,, | ||||||
| macro,Py_UNBLOCK_THREADS,3.2,, | macro,Py_UNBLOCK_THREADS,3.2,, | ||||||
|  |  | ||||||
|  | @ -59,24 +59,36 @@ perform some operation on a file. :: | ||||||
|    int |    int | ||||||
|    main(int argc, char *argv[]) |    main(int argc, char *argv[]) | ||||||
|    { |    { | ||||||
|        wchar_t *program = Py_DecodeLocale(argv[0], NULL); |        PyStatus status; | ||||||
|        if (program == NULL) { |        PyConfig config; | ||||||
|            fprintf(stderr, "Fatal error: cannot decode argv[0]\n"); |        PyConfig_InitPythonConfig(&config); | ||||||
|            exit(1); | 
 | ||||||
|  |        /* 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" |        PyRun_SimpleString("from time import time,ctime\n" | ||||||
|                           "print('Today is', ctime(time()))\n"); |                           "print('Today is', ctime(time()))\n"); | ||||||
|        if (Py_FinalizeEx() < 0) { |        if (Py_FinalizeEx() < 0) { | ||||||
|            exit(120); |            exit(120); | ||||||
|        } |        } | ||||||
|        PyMem_RawFree(program); |  | ||||||
|        return 0; |        return 0; | ||||||
|  | 
 | ||||||
|  |      exception: | ||||||
|  |         PyConfig_Clear(&config); | ||||||
|  |         Py_ExitStatusException(status); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
| The :c:func:`Py_SetProgramName` function should be called before | Setting :c:member:`PyConfig.program_name` should be called before | ||||||
| :c:func:`Py_Initialize` to inform the interpreter about paths to Python run-time | :c:func:`Py_InitializeFromConfig` to inform the interpreter about paths to Python run-time | ||||||
| libraries.  Next, the Python interpreter is initialized with | libraries.  Next, the Python interpreter is initialized with | ||||||
| :c:func:`Py_Initialize`, followed by the execution of a hard-coded Python script | :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 | that prints the date and time.  Afterwards, the :c:func:`Py_FinalizeEx` call shuts | ||||||
|  |  | ||||||
|  | @ -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`, | To add the module to the initialization table, use :c:func:`PyImport_AppendInittab`, | ||||||
| optionally followed by an import of the module:: | optionally followed by an import of the module:: | ||||||
| 
 | 
 | ||||||
|  |    #define PY_SSIZE_T_CLEAN | ||||||
|  |    #include <Python.h> | ||||||
|  | 
 | ||||||
|    int |    int | ||||||
|    main(int argc, char *argv[]) |    main(int argc, char *argv[]) | ||||||
|    { |    { | ||||||
|        wchar_t *program = Py_DecodeLocale(argv[0], NULL); |        PyStatus status; | ||||||
|        if (program == NULL) { |        PyConfig config; | ||||||
|            fprintf(stderr, "Fatal error: cannot decode argv[0]\n"); |        PyConfig_InitPythonConfig(&config); | ||||||
|            exit(1); |  | ||||||
|        } |  | ||||||
| 
 | 
 | ||||||
|        /* Add a built-in module, before Py_Initialize */ |        /* Add a built-in module, before Py_Initialize */ | ||||||
|        if (PyImport_AppendInittab("spam", PyInit_spam) == -1) { |        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 */ |        /* 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. |        /* Initialize the Python interpreter.  Required. | ||||||
|           If this step fails, it will be a fatal error. */ |           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, |        /* Optionally import the module; alternatively, | ||||||
|           import can be deferred until the embedded script |           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"); |            fprintf(stderr, "Error: could not import module 'spam'\n"); | ||||||
|        } |        } | ||||||
| 
 | 
 | ||||||
|        ... |        // ... use Python C API here ... | ||||||
| 
 | 
 | ||||||
|        PyMem_RawFree(program); |  | ||||||
|        return 0; |        return 0; | ||||||
|  | 
 | ||||||
|  |      exception: | ||||||
|  |         PyConfig_Clear(&config); | ||||||
|  |         Py_ExitStatusException(status); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
| .. note:: | .. note:: | ||||||
|  |  | ||||||
|  | @ -99,8 +99,7 @@ Embedded Python | ||||||
| 
 | 
 | ||||||
| If Python is embedded within another application :c:func:`Py_InitializeFromConfig` and | 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 | 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` | details are described at :ref:`init-path-config`. | ||||||
| can be used to bypass the initialization of the module search path. |  | ||||||
| 
 | 
 | ||||||
| .. seealso:: | .. seealso:: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1169,8 +1169,8 @@ following advice will prevent conflicts with other installations: | ||||||
|   listed. |   listed. | ||||||
| 
 | 
 | ||||||
| * If you are loading :file:`python3.dll` or :file:`python37.dll` in your own | * If you are loading :file:`python3.dll` or :file:`python37.dll` in your own | ||||||
|   executable, explicitly call :c:func:`Py_SetPath` or (at least) |   executable, explicitly set :c:member:`PyConfig.module_search_paths` before | ||||||
|   :c:func:`Py_SetProgramName` before :c:func:`Py_Initialize`. |   :c:func:`Py_InitializeFromConfig`. | ||||||
| 
 | 
 | ||||||
| * Clear and/or overwrite :envvar:`PYTHONPATH` and set :envvar:`PYTHONHOME` | * Clear and/or overwrite :envvar:`PYTHONPATH` and set :envvar:`PYTHONHOME` | ||||||
|   before launching :file:`python.exe` from your application. |   before launching :file:`python.exe` from your application. | ||||||
|  |  | ||||||
|  | @ -375,3 +375,23 @@ Removed | ||||||
|   * ``PyEval_CallMethod()``: use :c:func:`PyObject_CallMethod` instead. |   * ``PyEval_CallMethod()``: use :c:func:`PyObject_CallMethod` instead. | ||||||
| 
 | 
 | ||||||
|   (Contributed by Victor Stinner in :gh:`105107`.) |   (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`.) | ||||||
|  |  | ||||||
|  | @ -6,13 +6,6 @@ | ||||||
|    in all builds of Python */ |    in all builds of Python */ | ||||||
| PyAPI_FUNC(int) Py_FrozenMain(int argc, char **argv); | 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!) */ | /* PEP 432 Multi-phase initialization API (Private while provisional!) */ | ||||||
| 
 | 
 | ||||||
| PyAPI_FUNC(PyStatus) Py_PreInitialize( | 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 *, const char *); | ||||||
| PyAPI_FUNC(int) _Py_FdIsInteractive(FILE *fp, PyObject *filename); | 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_gitidentifier(void); | ||||||
| PyAPI_FUNC(const char *) _Py_gitversion(void); | PyAPI_FUNC(const char *) _Py_gitversion(void); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -23,8 +23,6 @@ extern PyStatus _PyUnicode_InitEncodings(PyThreadState *tstate); | ||||||
| extern int _PyUnicode_EnableLegacyWindowsFSEncoding(void); | extern int _PyUnicode_EnableLegacyWindowsFSEncoding(void); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| PyAPI_FUNC(void) _Py_ClearStandardStreamEncoding(void); |  | ||||||
| 
 |  | ||||||
| PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc); | PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc); | ||||||
| 
 | 
 | ||||||
| /* Various one-time initializers */ | /* Various one-time initializers */ | ||||||
|  |  | ||||||
|  | @ -34,18 +34,12 @@ PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv); | ||||||
| PyAPI_FUNC(int) Py_BytesMain(int argc, char **argv); | PyAPI_FUNC(int) Py_BytesMain(int argc, char **argv); | ||||||
| 
 | 
 | ||||||
| /* In pathconfig.c */ | /* In pathconfig.c */ | ||||||
| Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *); |  | ||||||
| PyAPI_FUNC(wchar_t *) Py_GetProgramName(void); | 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_GetPythonHome(void); | ||||||
| 
 |  | ||||||
| PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void); | PyAPI_FUNC(wchar_t *) Py_GetProgramFullPath(void); | ||||||
| 
 |  | ||||||
| PyAPI_FUNC(wchar_t *) Py_GetPrefix(void); | PyAPI_FUNC(wchar_t *) Py_GetPrefix(void); | ||||||
| PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void); | PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void); | ||||||
| PyAPI_FUNC(wchar_t *) Py_GetPath(void); | PyAPI_FUNC(wchar_t *) Py_GetPath(void); | ||||||
| Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetPath(const wchar_t *); |  | ||||||
| #ifdef MS_WINDOWS | #ifdef MS_WINDOWS | ||||||
| int _Py_CheckPython3(void); | int _Py_CheckPython3(void); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -10,10 +10,6 @@ extern "C" { | ||||||
| PyAPI_FUNC(PyObject *) PySys_GetObject(const char *); | PyAPI_FUNC(PyObject *) PySys_GetObject(const char *); | ||||||
| PyAPI_FUNC(int) PySys_SetObject(const char *, PyObject *); | 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, ...) | PyAPI_FUNC(void) PySys_WriteStdout(const char *format, ...) | ||||||
|                  Py_GCC_ATTRIBUTE((format(printf, 1, 2))); |                  Py_GCC_ATTRIBUTE((format(printf, 1, 2))); | ||||||
| PyAPI_FUNC(void) PySys_WriteStderr(const char *format, ...) | 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_FormatStderr(const char *format, ...); | ||||||
| 
 | 
 | ||||||
| PyAPI_FUNC(void) PySys_ResetWarnOptions(void); | 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); | PyAPI_FUNC(PyObject *) PySys_GetXOptions(void); | ||||||
| 
 | 
 | ||||||
| #if !defined(Py_LIMITED_API) | #if !defined(Py_LIMITED_API) | ||||||
|  |  | ||||||
|  | @ -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. | ||||||
|  | @ -1311,8 +1311,10 @@ | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
| [function.PySys_AddWarnOption] | [function.PySys_AddWarnOption] | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
|  |     abi_only = true | ||||||
| [function.PySys_AddWarnOptionUnicode] | [function.PySys_AddWarnOptionUnicode] | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
|  |     abi_only = true | ||||||
| [function.PySys_FormatStderr] | [function.PySys_FormatStderr] | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
| [function.PySys_FormatStdout] | [function.PySys_FormatStdout] | ||||||
|  | @ -1321,16 +1323,20 @@ | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
| [function.PySys_HasWarnOptions] | [function.PySys_HasWarnOptions] | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
|  |     abi_only = true | ||||||
| [function.PySys_ResetWarnOptions] | [function.PySys_ResetWarnOptions] | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
| [function.PySys_SetArgv] | [function.PySys_SetArgv] | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
|  |     abi_only = true | ||||||
| [function.PySys_SetArgvEx] | [function.PySys_SetArgvEx] | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
|  |     abi_only = true | ||||||
| [function.PySys_SetObject] | [function.PySys_SetObject] | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
| [function.PySys_SetPath] | [function.PySys_SetPath] | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
|  |     abi_only = true | ||||||
| [function.PySys_WriteStderr] | [function.PySys_WriteStderr] | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
| [function.PySys_WriteStdout] | [function.PySys_WriteStdout] | ||||||
|  | @ -1658,8 +1664,10 @@ | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
| [function.Py_SetProgramName] | [function.Py_SetProgramName] | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
|  |     abi_only = true | ||||||
| [function.Py_SetPythonHome] | [function.Py_SetPythonHome] | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
|  |     abi_only = true | ||||||
| [function.Py_SetRecursionLimit] | [function.Py_SetRecursionLimit] | ||||||
|     added = '3.2' |     added = '3.2' | ||||||
| [function.Py_VaBuildValue] | [function.Py_VaBuildValue] | ||||||
|  | @ -1990,6 +1998,7 @@ | ||||||
|     added = '3.7'  # (and 3.6.1 and 3.5.3) |     added = '3.7'  # (and 3.6.1 and 3.5.3) | ||||||
| [function.PySys_AddXOption] | [function.PySys_AddXOption] | ||||||
|     added = '3.7'  # (and 3.6.1 and 3.5.3) |     added = '3.7'  # (and 3.6.1 and 3.5.3) | ||||||
|  |     abi_only = true | ||||||
| [function.PySys_GetXOptions] | [function.PySys_GetXOptions] | ||||||
|     added = '3.7'  # (and 3.6.1 and 3.5.3) |     added = '3.7'  # (and 3.6.1 and 3.5.3) | ||||||
| [function.PyUnicode_AsUCS4] | [function.PyUnicode_AsUCS4] | ||||||
|  | @ -2020,6 +2029,7 @@ | ||||||
|     added = '3.7'  # (and 3.6.1 and 3.5.3) |     added = '3.7'  # (and 3.6.1 and 3.5.3) | ||||||
| [function.Py_SetPath] | [function.Py_SetPath] | ||||||
|     added = '3.7'  # (and 3.6.1 and 3.5.3) |     added = '3.7'  # (and 3.6.1 and 3.5.3) | ||||||
|  |     abi_only = true | ||||||
| [function.PyErr_SetExcFromWindowsErr] | [function.PyErr_SetExcFromWindowsErr] | ||||||
|     added = '3.7'  # (and 3.6.1 and 3.5.3) |     added = '3.7'  # (and 3.6.1 and 3.5.3) | ||||||
|     ifdef = 'MS_WINDOWS' |     ifdef = 'MS_WINDOWS' | ||||||
|  |  | ||||||
|  | @ -636,7 +636,6 @@ pymain_free(void) | ||||||
|        remain valid after Py_Finalize(), since |        remain valid after Py_Finalize(), since | ||||||
|        Py_Initialize()-Py_Finalize() can be called multiple times. */ |        Py_Initialize()-Py_Finalize() can be called multiple times. */ | ||||||
|     _PyPathConfig_ClearGlobal(); |     _PyPathConfig_ClearGlobal(); | ||||||
|     _Py_ClearStandardStreamEncoding(); |  | ||||||
|     _Py_ClearArgcArgv(); |     _Py_ClearArgcArgv(); | ||||||
|     _PyRuntime_Finalize(); |     _PyRuntime_Finalize(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -14,6 +14,15 @@ | ||||||
| #include <stdlib.h>               // putenv() | #include <stdlib.h>               // putenv() | ||||||
| #include <wchar.h> | #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; | int main_argc; | ||||||
| char **main_argv; | char **main_argv; | ||||||
| 
 | 
 | ||||||
|  | @ -204,23 +213,34 @@ static int test_repeated_simple_init(void) | ||||||
|  * Test forcing a particular IO encoding |  * 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 */ |     /* Output info for the test case to check */ | ||||||
|     if (encoding) { |     if (encoding) { | ||||||
|         printf("Expected encoding: %s\n", encoding); |         printf("Expected encoding: %ls\n", encoding); | ||||||
|     } else { |     } else { | ||||||
|         printf("Expected encoding: default\n"); |         printf("Expected encoding: default\n"); | ||||||
|     } |     } | ||||||
|     if (errors) { |     if (errors) { | ||||||
|         printf("Expected errors: %s\n", errors); |         printf("Expected errors: %ls\n", errors); | ||||||
|     } else { |     } else { | ||||||
|         printf("Expected errors: default\n"); |         printf("Expected errors: default\n"); | ||||||
|     } |     } | ||||||
|     fflush(stdout); |     fflush(stdout); | ||||||
|  | 
 | ||||||
|  |     PyConfig config; | ||||||
|  |     _PyConfig_InitCompatConfig(&config); | ||||||
|     /* Force the given IO encoding */ |     /* Force the given IO encoding */ | ||||||
|     Py_SetStandardStreamEncoding(encoding, errors); |     if (encoding) { | ||||||
|     _testembed_Py_InitializeFromConfig(); |         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( |     PyRun_SimpleString( | ||||||
|         "import sys;" |         "import sys;" | ||||||
|         "print('stdin: {0.encoding}:{0.errors}'.format(sys.stdin));" |         "print('stdin: {0.encoding}:{0.errors}'.format(sys.stdin));" | ||||||
|  | @ -237,19 +257,11 @@ static int test_forced_io_encoding(void) | ||||||
|     printf("--- Use defaults ---\n"); |     printf("--- Use defaults ---\n"); | ||||||
|     check_stdio_details(NULL, NULL); |     check_stdio_details(NULL, NULL); | ||||||
|     printf("--- Set errors only ---\n"); |     printf("--- Set errors only ---\n"); | ||||||
|     check_stdio_details(NULL, "ignore"); |     check_stdio_details(NULL, L"ignore"); | ||||||
|     printf("--- Set encoding only ---\n"); |     printf("--- Set encoding only ---\n"); | ||||||
|     check_stdio_details("iso8859-1", NULL); |     check_stdio_details(L"iso8859-1", NULL); | ||||||
|     printf("--- Set encoding and errors ---\n"); |     printf("--- Set encoding and errors ---\n"); | ||||||
|     check_stdio_details("iso8859-1", "replace"); |     check_stdio_details(L"iso8859-1", L"replace"); | ||||||
| 
 |  | ||||||
|     /* Check calling after initialization fails */ |  | ||||||
|     Py_Initialize(); |  | ||||||
| 
 |  | ||||||
|     if (Py_SetStandardStreamEncoding(NULL, NULL) == 0) { |  | ||||||
|         printf("Unexpected success calling Py_SetStandardStreamEncoding"); |  | ||||||
|     } |  | ||||||
|     Py_Finalize(); |  | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -639,11 +651,7 @@ static int test_init_from_config(void) | ||||||
|     /* FIXME: test path config: module_search_path .. dll_path */ |     /* FIXME: test path config: module_search_path .. dll_path */ | ||||||
| 
 | 
 | ||||||
|     putenv("PYTHONPLATLIBDIR=env_platlibdir"); |     putenv("PYTHONPLATLIBDIR=env_platlibdir"); | ||||||
|     status = PyConfig_SetBytesString(&config, &config.platlibdir, "my_platlibdir"); |     config_set_string(&config, &config.platlibdir, L"my_platlibdir"); | ||||||
|     if (PyStatus_Exception(status)) { |  | ||||||
|         PyConfig_Clear(&config); |  | ||||||
|         Py_ExitStatusException(status); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     putenv("PYTHONVERBOSE=0"); |     putenv("PYTHONVERBOSE=0"); | ||||||
|     Py_VerboseFlag = 0; |     Py_VerboseFlag = 0; | ||||||
|  | @ -682,12 +690,6 @@ static int test_init_from_config(void) | ||||||
|     config.buffered_stdio = 0; |     config.buffered_stdio = 0; | ||||||
| 
 | 
 | ||||||
|     putenv("PYTHONIOENCODING=cp424"); |     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_encoding, L"iso8859-1"); | ||||||
|     config_set_string(&config, &config.stdio_errors, L"replace"); |     config_set_string(&config, &config.stdio_errors, L"replace"); | ||||||
| 
 | 
 | ||||||
|  | @ -1410,11 +1412,7 @@ static int test_init_read_set(void) | ||||||
|     PyConfig config; |     PyConfig config; | ||||||
|     PyConfig_InitPythonConfig(&config); |     PyConfig_InitPythonConfig(&config); | ||||||
| 
 | 
 | ||||||
|     status = PyConfig_SetBytesString(&config, &config.program_name, |     config_set_string(&config, &config.program_name, L"./init_read_set"); | ||||||
|                                      "./init_read_set"); |  | ||||||
|     if (PyStatus_Exception(status)) { |  | ||||||
|         goto fail; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     status = PyConfig_Read(&config); |     status = PyConfig_Read(&config); | ||||||
|     if (PyStatus_Exception(status)) { |     if (PyStatus_Exception(status)) { | ||||||
|  |  | ||||||
|  | @ -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() ------------------------------------------- */ | /* --- Py_GetArgcArgv() ------------------------------------------- */ | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
|  | @ -1973,26 +1885,6 @@ config_init_stdio_encoding(PyConfig *config, | ||||||
| { | { | ||||||
|     PyStatus status; |     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
 |     // Exit if encoding and errors are defined
 | ||||||
|     if (config->stdio_encoding != NULL && config->stdio_errors != NULL) { |     if (config->stdio_encoding != NULL && config->stdio_errors != NULL) { | ||||||
|         return _PyStatus_OK(); |         return _PyStatus_OK(); | ||||||
|  |  | ||||||
|  | @ -211,7 +211,8 @@ path_out_of_memory(const char *func) | ||||||
|     _Py_FatalErrorFunc(func, "out of memory"); |     _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) | Py_SetPath(const wchar_t *path) | ||||||
| { | { | ||||||
|     if (path == NULL) { |     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) | Py_SetPythonHome(const wchar_t *home) | ||||||
| { | { | ||||||
|     int has_value = home && home[0]; |     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) | Py_SetProgramName(const wchar_t *program_name) | ||||||
| { | { | ||||||
|     int has_value = program_name && program_name[0]; |     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 * | wchar_t * | ||||||
| Py_GetPath(void) | Py_GetPath(void) | ||||||
|  |  | ||||||
|  | @ -2556,7 +2556,6 @@ init_sys_streams(PyThreadState *tstate) | ||||||
|     res = _PyStatus_ERR("can't initialize sys standard streams"); |     res = _PyStatus_ERR("can't initialize sys standard streams"); | ||||||
| 
 | 
 | ||||||
| done: | done: | ||||||
|     _Py_ClearStandardStreamEncoding(); |  | ||||||
|     Py_XDECREF(iomod); |     Py_XDECREF(iomod); | ||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2614,7 +2614,8 @@ _PySys_AddWarnOptionWithError(PyThreadState *tstate, PyObject *option) | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | // Removed in Python 3.13 API, but kept for the stable ABI
 | ||||||
|  | PyAPI_FUNC(void) | ||||||
| PySys_AddWarnOptionUnicode(PyObject *option) | PySys_AddWarnOptionUnicode(PyObject *option) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     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) | PySys_AddWarnOption(const wchar_t *s) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     PyThreadState *tstate = _PyThreadState_GET(); | ||||||
|  | @ -2645,7 +2647,8 @@ _Py_COMP_DIAG_POP | ||||||
|     Py_DECREF(unicode); |     Py_DECREF(unicode); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | // Removed in Python 3.13 API, but kept for the stable ABI
 | ||||||
|  | PyAPI_FUNC(int) | ||||||
| PySys_HasWarnOptions(void) | PySys_HasWarnOptions(void) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     PyThreadState *tstate = _PyThreadState_GET(); | ||||||
|  | @ -2718,7 +2721,8 @@ _PySys_AddXOptionWithError(const wchar_t *s) | ||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | // Removed in Python 3.13 API, but kept for the stable ABI
 | ||||||
|  | PyAPI_FUNC(void) | ||||||
| PySys_AddXOption(const wchar_t *s) | PySys_AddXOption(const wchar_t *s) | ||||||
| { | { | ||||||
|     PyThreadState *tstate = _PyThreadState_GET(); |     PyThreadState *tstate = _PyThreadState_GET(); | ||||||
|  | @ -3621,7 +3625,8 @@ makepathobject(const wchar_t *path, wchar_t delim) | ||||||
|     return v; |     return v; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | // Removed in Python 3.13 API, but kept for the stable ABI
 | ||||||
|  | PyAPI_FUNC(void) | ||||||
| PySys_SetPath(const wchar_t *path) | PySys_SetPath(const wchar_t *path) | ||||||
| { | { | ||||||
|     PyObject *v; |     PyObject *v; | ||||||
|  | @ -3653,7 +3658,8 @@ make_sys_argv(int argc, wchar_t * const * argv) | ||||||
|     return list; |     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) | PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath) | ||||||
| { | { | ||||||
|     wchar_t* empty_argv[1] = {L""}; |     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) | PySys_SetArgv(int argc, wchar_t **argv) | ||||||
| { | { | ||||||
| _Py_COMP_DIAG_PUSH | _Py_COMP_DIAG_PUSH | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Victor Stinner
						Victor Stinner