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