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