Skip to content

[PEP 741] gh-107954: Add PyInitConfig C API #110176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions Doc/c-api/config.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
.. highlight:: c

.. _config-c-api:

********************
Python Configuration
********************

.. versionadded:: 3.13

API part of the limited C API version 3.13 to configure the Python
initialization and get the Python runtime configuration.

See also :ref:`Python Initialization Configuration <init-config>`.


Initialize Python
=================

Configuration to customize Python initialization. Configuration option names
are names of a :c:type:`PyConfig` members.

.. c:struct:: PyInitConfig

Opaque structure to configure the Python initialization.


.. c:function:: PyInitConfig* PyInitConfig_Python_New(void)

Create a new initialization configuration using :ref:`Python Configuration
<init-python-config>` default values.

It must be freed by :c:func:`PyInitConfig_Free`.

Return ``NULL`` on memory allocation failure.


.. c:function:: PyInitConfig* PyInitConfig_Isolated_New(void)

Similar to :c:func:`PyInitConfig_Python_New`, but use :ref:`Isolated
Configuration <init-isolated-conf>` default values.


.. c:function:: void PyInitConfig_Free(PyInitConfig *config)

Free memory of an initialization configuration.


.. c:function:: int PyInitConfig_SetInt(PyInitConfig *config, const char *name, int64_t value)

Set an integer configuration option.

* Return ``0`` on success.
* Set an error in *config* and return ``-1`` on error.


.. c:function:: int PyInitConfig_SetStr(PyInitConfig *config, const char *name, const char *value)

Set a string configuration option from a null-terminated bytes string.

The bytes string is decoded by :c:func:`Py_DecodeLocale`. If Python is not
yet preinitialized, this function preinitializes it to ensure that encodings
are properly configured.

* Return ``0`` on success.
* Set an error in *config* and return ``-1`` on error.


.. c:function:: int PyInitConfig_SetWStr(PyInitConfig *config, const char *name, const wchar_t *value)

Set a string configuration option from a null-terminated wide string.

If Python is not yet preinitialized, this function preinitializes it.

* Return ``0`` on success.
* Set an error in *config* and return ``-1`` on error.


.. c:function:: int PyInitConfig_SetStrList(PyInitConfig *config, const char *name, size_t length, char * const *items)

Set a string list configuration option from an array of null-terminated
bytes strings.

The bytes string is decoded by :c:func:`Py_DecodeLocale`. If Python is not
yet preinitialized, this function preinitializes it to ensure that encodings
are properly configured.

* Return ``0`` on success.
* Set an error in *config* and return ``-1`` on error.


.. c:function:: int PyInitConfig_SetWStrList(PyInitConfig *config, const char *name, size_t length, wchar_t * const *items)

Set a string list configuration option from a null-terminated wide strings.

If Python is not yet preinitialized, this function preinitializes it.

* Return ``0`` on success.
* Set an error in *config* and return ``-1`` on error.


.. c:function:: int Py_InitializeFromInitConfig(PyInitConfig *config)

Initialize Python from the initialization configuration.

* Return ``0`` on success.
* Return ``-1`` if an error was set or if an exit code was set.


Error handling
==============

.. c:function:: int PyInitConfig_Exception(PyInitConfig* config)

Check if an exception is set in *config*:

* Return non-zero if an error was set or if an exit code was set.
* Return zero otherwise.


.. c:function:: int PyInitConfig_GetError(PyInitConfig* config, const char **err_msg)

Get the *config* error message.

* Set *\*err_msg* and return ``1`` if an error is set.
* Set *\*err_msg* to ``NULL`` and return ``0`` otherwise.


.. c:function:: int PyInitConfig_GetExitCode(PyInitConfig* config, int *exitcode)

Get the *config* exit code.

* Set *\*exitcode* and return ``1`` if an exit code is set.
* Return ``0`` otherwise.


.. c:function:: void Py_ExitWithInitConfig(PyInitConfig *config)

Exit Python and free memory of a initialization configuration.

If an error message is set, display the error message.

If an exit code is set, use it to exit the process.

The function does not return.


Example
-------

Code::

void init_python(void)
{
PyInitConfig *config = PyInitConfig_Python_New();
if (config == NULL) {
printf("Init allocation error\n");
return;
}

if (PyInitConfig_SetInt(config, "dev_mode", 1) < 0) {
goto error;
}

// Set a list of wide strings (argv)
wchar_t *argv[] = {L"my_program"", L"-c", L"pass"};
if (PyInitConfig_SetWStrList(config, "argv",
Py_ARRAY_LENGTH(argv), argv) < 0) {
goto error;
}

// Set a wide string (program_name)
if (PyInitConfig_SetWStr(config, "program_name", L"my_program") < 0) {
goto error;
}

// Set a list of bytes strings (xoptions)
char* xoptions[] = {"faulthandler"};
if (PyInitConfig_SetStrList(config, "xoptions",
Py_ARRAY_LENGTH(xoptions), xoptions) < 0) {
goto error;
}

if (Py_InitializeFromInitConfig(config) < 0) {
Py_ExitWithInitConfig(config);
}
PyInitConfig_Free(config);
}
1 change: 1 addition & 0 deletions Doc/c-api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ document the API functions in detail.
concrete.rst
init.rst
init_config.rst
config.rst
memory.rst
objimpl.rst
apiabiversion.rst
3 changes: 2 additions & 1 deletion Doc/c-api/init.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
Initialization, Finalization, and Threads
*****************************************

See also :ref:`Python Initialization Configuration <init-config>`.
See also the :ref:`Python Initialization Configuration <init-config>`
and the :ref:`Python Configuration <config-c-api>`

.. _pre-init-safe:

Expand Down
3 changes: 2 additions & 1 deletion Doc/c-api/init_config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ There are two kinds of configuration:
The :c:func:`Py_RunMain` function can be used to write a customized Python
program.

See also :ref:`Initialization, Finalization, and Threads <initialization>`.
See also :ref:`Initialization, Finalization, and Threads <initialization>`
and the :ref:`Python Configuration <config-c-api>`.

.. seealso::
:pep:`587` "Python Initialization Configuration".
Expand Down
13 changes: 13 additions & 0 deletions Doc/data/stable_abi.dat

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,24 @@ New Features
* Add :c:func:`Py_HashPointer` function to hash a pointer.
(Contributed by Victor Stinner in :gh:`111545`.)

* Add functions to the limited C API to configure the Python initialization:

* :c:func:`PyInitConfig_Python_New`
* :c:func:`PyInitConfig_Isolated_New`
* :c:func:`PyInitConfig_Free`
* :c:func:`PyInitConfig_SetInt`
* :c:func:`PyInitConfig_SetStr`
* :c:func:`PyInitConfig_SetWStr`
* :c:func:`PyInitConfig_SetStrList`
* :c:func:`PyInitConfig_SetWStrList`
* :c:func:`PyInitConfig_Exception`
* :c:func:`PyInitConfig_GetError`
* :c:func:`PyInitConfig_GetExitCode`
* :c:func:`Py_InitializeFromInitConfig`
* :c:func:`Py_ExitWithInitConfig`

(Contributed by Victor Stinner in :gh:`107954`.)


Porting to Python 3.13
----------------------
Expand Down
2 changes: 1 addition & 1 deletion Include/Python.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
#include "sliceobject.h"
#include "cpython/cellobject.h"
#include "iterobject.h"
#include "cpython/initconfig.h"
#include "initconfig.h"
#include "pystate.h"
#include "cpython/genobject.h"
#include "descrobject.h"
Expand Down
13 changes: 2 additions & 11 deletions Include/cpython/initconfig.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#ifndef Py_PYCORECONFIG_H
#define Py_PYCORECONFIG_H
#ifndef Py_LIMITED_API
#ifdef __cplusplus
extern "C" {
#ifndef Py_CPYTHON_INITCONFIG_H
# error "this header file must not be included directly"
#endif

/* --- PyStatus ----------------------------------------------- */
Expand Down Expand Up @@ -263,9 +260,3 @@ PyAPI_FUNC(PyStatus) PyConfig_SetWideStringList(PyConfig *config,

See also PyConfig.orig_argv. */
PyAPI_FUNC(void) Py_GetArgcArgv(int *argc, wchar_t ***argv);

#ifdef __cplusplus
}
#endif
#endif /* !Py_LIMITED_API */
#endif /* !Py_PYCORECONFIG_H */
Loading