1
2/* Testing module for multi-phase initialization of extension modules (PEP 489)
3 */
4#ifndef Py_BUILD_CORE_BUILTIN
5#  define Py_BUILD_CORE_MODULE 1
6#endif
7
8#include "Python.h"
9#include "pycore_namespace.h"     // _PyNamespace_New()
10
11/* State for testing module state access from methods */
12
13typedef struct {
14    int counter;
15} meth_state;
16
17/*[clinic input]
18module _testmultiphase
19
20class _testmultiphase.StateAccessType "StateAccessTypeObject *" "!StateAccessType"
21[clinic start generated code]*/
22/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bab9f2fe3bd312ff]*/
23
24/* Example objects */
25typedef struct {
26    PyObject_HEAD
27    PyObject            *x_attr;        /* Attributes dictionary */
28} ExampleObject;
29
30typedef struct {
31    PyObject *integer;
32} testmultiphase_state;
33
34typedef struct {
35    PyObject_HEAD
36} StateAccessTypeObject;
37
38/* Example methods */
39
40static int
41Example_traverse(ExampleObject *self, visitproc visit, void *arg)
42{
43    Py_VISIT(self->x_attr);
44    return 0;
45}
46
47static void
48Example_finalize(ExampleObject *self)
49{
50    Py_CLEAR(self->x_attr);
51}
52
53static PyObject *
54Example_demo(ExampleObject *self, PyObject *args)
55{
56    PyObject *o = NULL;
57    if (!PyArg_ParseTuple(args, "|O:demo", &o))
58        return NULL;
59    if (o != NULL && PyUnicode_Check(o)) {
60        Py_INCREF(o);
61        return o;
62    }
63    Py_RETURN_NONE;
64}
65
66#include "clinic/_testmultiphase.c.h"
67
68static PyMethodDef Example_methods[] = {
69    {"demo",            (PyCFunction)Example_demo,  METH_VARARGS,
70        PyDoc_STR("demo() -> None")},
71    {NULL,              NULL}           /* sentinel */
72};
73
74static PyObject *
75Example_getattro(ExampleObject *self, PyObject *name)
76{
77    if (self->x_attr != NULL) {
78        PyObject *v = PyDict_GetItemWithError(self->x_attr, name);
79        if (v != NULL) {
80            Py_INCREF(v);
81            return v;
82        }
83        else if (PyErr_Occurred()) {
84            return NULL;
85        }
86    }
87    return PyObject_GenericGetAttr((PyObject *)self, name);
88}
89
90static int
91Example_setattr(ExampleObject *self, const char *name, PyObject *v)
92{
93    if (self->x_attr == NULL) {
94        self->x_attr = PyDict_New();
95        if (self->x_attr == NULL)
96            return -1;
97    }
98    if (v == NULL) {
99        int rv = PyDict_DelItemString(self->x_attr, name);
100        if (rv < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
101            PyErr_SetString(PyExc_AttributeError,
102                "delete non-existing Example attribute");
103        return rv;
104    }
105    else
106        return PyDict_SetItemString(self->x_attr, name, v);
107}
108
109static PyType_Slot Example_Type_slots[] = {
110    {Py_tp_doc, "The Example type"},
111    {Py_tp_finalize, Example_finalize},
112    {Py_tp_traverse, Example_traverse},
113    {Py_tp_getattro, Example_getattro},
114    {Py_tp_setattr, Example_setattr},
115    {Py_tp_methods, Example_methods},
116    {0, 0},
117};
118
119static PyType_Spec Example_Type_spec = {
120    "_testimportexec.Example",
121    sizeof(ExampleObject),
122    0,
123    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
124    Example_Type_slots
125};
126
127
128static PyModuleDef def_meth_state_access;
129static PyModuleDef def_nonmodule;
130static PyModuleDef def_nonmodule_with_methods;
131
132/*[clinic input]
133_testmultiphase.StateAccessType.get_defining_module
134
135    cls: defining_class
136
137Return the module of the defining class.
138
139Also tests that result of PyType_GetModuleByDef matches defining_class's
140module.
141[clinic start generated code]*/
142
143static PyObject *
144_testmultiphase_StateAccessType_get_defining_module_impl(StateAccessTypeObject *self,
145                                                         PyTypeObject *cls)
146/*[clinic end generated code: output=ba2a14284a5d0921 input=d2c7245c8a9d06f8]*/
147{
148    PyObject *retval;
149    retval = PyType_GetModule(cls);
150    if (retval == NULL) {
151        return NULL;
152    }
153    assert(PyType_GetModuleByDef(Py_TYPE(self), &def_meth_state_access) == retval);
154    Py_INCREF(retval);
155    return retval;
156}
157
158/*[clinic input]
159_testmultiphase.StateAccessType.getmodulebydef_bad_def
160
161    cls: defining_class
162
163Test that result of PyType_GetModuleByDef with a bad def is NULL.
164[clinic start generated code]*/
165
166static PyObject *
167_testmultiphase_StateAccessType_getmodulebydef_bad_def_impl(StateAccessTypeObject *self,
168                                                            PyTypeObject *cls)
169/*[clinic end generated code: output=64509074dfcdbd31 input=edaff09aa4788204]*/
170{
171    PyType_GetModuleByDef(Py_TYPE(self), &def_nonmodule);  // should raise
172    assert(PyErr_Occurred());
173    return NULL;
174}
175
176/*[clinic input]
177_testmultiphase.StateAccessType.increment_count_clinic
178
179    cls: defining_class
180    /
181    n: int = 1
182    *
183    twice: bool = False
184
185Add 'n' from the module-state counter.
186
187Pass 'twice' to double that amount.
188
189This tests Argument Clinic support for defining_class.
190[clinic start generated code]*/
191
192static PyObject *
193_testmultiphase_StateAccessType_increment_count_clinic_impl(StateAccessTypeObject *self,
194                                                            PyTypeObject *cls,
195                                                            int n, int twice)
196/*[clinic end generated code: output=3b34f86bc5473204 input=551d482e1fe0b8f5]*/
197{
198    meth_state *m_state = PyType_GetModuleState(cls);
199    if (twice) {
200        n *= 2;
201    }
202    m_state->counter += n;
203
204    Py_RETURN_NONE;
205}
206
207PyDoc_STRVAR(_StateAccessType_decrement_count__doc__,
208"decrement_count($self, /, n=1, *, twice=None)\n"
209"--\n"
210"\n"
211"Add 'n' from the module-state counter.\n"
212"Pass 'twice' to double that amount.\n"
213"(This is to test both positional and keyword arguments.");
214
215// Intentionally does not use Argument Clinic
216static PyObject *
217_StateAccessType_increment_count_noclinic(StateAccessTypeObject *self,
218                                          PyTypeObject *defining_class,
219                                          PyObject *const *args,
220                                          Py_ssize_t nargs,
221                                          PyObject *kwnames)
222{
223    if (!_PyArg_CheckPositional("StateAccessTypeObject.decrement_count", nargs, 0, 1)) {
224        return NULL;
225    }
226    long n = 1;
227    if (nargs) {
228        n = PyLong_AsLong(args[0]);
229        if (PyErr_Occurred()) {
230            return NULL;
231        }
232    }
233    if (kwnames && PyTuple_Check(kwnames)) {
234        if (PyTuple_GET_SIZE(kwnames) > 1 ||
235            PyUnicode_CompareWithASCIIString(
236                PyTuple_GET_ITEM(kwnames, 0),
237                "twice"
238            )) {
239            PyErr_SetString(
240                PyExc_TypeError,
241                "decrement_count only takes 'twice' keyword argument"
242            );
243            return NULL;
244        }
245        n *= 2;
246    }
247    meth_state *m_state = PyType_GetModuleState(defining_class);
248    m_state->counter += n;
249
250    Py_RETURN_NONE;
251}
252
253/*[clinic input]
254_testmultiphase.StateAccessType.get_count
255
256    cls: defining_class
257
258Return the value of the module-state counter.
259[clinic start generated code]*/
260
261static PyObject *
262_testmultiphase_StateAccessType_get_count_impl(StateAccessTypeObject *self,
263                                               PyTypeObject *cls)
264/*[clinic end generated code: output=64600f95b499a319 input=d5d181f12384849f]*/
265{
266    meth_state *m_state = PyType_GetModuleState(cls);
267    return PyLong_FromLong(m_state->counter);
268}
269
270static PyMethodDef StateAccessType_methods[] = {
271    _TESTMULTIPHASE_STATEACCESSTYPE_GET_DEFINING_MODULE_METHODDEF
272    _TESTMULTIPHASE_STATEACCESSTYPE_GETMODULEBYDEF_BAD_DEF_METHODDEF
273    _TESTMULTIPHASE_STATEACCESSTYPE_GET_COUNT_METHODDEF
274    _TESTMULTIPHASE_STATEACCESSTYPE_INCREMENT_COUNT_CLINIC_METHODDEF
275    {
276        "increment_count_noclinic",
277        _PyCFunction_CAST(_StateAccessType_increment_count_noclinic),
278        METH_METHOD|METH_FASTCALL|METH_KEYWORDS,
279        _StateAccessType_decrement_count__doc__
280    },
281    {NULL,              NULL}           /* sentinel */
282};
283
284static PyType_Slot StateAccessType_Type_slots[] = {
285    {Py_tp_doc, "Type for testing per-module state access from methods."},
286    {Py_tp_methods, StateAccessType_methods},
287    {0, NULL}
288};
289
290static PyType_Spec StateAccessType_spec = {
291    "_testimportexec.StateAccessType",
292    sizeof(StateAccessTypeObject),
293    0,
294    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE | Py_TPFLAGS_BASETYPE,
295    StateAccessType_Type_slots
296};
297
298/* Function of two integers returning integer */
299
300PyDoc_STRVAR(testexport_foo_doc,
301"foo(i,j)\n\
302\n\
303Return the sum of i and j.");
304
305static PyObject *
306testexport_foo(PyObject *self, PyObject *args)
307{
308    long i, j;
309    long res;
310    if (!PyArg_ParseTuple(args, "ll:foo", &i, &j))
311        return NULL;
312    res = i + j;
313    return PyLong_FromLong(res);
314}
315
316/* Test that PyState registration fails  */
317
318PyDoc_STRVAR(call_state_registration_func_doc,
319"register_state(0): call PyState_FindModule()\n\
320register_state(1): call PyState_AddModule()\n\
321register_state(2): call PyState_RemoveModule()");
322
323static PyObject *
324call_state_registration_func(PyObject *mod, PyObject *args)
325{
326    int i, ret;
327    PyModuleDef *def = PyModule_GetDef(mod);
328    if (def == NULL) {
329        return NULL;
330    }
331    if (!PyArg_ParseTuple(args, "i:call_state_registration_func", &i))
332        return NULL;
333    switch (i) {
334        case 0:
335            mod = PyState_FindModule(def);
336            if (mod == NULL) {
337                Py_RETURN_NONE;
338            }
339            return mod;
340        case 1:
341            ret = PyState_AddModule(mod, def);
342            if (ret != 0) {
343                return NULL;
344            }
345            break;
346        case 2:
347            ret = PyState_RemoveModule(def);
348            if (ret != 0) {
349                return NULL;
350            }
351            break;
352    }
353    Py_RETURN_NONE;
354}
355
356
357static PyType_Slot Str_Type_slots[] = {
358    {Py_tp_base, NULL}, /* filled out in module exec function */
359    {0, 0},
360};
361
362static PyType_Spec Str_Type_spec = {
363    "_testimportexec.Str",
364    0,
365    0,
366    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
367    Str_Type_slots
368};
369
370static PyMethodDef testexport_methods[] = {
371    {"foo",             testexport_foo,         METH_VARARGS,
372        testexport_foo_doc},
373    {"call_state_registration_func",  call_state_registration_func,
374        METH_VARARGS, call_state_registration_func_doc},
375    {NULL,              NULL}           /* sentinel */
376};
377
378static int execfunc(PyObject *m)
379{
380    PyObject *temp = NULL;
381
382    /* Due to cross platform compiler issues the slots must be filled
383     * here. It's required for portability to Windows without requiring
384     * C++. */
385    Str_Type_slots[0].pfunc = &PyUnicode_Type;
386
387    /* Add a custom type */
388    temp = PyType_FromSpec(&Example_Type_spec);
389    if (temp == NULL) {
390        goto fail;
391    }
392    if (PyModule_AddObject(m, "Example", temp) != 0) {
393        Py_DECREF(temp);
394        goto fail;
395    }
396
397
398    /* Add an exception type */
399    temp = PyErr_NewException("_testimportexec.error", NULL, NULL);
400    if (temp == NULL) {
401        goto fail;
402    }
403    if (PyModule_AddObject(m, "error", temp) != 0) {
404        Py_DECREF(temp);
405        goto fail;
406    }
407
408    /* Add Str */
409    temp = PyType_FromSpec(&Str_Type_spec);
410    if (temp == NULL) {
411        goto fail;
412    }
413    if (PyModule_AddObject(m, "Str", temp) != 0) {
414        Py_DECREF(temp);
415        goto fail;
416    }
417
418    if (PyModule_AddIntConstant(m, "int_const", 1969) != 0) {
419        goto fail;
420    }
421
422    if (PyModule_AddStringConstant(m, "str_const", "something different") != 0) {
423        goto fail;
424    }
425
426    return 0;
427 fail:
428    return -1;
429}
430
431/* Helper for module definitions; there'll be a lot of them */
432
433#define TEST_MODULE_DEF(name, slots, methods) { \
434    PyModuleDef_HEAD_INIT,                      /* m_base */ \
435    name,                                       /* m_name */ \
436    PyDoc_STR("Test module " name),             /* m_doc */ \
437    0,                                          /* m_size */ \
438    methods,                                    /* m_methods */ \
439    slots,                                      /* m_slots */ \
440    NULL,                                       /* m_traverse */ \
441    NULL,                                       /* m_clear */ \
442    NULL,                                       /* m_free */ \
443}
444
445static PyModuleDef_Slot main_slots[] = {
446    {Py_mod_exec, execfunc},
447    {0, NULL},
448};
449
450static PyModuleDef main_def = TEST_MODULE_DEF("main", main_slots, testexport_methods);
451
452PyMODINIT_FUNC
453PyInit__testmultiphase(void)
454{
455    return PyModuleDef_Init(&main_def);
456}
457
458
459/**** Importing a non-module object ****/
460
461/* Create a SimpleNamespace(three=3) */
462static PyObject*
463createfunc_nonmodule(PyObject *spec, PyModuleDef *def)
464{
465    PyObject *dct, *ns, *three;
466
467    if (def != &def_nonmodule && def != &def_nonmodule_with_methods) {
468        PyErr_SetString(PyExc_SystemError, "def does not match");
469        return NULL;
470    }
471
472    dct = PyDict_New();
473    if (dct == NULL)
474        return NULL;
475
476    three = PyLong_FromLong(3);
477    if (three == NULL) {
478        Py_DECREF(dct);
479        return NULL;
480    }
481    PyDict_SetItemString(dct, "three", three);
482    Py_DECREF(three);
483
484    ns = _PyNamespace_New(dct);
485    Py_DECREF(dct);
486    return ns;
487}
488
489static PyModuleDef_Slot slots_create_nonmodule[] = {
490    {Py_mod_create, createfunc_nonmodule},
491    {0, NULL},
492};
493
494static PyModuleDef def_nonmodule = TEST_MODULE_DEF(
495    "_testmultiphase_nonmodule", slots_create_nonmodule, NULL);
496
497PyMODINIT_FUNC
498PyInit__testmultiphase_nonmodule(void)
499{
500    return PyModuleDef_Init(&def_nonmodule);
501}
502
503PyDoc_STRVAR(nonmodule_bar_doc,
504"bar(i,j)\n\
505\n\
506Return the difference of i - j.");
507
508static PyObject *
509nonmodule_bar(PyObject *self, PyObject *args)
510{
511    long i, j;
512    long res;
513    if (!PyArg_ParseTuple(args, "ll:bar", &i, &j))
514        return NULL;
515    res = i - j;
516    return PyLong_FromLong(res);
517}
518
519static PyMethodDef nonmodule_methods[] = {
520    {"bar", nonmodule_bar, METH_VARARGS, nonmodule_bar_doc},
521    {NULL, NULL}           /* sentinel */
522};
523
524static PyModuleDef def_nonmodule_with_methods = TEST_MODULE_DEF(
525    "_testmultiphase_nonmodule_with_methods", slots_create_nonmodule, nonmodule_methods);
526
527PyMODINIT_FUNC
528PyInit__testmultiphase_nonmodule_with_methods(void)
529{
530    return PyModuleDef_Init(&def_nonmodule_with_methods);
531}
532
533/**** Non-ASCII-named modules ****/
534
535static PyModuleDef def_nonascii_latin = { \
536    PyModuleDef_HEAD_INIT,                      /* m_base */
537    "_testmultiphase_nonascii_latin",           /* m_name */
538    PyDoc_STR("Module named in Czech"),         /* m_doc */
539    0,                                          /* m_size */
540    NULL,                                       /* m_methods */
541    NULL,                                       /* m_slots */
542    NULL,                                       /* m_traverse */
543    NULL,                                       /* m_clear */
544    NULL,                                       /* m_free */
545};
546
547PyMODINIT_FUNC
548PyInitU__testmultiphase_zkouka_naten_evc07gi8e(void)
549{
550    return PyModuleDef_Init(&def_nonascii_latin);
551}
552
553static PyModuleDef def_nonascii_kana = { \
554    PyModuleDef_HEAD_INIT,                      /* m_base */
555    "_testmultiphase_nonascii_kana",            /* m_name */
556    PyDoc_STR("Module named in Japanese"),      /* m_doc */
557    0,                                          /* m_size */
558    NULL,                                       /* m_methods */
559    NULL,                                       /* m_slots */
560    NULL,                                       /* m_traverse */
561    NULL,                                       /* m_clear */
562    NULL,                                       /* m_free */
563};
564
565PyMODINIT_FUNC
566PyInitU_eckzbwbhc6jpgzcx415x(void)
567{
568    return PyModuleDef_Init(&def_nonascii_kana);
569}
570
571/*** Module with a single-character name ***/
572
573PyMODINIT_FUNC
574PyInit_x(void)
575{
576    return PyModuleDef_Init(&main_def);
577}
578
579/**** Testing NULL slots ****/
580
581static PyModuleDef null_slots_def = TEST_MODULE_DEF(
582    "_testmultiphase_null_slots", NULL, NULL);
583
584PyMODINIT_FUNC
585PyInit__testmultiphase_null_slots(void)
586{
587    return PyModuleDef_Init(&null_slots_def);
588}
589
590/**** Problematic modules ****/
591
592static PyModuleDef_Slot slots_bad_large[] = {
593    {_Py_mod_LAST_SLOT + 1, NULL},
594    {0, NULL},
595};
596
597static PyModuleDef def_bad_large = TEST_MODULE_DEF(
598    "_testmultiphase_bad_slot_large", slots_bad_large, NULL);
599
600PyMODINIT_FUNC
601PyInit__testmultiphase_bad_slot_large(void)
602{
603    return PyModuleDef_Init(&def_bad_large);
604}
605
606static PyModuleDef_Slot slots_bad_negative[] = {
607    {-1, NULL},
608    {0, NULL},
609};
610
611static PyModuleDef def_bad_negative = TEST_MODULE_DEF(
612    "_testmultiphase_bad_slot_negative", slots_bad_negative, NULL);
613
614PyMODINIT_FUNC
615PyInit__testmultiphase_bad_slot_negative(void)
616{
617    return PyModuleDef_Init(&def_bad_negative);
618}
619
620static PyModuleDef def_create_int_with_state = { \
621    PyModuleDef_HEAD_INIT,                      /* m_base */
622    "create_with_state",                        /* m_name */
623    PyDoc_STR("Not a PyModuleObject object, but requests per-module state"),
624    10,                                         /* m_size */
625    NULL,                                       /* m_methods */
626    slots_create_nonmodule,                     /* m_slots */
627    NULL,                                       /* m_traverse */
628    NULL,                                       /* m_clear */
629    NULL,                                       /* m_free */
630};
631
632PyMODINIT_FUNC
633PyInit__testmultiphase_create_int_with_state(void)
634{
635    return PyModuleDef_Init(&def_create_int_with_state);
636}
637
638
639static PyModuleDef def_negative_size = { \
640    PyModuleDef_HEAD_INIT,                      /* m_base */
641    "negative_size",                            /* m_name */
642    PyDoc_STR("PyModuleDef with negative m_size"),
643    -1,                                         /* m_size */
644    NULL,                                       /* m_methods */
645    slots_create_nonmodule,                     /* m_slots */
646    NULL,                                       /* m_traverse */
647    NULL,                                       /* m_clear */
648    NULL,                                       /* m_free */
649};
650
651PyMODINIT_FUNC
652PyInit__testmultiphase_negative_size(void)
653{
654    return PyModuleDef_Init(&def_negative_size);
655}
656
657
658static PyModuleDef uninitialized_def = TEST_MODULE_DEF("main", main_slots, testexport_methods);
659
660PyMODINIT_FUNC
661PyInit__testmultiphase_export_uninitialized(void)
662{
663    return (PyObject*) &uninitialized_def;
664}
665
666PyMODINIT_FUNC
667PyInit__testmultiphase_export_null(void)
668{
669    return NULL;
670}
671
672PyMODINIT_FUNC
673PyInit__testmultiphase_export_raise(void)
674{
675    PyErr_SetString(PyExc_SystemError, "bad export function");
676    return NULL;
677}
678
679PyMODINIT_FUNC
680PyInit__testmultiphase_export_unreported_exception(void)
681{
682    PyErr_SetString(PyExc_SystemError, "bad export function");
683    return PyModuleDef_Init(&main_def);
684}
685
686static PyObject*
687createfunc_null(PyObject *spec, PyModuleDef *def)
688{
689    return NULL;
690}
691
692static PyModuleDef_Slot slots_create_null[] = {
693    {Py_mod_create, createfunc_null},
694    {0, NULL},
695};
696
697static PyModuleDef def_create_null = TEST_MODULE_DEF(
698    "_testmultiphase_create_null", slots_create_null, NULL);
699
700PyMODINIT_FUNC
701PyInit__testmultiphase_create_null(void)
702{
703    return PyModuleDef_Init(&def_create_null);
704}
705
706static PyObject*
707createfunc_raise(PyObject *spec, PyModuleDef *def)
708{
709    PyErr_SetString(PyExc_SystemError, "bad create function");
710    return NULL;
711}
712
713static PyModuleDef_Slot slots_create_raise[] = {
714    {Py_mod_create, createfunc_raise},
715    {0, NULL},
716};
717
718static PyModuleDef def_create_raise = TEST_MODULE_DEF(
719    "_testmultiphase_create_null", slots_create_raise, NULL);
720
721PyMODINIT_FUNC
722PyInit__testmultiphase_create_raise(void)
723{
724    return PyModuleDef_Init(&def_create_raise);
725}
726
727static PyObject*
728createfunc_unreported_exception(PyObject *spec, PyModuleDef *def)
729{
730    PyErr_SetString(PyExc_SystemError, "bad create function");
731    return PyModule_New("foo");
732}
733
734static PyModuleDef_Slot slots_create_unreported_exception[] = {
735    {Py_mod_create, createfunc_unreported_exception},
736    {0, NULL},
737};
738
739static PyModuleDef def_create_unreported_exception = TEST_MODULE_DEF(
740    "_testmultiphase_create_unreported_exception", slots_create_unreported_exception, NULL);
741
742PyMODINIT_FUNC
743PyInit__testmultiphase_create_unreported_exception(void)
744{
745    return PyModuleDef_Init(&def_create_unreported_exception);
746}
747
748static PyModuleDef_Slot slots_nonmodule_with_exec_slots[] = {
749    {Py_mod_create, createfunc_nonmodule},
750    {Py_mod_exec, execfunc},
751    {0, NULL},
752};
753
754static PyModuleDef def_nonmodule_with_exec_slots = TEST_MODULE_DEF(
755    "_testmultiphase_nonmodule_with_exec_slots", slots_nonmodule_with_exec_slots, NULL);
756
757PyMODINIT_FUNC
758PyInit__testmultiphase_nonmodule_with_exec_slots(void)
759{
760    return PyModuleDef_Init(&def_nonmodule_with_exec_slots);
761}
762
763static int
764execfunc_err(PyObject *mod)
765{
766    return -1;
767}
768
769static PyModuleDef_Slot slots_exec_err[] = {
770    {Py_mod_exec, execfunc_err},
771    {0, NULL},
772};
773
774static PyModuleDef def_exec_err = TEST_MODULE_DEF(
775    "_testmultiphase_exec_err", slots_exec_err, NULL);
776
777PyMODINIT_FUNC
778PyInit__testmultiphase_exec_err(void)
779{
780    return PyModuleDef_Init(&def_exec_err);
781}
782
783static int
784execfunc_raise(PyObject *spec)
785{
786    PyErr_SetString(PyExc_SystemError, "bad exec function");
787    return -1;
788}
789
790static PyModuleDef_Slot slots_exec_raise[] = {
791    {Py_mod_exec, execfunc_raise},
792    {0, NULL},
793};
794
795static PyModuleDef def_exec_raise = TEST_MODULE_DEF(
796    "_testmultiphase_exec_raise", slots_exec_raise, NULL);
797
798PyMODINIT_FUNC
799PyInit__testmultiphase_exec_raise(void)
800{
801    return PyModuleDef_Init(&def_exec_raise);
802}
803
804static int
805execfunc_unreported_exception(PyObject *mod)
806{
807    PyErr_SetString(PyExc_SystemError, "bad exec function");
808    return 0;
809}
810
811static PyModuleDef_Slot slots_exec_unreported_exception[] = {
812    {Py_mod_exec, execfunc_unreported_exception},
813    {0, NULL},
814};
815
816static PyModuleDef def_exec_unreported_exception = TEST_MODULE_DEF(
817    "_testmultiphase_exec_unreported_exception", slots_exec_unreported_exception, NULL);
818
819PyMODINIT_FUNC
820PyInit__testmultiphase_exec_unreported_exception(void)
821{
822    return PyModuleDef_Init(&def_exec_unreported_exception);
823}
824
825static int
826meth_state_access_exec(PyObject *m)
827{
828    PyObject *temp;
829    meth_state *m_state;
830
831    m_state = PyModule_GetState(m);
832    if (m_state == NULL) {
833        return -1;
834    }
835
836    temp = PyType_FromModuleAndSpec(m, &StateAccessType_spec, NULL);
837    if (temp == NULL) {
838        return -1;
839    }
840    if (PyModule_AddObject(m, "StateAccessType", temp) != 0) {
841        Py_DECREF(temp);
842        return -1;
843    }
844
845
846    return 0;
847}
848
849static PyModuleDef_Slot meth_state_access_slots[] = {
850    {Py_mod_exec, meth_state_access_exec},
851    {0, NULL}
852};
853
854static PyModuleDef def_meth_state_access = {
855    PyModuleDef_HEAD_INIT,
856    .m_name = "_testmultiphase_meth_state_access",
857    .m_doc = PyDoc_STR("Module testing access"
858                       " to state from methods."),
859    .m_size = sizeof(meth_state),
860    .m_slots = meth_state_access_slots,
861};
862
863PyMODINIT_FUNC
864PyInit__testmultiphase_meth_state_access(void)
865{
866    return PyModuleDef_Init(&def_meth_state_access);
867}
868
869static PyModuleDef def_module_state_shared = {
870    PyModuleDef_HEAD_INIT,
871    .m_name = "_test_module_state_shared",
872    .m_doc = PyDoc_STR("Regression Test module for single-phase init."),
873    .m_size = -1,
874};
875
876PyMODINIT_FUNC
877PyInit__test_module_state_shared(void)
878{
879    PyObject *module = PyModule_Create(&def_module_state_shared);
880    if (module == NULL) {
881        return NULL;
882    }
883
884    if (PyModule_AddObjectRef(module, "Error", PyExc_Exception) < 0) {
885        Py_DECREF(module);
886        return NULL;
887    }
888    return module;
889}
890
891
892/*** Helper for imp test ***/
893
894static PyModuleDef imp_dummy_def = TEST_MODULE_DEF("imp_dummy", main_slots, testexport_methods);
895
896PyMODINIT_FUNC
897PyInit_imp_dummy(void)
898{
899    return PyModuleDef_Init(&imp_dummy_def);
900}
901
902