Skip to content

Commit

Permalink
pythongh-107954: Add PyInitConfig C API
Browse files Browse the repository at this point in the history
Add PyInitConfig functions:

* PyInitConfig_Python_New()
* PyInitConfig_Isolated_New()
* PyInitConfig_Free(config)
* PyInitConfig_SetInt(config, key, value)
* PyInitConfig_SetStr(config, key, value)
* PyInitConfig_SetWStr(config, key, value)
* PyInitConfig_SetStrList(config, key, length, items)
* PyInitConfig_SetWStrList(config, key, length, items)
* PyInitConfig_Exception(config)
* PyInitConfig_GetError(config, &err_msg)
* PyInitConfig_GetExitCode(config, &exitcode)

Add also functions using it:

* Py_InitializeFromInitConfig(config)
* Py_ExitWithInitConfig(config)

Add these functions to the limited C API.

Changes:

* Add Doc/c-api/config.rst.
* Add Include/initconfig.h header.
  • Loading branch information
vstinner committed Mar 14, 2024
1 parent f20dfb7 commit 65e49ac
Show file tree
Hide file tree
Showing 18 changed files with 875 additions and 53 deletions.
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 @@ -1649,6 +1649,24 @@ New Features
between native integer types and Python :class:`int` objects.
(Contributed by Steve Dower in :gh:`111140`.)

* 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 @@ -266,9 +263,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

0 comments on commit 65e49ac

Please sign in to comment.