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 /* Example methods */
14 
15 static int
16 Example_traverse(ExampleObject *self, visitproc visit, void *arg)
17 {
18     Py_VISIT(self->x_attr);
19     return 0;
20 }
21 
22 static int
23 Example_finalize(ExampleObject *self)
24 {
25     Py_CLEAR(self->x_attr);
26     return 0;
27 }
28 
29 static PyObject *
30 Example_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 
44 static PyMethodDef Example_methods[] = {
45     {"demo",            (PyCFunction)Example_demo,  METH_VARARGS,
46         PyDoc_STR("demo() -> None")},
47     {NULL,              NULL}           /* sentinel */
48 };
49 
50 static PyObject *
51 Example_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 
63 static int
64 Example_setattr(ExampleObject *self, const char *name, PyObject *v)
65 {
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 
82 static PyType_Slot Example_Type_slots[] = {
83     {Py_tp_doc, "The Example type"},
84     {Py_tp_finalize, Example_finalize},
85     {Py_tp_traverse, Example_traverse},
86     {Py_tp_getattro, Example_getattro},
87     {Py_tp_setattr, Example_setattr},
88     {Py_tp_methods, Example_methods},
89     {0, 0},
90 };
91 
92 static PyType_Spec Example_Type_spec = {
93     "_testimportexec.Example",
94     sizeof(ExampleObject),
95     0,
96     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE,
97     Example_Type_slots
98 };
99 
100 /* Function of two integers returning integer */
101 
102 PyDoc_STRVAR(testexport_foo_doc,
103 "foo(i,j)\n\
104 \n\
105 Return the sum of i and j.");
106 
107 static PyObject *
108 testexport_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 
120 PyDoc_STRVAR(call_state_registration_func_doc,
121 "register_state(0): call PyState_FindModule()\n\
122 register_state(1): call PyState_AddModule()\n\
123 register_state(2): call PyState_RemoveModule()");
124 
125 static PyObject *
126 call_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 
159 static PyType_Slot Str_Type_slots[] = {
160     {Py_tp_base, NULL}, /* filled out in module exec function */
161     {0, 0},
162 };
163 
164 static 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 
172 static 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 
180 static 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 
234 PyModuleDef_Slot main_slots[] = {
235     {Py_mod_exec, execfunc},
236     {0, NULL},
237 };
238 
239 static PyModuleDef main_def = TEST_MODULE_DEF("main", main_slots, testexport_methods);
240 
241 PyMODINIT_FUNC
242 PyInit__testmultiphase(PyObject *spec)
243 {
244     return PyModuleDef_Init(&main_def);
245 }
246 
247 
248 /**** Importing a non-module object ****/
249 
250 static PyModuleDef def_nonmodule;
251 static PyModuleDef def_nonmodule_with_methods;
252 
253 /* Create a SimpleNamespace(three=3) */
254 static PyObject*
255 createfunc_nonmodule(PyObject *spec, PyModuleDef *def)
256 {
257     PyObject *dct, *ns, *three;
258 
259     if (def != &def_nonmodule && def != &def_nonmodule_with_methods) {
260         PyErr_SetString(PyExc_SystemError, "def does not match");
261         return NULL;
262     }
263 
264     dct = PyDict_New();
265     if (dct == NULL)
266         return NULL;
267 
268     three = PyLong_FromLong(3);
269     if (three == NULL) {
270         Py_DECREF(dct);
271         return NULL;
272     }
273     PyDict_SetItemString(dct, "three", three);
274     Py_DECREF(three);
275 
276     ns = _PyNamespace_New(dct);
277     Py_DECREF(dct);
278     return ns;
279 }
280 
281 static PyModuleDef_Slot slots_create_nonmodule[] = {
282     {Py_mod_create, createfunc_nonmodule},
283     {0, NULL},
284 };
285 
286 static PyModuleDef def_nonmodule = TEST_MODULE_DEF(
287     "_testmultiphase_nonmodule", slots_create_nonmodule, NULL);
288 
289 PyMODINIT_FUNC
290 PyInit__testmultiphase_nonmodule(PyObject *spec)
291 {
292     return PyModuleDef_Init(&def_nonmodule);
293 }
294 
295 PyDoc_STRVAR(nonmodule_bar_doc,
296 "bar(i,j)\n\
297 \n\
298 Return the difference of i - j.");
299 
300 static PyObject *
301 nonmodule_bar(PyObject *self, PyObject *args)
302 {
303     long i, j;
304     long res;
305     if (!PyArg_ParseTuple(args, "ll:bar", &i, &j))
306         return NULL;
307     res = i - j;
308     return PyLong_FromLong(res);
309 }
310 
311 static PyMethodDef nonmodule_methods[] = {
312     {"bar", nonmodule_bar, METH_VARARGS, nonmodule_bar_doc},
313     {NULL, NULL}           /* sentinel */
314 };
315 
316 static PyModuleDef def_nonmodule_with_methods = TEST_MODULE_DEF(
317     "_testmultiphase_nonmodule_with_methods", slots_create_nonmodule, nonmodule_methods);
318 
319 PyMODINIT_FUNC
320 PyInit__testmultiphase_nonmodule_with_methods(PyObject *spec)
321 {
322     return PyModuleDef_Init(&def_nonmodule_with_methods);
323 }
324 
325 /**** Non-ASCII-named modules ****/
326 
327 static PyModuleDef def_nonascii_latin = { \
328     PyModuleDef_HEAD_INIT,                      /* m_base */
329     "_testmultiphase_nonascii_latin",           /* m_name */
330     PyDoc_STR("Module named in Czech"),         /* m_doc */
331     0,                                          /* m_size */
332     NULL,                                       /* m_methods */
333     NULL,                                       /* m_slots */
334     NULL,                                       /* m_traverse */
335     NULL,                                       /* m_clear */
336     NULL,                                       /* m_free */
337 };
338 
339 PyMODINIT_FUNC
340 PyInitU__testmultiphase_zkouka_naten_evc07gi8e(PyObject *spec)
341 {
342     return PyModuleDef_Init(&def_nonascii_latin);
343 }
344 
345 static PyModuleDef def_nonascii_kana = { \
346     PyModuleDef_HEAD_INIT,                      /* m_base */
347     "_testmultiphase_nonascii_kana",            /* m_name */
348     PyDoc_STR("Module named in Japanese"),      /* m_doc */
349     0,                                          /* m_size */
350     NULL,                                       /* m_methods */
351     NULL,                                       /* m_slots */
352     NULL,                                       /* m_traverse */
353     NULL,                                       /* m_clear */
354     NULL,                                       /* m_free */
355 };
356 
357 PyMODINIT_FUNC
358 PyInitU_eckzbwbhc6jpgzcx415x(PyObject *spec)
359 {
360     return PyModuleDef_Init(&def_nonascii_kana);
361 }
362 
363 /*** Module with a single-character name ***/
364 
365 PyMODINIT_FUNC
366 PyInit_x(PyObject *spec)
367 {
368     return PyModuleDef_Init(&main_def);
369 }
370 
371 /**** Testing NULL slots ****/
372 
373 static PyModuleDef null_slots_def = TEST_MODULE_DEF(
374     "_testmultiphase_null_slots", NULL, NULL);
375 
376 PyMODINIT_FUNC
377 PyInit__testmultiphase_null_slots(PyObject *spec)
378 {
379     return PyModuleDef_Init(&null_slots_def);
380 }
381 
382 /**** Problematic modules ****/
383 
384 static PyModuleDef_Slot slots_bad_large[] = {
385     {_Py_mod_LAST_SLOT + 1, NULL},
386     {0, NULL},
387 };
388 
389 static PyModuleDef def_bad_large = TEST_MODULE_DEF(
390     "_testmultiphase_bad_slot_large", slots_bad_large, NULL);
391 
392 PyMODINIT_FUNC
393 PyInit__testmultiphase_bad_slot_large(PyObject *spec)
394 {
395     return PyModuleDef_Init(&def_bad_large);
396 }
397 
398 static PyModuleDef_Slot slots_bad_negative[] = {
399     {-1, NULL},
400     {0, NULL},
401 };
402 
403 static PyModuleDef def_bad_negative = TEST_MODULE_DEF(
404     "_testmultiphase_bad_slot_negative", slots_bad_negative, NULL);
405 
406 PyMODINIT_FUNC
407 PyInit__testmultiphase_bad_slot_negative(PyObject *spec)
408 {
409     return PyModuleDef_Init(&def_bad_negative);
410 }
411 
412 static PyModuleDef def_create_int_with_state = { \
413     PyModuleDef_HEAD_INIT,                      /* m_base */
414     "create_with_state",                        /* m_name */
415     PyDoc_STR("Not a PyModuleObject object, but requests per-module state"),
416     10,                                         /* m_size */
417     NULL,                                       /* m_methods */
418     slots_create_nonmodule,                     /* m_slots */
419     NULL,                                       /* m_traverse */
420     NULL,                                       /* m_clear */
421     NULL,                                       /* m_free */
422 };
423 
424 PyMODINIT_FUNC
425 PyInit__testmultiphase_create_int_with_state(PyObject *spec)
426 {
427     return PyModuleDef_Init(&def_create_int_with_state);
428 }
429 
430 
431 static PyModuleDef def_negative_size = { \
432     PyModuleDef_HEAD_INIT,                      /* m_base */
433     "negative_size",                            /* m_name */
434     PyDoc_STR("PyModuleDef with negative m_size"),
435     -1,                                         /* m_size */
436     NULL,                                       /* m_methods */
437     slots_create_nonmodule,                     /* m_slots */
438     NULL,                                       /* m_traverse */
439     NULL,                                       /* m_clear */
440     NULL,                                       /* m_free */
441 };
442 
443 PyMODINIT_FUNC
444 PyInit__testmultiphase_negative_size(PyObject *spec)
445 {
446     return PyModuleDef_Init(&def_negative_size);
447 }
448 
449 
450 static PyModuleDef uninitialized_def = TEST_MODULE_DEF("main", main_slots, testexport_methods);
451 
452 PyMODINIT_FUNC
453 PyInit__testmultiphase_export_uninitialized(PyObject *spec)
454 {
455     return (PyObject*) &uninitialized_def;
456 }
457 
458 PyMODINIT_FUNC
459 PyInit__testmultiphase_export_null(PyObject *spec)
460 {
461     return NULL;
462 }
463 
464 PyMODINIT_FUNC
465 PyInit__testmultiphase_export_raise(PyObject *spec)
466 {
467     PyErr_SetString(PyExc_SystemError, "bad export function");
468     return NULL;
469 }
470 
471 PyMODINIT_FUNC
472 PyInit__testmultiphase_export_unreported_exception(PyObject *spec)
473 {
474     PyErr_SetString(PyExc_SystemError, "bad export function");
475     return PyModuleDef_Init(&main_def);
476 }
477 
478 static PyObject*
479 createfunc_null(PyObject *spec, PyModuleDef *def)
480 {
481     return NULL;
482 }
483 
484 PyModuleDef_Slot slots_create_null[] = {
485     {Py_mod_create, createfunc_null},
486     {0, NULL},
487 };
488 
489 static PyModuleDef def_create_null = TEST_MODULE_DEF(
490     "_testmultiphase_create_null", slots_create_null, NULL);
491 
492 PyMODINIT_FUNC
493 PyInit__testmultiphase_create_null(PyObject *spec)
494 {
495     return PyModuleDef_Init(&def_create_null);
496 }
497 
498 static PyObject*
499 createfunc_raise(PyObject *spec, PyModuleDef *def)
500 {
501     PyErr_SetString(PyExc_SystemError, "bad create function");
502     return NULL;
503 }
504 
505 static PyModuleDef_Slot slots_create_raise[] = {
506     {Py_mod_create, createfunc_raise},
507     {0, NULL},
508 };
509 
510 static PyModuleDef def_create_raise = TEST_MODULE_DEF(
511     "_testmultiphase_create_null", slots_create_raise, NULL);
512 
513 PyMODINIT_FUNC
514 PyInit__testmultiphase_create_raise(PyObject *spec)
515 {
516     return PyModuleDef_Init(&def_create_raise);
517 }
518 
519 static PyObject*
520 createfunc_unreported_exception(PyObject *spec, PyModuleDef *def)
521 {
522     PyErr_SetString(PyExc_SystemError, "bad create function");
523     return PyModule_New("foo");
524 }
525 
526 static PyModuleDef_Slot slots_create_unreported_exception[] = {
527     {Py_mod_create, createfunc_unreported_exception},
528     {0, NULL},
529 };
530 
531 static PyModuleDef def_create_unreported_exception = TEST_MODULE_DEF(
532     "_testmultiphase_create_unreported_exception", slots_create_unreported_exception, NULL);
533 
534 PyMODINIT_FUNC
535 PyInit__testmultiphase_create_unreported_exception(PyObject *spec)
536 {
537     return PyModuleDef_Init(&def_create_unreported_exception);
538 }
539 
540 static PyModuleDef_Slot slots_nonmodule_with_exec_slots[] = {
541     {Py_mod_create, createfunc_nonmodule},
542     {Py_mod_exec, execfunc},
543     {0, NULL},
544 };
545 
546 static PyModuleDef def_nonmodule_with_exec_slots = TEST_MODULE_DEF(
547     "_testmultiphase_nonmodule_with_exec_slots", slots_nonmodule_with_exec_slots, NULL);
548 
549 PyMODINIT_FUNC
550 PyInit__testmultiphase_nonmodule_with_exec_slots(PyObject *spec)
551 {
552     return PyModuleDef_Init(&def_nonmodule_with_exec_slots);
553 }
554 
555 static int
556 execfunc_err(PyObject *mod)
557 {
558     return -1;
559 }
560 
561 static PyModuleDef_Slot slots_exec_err[] = {
562     {Py_mod_exec, execfunc_err},
563     {0, NULL},
564 };
565 
566 static PyModuleDef def_exec_err = TEST_MODULE_DEF(
567     "_testmultiphase_exec_err", slots_exec_err, NULL);
568 
569 PyMODINIT_FUNC
570 PyInit__testmultiphase_exec_err(PyObject *spec)
571 {
572     return PyModuleDef_Init(&def_exec_err);
573 }
574 
575 static int
576 execfunc_raise(PyObject *spec)
577 {
578     PyErr_SetString(PyExc_SystemError, "bad exec function");
579     return -1;
580 }
581 
582 static PyModuleDef_Slot slots_exec_raise[] = {
583     {Py_mod_exec, execfunc_raise},
584     {0, NULL},
585 };
586 
587 static PyModuleDef def_exec_raise = TEST_MODULE_DEF(
588     "_testmultiphase_exec_raise", slots_exec_raise, NULL);
589 
590 PyMODINIT_FUNC
591 PyInit__testmultiphase_exec_raise(PyObject *mod)
592 {
593     return PyModuleDef_Init(&def_exec_raise);
594 }
595 
596 static int
597 execfunc_unreported_exception(PyObject *mod)
598 {
599     PyErr_SetString(PyExc_SystemError, "bad exec function");
600     return 0;
601 }
602 
603 static PyModuleDef_Slot slots_exec_unreported_exception[] = {
604     {Py_mod_exec, execfunc_unreported_exception},
605     {0, NULL},
606 };
607 
608 static PyModuleDef def_exec_unreported_exception = TEST_MODULE_DEF(
609     "_testmultiphase_exec_unreported_exception", slots_exec_unreported_exception, NULL);
610 
611 PyMODINIT_FUNC
612 PyInit__testmultiphase_exec_unreported_exception(PyObject *spec)
613 {
614     return PyModuleDef_Init(&def_exec_unreported_exception);
615 }
616 
617 /*** Helper for imp test ***/
618 
619 static PyModuleDef imp_dummy_def = TEST_MODULE_DEF("imp_dummy", main_slots, testexport_methods);
620 
621 PyMODINIT_FUNC
622 PyInit_imp_dummy(PyObject *spec)
623 {
624     return PyModuleDef_Init(&imp_dummy_def);
625 }
626