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
Example_traverse(ExampleObject * self,visitproc visit,void * arg)16 Example_traverse(ExampleObject *self, visitproc visit, void *arg)
17 {
18 Py_VISIT(self->x_attr);
19 return 0;
20 }
21
22 static int
Example_finalize(ExampleObject * self)23 Example_finalize(ExampleObject *self)
24 {
25 Py_CLEAR(self->x_attr);
26 return 0;
27 }
28
29 static PyObject *
Example_demo(ExampleObject * self,PyObject * args)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 *
Example_getattro(ExampleObject * self,PyObject * name)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
Example_setattr(ExampleObject * self,const char * name,PyObject * v)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 *
testexport_foo(PyObject * self,PyObject * args)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 *
call_state_registration_func(PyObject * mod,PyObject * args)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
execfunc(PyObject * m)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
PyInit__testmultiphase(PyObject * spec)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*
createfunc_nonmodule(PyObject * spec,PyModuleDef * def)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
PyInit__testmultiphase_nonmodule(PyObject * spec)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 *
nonmodule_bar(PyObject * self,PyObject * args)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
PyInit__testmultiphase_nonmodule_with_methods(PyObject * spec)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
PyInitU__testmultiphase_zkouka_naten_evc07gi8e(PyObject * spec)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
PyInitU_eckzbwbhc6jpgzcx415x(PyObject * spec)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
PyInit_x(PyObject * spec)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
PyInit__testmultiphase_null_slots(PyObject * spec)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
PyInit__testmultiphase_bad_slot_large(PyObject * spec)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
PyInit__testmultiphase_bad_slot_negative(PyObject * spec)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
PyInit__testmultiphase_create_int_with_state(PyObject * spec)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
PyInit__testmultiphase_negative_size(PyObject * spec)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
PyInit__testmultiphase_export_uninitialized(PyObject * spec)453 PyInit__testmultiphase_export_uninitialized(PyObject *spec)
454 {
455 return (PyObject*) &uninitialized_def;
456 }
457
458 PyMODINIT_FUNC
PyInit__testmultiphase_export_null(PyObject * spec)459 PyInit__testmultiphase_export_null(PyObject *spec)
460 {
461 return NULL;
462 }
463
464 PyMODINIT_FUNC
PyInit__testmultiphase_export_raise(PyObject * spec)465 PyInit__testmultiphase_export_raise(PyObject *spec)
466 {
467 PyErr_SetString(PyExc_SystemError, "bad export function");
468 return NULL;
469 }
470
471 PyMODINIT_FUNC
PyInit__testmultiphase_export_unreported_exception(PyObject * spec)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*
createfunc_null(PyObject * spec,PyModuleDef * def)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
PyInit__testmultiphase_create_null(PyObject * spec)493 PyInit__testmultiphase_create_null(PyObject *spec)
494 {
495 return PyModuleDef_Init(&def_create_null);
496 }
497
498 static PyObject*
createfunc_raise(PyObject * spec,PyModuleDef * def)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
PyInit__testmultiphase_create_raise(PyObject * spec)514 PyInit__testmultiphase_create_raise(PyObject *spec)
515 {
516 return PyModuleDef_Init(&def_create_raise);
517 }
518
519 static PyObject*
createfunc_unreported_exception(PyObject * spec,PyModuleDef * def)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
PyInit__testmultiphase_create_unreported_exception(PyObject * spec)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
PyInit__testmultiphase_nonmodule_with_exec_slots(PyObject * spec)550 PyInit__testmultiphase_nonmodule_with_exec_slots(PyObject *spec)
551 {
552 return PyModuleDef_Init(&def_nonmodule_with_exec_slots);
553 }
554
555 static int
execfunc_err(PyObject * mod)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
PyInit__testmultiphase_exec_err(PyObject * spec)570 PyInit__testmultiphase_exec_err(PyObject *spec)
571 {
572 return PyModuleDef_Init(&def_exec_err);
573 }
574
575 static int
execfunc_raise(PyObject * spec)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
PyInit__testmultiphase_exec_raise(PyObject * mod)591 PyInit__testmultiphase_exec_raise(PyObject *mod)
592 {
593 return PyModuleDef_Init(&def_exec_raise);
594 }
595
596 static int
execfunc_unreported_exception(PyObject * mod)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
PyInit__testmultiphase_exec_unreported_exception(PyObject * spec)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
PyInit_imp_dummy(PyObject * spec)622 PyInit_imp_dummy(PyObject *spec)
623 {
624 return PyModuleDef_Init(&imp_dummy_def);
625 }
626