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_GetErrorMsg(config)

Add also functions using it:

* Py_InitializeFromInitConfig(config)
* Py_ExitWithInitConfig(config)

* Add functions to get runtime config:

  * PyConfig_GetInt()
  * PyConfig_GetStr()
  * PyConfig_GetStrList()

Add these functions to the limited C API.

Changes:

* Add Doc/c-api/config.rst.
* Add Include/initconfig.h header.
* Add Modules/_testcapi/config.c
* Add Lib/test/test_capi/test_config.py.
  • Loading branch information
vstinner committed Nov 30, 2023
1 parent 6d5e0dc commit 624cbcb
Show file tree
Hide file tree
Showing 23 changed files with 1,256 additions and 99 deletions.
201 changes: 201 additions & 0 deletions Doc/c-api/config.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
.. 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
=================

.. 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 a initialization configuration.
.. c:function:: int PyInitConfig_SetInt(PyInitConfig *config, const char *key, int64_t value)
Set an integer configuration option.
Return 0 on success, or return -1 on error.
.. c:function:: int PyInitConfig_SetStr(PyInitConfig *config, const char *key, const char *value)
Set a string configuration option from a bytes string.
The bytes string is decoded by Py_DecodeLocale(). Preinitialize Python if
needed to ensure that encodings are properly configured.
Return 0 on success, or return -1 on error.
.. c:function:: int PyInitConfig_SetWStr(PyInitConfig *config, const char *key, const wchar_t *value)
Set a string configuration option from a wide string.
Preinitialize Python if needed.
Return ``0`` on success, or return ``-1`` on error.
.. c:function:: int PyInitConfig_SetStrList(PyInitConfig *config, const char *key, size_t length, char * const *items)
Set a string list configuration option from bytes strings.
The bytes strings are decoded by Py_DecodeLocale(). Preinitialize Python if
needed to ensure that encodings are properly configured.
Return ``0`` on success, or return ``-1`` on error.
.. c:function:: int PyInitConfig_SetWStrList(PyInitConfig *config, const char *key, size_t length, wchar_t * const *items)
Set a string list configuration option from a wide strings.
Preinitialize Python if needed.
Return 0 on success, or return -1 on error.
.. c:function:: int Py_InitializeFromInitConfig(PyInitConfig *config)
Initialize Python from the initialization configuration.
Return ``0`` on success.
Return ``-1`` if Python wants to exit and on error. Call
:c:func:`Py_ExitWithInitConfig` in this case.
.. c:function:: char* PyInitConfig_GetErrorMsg(PyInitConfig* config)
Get the current error message.
Return a UTF-8 string allocated by ``malloc()``. It must be released by
``free()``.
Return ``NULL`` on memory allocation failure.
.. c:function:: void Py_ExitWithInitConfig(PyInitConfig *config)
Exit Python and free memory of a initialization configuration.
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);
}
Get Python runtime configuration
================================
.. c:function:: int PyConfig_GetInt(const char *key, int64_t *value)
Get an integer configuration option.
Return ``0`` and set *\*value* on success.
Raise an exception return ``-1`` on error.
.. c:function:: int PyConfig_GetStr(const char *key, PyObject **value)
Get a string configuration option.
Return ``0`` and set *\*value* on success. *\*value* can be set to a Python
:class:`str` object or to ``None``.
Raise an exception return ``-1`` on error.
.. c:function:: int PyConfig_GetStrList(const char *key, PyObject **value)
Get a string configuration option.
Return ``0`` and set *\*value* to a Python list on success.
Raise an exception return ``-1`` on error.
Example
-------
Code::
static int get_bytes_warning(void)
{
int64_t bytes_warning;
if (PyConfig_GetInt("bytes_warning", &bytes_warning) < 0) {
// Silently ignore the error
PyErr_Clear();
return -1;
}
return (int)bytes_warning;
}
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
11 changes: 11 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.

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

0 comments on commit 624cbcb

Please sign in to comment.