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