Skip to content

Commit 1a65816

Browse files
committed
Remove module states
1 parent f6465bd commit 1a65816

7 files changed

Lines changed: 53 additions & 94 deletions

File tree

Doc/extending/extending.rst

Lines changed: 40 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -204,59 +204,26 @@ value must be in a particular range or must satisfy other conditions,
204204
:c:data:`PyExc_ValueError` is appropriate.
205205

206206
You can also define a new exception that is unique to your module. For this, you
207-
usually declare an object variable in the module's state and initialize it
208-
in the module's :c:data:`Py_mod_exec` function (:c:func:`!spam_module_exec`)
209-
with an exception object::
210-
211-
typedef struct {
212-
PyObject *SpamError;
213-
} spam_state;
207+
usually declare a static object variable at the beginning of your file::
214208

215-
static int
216-
spam_module_exec(PyObject *module)
217-
{
218-
spam_state *state = PyModule_GetState(module);
219-
if (state == NULL) {
220-
return -1;
221-
}
209+
static PyObject *SpamError;
222210

223-
state->SpamError = PyErr_NewException("spam.error", NULL, NULL);
224-
if (state->SpamError == NULL) {
225-
return -1;
226-
}
227-
if (PyModule_AddObjectRef(module, "SpamError", state->SpamError) < 0) {
228-
return -1; // followed by spam_module_free() then Py_CLEAR()
229-
}
211+
and initialize it in the module's :c:data:`Py_mod_exec` function
212+
(:c:func:`!spam_module_exec`)
230213

231-
return 0;
232-
}
214+
with an exception object::
233215

234216
static int
235-
spam_module_traverse(PyObject *module, visitproc visit, void *arg) {
236-
spam_state *state = PyModule_GetState(module);
237-
if (state == NULL) {
217+
spam_module_exec(PyObject *m)
218+
{
219+
SpamError = PyErr_NewException("spam.error", NULL, NULL);
220+
if (PyModule_AddObjectRef(m, "error", SpamError) < 0) {
238221
return -1;
239222
}
240-
Py_VISIT(st->SpamError);
241-
return 0;
242-
}
243223

244-
static int
245-
spam_module_clear(PyObject *module) {
246-
spam_state *state = PyModule_GetState(module);
247-
if (state == NULL) {
248-
return -1;
249-
}
250-
Py_CLEAR(st->SpamError);
251224
return 0;
252225
}
253226

254-
static void
255-
spam_module_free(void *module)
256-
{
257-
(void)spam_module_clear((PyObject *)module);
258-
}
259-
260227
static PyModuleDef_Slot spam_module_slots[] = {
261228
{Py_mod_exec, spam_module_exec},
262229
{0, NULL}
@@ -265,11 +232,8 @@ with an exception object::
265232
static struct PyModuleDef spam_module = {
266233
.m_base = PyModuleDef_HEAD_INIT,
267234
.m_name = "spam",
268-
.m_size = sizeof(spam_state), // size of per-module state
235+
.m_size = 0, // non-negative
269236
.m_slots = spam_module_slots,
270-
.m_traverse = spam_module_traverse,
271-
.m_clear = spam_module_clear,
272-
.m_free = spam_module_free,
273237
};
274238

275239
PyMODINIT_FUNC
@@ -306,10 +270,7 @@ call to :c:func:`PyErr_SetString` as shown below::
306270
return NULL;
307271
sts = system(command);
308272
if (sts < 0) {
309-
spam_state *state = PyModule_GetState(self);
310-
if (state != NULL) {
311-
PyErr_SetString(state->SpamError, "System command failed");
312-
}
273+
PyErr_SetString(SpamError, "System command failed");
313274
return NULL;
314275
}
315276
return PyLong_FromLong(sts);
@@ -1297,25 +1258,19 @@ The ``#define`` is used to tell the header file that it is being included in the
12971258
exporting module, not a client module. Finally, the module's initialization
12981259
function must take care of initializing the C API pointer array::
12991260

1300-
typedef struct {
1301-
void *PySpam_API[PySpam_API_pointers];
1302-
} spam_state;
1303-
13041261
static int
1305-
spam_module_exec(PyObject *module)
1262+
spam_module_exec(PyObject *m)
13061263
{
1307-
spam_state *state = PyModule_GetState(module);
1308-
if (state == NULL) {
1309-
return -1;
1310-
}
1264+
static void *PySpam_API[PySpam_API_pointers];
1265+
PyObject *c_api_object;
13111266

13121267
/* Initialize the C API pointer array */
1313-
state->PySpam_API[PySpam_System_NUM] = PySpam_System;
1268+
PySpam_API[PySpam_System_NUM] = (void *)PySpam_System;
13141269

13151270
/* Create a Capsule containing the API pointer array's address */
1316-
PyObject *capi = PyCapsule_New(state->PySpam_API, "spam._C_API", NULL);
1317-
if (PyModule_Add(module, "_C_API", capi) < 0) {
1318-
Py_CLEAR(capi);
1271+
c_api_object = PyCapsule_New((void *)PySpam_API, "spam._C_API", NULL);
1272+
1273+
if (PyModule_Add(m, "_C_API", c_api_object) < 0) {
13191274
return -1;
13201275
}
13211276

@@ -1330,7 +1285,7 @@ function must take care of initializing the C API pointer array::
13301285
static struct PyModuleDef spam_module = {
13311286
.m_base = PyModuleDef_HEAD_INIT,
13321287
.m_name = "spam",
1333-
.m_size = sizeof(spam_state),
1288+
.m_size = 0,
13341289
.m_slots = spam_module_slots,
13351290
};
13361291

@@ -1340,6 +1295,9 @@ function must take care of initializing the C API pointer array::
13401295
return PyModuleDef_Init(&spam_module);
13411296
}
13421297

1298+
Note that ``PySpam_API`` is declared ``static``; otherwise the pointer
1299+
array would disappear when :c:func:`!PyInit_spam` terminates!
1300+
13431301
The bulk of the work is in the header file :file:`spammodule.h`, which looks
13441302
like this::
13451303

@@ -1368,9 +1326,21 @@ like this::
13681326
#else
13691327
/* This section is used in modules that use spammodule's API */
13701328

1329+
static void **PySpam_API;
1330+
13711331
#define PySpam_System \
13721332
(*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])
13731333

1334+
/* Return -1 on error, 0 on success.
1335+
* PyCapsule_Import will set an exception if there's an error.
1336+
*/
1337+
static int
1338+
import_spam(void)
1339+
{
1340+
PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
1341+
return (PySpam_API != NULL) ? 0 : -1;
1342+
}
1343+
13741344
#endif
13751345

13761346
#ifdef __cplusplus
@@ -1379,22 +1349,15 @@ like this::
13791349

13801350
#endif /* !defined(Py_SPAMMODULE_H) */
13811351

1382-
1383-
typedef struct {
1384-
void **PySpam_API;
1385-
} client_state;
1352+
All that a client module must do in order to have access to the function
1353+
:c:func:`!PySpam_System` is to call the function (or rather macro)
1354+
:c:func:`!import_spam` in its initialization function::
13861355

13871356
static int
1388-
client_module_exec(PyObject *module)
1357+
client_module_exec(PyObject *m)
13891358
{
1390-
client_state *state = PyModule_GetState(module);
1391-
if (state == NULL) {
1359+
if (import_spam() < 0)
13921360
return -1;
1393-
}
1394-
state->PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
1395-
if (state->PySpam_API == NULL) {
1396-
return -1;
1397-
}
13981361
/* additional initialization can happen here */
13991362
return 0;
14001363
}
@@ -1407,7 +1370,7 @@ like this::
14071370
static struct PyModuleDef client_module = {
14081371
.m_base = PyModuleDef_HEAD_INIT,
14091372
.m_name = "client",
1410-
.m_size = sizeof(client_state),
1373+
.m_size = 0,
14111374
.m_slots = client_module_slots,
14121375
};
14131376

Doc/extending/newtypes_tutorial.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ This initializes the :class:`!Custom` type, filling in a number of members
180180
to the appropriate default values, including :c:member:`~PyObject.ob_type` that we initially
181181
set to ``NULL``. ::
182182

183-
if (PyModule_AddObjectRef(mod, "Custom", (PyObject *)&CustomType) < 0) {
183+
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
184184
return -1;
185185
}
186186

@@ -878,13 +878,13 @@ issues, you can't fill that field directly with a reference to
878878
function::
879879

880880
static int
881-
sublist_module_exec(PyObject *mod)
881+
sublist_module_exec(PyObject *m)
882882
{
883883
SubListType.tp_base = &PyList_Type;
884884
if (PyType_Ready(&SubListType) < 0)
885885
return -1;
886886

887-
if (PyModule_AddObjectRef(mod, "SubList", (PyObject *)&SubListType) < 0) {
887+
if (PyModule_AddObjectRef(m, "SubList", (PyObject *) &SubListType) < 0) {
888888
return -1;
889889
}
890890

Doc/includes/newtypes/custom.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ static PyTypeObject CustomType = {
1717
};
1818

1919
static int
20-
custom_module_exec(PyObject *mod)
20+
custom_module_exec(PyObject *m)
2121
{
2222
if (PyType_Ready(&CustomType) < 0)
2323
return -1;
2424

25-
if (PyModule_AddObjectRef(mod, "Custom", (PyObject *)&CustomType) < 0) {
25+
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
2626
return -1;
2727
}
2828

Doc/includes/newtypes/custom2.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,12 @@ static PyTypeObject CustomType = {
107107
};
108108

109109
static int
110-
custom_module_exec(PyObject *mod)
110+
custom_module_exec(PyObject *m)
111111
{
112112
if (PyType_Ready(&CustomType) < 0)
113113
return -1;
114114

115-
if (PyModule_AddObjectRef(mod, "Custom", (PyObject *)&CustomType) < 0) {
115+
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
116116
return -1;
117117
}
118118

@@ -121,7 +121,6 @@ custom_module_exec(PyObject *mod)
121121

122122
static PyModuleDef_Slot custom_module_slots[] = {
123123
{Py_mod_exec, custom_module_exec},
124-
// Just use this while using static types
125124
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
126125
{0, NULL}
127126
};

Doc/includes/newtypes/custom3.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,12 @@ static PyTypeObject CustomType = {
152152
};
153153

154154
static int
155-
custom_module_exec(PyObject *mod)
155+
custom_module_exec(PyObject *m)
156156
{
157157
if (PyType_Ready(&CustomType) < 0)
158158
return -1;
159159

160-
if (PyModule_AddObjectRef(mod, "Custom", (PyObject *)&CustomType) < 0) {
160+
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
161161
return -1;
162162
}
163163

@@ -166,7 +166,6 @@ custom_module_exec(PyObject *mod)
166166

167167
static PyModuleDef_Slot custom_module_slots[] = {
168168
{Py_mod_exec, custom_module_exec},
169-
// Just use this while using static types
170169
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
171170
{0, NULL}
172171
};

Doc/includes/newtypes/custom4.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,12 @@ static PyTypeObject CustomType = {
171171
};
172172

173173
static int
174-
custom_module_exec(PyObject *mod)
174+
custom_module_exec(PyObject *m)
175175
{
176176
if (PyType_Ready(&CustomType) < 0)
177177
return -1;
178178

179-
if (PyModule_AddObjectRef(mod, "Custom", (PyObject *)&CustomType) < 0) {
179+
if (PyModule_AddObjectRef(m, "Custom", (PyObject *) &CustomType) < 0) {
180180
return -1;
181181
}
182182

@@ -185,7 +185,6 @@ custom_module_exec(PyObject *mod)
185185

186186
static PyModuleDef_Slot custom_module_slots[] = {
187187
{Py_mod_exec, custom_module_exec},
188-
// Just use this while using static types
189188
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
190189
{0, NULL}
191190
};

Doc/includes/newtypes/sublist.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ static PyTypeObject SubListType = {
4242
};
4343

4444
static int
45-
sublist_module_exec(PyObject *mod)
45+
sublist_module_exec(PyObject *m)
4646
{
4747
SubListType.tp_base = &PyList_Type;
4848
if (PyType_Ready(&SubListType) < 0)
4949
return -1;
5050

51-
if (PyModule_AddObjectRef(mod, "SubList", (PyObject *)&SubListType) < 0) {
51+
if (PyModule_AddObjectRef(m, "SubList", (PyObject *) &SubListType) < 0) {
5252
return -1;
5353
}
5454

@@ -57,7 +57,6 @@ sublist_module_exec(PyObject *mod)
5757

5858
static PyModuleDef_Slot sublist_module_slots[] = {
5959
{Py_mod_exec, sublist_module_exec},
60-
// Just use this while using static types
6160
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
6261
{0, NULL}
6362
};

0 commit comments

Comments
 (0)