Skip to content

Commit e85efd1

Browse files
committed
pythongh-107954: Add PyInitConfig C API
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.
1 parent 6d5e0dc commit e85efd1

26 files changed

+1302
-99
lines changed

Doc/c-api/config.rst

+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
.. highlight:: c
2+
3+
.. _config-c-api:
4+
5+
********************
6+
Python Configuration
7+
********************
8+
9+
.. versionadded:: 3.13
10+
11+
API part of the limited C API version 3.13 to configure the Python
12+
initialization and get the Python runtime configuration.
13+
14+
See also :ref:`Python Initialization Configuration <init-config>`.
15+
16+
17+
Initialize Python
18+
=================
19+
20+
.. c:struct:: PyInitConfig
21+
22+
Opaque structure to configure the Python initialization.
23+
24+
25+
.. c:function:: PyInitConfig* PyInitConfig_Python_New(void)
26+
27+
Create a new initialization configuration using :ref:`Python Configuration
28+
<init-python-config>` default values.
29+
30+
It must be freed by c:func:`PyInitConfig_Free`.
31+
32+
Return ``NULL`` on memory allocation failure.
33+
34+
35+
.. c:function:: PyInitConfig* PyInitConfig_Isolated_New(void)
36+
37+
Similar to :c:func:`PyInitConfig_Python_New`, but use :ref:`Isolated
38+
Configuration <init-isolated-conf>` default values.
39+
40+
41+
.. c:function:: void PyInitConfig_Free(PyInitConfig *config)
42+
43+
Free memory of a initialization configuration.
44+
45+
46+
.. c:function:: int PyInitConfig_SetInt(PyInitConfig *config, const char *key, int64_t value)
47+
48+
Set an integer configuration option.
49+
50+
Return 0 on success, or return -1 on error.
51+
52+
53+
.. c:function:: int PyInitConfig_SetStr(PyInitConfig *config, const char *key, const char *value)
54+
55+
Set a string configuration option from a bytes string.
56+
57+
The bytes string is decoded by Py_DecodeLocale(). Preinitialize Python if
58+
needed to ensure that encodings are properly configured.
59+
60+
Return 0 on success, or return -1 on error.
61+
62+
.. c:function:: int PyInitConfig_SetWStr(PyInitConfig *config, const char *key, const wchar_t *value)
63+
64+
Set a string configuration option from a wide string.
65+
66+
Preinitialize Python if needed.
67+
68+
Return ``0`` on success, or return ``-1`` on error.
69+
70+
71+
.. c:function:: int PyInitConfig_SetStrList(PyInitConfig *config, const char *key, size_t length, char * const *items)
72+
73+
Set a string list configuration option from bytes strings.
74+
75+
The bytes strings are decoded by Py_DecodeLocale(). Preinitialize Python if
76+
needed to ensure that encodings are properly configured.
77+
78+
Return ``0`` on success, or return ``-1`` on error.
79+
80+
81+
.. c:function:: int PyInitConfig_SetWStrList(PyInitConfig *config, const char *key, size_t length, wchar_t * const *items)
82+
83+
Set a string list configuration option from a wide strings.
84+
Preinitialize Python if needed.
85+
Return 0 on success, or return -1 on error.
86+
87+
88+
.. c:function:: int Py_InitializeFromInitConfig(PyInitConfig *config)
89+
90+
Initialize Python from the initialization configuration.
91+
92+
Return ``0`` on success.
93+
94+
Return ``-1`` if Python wants to exit and on error. Call
95+
:c:func:`Py_ExitWithInitConfig` in this case.
96+
97+
98+
.. c:function:: char* PyInitConfig_GetErrorMsg(PyInitConfig* config)
99+
100+
Get the current error message.
101+
102+
Return a UTF-8 string allocated by ``malloc()``. It must be released by
103+
``free()``.
104+
105+
Return ``NULL`` on memory allocation failure.
106+
107+
108+
.. c:function:: void Py_ExitWithInitConfig(PyInitConfig *config)
109+
110+
Exit Python and free memory of a initialization configuration.
111+
112+
The function does not return.
113+
114+
Example
115+
-------
116+
117+
Code::
118+
119+
void init_python(void)
120+
{
121+
PyInitConfig *config = PyInitConfig_Python_New();
122+
if (config == NULL) {
123+
printf("Init allocation error\n");
124+
return;
125+
}
126+
127+
if (PyInitConfig_SetInt(config, "dev_mode", 1) < 0) {
128+
goto error;
129+
}
130+
131+
// Set a list of wide strings (argv)
132+
wchar_t *argv[] = {L"my_program"", L"-c", L"pass"};
133+
if (PyInitConfig_SetWStrList(config, "argv",
134+
Py_ARRAY_LENGTH(argv), argv) < 0) {
135+
goto error;
136+
}
137+
138+
// Set a wide string (program_name)
139+
if (PyInitConfig_SetWStr(config, "program_name", L"my_program") < 0) {
140+
goto error;
141+
}
142+
143+
// Set a list of bytes strings (xoptions)
144+
char* xoptions[] = {"faulthandler"};
145+
if (PyInitConfig_SetStrList(config, "xoptions",
146+
Py_ARRAY_LENGTH(xoptions), xoptions) < 0) {
147+
goto error;
148+
}
149+
150+
if (Py_InitializeFromInitConfig(config) < 0) {
151+
Py_ExitWithInitConfig(config);
152+
}
153+
PyInitConfig_Free(config);
154+
}
155+
156+
157+
Get the current Python configuration
158+
====================================
159+
160+
.. c:function:: int PyConfig_GetInt(const char *key, int64_t *value)
161+
162+
Get an integer configuration option.
163+
164+
Return ``0`` and set *\*value* on success.
165+
166+
Raise an exception return ``-1`` on error.
167+
168+
169+
.. c:function:: int PyConfig_GetStr(const char *key, PyObject **value)
170+
171+
Get a string configuration option.
172+
173+
Return ``0`` and set *\*value* on success. *\*value* can be set to a Python
174+
:class:`str` object or to ``None``.
175+
176+
Raise an exception return ``-1`` on error.
177+
178+
179+
.. c:function:: int PyConfig_GetStrList(const char *key, PyObject **value)
180+
181+
Get a string configuration option.
182+
183+
Return ``0`` and set *\*value* to a Python list on success.
184+
185+
Raise an exception return ``-1`` on error.
186+
187+
Example
188+
-------
189+
190+
Code::
191+
192+
static int get_bytes_warning(void)
193+
{
194+
int64_t bytes_warning;
195+
if (PyConfig_GetInt("bytes_warning", &bytes_warning) < 0) {
196+
// Silently ignore the error
197+
PyErr_Clear();
198+
return -1;
199+
}
200+
return (int)bytes_warning;
201+
}

Doc/c-api/init.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
Initialization, Finalization, and Threads
88
*****************************************
99

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

1213
.. _pre-init-safe:
1314

Doc/c-api/init_config.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ There are two kinds of configuration:
2727
The :c:func:`Py_RunMain` function can be used to write a customized Python
2828
program.
2929

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

3233
.. seealso::
3334
:pep:`587` "Python Initialization Configuration".

Doc/data/stable_abi.dat

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Doc/whatsnew/3.13.rst

+24
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,30 @@ New Features
12301230
:exc:`KeyError` if the key missing.
12311231
(Contributed by Stefan Behnel and Victor Stinner in :gh:`111262`.)
12321232

1233+
* Add functions to the limited C API to configure the Python initialization:
1234+
1235+
* :c:func:`PyInitConfig_Python_New`
1236+
* :c:func:`PyInitConfig_Isolated_New`
1237+
* :c:func:`PyInitConfig_Free`
1238+
* :c:func:`PyInitConfig_SetInt`
1239+
* :c:func:`PyInitConfig_SetStr`
1240+
* :c:func:`PyInitConfig_SetWStr`
1241+
* :c:func:`PyInitConfig_SetStrList`
1242+
* :c:func:`PyInitConfig_SetWStrList`
1243+
* :c:func:`PyInitConfig_GetErrorMsg`
1244+
* :c:func:`Py_InitializeFromInitConfig`
1245+
* :c:func:`Py_ExitWithInitConfig`
1246+
1247+
(Contributed by Victor Stinner in :gh:`107954`.)
1248+
1249+
* Add functions to get the current Python configuration:
1250+
1251+
* :c:func:`PyConfig_GetInt`
1252+
* :c:func:`PyConfig_GetStr`
1253+
* :c:func:`PyConfig_GetStrList`
1254+
1255+
(Contributed by Victor Stinner in :gh:`107954`.)
1256+
12331257

12341258
Porting to Python 3.13
12351259
----------------------

Include/Python.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@
8888
#include "sliceobject.h"
8989
#include "cpython/cellobject.h"
9090
#include "iterobject.h"
91-
#include "cpython/initconfig.h"
91+
#include "initconfig.h"
9292
#include "pystate.h"
9393
#include "cpython/genobject.h"
9494
#include "descrobject.h"

Include/cpython/initconfig.h

+2-11
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
#ifndef Py_PYCORECONFIG_H
2-
#define Py_PYCORECONFIG_H
3-
#ifndef Py_LIMITED_API
4-
#ifdef __cplusplus
5-
extern "C" {
1+
#ifndef Py_CPYTHON_INITCONFIG_H
2+
# error "this header file must not be included directly"
63
#endif
74

85
/* --- PyStatus ----------------------------------------------- */
@@ -263,9 +260,3 @@ PyAPI_FUNC(PyStatus) PyConfig_SetWideStringList(PyConfig *config,
263260
264261
See also PyConfig.orig_argv. */
265262
PyAPI_FUNC(void) Py_GetArgcArgv(int *argc, wchar_t ***argv);
266-
267-
#ifdef __cplusplus
268-
}
269-
#endif
270-
#endif /* !Py_LIMITED_API */
271-
#endif /* !Py_PYCORECONFIG_H */

0 commit comments

Comments
 (0)