1 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 15static int 16Example_traverse(ExampleObject *self, visitproc visit, void *arg) 17{ 18 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; 27} 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 } 39 Py_INCREF(Py_None); 40 return Py_None; 41} 42 43 44static PyMethodDef Example_methods[] = { 45 {"demo", (PyCFunction)Example_demo, METH_VARARGS, 46 PyDoc_STR("demo() -> None")}, 47 {NULL, NULL} /* sentinel */ 48}; 49 50static PyObject * 51Example_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 63static int 64Example_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 82static 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 92static 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 102PyDoc_STRVAR(testexport_foo_doc, 103"foo(i,j)\n\ 104\n\ 105Return the sum of i and j."); 106 107static PyObject * 108testexport_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 120PyDoc_STRVAR(call_state_registration_func_doc, 121"register_state(0): call PyState_FindModule()\n\ 122register_state(1): call PyState_AddModule()\n\ 123register_state(2): call PyState_RemoveModule()"); 124 125static PyObject * 126call_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 159static PyType_Slot Str_Type_slots[] = { 160 {Py_tp_base, NULL}, /* filled out in module exec function */ 161 {0, 0}, 162}; 163 164static 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 172static 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 180static 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 234PyModuleDef_Slot main_slots[] = { 235 {Py_mod_exec, execfunc}, 236 {0, NULL}, 237}; 238 239static PyModuleDef main_def = TEST_MODULE_DEF("main", main_slots, testexport_methods); 240 241PyMODINIT_FUNC 242PyInit__testmultiphase(PyObject *spec) 243{ 244 return PyModuleDef_Init(&main_def); 245} 246 247 248/**** Importing a non-module object ****/ 249 250static PyModuleDef def_nonmodule; 251static PyModuleDef def_nonmodule_with_methods; 252 253/* Create a SimpleNamespace(three=3) */ 254static PyObject* 255createfunc_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 281static PyModuleDef_Slot slots_create_nonmodule[] = { 282 {Py_mod_create, createfunc_nonmodule}, 283 {0, NULL}, 284}; 285 286static PyModuleDef def_nonmodule = TEST_MODULE_DEF( 287 "_testmultiphase_nonmodule", slots_create_nonmodule, NULL); 288 289PyMODINIT_FUNC 290PyInit__testmultiphase_nonmodule(PyObject *spec) 291{ 292 return PyModuleDef_Init(&def_nonmodule); 293} 294 295PyDoc_STRVAR(nonmodule_bar_doc, 296"bar(i,j)\n\ 297\n\ 298Return the difference of i - j."); 299 300static PyObject * 301nonmodule_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 311static PyMethodDef nonmodule_methods[] = { 312 {"bar", nonmodule_bar, METH_VARARGS, nonmodule_bar_doc}, 313 {NULL, NULL} /* sentinel */ 314}; 315 316static PyModuleDef def_nonmodule_with_methods = TEST_MODULE_DEF( 317 "_testmultiphase_nonmodule_with_methods", slots_create_nonmodule, nonmodule_methods); 318 319PyMODINIT_FUNC 320PyInit__testmultiphase_nonmodule_with_methods(PyObject *spec) 321{ 322 return PyModuleDef_Init(&def_nonmodule_with_methods); 323} 324 325/**** Non-ASCII-named modules ****/ 326 327static 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 339PyMODINIT_FUNC 340PyInitU__testmultiphase_zkouka_naten_evc07gi8e(PyObject *spec) 341{ 342 return PyModuleDef_Init(&def_nonascii_latin); 343} 344 345static 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 357PyMODINIT_FUNC 358PyInitU_eckzbwbhc6jpgzcx415x(PyObject *spec) 359{ 360 return PyModuleDef_Init(&def_nonascii_kana); 361} 362 363/*** Module with a single-character name ***/ 364 365PyMODINIT_FUNC 366PyInit_x(PyObject *spec) 367{ 368 return PyModuleDef_Init(&main_def); 369} 370 371/**** Testing NULL slots ****/ 372 373static PyModuleDef null_slots_def = TEST_MODULE_DEF( 374 "_testmultiphase_null_slots", NULL, NULL); 375 376PyMODINIT_FUNC 377PyInit__testmultiphase_null_slots(PyObject *spec) 378{ 379 return PyModuleDef_Init(&null_slots_def); 380} 381 382/**** Problematic modules ****/ 383 384static PyModuleDef_Slot slots_bad_large[] = { 385 {_Py_mod_LAST_SLOT + 1, NULL}, 386 {0, NULL}, 387}; 388 389static PyModuleDef def_bad_large = TEST_MODULE_DEF( 390 "_testmultiphase_bad_slot_large", slots_bad_large, NULL); 391 392PyMODINIT_FUNC 393PyInit__testmultiphase_bad_slot_large(PyObject *spec) 394{ 395 return PyModuleDef_Init(&def_bad_large); 396} 397 398static PyModuleDef_Slot slots_bad_negative[] = { 399 {-1, NULL}, 400 {0, NULL}, 401}; 402 403static PyModuleDef def_bad_negative = TEST_MODULE_DEF( 404 "_testmultiphase_bad_slot_negative", slots_bad_negative, NULL); 405 406PyMODINIT_FUNC 407PyInit__testmultiphase_bad_slot_negative(PyObject *spec) 408{ 409 return PyModuleDef_Init(&def_bad_negative); 410} 411 412static 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 424PyMODINIT_FUNC 425PyInit__testmultiphase_create_int_with_state(PyObject *spec) 426{ 427 return PyModuleDef_Init(&def_create_int_with_state); 428} 429 430 431static 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 443PyMODINIT_FUNC 444PyInit__testmultiphase_negative_size(PyObject *spec) 445{ 446 return PyModuleDef_Init(&def_negative_size); 447} 448 449 450static PyModuleDef uninitialized_def = TEST_MODULE_DEF("main", main_slots, testexport_methods); 451 452PyMODINIT_FUNC 453PyInit__testmultiphase_export_uninitialized(PyObject *spec) 454{ 455 return (PyObject*) &uninitialized_def; 456} 457 458PyMODINIT_FUNC 459PyInit__testmultiphase_export_null(PyObject *spec) 460{ 461 return NULL; 462} 463 464PyMODINIT_FUNC 465PyInit__testmultiphase_export_raise(PyObject *spec) 466{ 467 PyErr_SetString(PyExc_SystemError, "bad export function"); 468 return NULL; 469} 470 471PyMODINIT_FUNC 472PyInit__testmultiphase_export_unreported_exception(PyObject *spec) 473{ 474 PyErr_SetString(PyExc_SystemError, "bad export function"); 475 return PyModuleDef_Init(&main_def); 476} 477 478static PyObject* 479createfunc_null(PyObject *spec, PyModuleDef *def) 480{ 481 return NULL; 482} 483 484PyModuleDef_Slot slots_create_null[] = { 485 {Py_mod_create, createfunc_null}, 486 {0, NULL}, 487}; 488 489static PyModuleDef def_create_null = TEST_MODULE_DEF( 490 "_testmultiphase_create_null", slots_create_null, NULL); 491 492PyMODINIT_FUNC 493PyInit__testmultiphase_create_null(PyObject *spec) 494{ 495 return PyModuleDef_Init(&def_create_null); 496} 497 498static PyObject* 499createfunc_raise(PyObject *spec, PyModuleDef *def) 500{ 501 PyErr_SetString(PyExc_SystemError, "bad create function"); 502 return NULL; 503} 504 505static PyModuleDef_Slot slots_create_raise[] = { 506 {Py_mod_create, createfunc_raise}, 507 {0, NULL}, 508}; 509 510static PyModuleDef def_create_raise = TEST_MODULE_DEF( 511 "_testmultiphase_create_null", slots_create_raise, NULL); 512 513PyMODINIT_FUNC 514PyInit__testmultiphase_create_raise(PyObject *spec) 515{ 516 return PyModuleDef_Init(&def_create_raise); 517} 518 519static PyObject* 520createfunc_unreported_exception(PyObject *spec, PyModuleDef *def) 521{ 522 PyErr_SetString(PyExc_SystemError, "bad create function"); 523 return PyModule_New("foo"); 524} 525 526static PyModuleDef_Slot slots_create_unreported_exception[] = { 527 {Py_mod_create, createfunc_unreported_exception}, 528 {0, NULL}, 529}; 530 531static PyModuleDef def_create_unreported_exception = TEST_MODULE_DEF( 532 "_testmultiphase_create_unreported_exception", slots_create_unreported_exception, NULL); 533 534PyMODINIT_FUNC 535PyInit__testmultiphase_create_unreported_exception(PyObject *spec) 536{ 537 return PyModuleDef_Init(&def_create_unreported_exception); 538} 539 540static PyModuleDef_Slot slots_nonmodule_with_exec_slots[] = { 541 {Py_mod_create, createfunc_nonmodule}, 542 {Py_mod_exec, execfunc}, 543 {0, NULL}, 544}; 545 546static PyModuleDef def_nonmodule_with_exec_slots = TEST_MODULE_DEF( 547 "_testmultiphase_nonmodule_with_exec_slots", slots_nonmodule_with_exec_slots, NULL); 548 549PyMODINIT_FUNC 550PyInit__testmultiphase_nonmodule_with_exec_slots(PyObject *spec) 551{ 552 return PyModuleDef_Init(&def_nonmodule_with_exec_slots); 553} 554 555static int 556execfunc_err(PyObject *mod) 557{ 558 return -1; 559} 560 561static PyModuleDef_Slot slots_exec_err[] = { 562 {Py_mod_exec, execfunc_err}, 563 {0, NULL}, 564}; 565 566static PyModuleDef def_exec_err = TEST_MODULE_DEF( 567 "_testmultiphase_exec_err", slots_exec_err, NULL); 568 569PyMODINIT_FUNC 570PyInit__testmultiphase_exec_err(PyObject *spec) 571{ 572 return PyModuleDef_Init(&def_exec_err); 573} 574 575static int 576execfunc_raise(PyObject *spec) 577{ 578 PyErr_SetString(PyExc_SystemError, "bad exec function"); 579 return -1; 580} 581 582static PyModuleDef_Slot slots_exec_raise[] = { 583 {Py_mod_exec, execfunc_raise}, 584 {0, NULL}, 585}; 586 587static PyModuleDef def_exec_raise = TEST_MODULE_DEF( 588 "_testmultiphase_exec_raise", slots_exec_raise, NULL); 589 590PyMODINIT_FUNC 591PyInit__testmultiphase_exec_raise(PyObject *mod) 592{ 593 return PyModuleDef_Init(&def_exec_raise); 594} 595 596static int 597execfunc_unreported_exception(PyObject *mod) 598{ 599 PyErr_SetString(PyExc_SystemError, "bad exec function"); 600 return 0; 601} 602 603static PyModuleDef_Slot slots_exec_unreported_exception[] = { 604 {Py_mod_exec, execfunc_unreported_exception}, 605 {0, NULL}, 606}; 607 608static PyModuleDef def_exec_unreported_exception = TEST_MODULE_DEF( 609 "_testmultiphase_exec_unreported_exception", slots_exec_unreported_exception, NULL); 610 611PyMODINIT_FUNC 612PyInit__testmultiphase_exec_unreported_exception(PyObject *spec) 613{ 614 return PyModuleDef_Init(&def_exec_unreported_exception); 615} 616 617/*** Helper for imp test ***/ 618 619static PyModuleDef imp_dummy_def = TEST_MODULE_DEF("imp_dummy", main_slots, testexport_methods); 620 621PyMODINIT_FUNC 622PyInit_imp_dummy(PyObject *spec) 623{ 624 return PyModuleDef_Init(&imp_dummy_def); 625} 626