1
2 /* Testing module for multi-phase initialization of extension modules (PEP 489)
3 */
4
5 #include "Python.h"
6
7 /* Example objects */
8 typedef struct {
9 PyObject_HEAD
10 PyObject *x_attr; /* Attributes dictionary */
11 } ExampleObject;
12
13 typedef struct {
14 PyObject *integer;
15 } testmultiphase_state;
16
17 /* Example methods */
18
19 static int
Example_traverse(ExampleObject * self,visitproc visit,void * arg)20 Example_traverse(ExampleObject *self, visitproc visit, void *arg)
21 {
22 Py_VISIT(self->x_attr);
23 return 0;
24 }
25
26 static void
Example_finalize(ExampleObject * self)27 Example_finalize(ExampleObject *self)
28 {
29 Py_CLEAR(self->x_attr);
30 }
31
32 static PyObject *
Example_demo(ExampleObject * self,PyObject * args)33 Example_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 }
42 Py_RETURN_NONE;
43 }
44
45
46 static PyMethodDef Example_methods[] = {
47 {"demo", (PyCFunction)Example_demo, METH_VARARGS,
48 PyDoc_STR("demo() -> None")},
49 {NULL, NULL} /* sentinel */
50 };
51
52 static PyObject *
Example_getattro(ExampleObject * self,PyObject * name)53 Example_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
65 static int
Example_setattr(ExampleObject * self,const char * name,PyObject * v)66 Example_setattr(ExampleObject *self, const char *name, PyObject *v)
67 {
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
84 static PyType_Slot Example_Type_slots[] = {
85 {Py_tp_doc, "The Example type"},
86 {Py_tp_finalize, Example_finalize},
87 {Py_tp_traverse, Example_traverse},
88 {Py_tp_getattro, Example_getattro},
89 {Py_tp_setattr, Example_setattr},
90 {Py_tp_methods, Example_methods},
91 {0, 0},
92 };
93
94 static PyType_Spec Example_Type_spec = {
95 "_testimportexec.Example",
96 sizeof(ExampleObject),
97 0,
98 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE,
99 Example_Type_slots
100 };
101
102 /* Function of two integers returning integer */
103
104 PyDoc_STRVAR(testexport_foo_doc,
105 "foo(i,j)\n\
106 \n\
107 Return the sum of i and j.");
108
109 static PyObject *
testexport_foo(PyObject * self,PyObject * args)110 testexport_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
122 PyDoc_STRVAR(call_state_registration_func_doc,
123 "register_state(0): call PyState_FindModule()\n\
124 register_state(1): call PyState_AddModule()\n\
125 register_state(2): call PyState_RemoveModule()");
126
127 static PyObject *
call_state_registration_func(PyObject * mod,PyObject * args)128 call_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
161 static PyType_Slot Str_Type_slots[] = {
162 {Py_tp_base, NULL}, /* filled out in module exec function */
163 {0, 0},
164 };
165
166 static 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
174 static 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
execfunc(PyObject * m)182 static 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 */
224
225 #define TEST_MODULE_DEF_EX(name, slots, methods, statesize, traversefunc) { \
226 PyModuleDef_HEAD_INIT, /* m_base */ \
227 name, /* m_name */ \
228 PyDoc_STR("Test module " name), /* m_doc */ \
229 statesize, /* m_size */ \
230 methods, /* m_methods */ \
231 slots, /* m_slots */ \
232 traversefunc, /* m_traverse */ \
233 NULL, /* m_clear */ \
234 NULL, /* m_free */ \
235 }
236
237 #define TEST_MODULE_DEF(name, slots, methods) TEST_MODULE_DEF_EX(name, slots, methods, 0, NULL)
238
239 static PyModuleDef_Slot main_slots[] = {
240 {Py_mod_exec, execfunc},
241 {0, NULL},
242 };
243
244 static PyModuleDef main_def = TEST_MODULE_DEF("main", main_slots, testexport_methods);
245
246 PyMODINIT_FUNC
PyInit__testmultiphase(PyObject * spec)247 PyInit__testmultiphase(PyObject *spec)
248 {
249 return PyModuleDef_Init(&main_def);
250 }
251
252
253 /**** Importing a non-module object ****/
254
255 static PyModuleDef def_nonmodule;
256 static PyModuleDef def_nonmodule_with_methods;
257
258 /* Create a SimpleNamespace(three=3) */
259 static PyObject*
createfunc_nonmodule(PyObject * spec,PyModuleDef * def)260 createfunc_nonmodule(PyObject *spec, PyModuleDef *def)
261 {
262 PyObject *dct, *ns, *three;
263
264 if (def != &def_nonmodule && def != &def_nonmodule_with_methods) {
265 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);
279 Py_DECREF(three);
280
281 ns = _PyNamespace_New(dct);
282 Py_DECREF(dct);
283 return ns;
284 }
285
286 static PyModuleDef_Slot slots_create_nonmodule[] = {
287 {Py_mod_create, createfunc_nonmodule},
288 {0, NULL},
289 };
290
291 static PyModuleDef def_nonmodule = TEST_MODULE_DEF(
292 "_testmultiphase_nonmodule", slots_create_nonmodule, NULL);
293
294 PyMODINIT_FUNC
PyInit__testmultiphase_nonmodule(PyObject * spec)295 PyInit__testmultiphase_nonmodule(PyObject *spec)
296 {
297 return PyModuleDef_Init(&def_nonmodule);
298 }
299
300 PyDoc_STRVAR(nonmodule_bar_doc,
301 "bar(i,j)\n\
302 \n\
303 Return the difference of i - j.");
304
305 static PyObject *
nonmodule_bar(PyObject * self,PyObject * args)306 nonmodule_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
316 static PyMethodDef nonmodule_methods[] = {
317 {"bar", nonmodule_bar, METH_VARARGS, nonmodule_bar_doc},
318 {NULL, NULL} /* sentinel */
319 };
320
321 static PyModuleDef def_nonmodule_with_methods = TEST_MODULE_DEF(
322 "_testmultiphase_nonmodule_with_methods", slots_create_nonmodule, nonmodule_methods);
323
324 PyMODINIT_FUNC
PyInit__testmultiphase_nonmodule_with_methods(PyObject * spec)325 PyInit__testmultiphase_nonmodule_with_methods(PyObject *spec)
326 {
327 return PyModuleDef_Init(&def_nonmodule_with_methods);
328 }
329
330 /**** Non-ASCII-named modules ****/
331
332 static 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
344 PyMODINIT_FUNC
PyInitU__testmultiphase_zkouka_naten_evc07gi8e(PyObject * spec)345 PyInitU__testmultiphase_zkouka_naten_evc07gi8e(PyObject *spec)
346 {
347 return PyModuleDef_Init(&def_nonascii_latin);
348 }
349
350 static 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
362 PyMODINIT_FUNC
PyInitU_eckzbwbhc6jpgzcx415x(PyObject * spec)363 PyInitU_eckzbwbhc6jpgzcx415x(PyObject *spec)
364 {
365 return PyModuleDef_Init(&def_nonascii_kana);
366 }
367
368 /*** Module with a single-character name ***/
369
370 PyMODINIT_FUNC
PyInit_x(PyObject * spec)371 PyInit_x(PyObject *spec)
372 {
373 return PyModuleDef_Init(&main_def);
374 }
375
376 /**** Testing NULL slots ****/
377
378 static PyModuleDef null_slots_def = TEST_MODULE_DEF(
379 "_testmultiphase_null_slots", NULL, NULL);
380
381 PyMODINIT_FUNC
PyInit__testmultiphase_null_slots(PyObject * spec)382 PyInit__testmultiphase_null_slots(PyObject *spec)
383 {
384 return PyModuleDef_Init(&null_slots_def);
385 }
386
387 /**** Problematic modules ****/
388
389 static PyModuleDef_Slot slots_bad_large[] = {
390 {_Py_mod_LAST_SLOT + 1, NULL},
391 {0, NULL},
392 };
393
394 static PyModuleDef def_bad_large = TEST_MODULE_DEF(
395 "_testmultiphase_bad_slot_large", slots_bad_large, NULL);
396
397 PyMODINIT_FUNC
PyInit__testmultiphase_bad_slot_large(PyObject * spec)398 PyInit__testmultiphase_bad_slot_large(PyObject *spec)
399 {
400 return PyModuleDef_Init(&def_bad_large);
401 }
402
403 static PyModuleDef_Slot slots_bad_negative[] = {
404 {-1, NULL},
405 {0, NULL},
406 };
407
408 static PyModuleDef def_bad_negative = TEST_MODULE_DEF(
409 "_testmultiphase_bad_slot_negative", slots_bad_negative, NULL);
410
411 PyMODINIT_FUNC
PyInit__testmultiphase_bad_slot_negative(PyObject * spec)412 PyInit__testmultiphase_bad_slot_negative(PyObject *spec)
413 {
414 return PyModuleDef_Init(&def_bad_negative);
415 }
416
417 static 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
429 PyMODINIT_FUNC
PyInit__testmultiphase_create_int_with_state(PyObject * spec)430 PyInit__testmultiphase_create_int_with_state(PyObject *spec)
431 {
432 return PyModuleDef_Init(&def_create_int_with_state);
433 }
434
435
436 static 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
448 PyMODINIT_FUNC
PyInit__testmultiphase_negative_size(PyObject * spec)449 PyInit__testmultiphase_negative_size(PyObject *spec)
450 {
451 return PyModuleDef_Init(&def_negative_size);
452 }
453
454
455 static PyModuleDef uninitialized_def = TEST_MODULE_DEF("main", main_slots, testexport_methods);
456
457 PyMODINIT_FUNC
PyInit__testmultiphase_export_uninitialized(PyObject * spec)458 PyInit__testmultiphase_export_uninitialized(PyObject *spec)
459 {
460 return (PyObject*) &uninitialized_def;
461 }
462
463 PyMODINIT_FUNC
PyInit__testmultiphase_export_null(PyObject * spec)464 PyInit__testmultiphase_export_null(PyObject *spec)
465 {
466 return NULL;
467 }
468
469 PyMODINIT_FUNC
PyInit__testmultiphase_export_raise(PyObject * spec)470 PyInit__testmultiphase_export_raise(PyObject *spec)
471 {
472 PyErr_SetString(PyExc_SystemError, "bad export function");
473 return NULL;
474 }
475
476 PyMODINIT_FUNC
PyInit__testmultiphase_export_unreported_exception(PyObject * spec)477 PyInit__testmultiphase_export_unreported_exception(PyObject *spec)
478 {
479 PyErr_SetString(PyExc_SystemError, "bad export function");
480 return PyModuleDef_Init(&main_def);
481 }
482
483 static PyObject*
createfunc_null(PyObject * spec,PyModuleDef * def)484 createfunc_null(PyObject *spec, PyModuleDef *def)
485 {
486 return NULL;
487 }
488
489 static PyModuleDef_Slot slots_create_null[] = {
490 {Py_mod_create, createfunc_null},
491 {0, NULL},
492 };
493
494 static PyModuleDef def_create_null = TEST_MODULE_DEF(
495 "_testmultiphase_create_null", slots_create_null, NULL);
496
497 PyMODINIT_FUNC
PyInit__testmultiphase_create_null(PyObject * spec)498 PyInit__testmultiphase_create_null(PyObject *spec)
499 {
500 return PyModuleDef_Init(&def_create_null);
501 }
502
503 static PyObject*
createfunc_raise(PyObject * spec,PyModuleDef * def)504 createfunc_raise(PyObject *spec, PyModuleDef *def)
505 {
506 PyErr_SetString(PyExc_SystemError, "bad create function");
507 return NULL;
508 }
509
510 static PyModuleDef_Slot slots_create_raise[] = {
511 {Py_mod_create, createfunc_raise},
512 {0, NULL},
513 };
514
515 static PyModuleDef def_create_raise = TEST_MODULE_DEF(
516 "_testmultiphase_create_null", slots_create_raise, NULL);
517
518 PyMODINIT_FUNC
PyInit__testmultiphase_create_raise(PyObject * spec)519 PyInit__testmultiphase_create_raise(PyObject *spec)
520 {
521 return PyModuleDef_Init(&def_create_raise);
522 }
523
524 static PyObject*
createfunc_unreported_exception(PyObject * spec,PyModuleDef * def)525 createfunc_unreported_exception(PyObject *spec, PyModuleDef *def)
526 {
527 PyErr_SetString(PyExc_SystemError, "bad create function");
528 return PyModule_New("foo");
529 }
530
531 static PyModuleDef_Slot slots_create_unreported_exception[] = {
532 {Py_mod_create, createfunc_unreported_exception},
533 {0, NULL},
534 };
535
536 static PyModuleDef def_create_unreported_exception = TEST_MODULE_DEF(
537 "_testmultiphase_create_unreported_exception", slots_create_unreported_exception, NULL);
538
539 PyMODINIT_FUNC
PyInit__testmultiphase_create_unreported_exception(PyObject * spec)540 PyInit__testmultiphase_create_unreported_exception(PyObject *spec)
541 {
542 return PyModuleDef_Init(&def_create_unreported_exception);
543 }
544
545 static PyModuleDef_Slot slots_nonmodule_with_exec_slots[] = {
546 {Py_mod_create, createfunc_nonmodule},
547 {Py_mod_exec, execfunc},
548 {0, NULL},
549 };
550
551 static PyModuleDef def_nonmodule_with_exec_slots = TEST_MODULE_DEF(
552 "_testmultiphase_nonmodule_with_exec_slots", slots_nonmodule_with_exec_slots, NULL);
553
554 PyMODINIT_FUNC
PyInit__testmultiphase_nonmodule_with_exec_slots(PyObject * spec)555 PyInit__testmultiphase_nonmodule_with_exec_slots(PyObject *spec)
556 {
557 return PyModuleDef_Init(&def_nonmodule_with_exec_slots);
558 }
559
560 static int
execfunc_err(PyObject * mod)561 execfunc_err(PyObject *mod)
562 {
563 return -1;
564 }
565
566 static PyModuleDef_Slot slots_exec_err[] = {
567 {Py_mod_exec, execfunc_err},
568 {0, NULL},
569 };
570
571 static PyModuleDef def_exec_err = TEST_MODULE_DEF(
572 "_testmultiphase_exec_err", slots_exec_err, NULL);
573
574 PyMODINIT_FUNC
PyInit__testmultiphase_exec_err(PyObject * spec)575 PyInit__testmultiphase_exec_err(PyObject *spec)
576 {
577 return PyModuleDef_Init(&def_exec_err);
578 }
579
580 static int
execfunc_raise(PyObject * spec)581 execfunc_raise(PyObject *spec)
582 {
583 PyErr_SetString(PyExc_SystemError, "bad exec function");
584 return -1;
585 }
586
587 static PyModuleDef_Slot slots_exec_raise[] = {
588 {Py_mod_exec, execfunc_raise},
589 {0, NULL},
590 };
591
592 static PyModuleDef def_exec_raise = TEST_MODULE_DEF(
593 "_testmultiphase_exec_raise", slots_exec_raise, NULL);
594
595 PyMODINIT_FUNC
PyInit__testmultiphase_exec_raise(PyObject * mod)596 PyInit__testmultiphase_exec_raise(PyObject *mod)
597 {
598 return PyModuleDef_Init(&def_exec_raise);
599 }
600
601 static int
execfunc_unreported_exception(PyObject * mod)602 execfunc_unreported_exception(PyObject *mod)
603 {
604 PyErr_SetString(PyExc_SystemError, "bad exec function");
605 return 0;
606 }
607
608 static PyModuleDef_Slot slots_exec_unreported_exception[] = {
609 {Py_mod_exec, execfunc_unreported_exception},
610 {0, NULL},
611 };
612
613 static PyModuleDef def_exec_unreported_exception = TEST_MODULE_DEF(
614 "_testmultiphase_exec_unreported_exception", slots_exec_unreported_exception, NULL);
615
616 PyMODINIT_FUNC
PyInit__testmultiphase_exec_unreported_exception(PyObject * spec)617 PyInit__testmultiphase_exec_unreported_exception(PyObject *spec)
618 {
619 return PyModuleDef_Init(&def_exec_unreported_exception);
620 }
621
622 static int
bad_traverse(PyObject * self,visitproc visit,void * arg)623 bad_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
631 static int
execfunc_with_bad_traverse(PyObject * mod)632 execfunc_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
646 static PyModuleDef_Slot slots_with_bad_traverse[] = {
647 {Py_mod_exec, execfunc_with_bad_traverse},
648 {0, NULL}
649 };
650
651 static 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
655 PyMODINIT_FUNC
PyInit__testmultiphase_with_bad_traverse(PyObject * spec)656 PyInit__testmultiphase_with_bad_traverse(PyObject *spec) {
657 return PyModuleDef_Init(&def_with_bad_traverse);
658 }
659
660 /*** Helper for imp test ***/
661
662 static PyModuleDef imp_dummy_def = TEST_MODULE_DEF("imp_dummy", main_slots, testexport_methods);
663
664 PyMODINIT_FUNC
PyInit_imp_dummy(PyObject * spec)665 PyInit_imp_dummy(PyObject *spec)
666 {
667 return PyModuleDef_Init(&imp_dummy_def);
668 }
669
670