Skip to content

Commit 441b10c

Browse files
authored
bpo-38304: Add PyConfig.struct_size (GH-16451)
Add a new struct_size field to PyPreConfig and PyConfig structures to allow to modify these structures in the future without breaking the backward compatibility. * Replace private _config_version field with public struct_size field in PyPreConfig and PyConfig. * Public PyPreConfig_InitIsolatedConfig() and PyPreConfig_InitPythonConfig() return type becomes PyStatus, instead of void. * Internal _PyConfig_InitCompatConfig(), _PyPreConfig_InitCompatConfig(), _PyPreConfig_InitFromConfig(), _PyPreConfig_InitFromPreConfig() return type becomes PyStatus, instead of void. * Remove _Py_CONFIG_VERSION * Update the Initialization Configuration documentation.
1 parent 52d1b86 commit 441b10c

File tree

13 files changed

+350
-60
lines changed

13 files changed

+350
-60
lines changed

Doc/c-api/init_config.rst

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,18 +194,25 @@ PyPreConfig
194194
* Configure the LC_CTYPE locale
195195
* Set the UTF-8 mode
196196
197+
The :c:member:`struct_size` field must be explicitly initialized to
198+
``sizeof(PyPreConfig)``.
199+
197200
Function to initialize a preconfiguration:
198201
199-
.. c:function:: void PyPreConfig_InitIsolatedConfig(PyPreConfig *preconfig)
202+
.. c:function:: PyStatus PyPreConfig_InitIsolatedConfig(PyPreConfig *preconfig)
200203
201204
Initialize the preconfiguration with :ref:`Python Configuration
202205
<init-python-config>`.
203206
204-
.. c:function:: void PyPreConfig_InitPythonConfig(PyPreConfig *preconfig)
207+
.. c:function:: PyStatus PyPreConfig_InitPythonConfig(PyPreConfig *preconfig)
205208
206209
Initialize the preconfiguration with :ref:`Isolated Configuration
207210
<init-isolated-conf>`.
208211
212+
The caller of these functions is responsible to handle exceptions (error or
213+
exit) using :c:func:`PyStatus_Exception` and
214+
:c:func:`Py_ExitStatusException`.
215+
209216
Structure fields:
210217
211218
.. c:member:: int allocator
@@ -267,6 +274,13 @@ PyPreConfig
267274
same way the regular Python parses command line arguments: see
268275
:ref:`Command Line Arguments <using-on-cmdline>`.
269276
277+
.. c:member:: size_t struct_size
278+
279+
Size of the structure in bytes: must be initialized to
280+
``sizeof(PyPreConfig)``.
281+
282+
Field used for API and ABI compatibility.
283+
270284
.. c:member:: int use_environment
271285
272286
See :c:member:`PyConfig.use_environment`.
@@ -316,12 +330,18 @@ the preinitialization.
316330
317331
Example using the preinitialization to enable the UTF-8 Mode::
318332
333+
PyStatus status;
319334
PyPreConfig preconfig;
320-
PyPreConfig_InitPythonConfig(&preconfig);
335+
preconfig.struct_size = sizeof(PyPreConfig);
336+
337+
status = PyPreConfig_InitPythonConfig(&preconfig);
338+
if (PyStatus_Exception(status)) {
339+
Py_ExitStatusException(status);
340+
}
321341
322342
preconfig.utf8_mode = 1;
323343
324-
PyStatus status = Py_PreInitialize(&preconfig);
344+
status = Py_PreInitialize(&preconfig);
325345
if (PyStatus_Exception(status)) {
326346
Py_ExitStatusException(status);
327347
}
@@ -340,6 +360,9 @@ PyConfig
340360
341361
Structure containing most parameters to configure Python.
342362
363+
The :c:member:`struct_size` field must be explicitly initialized to
364+
``sizeof(PyConfig)``.
365+
343366
Structure methods:
344367
345368
.. c:function:: PyStatus PyConfig_InitPythonConfig(PyConfig *config)
@@ -656,6 +679,13 @@ PyConfig
656679
Encoding and encoding errors of :data:`sys.stdin`, :data:`sys.stdout` and
657680
:data:`sys.stderr`.
658681
682+
.. c:member:: size_t struct_size
683+
684+
Size of the structure in bytes: must be initialized to
685+
``sizeof(PyConfig)``.
686+
687+
Field used for API and ABI compatibility.
688+
659689
.. c:member:: int tracemalloc
660690
661691
If non-zero, call :func:`tracemalloc.start` at startup.
@@ -718,6 +748,7 @@ Example setting the program name::
718748
{
719749
PyStatus status;
720750
PyConfig config;
751+
config.struct_size = sizeof(PyConfig);
721752
722753
status = PyConfig_InitPythonConfig(&config);
723754
if (PyStatus_Exception(status)) {
@@ -750,6 +781,7 @@ configuration, and then override some parameters::
750781
{
751782
PyStatus status;
752783
PyConfig config;
784+
config.struct_size = sizeof(PyConfig);
753785
754786
status = PyConfig_InitPythonConfig(&config);
755787
if (PyStatus_Exception(status)) {
@@ -835,8 +867,9 @@ Example of customized Python always running in isolated mode::
835867
836868
int main(int argc, char **argv)
837869
{
838-
PyConfig config;
839870
PyStatus status;
871+
PyConfig config;
872+
config.struct_size = sizeof(PyConfig);
840873
841874
status = PyConfig_InitPythonConfig(&config);
842875
if (PyStatus_Exception(status)) {
@@ -1028,6 +1061,7 @@ phases::
10281061
{
10291062
PyStatus status;
10301063
PyConfig config;
1064+
config.struct_size = sizeof(PyConfig);
10311065
10321066
status = PyConfig_InitPythonConfig(&config);
10331067
if (PyStatus_Exception(status)) {

Include/cpython/initconfig.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ PyAPI_FUNC(PyStatus) PyWideStringList_Insert(PyWideStringList *list,
4545
/* --- PyPreConfig ----------------------------------------------- */
4646

4747
typedef struct {
48-
int _config_version; /* Internal configuration version,
49-
used for ABI compatibility */
48+
/* Size of the structure in bytes: must be initialized to
49+
sizeof(PyPreConfig). Field used for API and ABI compatibility. */
50+
size_t struct_size;
51+
5052
int _config_init; /* _PyConfigInitEnum value */
5153

5254
/* Parse Py_PreInitializeFromBytesArgs() arguments?
@@ -122,15 +124,17 @@ typedef struct {
122124
int allocator;
123125
} PyPreConfig;
124126

125-
PyAPI_FUNC(void) PyPreConfig_InitPythonConfig(PyPreConfig *config);
126-
PyAPI_FUNC(void) PyPreConfig_InitIsolatedConfig(PyPreConfig *config);
127+
PyAPI_FUNC(PyStatus) PyPreConfig_InitPythonConfig(PyPreConfig *config);
128+
PyAPI_FUNC(PyStatus) PyPreConfig_InitIsolatedConfig(PyPreConfig *config);
127129

128130

129131
/* --- PyConfig ---------------------------------------------- */
130132

131133
typedef struct {
132-
int _config_version; /* Internal configuration version,
133-
used for ABI compatibility */
134+
/* Size of the structure in bytes: must be initialized to
135+
sizeof(PyConfig). Field used for API and ABI compatibility. */
136+
size_t struct_size;
137+
134138
int _config_init; /* _PyConfigInitEnum value */
135139

136140
int isolated; /* Isolated mode? see PyPreConfig.isolated */
@@ -403,7 +407,6 @@ typedef struct {
403407

404408
/* If equal to 0, stop Python initialization before the "main" phase */
405409
int _init_main;
406-
407410
} PyConfig;
408411

409412
PyAPI_FUNC(PyStatus) PyConfig_InitPythonConfig(PyConfig *config);

Include/internal/pycore_initconfig.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ extern "C" {
4040
(err._type == _PyStatus_TYPE_EXIT)
4141
#define _PyStatus_EXCEPTION(err) \
4242
(err._type != _PyStatus_TYPE_OK)
43+
#define _PyStatus_UPDATE_FUNC(err) \
44+
do { err.func = _PyStatus_GET_FUNC(); } while (0)
4345

4446
/* --- PyWideStringList ------------------------------------------------ */
4547

@@ -118,11 +120,11 @@ extern PyStatus _PyPreCmdline_Read(_PyPreCmdline *cmdline,
118120

119121
/* --- PyPreConfig ----------------------------------------------- */
120122

121-
PyAPI_FUNC(void) _PyPreConfig_InitCompatConfig(PyPreConfig *preconfig);
122-
extern void _PyPreConfig_InitFromConfig(
123+
PyAPI_FUNC(PyStatus) _PyPreConfig_InitCompatConfig(PyPreConfig *preconfig);
124+
extern PyStatus _PyPreConfig_InitFromConfig(
123125
PyPreConfig *preconfig,
124126
const PyConfig *config);
125-
extern void _PyPreConfig_InitFromPreConfig(
127+
extern PyStatus _PyPreConfig_InitFromPreConfig(
126128
PyPreConfig *preconfig,
127129
const PyPreConfig *config2);
128130
extern PyObject* _PyPreConfig_AsDict(const PyPreConfig *preconfig);
@@ -135,16 +137,14 @@ extern PyStatus _PyPreConfig_Write(const PyPreConfig *preconfig);
135137

136138
/* --- PyConfig ---------------------------------------------- */
137139

138-
#define _Py_CONFIG_VERSION 1
139-
140140
typedef enum {
141141
/* Py_Initialize() API: backward compatibility with Python 3.6 and 3.7 */
142142
_PyConfig_INIT_COMPAT = 1,
143143
_PyConfig_INIT_PYTHON = 2,
144144
_PyConfig_INIT_ISOLATED = 3
145145
} _PyConfigInitEnum;
146146

147-
PyAPI_FUNC(void) _PyConfig_InitCompatConfig(PyConfig *config);
147+
PyAPI_FUNC(PyStatus) _PyConfig_InitCompatConfig(PyConfig *config);
148148
extern PyStatus _PyConfig_Copy(
149149
PyConfig *config,
150150
const PyConfig *config2);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Add a new ``struct_size`` field to :c:type:`PyPreConfig` and :c:type:`PyConfig`
2+
structures to allow to modify these structures in the future without breaking
3+
the backward compatibility.

Modules/main.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,20 @@ pymain_init(const _PyArgv *args)
5353
#endif
5454

5555
PyPreConfig preconfig;
56-
PyPreConfig_InitPythonConfig(&preconfig);
56+
preconfig.struct_size = sizeof(PyPreConfig);
57+
58+
status = PyPreConfig_InitPythonConfig(&preconfig);
59+
if (_PyStatus_EXCEPTION(status)) {
60+
return status;
61+
}
62+
5763
status = _Py_PreInitializeFromPyArgv(&preconfig, args);
5864
if (_PyStatus_EXCEPTION(status)) {
5965
return status;
6066
}
6167

6268
PyConfig config;
69+
config.struct_size = sizeof(PyConfig);
6370
status = PyConfig_InitPythonConfig(&config);
6471
if (_PyStatus_EXCEPTION(status)) {
6572
goto done;

Programs/_freeze_importlib.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ main(int argc, char *argv[])
7878

7979
PyStatus status;
8080
PyConfig config;
81+
config.struct_size = sizeof(PyConfig);
8182

8283
status = PyConfig_InitIsolatedConfig(&config);
8384
if (PyStatus_Exception(status)) {

0 commit comments

Comments
 (0)