Skip to content

Commit 47c117a

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_Exception(config) * PyInitConfig_GetError(config, &err_msg) * PyInitConfig_GetExitCode(config, &exitcode) 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 05a370a commit 47c117a

27 files changed

+1464
-100
lines changed

Doc/c-api/config.rst

+239
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
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+
Configuration to customize Python initialization. Configuration option names
21+
are names of a :c:type:`PyConfig` members.
22+
23+
.. c:struct:: PyInitConfig
24+
25+
Opaque structure to configure the Python initialization.
26+
27+
28+
.. c:function:: PyInitConfig* PyInitConfig_Python_New(void)
29+
30+
Create a new initialization configuration using :ref:`Python Configuration
31+
<init-python-config>` default values.
32+
33+
It must be freed by :c:func:`PyInitConfig_Free`.
34+
35+
Return ``NULL`` on memory allocation failure.
36+
37+
38+
.. c:function:: PyInitConfig* PyInitConfig_Isolated_New(void)
39+
40+
Similar to :c:func:`PyInitConfig_Python_New`, but use :ref:`Isolated
41+
Configuration <init-isolated-conf>` default values.
42+
43+
44+
.. c:function:: void PyInitConfig_Free(PyInitConfig *config)
45+
46+
Free memory of an initialization configuration.
47+
48+
49+
.. c:function:: int PyInitConfig_SetInt(PyInitConfig *config, const char *name, int64_t value)
50+
51+
Set an integer configuration option.
52+
53+
* Return ``0`` on success.
54+
* Set an error in *config* and return ``-1`` on error.
55+
56+
57+
.. c:function:: int PyInitConfig_SetStr(PyInitConfig *config, const char *name, const char *value)
58+
59+
Set a string configuration option from a null-terminated bytes string.
60+
61+
The bytes string is decoded by :c:func:`Py_DecodeLocale`. If Python is not
62+
yet preinitialized, this function preinitializes it to ensure that encodings
63+
are properly configured.
64+
65+
* Return ``0`` on success.
66+
* Set an error in *config* and return ``-1`` on error.
67+
68+
69+
.. c:function:: int PyInitConfig_SetWStr(PyInitConfig *config, const char *name, const wchar_t *value)
70+
71+
Set a string configuration option from a null-terminated wide string.
72+
73+
If Python is not yet preinitialized, this function preinitializes it.
74+
75+
* Return ``0`` on success.
76+
* Set an error in *config* and return ``-1`` on error.
77+
78+
79+
.. c:function:: int PyInitConfig_SetStrList(PyInitConfig *config, const char *name, size_t length, char * const *items)
80+
81+
Set a string list configuration option from an array of null-terminated
82+
bytes strings.
83+
84+
The bytes string is decoded by :c:func:`Py_DecodeLocale`. If Python is not
85+
yet preinitialized, this function preinitializes it to ensure that encodings
86+
are properly configured.
87+
88+
* Return ``0`` on success.
89+
* Set an error in *config* and return ``-1`` on error.
90+
91+
92+
.. c:function:: int PyInitConfig_SetWStrList(PyInitConfig *config, const char *name, size_t length, wchar_t * const *items)
93+
94+
Set a string list configuration option from a null-terminated wide strings.
95+
96+
If Python is not yet preinitialized, this function preinitializes it.
97+
98+
* Return ``0`` on success.
99+
* Set an error in *config* and return ``-1`` on error.
100+
101+
102+
.. c:function:: int Py_InitializeFromInitConfig(PyInitConfig *config)
103+
104+
Initialize Python from the initialization configuration.
105+
106+
* Return ``0`` on success.
107+
* Return ``-1`` if an error was set or if an exit code was set.
108+
109+
110+
Error handling
111+
==============
112+
113+
.. c:function:: int PyInitConfig_Exception(PyInitConfig* config)
114+
115+
Check if an exception is set in *config*:
116+
117+
* Return non-zero if an error was set or if an exit code was set.
118+
* Return zero otherwise.
119+
120+
121+
.. c:function:: int PyInitConfig_GetError(PyInitConfig* config, const char **err_msg)
122+
123+
Get the *config* error message.
124+
125+
* Set *\*err_msg* and return ``1`` if an error is set.
126+
* Set *\*err_msg* to ``NULL`` and return ``0`` otherwise.
127+
128+
129+
.. c:function:: int PyInitConfig_GetExitCode(PyInitConfig* config, int *exitcode)
130+
131+
Get the *config* exit code.
132+
133+
* Set *\*exitcode* and return ``1`` if an exit code is set.
134+
* Return ``0`` otherwise.
135+
136+
137+
.. c:function:: void Py_ExitWithInitConfig(PyInitConfig *config)
138+
139+
Exit Python and free memory of a initialization configuration.
140+
141+
If an error message is set, display the error message.
142+
143+
If an exit code is set, use it to exit the process.
144+
145+
The function does not return.
146+
147+
148+
Example
149+
-------
150+
151+
Code::
152+
153+
void init_python(void)
154+
{
155+
PyInitConfig *config = PyInitConfig_Python_New();
156+
if (config == NULL) {
157+
printf("Init allocation error\n");
158+
return;
159+
}
160+
161+
if (PyInitConfig_SetInt(config, "dev_mode", 1) < 0) {
162+
goto error;
163+
}
164+
165+
// Set a list of wide strings (argv)
166+
wchar_t *argv[] = {L"my_program"", L"-c", L"pass"};
167+
if (PyInitConfig_SetWStrList(config, "argv",
168+
Py_ARRAY_LENGTH(argv), argv) < 0) {
169+
goto error;
170+
}
171+
172+
// Set a wide string (program_name)
173+
if (PyInitConfig_SetWStr(config, "program_name", L"my_program") < 0) {
174+
goto error;
175+
}
176+
177+
// Set a list of bytes strings (xoptions)
178+
char* xoptions[] = {"faulthandler"};
179+
if (PyInitConfig_SetStrList(config, "xoptions",
180+
Py_ARRAY_LENGTH(xoptions), xoptions) < 0) {
181+
goto error;
182+
}
183+
184+
if (Py_InitializeFromInitConfig(config) < 0) {
185+
Py_ExitWithInitConfig(config);
186+
}
187+
PyInitConfig_Free(config);
188+
}
189+
190+
191+
Get the current Python configuration
192+
====================================
193+
194+
Get a configuration option where *name* is the name of a :c:type:`PyConfig`
195+
member.
196+
197+
.. c:function:: int PyConfig_GetInt(const char *name, int64_t *value)
198+
199+
Get an integer configuration option.
200+
201+
Return ``0`` and set *\*value* on success.
202+
203+
Raise an exception and return ``-1`` on error.
204+
205+
206+
.. c:function:: int PyConfig_GetStr(const char *name, PyObject **value)
207+
208+
Get a string configuration option.
209+
210+
Return ``0`` and set *\*value* on success. *\*value* can be set to a Python
211+
:class:`str` object or to ``None``.
212+
213+
Raise an exception and return ``-1`` on error.
214+
215+
216+
.. c:function:: int PyConfig_GetStrList(const char *name, PyObject **value)
217+
218+
Get a string configuration option.
219+
220+
Return ``0`` and set *\*value* to a Python list of strings on success.
221+
222+
Raise an exception and return ``-1`` on error.
223+
224+
225+
Example
226+
-------
227+
228+
Code::
229+
230+
static int get_bytes_warning(void)
231+
{
232+
int64_t bytes_warning;
233+
if (PyConfig_GetInt("bytes_warning", &bytes_warning) < 0) {
234+
// Silently ignore the error
235+
PyErr_Clear();
236+
return -1;
237+
}
238+
return (int)bytes_warning;
239+
}

Doc/c-api/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ document the API functions in detail.
2222
concrete.rst
2323
init.rst
2424
init_config.rst
25+
config.rst
2526
memory.rst
2627
objimpl.rst
2728
apiabiversion.rst

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

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

Doc/whatsnew/3.13.rst

+26
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,32 @@ 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_Exception`
1244+
* :c:func:`PyInitConfig_GetError`
1245+
* :c:func:`PyInitConfig_GetExitCode`
1246+
* :c:func:`Py_InitializeFromInitConfig`
1247+
* :c:func:`Py_ExitWithInitConfig`
1248+
1249+
(Contributed by Victor Stinner in :gh:`107954`.)
1250+
1251+
* Add functions to get the current Python configuration:
1252+
1253+
* :c:func:`PyConfig_GetInt`
1254+
* :c:func:`PyConfig_GetStr`
1255+
* :c:func:`PyConfig_GetStrList`
1256+
1257+
(Contributed by Victor Stinner in :gh:`107954`.)
1258+
12331259

12341260
Porting to Python 3.13
12351261
----------------------

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)