blob: 7b98be2b8efe5b700ba4b79615481bd231ab80dd [file] [log] [blame]
Nick Coghland5cacbb2015-05-23 22:24:10 +10001
2/* Testing module for multi-phase initialization of extension modules (PEP 489)
3 */
4
5#include "Python.h"
6
7/* Example objects */
8typedef struct {
9 PyObject_HEAD
10 PyObject *x_attr; /* Attributes dictionary */
11} ExampleObject;
12
13/* Example methods */
14
15static void
16Example_dealloc(ExampleObject *self)
17{
18 Py_XDECREF(self->x_attr);
19 PyObject_Del(self);
20}
21
22static PyObject *
23Example_demo(ExampleObject *self, PyObject *args)
24{
25 PyObject *o = NULL;
26 if (!PyArg_ParseTuple(args, "|O:demo", &o))
27 return NULL;
28 if (o != NULL && PyUnicode_Check(o)) {
29 Py_INCREF(o);
30 return o;
31 }
32 Py_INCREF(Py_None);
33 return Py_None;
34}
35
36
37static PyMethodDef Example_methods[] = {
38 {"demo", (PyCFunction)Example_demo, METH_VARARGS,
39 PyDoc_STR("demo() -> None")},
40 {NULL, NULL} /* sentinel */
41};
42
43static PyObject *
44Example_getattro(ExampleObject *self, PyObject *name)
45{
46 if (self->x_attr != NULL) {
47 PyObject *v = PyDict_GetItem(self->x_attr, name);
48 if (v != NULL) {
49 Py_INCREF(v);
50 return v;
51 }
52 }
53 return PyObject_GenericGetAttr((PyObject *)self, name);
54}
55
56static int
57Example_setattr(ExampleObject *self, char *name, PyObject *v)
58{
59 if (self->x_attr == NULL) {
60 self->x_attr = PyDict_New();
61 if (self->x_attr == NULL)
62 return -1;
63 }
64 if (v == NULL) {
65 int rv = PyDict_DelItemString(self->x_attr, name);
66 if (rv < 0)
67 PyErr_SetString(PyExc_AttributeError,
68 "delete non-existing Example attribute");
69 return rv;
70 }
71 else
72 return PyDict_SetItemString(self->x_attr, name, v);
73}
74
75static PyType_Slot Example_Type_slots[] = {
76 {Py_tp_doc, "The Example type"},
77 {Py_tp_dealloc, Example_dealloc},
78 {Py_tp_getattro, Example_getattro},
79 {Py_tp_setattr, Example_setattr},
80 {Py_tp_methods, Example_methods},
81 {0, 0},
82};
83
84static PyType_Spec Example_Type_spec = {
85 "_testimportexec.Example",
86 sizeof(ExampleObject),
87 0,
88 Py_TPFLAGS_DEFAULT,
89 Example_Type_slots
90};
91
92/* Function of two integers returning integer */
93
94PyDoc_STRVAR(testexport_foo_doc,
95"foo(i,j)\n\
96\n\
97Return the sum of i and j.");
98
99static PyObject *
100testexport_foo(PyObject *self, PyObject *args)
101{
102 long i, j;
103 long res;
104 if (!PyArg_ParseTuple(args, "ll:foo", &i, &j))
105 return NULL;
106 res = i + j;
107 return PyLong_FromLong(res);
108}
109
110/* Test that PyState registration fails */
111
112PyDoc_STRVAR(call_state_registration_func_doc,
113"register_state(0): call PyState_FindModule()\n\
114register_state(1): call PyState_AddModule()\n\
115register_state(2): call PyState_RemoveModule()");
116
117static PyObject *
118call_state_registration_func(PyObject *mod, PyObject *args)
119{
120 int i, ret;
121 PyModuleDef *def = PyModule_GetDef(mod);
122 if (def == NULL) {
123 return NULL;
124 }
125 if (!PyArg_ParseTuple(args, "i:call_state_registration_func", &i))
126 return NULL;
127 switch (i) {
128 case 0:
129 mod = PyState_FindModule(def);
130 if (mod == NULL) {
131 Py_RETURN_NONE;
132 }
133 return mod;
134 case 1:
135 ret = PyState_AddModule(mod, def);
136 if (ret != 0) {
137 return NULL;
138 }
139 break;
140 case 2:
141 ret = PyState_RemoveModule(def);
142 if (ret != 0) {
143 return NULL;
144 }
145 break;
146 }
147 Py_RETURN_NONE;
148}
149
150
151static PyType_Slot Str_Type_slots[] = {
152 {Py_tp_base, NULL}, /* filled out in module exec function */
153 {0, 0},
154};
155
156static PyType_Spec Str_Type_spec = {
157 "_testimportexec.Str",
158 0,
159 0,
160 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
161 Str_Type_slots
162};
163
164static PyMethodDef testexport_methods[] = {
165 {"foo", testexport_foo, METH_VARARGS,
166 testexport_foo_doc},
167 {"call_state_registration_func", call_state_registration_func,
168 METH_VARARGS, call_state_registration_func_doc},
169 {NULL, NULL} /* sentinel */
170};
171
172static int execfunc(PyObject *m)
173{
174 PyObject *temp = NULL;
175
176 /* Due to cross platform compiler issues the slots must be filled
177 * here. It's required for portability to Windows without requiring
178 * C++. */
179 Str_Type_slots[0].pfunc = &PyUnicode_Type;
180
181 /* Add a custom type */
182 temp = PyType_FromSpec(&Example_Type_spec);
183 if (temp == NULL)
184 goto fail;
185 if (PyModule_AddObject(m, "Example", temp) != 0)
186 goto fail;
187
188 /* Add an exception type */
189 temp = PyErr_NewException("_testimportexec.error", NULL, NULL);
190 if (temp == NULL)
191 goto fail;
192 if (PyModule_AddObject(m, "error", temp) != 0)
193 goto fail;
194
195 /* Add Str */
196 temp = PyType_FromSpec(&Str_Type_spec);
197 if (temp == NULL)
198 goto fail;
199 if (PyModule_AddObject(m, "Str", temp) != 0)
200 goto fail;
201
202 if (PyModule_AddIntConstant(m, "int_const", 1969) != 0)
203 goto fail;
204
205 if (PyModule_AddStringConstant(m, "str_const", "something different") != 0)
206 goto fail;
207
208 return 0;
209 fail:
210 return -1;
211}
212
213/* Helper for module definitions; there'll be a lot of them */
214#define TEST_MODULE_DEF(name, slots, methods) { \
215 PyModuleDef_HEAD_INIT, /* m_base */ \
216 name, /* m_name */ \
217 PyDoc_STR("Test module " name), /* m_doc */ \
218 0, /* m_size */ \
219 methods, /* m_methods */ \
220 slots, /* m_slots */ \
221 NULL, /* m_traverse */ \
222 NULL, /* m_clear */ \
223 NULL, /* m_free */ \
224}
225
226PyModuleDef_Slot main_slots[] = {
227 {Py_mod_exec, execfunc},
228 {0, NULL},
229};
230
231static PyModuleDef main_def = TEST_MODULE_DEF("main", main_slots, testexport_methods);
232
233PyMODINIT_FUNC
234PyInit__testmultiphase(PyObject *spec)
235{
236 return PyModuleDef_Init(&main_def);
237}
238
239
240/**** Importing a non-module object ****/
241
242static PyModuleDef def_nonmodule;
243
244/* Create a SimpleNamespace(three=3) */
245static PyObject*
246createfunc_nonmodule(PyObject *spec, PyModuleDef *def)
247{
248 PyObject *dct, *ns, *three;
249
250 if (def != &def_nonmodule) {
251 PyErr_SetString(PyExc_SystemError, "def does not match");
252 return NULL;
253 }
254
255 dct = PyDict_New();
256 if (dct == NULL)
257 return NULL;
258
259 three = PyLong_FromLong(3);
260 if (three == NULL) {
261 Py_DECREF(dct);
262 return NULL;
263 }
264 PyDict_SetItemString(dct, "three", three);
Nick Coghlana48db2b2015-05-24 01:03:46 +1000265 Py_DECREF(three);
Nick Coghland5cacbb2015-05-23 22:24:10 +1000266
267 ns = _PyNamespace_New(dct);
268 Py_DECREF(dct);
269 return ns;
270}
271
272static PyModuleDef_Slot slots_create_nonmodule[] = {
273 {Py_mod_create, createfunc_nonmodule},
274 {0, NULL},
275};
276
277static PyModuleDef def_nonmodule = TEST_MODULE_DEF(
278 "_testmultiphase_nonmodule", slots_create_nonmodule, NULL);
279
280PyMODINIT_FUNC
281PyInit__testmultiphase_nonmodule(PyObject *spec)
282{
283 return PyModuleDef_Init(&def_nonmodule);
284}
285
286/**** Non-ASCII-named modules ****/
287
288static PyModuleDef def_nonascii_latin = { \
289 PyModuleDef_HEAD_INIT, /* m_base */
290 "_testmultiphase_nonascii_latin", /* m_name */
291 PyDoc_STR("Module named in Czech"), /* m_doc */
292 0, /* m_size */
293 NULL, /* m_methods */
294 NULL, /* m_slots */
295 NULL, /* m_traverse */
296 NULL, /* m_clear */
297 NULL, /* m_free */
298};
299
300PyMODINIT_FUNC
301PyInitU__testmultiphase_zkouka_naten_evc07gi8e(PyObject *spec)
302{
303 return PyModuleDef_Init(&def_nonascii_latin);
304}
305
306static PyModuleDef def_nonascii_kana = { \
307 PyModuleDef_HEAD_INIT, /* m_base */
308 "_testmultiphase_nonascii_kana", /* m_name */
309 PyDoc_STR("Module named in Japanese"), /* m_doc */
310 0, /* m_size */
311 NULL, /* m_methods */
312 NULL, /* m_slots */
313 NULL, /* m_traverse */
314 NULL, /* m_clear */
315 NULL, /* m_free */
316};
317
318PyMODINIT_FUNC
319PyInitU_eckzbwbhc6jpgzcx415x(PyObject *spec)
320{
321 return PyModuleDef_Init(&def_nonascii_kana);
322}
323
Benjamin Petersone20056c2015-05-29 17:10:30 -0500324/*** Module with a single-character name ***/
325
326PyMODINIT_FUNC
327PyInit_x(PyObject *spec)
328{
329 return PyModuleDef_Init(&main_def);
330}
331
Nick Coghland5cacbb2015-05-23 22:24:10 +1000332/**** Testing NULL slots ****/
333
334static PyModuleDef null_slots_def = TEST_MODULE_DEF(
335 "_testmultiphase_null_slots", NULL, NULL);
336
337PyMODINIT_FUNC
338PyInit__testmultiphase_null_slots(PyObject *spec)
339{
340 return PyModuleDef_Init(&null_slots_def);
341}
342
343/**** Problematic modules ****/
344
345static PyModuleDef_Slot slots_bad_large[] = {
346 {_Py_mod_LAST_SLOT + 1, NULL},
347 {0, NULL},
348};
349
350static PyModuleDef def_bad_large = TEST_MODULE_DEF(
351 "_testmultiphase_bad_slot_large", slots_bad_large, NULL);
352
353PyMODINIT_FUNC
354PyInit__testmultiphase_bad_slot_large(PyObject *spec)
355{
356 return PyModuleDef_Init(&def_bad_large);
357}
358
359static PyModuleDef_Slot slots_bad_negative[] = {
360 {-1, NULL},
361 {0, NULL},
362};
363
364static PyModuleDef def_bad_negative = TEST_MODULE_DEF(
365 "_testmultiphase_bad_slot_negative", slots_bad_negative, NULL);
366
367PyMODINIT_FUNC
368PyInit__testmultiphase_bad_slot_negative(PyObject *spec)
369{
370 return PyModuleDef_Init(&def_bad_negative);
371}
372
373static PyModuleDef def_create_int_with_state = { \
374 PyModuleDef_HEAD_INIT, /* m_base */
375 "create_with_state", /* m_name */
376 PyDoc_STR("Not a PyModuleObject object, but requests per-module state"),
377 10, /* m_size */
378 NULL, /* m_methods */
379 slots_create_nonmodule, /* m_slots */
380 NULL, /* m_traverse */
381 NULL, /* m_clear */
382 NULL, /* m_free */
383};
384
385PyMODINIT_FUNC
386PyInit__testmultiphase_create_int_with_state(PyObject *spec)
387{
388 return PyModuleDef_Init(&def_create_int_with_state);
389}
390
391
392static PyModuleDef def_negative_size = { \
393 PyModuleDef_HEAD_INIT, /* m_base */
394 "negative_size", /* m_name */
395 PyDoc_STR("PyModuleDef with negative m_size"),
396 -1, /* m_size */
397 NULL, /* m_methods */
398 slots_create_nonmodule, /* m_slots */
399 NULL, /* m_traverse */
400 NULL, /* m_clear */
401 NULL, /* m_free */
402};
403
404PyMODINIT_FUNC
405PyInit__testmultiphase_negative_size(PyObject *spec)
406{
407 return PyModuleDef_Init(&def_negative_size);
408}
409
410
411static PyModuleDef uninitialized_def = TEST_MODULE_DEF("main", main_slots, testexport_methods);
412
413PyMODINIT_FUNC
414PyInit__testmultiphase_export_uninitialized(PyObject *spec)
415{
416 return (PyObject*) &uninitialized_def;
417}
418
419PyMODINIT_FUNC
420PyInit__testmultiphase_export_null(PyObject *spec)
421{
422 return NULL;
423}
424
425PyMODINIT_FUNC
426PyInit__testmultiphase_export_raise(PyObject *spec)
427{
428 PyErr_SetString(PyExc_SystemError, "bad export function");
429 return NULL;
430}
431
432PyMODINIT_FUNC
433PyInit__testmultiphase_export_unreported_exception(PyObject *spec)
434{
435 PyErr_SetString(PyExc_SystemError, "bad export function");
436 return PyModuleDef_Init(&main_def);
437}
438
439static PyObject*
440createfunc_null(PyObject *spec, PyModuleDef *def)
441{
442 return NULL;
443}
444
445PyModuleDef_Slot slots_create_null[] = {
446 {Py_mod_create, createfunc_null},
447 {0, NULL},
448};
449
450static PyModuleDef def_create_null = TEST_MODULE_DEF(
451 "_testmultiphase_create_null", slots_create_null, NULL);
452
453PyMODINIT_FUNC
454PyInit__testmultiphase_create_null(PyObject *spec)
455{
456 return PyModuleDef_Init(&def_create_null);
457}
458
459static PyObject*
460createfunc_raise(PyObject *spec, PyModuleDef *def)
461{
462 PyErr_SetString(PyExc_SystemError, "bad create function");
463 return NULL;
464}
465
466static PyModuleDef_Slot slots_create_raise[] = {
467 {Py_mod_create, createfunc_raise},
468 {0, NULL},
469};
470
471static PyModuleDef def_create_raise = TEST_MODULE_DEF(
472 "_testmultiphase_create_null", slots_create_raise, NULL);
473
474PyMODINIT_FUNC
475PyInit__testmultiphase_create_raise(PyObject *spec)
476{
477 return PyModuleDef_Init(&def_create_raise);
478}
479
480static PyObject*
481createfunc_unreported_exception(PyObject *spec, PyModuleDef *def)
482{
483 PyErr_SetString(PyExc_SystemError, "bad create function");
484 return PyModule_New("foo");
485}
486
487static PyModuleDef_Slot slots_create_unreported_exception[] = {
488 {Py_mod_create, createfunc_unreported_exception},
489 {0, NULL},
490};
491
492static PyModuleDef def_create_unreported_exception = TEST_MODULE_DEF(
493 "_testmultiphase_create_unreported_exception", slots_create_unreported_exception, NULL);
494
495PyMODINIT_FUNC
496PyInit__testmultiphase_create_unreported_exception(PyObject *spec)
497{
498 return PyModuleDef_Init(&def_create_unreported_exception);
499}
500
501static PyModuleDef_Slot slots_nonmodule_with_exec_slots[] = {
502 {Py_mod_create, createfunc_nonmodule},
503 {Py_mod_exec, execfunc},
504 {0, NULL},
505};
506
507static PyModuleDef def_nonmodule_with_exec_slots = TEST_MODULE_DEF(
508 "_testmultiphase_nonmodule_with_exec_slots", slots_nonmodule_with_exec_slots, NULL);
509
510PyMODINIT_FUNC
511PyInit__testmultiphase_nonmodule_with_exec_slots(PyObject *spec)
512{
513 return PyModuleDef_Init(&def_nonmodule_with_exec_slots);
514}
515
516static int
517execfunc_err(PyObject *mod)
518{
519 return -1;
520}
521
522static PyModuleDef_Slot slots_exec_err[] = {
523 {Py_mod_exec, execfunc_err},
524 {0, NULL},
525};
526
527static PyModuleDef def_exec_err = TEST_MODULE_DEF(
528 "_testmultiphase_exec_err", slots_exec_err, NULL);
529
530PyMODINIT_FUNC
531PyInit__testmultiphase_exec_err(PyObject *spec)
532{
533 return PyModuleDef_Init(&def_exec_err);
534}
535
536static int
537execfunc_raise(PyObject *spec)
538{
539 PyErr_SetString(PyExc_SystemError, "bad exec function");
540 return -1;
541}
542
543static PyModuleDef_Slot slots_exec_raise[] = {
544 {Py_mod_exec, execfunc_raise},
545 {0, NULL},
546};
547
548static PyModuleDef def_exec_raise = TEST_MODULE_DEF(
549 "_testmultiphase_exec_raise", slots_exec_raise, NULL);
550
551PyMODINIT_FUNC
552PyInit__testmultiphase_exec_raise(PyObject *mod)
553{
554 return PyModuleDef_Init(&def_exec_raise);
555}
556
557static int
558execfunc_unreported_exception(PyObject *mod)
559{
560 PyErr_SetString(PyExc_SystemError, "bad exec function");
561 return 0;
562}
563
564static PyModuleDef_Slot slots_exec_unreported_exception[] = {
565 {Py_mod_exec, execfunc_unreported_exception},
566 {0, NULL},
567};
568
569static PyModuleDef def_exec_unreported_exception = TEST_MODULE_DEF(
570 "_testmultiphase_exec_unreported_exception", slots_exec_unreported_exception, NULL);
571
572PyMODINIT_FUNC
573PyInit__testmultiphase_exec_unreported_exception(PyObject *spec)
574{
575 return PyModuleDef_Init(&def_exec_unreported_exception);
576}