mirror of
https://github.com/python/cpython.git
synced 2026-05-06 04:37:33 -04:00
508b49845d
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
630 lines
21 KiB
C
630 lines
21 KiB
C
#define Py_LIMITED_API 0x030f0000
|
|
|
|
#include "parts.h"
|
|
|
|
PyABIInfo_VAR(abi_info);
|
|
|
|
/* Define a bunch of (mostly nonsensical) functions to put in slots, so
|
|
* Lib/test/test_capi/test_slots.py can verify they've been assigned to
|
|
* the right slots.
|
|
|
|
* This module is full of "magic constants" which simply need to match
|
|
* between the C and Python part of the tests.
|
|
*/
|
|
|
|
// getbufferproc: export buffer; increment a counter
|
|
static int
|
|
demo_getbuffer(PyObject *exporter, Py_buffer *view, int flags)
|
|
{
|
|
Py_INCREF(exporter);
|
|
// PyObject_GetTypeData & Py_TYPE: safe on non-subclassable type
|
|
int *data = PyObject_GetTypeData(exporter, Py_TYPE(exporter));
|
|
if (!data) {
|
|
return -1;
|
|
}
|
|
(*data)++;
|
|
return PyBuffer_FillInfo(view, exporter, "buf", 4, 1, flags);
|
|
}
|
|
|
|
// releasebufferproc: release buffer; decrement a counter
|
|
static void
|
|
demo_releasebuffer(PyObject *exporter, Py_buffer *view)
|
|
{
|
|
Py_DECREF(exporter);
|
|
// PyObject_GetTypeData & Py_TYPE: safe on non-subclassable type
|
|
int *data = PyObject_GetTypeData(exporter, Py_TYPE(exporter));
|
|
if (!data) {
|
|
PyErr_WriteUnraisable(exporter);
|
|
return;
|
|
}
|
|
(*data)--;
|
|
return;
|
|
}
|
|
|
|
// objobjargproc: raise KeyError
|
|
static int
|
|
demo_ass_subscript(PyObject *o, PyObject *key, PyObject *v)
|
|
{
|
|
PyErr_Format(PyExc_KeyError, "I don't like that key");
|
|
return -1;
|
|
}
|
|
|
|
// lenfunc: report 456
|
|
static Py_ssize_t
|
|
demo_length(PyObject *o)
|
|
{
|
|
return (Py_ssize_t)456;
|
|
}
|
|
|
|
// binaryfunc; return constant value
|
|
static PyObject *binop_123(PyObject* a, PyObject *b) { return PyLong_FromLong(123); }
|
|
static PyObject *binop_234(PyObject* a, PyObject *b) { return PyLong_FromLong(234); }
|
|
static PyObject *binop_345(PyObject* a, PyObject *b) { return PyLong_FromLong(345); }
|
|
static PyObject *binop_456(PyObject* a, PyObject *b) { return PyLong_FromLong(456); }
|
|
static PyObject *binop_567(PyObject* a, PyObject *b) { return PyLong_FromLong(567); }
|
|
static PyObject *binop_678(PyObject* a, PyObject *b) { return PyLong_FromLong(678); }
|
|
|
|
static PyObject *
|
|
type_from_slots(PyObject* module, PyObject *args)
|
|
{
|
|
char *case_name;
|
|
if (!PyArg_ParseTuple(args, "s", &case_name)) {
|
|
return NULL;
|
|
}
|
|
#define CASE(NAME) \
|
|
if (strcmp(case_name, NAME) == 0) { \
|
|
return PyType_FromSlots((PySlot[]) { \
|
|
PySlot_DATA(Py_tp_name, "_testlimitedcapi.MyType"), \
|
|
PySlot_DATA(Py_tp_module, module), \
|
|
/////////////////////////////////////////////////////////////////////////
|
|
#define ENDCASE() \
|
|
PySlot_END \
|
|
}); \
|
|
} \
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
CASE("basic")
|
|
ENDCASE()
|
|
CASE("foreign_slot")
|
|
PySlot_DATA(Py_mod_name, "this is not a module"),
|
|
ENDCASE()
|
|
CASE("basicsize")
|
|
PySlot_SIZE(Py_tp_basicsize, 256),
|
|
ENDCASE()
|
|
CASE("extra_basicsize")
|
|
PySlot_SIZE(Py_tp_extra_basicsize, 256),
|
|
ENDCASE()
|
|
CASE("itemsize")
|
|
PySlot_SIZE(Py_tp_itemsize, 16),
|
|
ENDCASE()
|
|
CASE("flags")
|
|
PySlot_UINT64(Py_tp_flags,
|
|
Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_BASETYPE),
|
|
ENDCASE()
|
|
CASE("matmul_123")
|
|
PySlot_FUNC(Py_nb_matrix_multiply, binop_123),
|
|
ENDCASE()
|
|
CASE("optional_end")
|
|
{.sl_flags=PySlot_OPTIONAL},
|
|
ENDCASE()
|
|
CASE("invalid")
|
|
{.sl_id=Py_slot_invalid},
|
|
ENDCASE()
|
|
CASE("invalid_fbad")
|
|
{.sl_id=0xfbad},
|
|
ENDCASE()
|
|
CASE("optional_invalid")
|
|
{.sl_id=Py_slot_invalid, .sl_flags=PySlot_OPTIONAL},
|
|
PySlot_SIZE(Py_tp_extra_basicsize, 256),
|
|
ENDCASE()
|
|
CASE("optional_invalid_fbad")
|
|
{.sl_id=0xfbad, .sl_flags=PySlot_OPTIONAL},
|
|
PySlot_SIZE(Py_tp_extra_basicsize, 256),
|
|
ENDCASE()
|
|
CASE("old_slot_numbers")
|
|
PySlot_FUNC(1, demo_getbuffer),
|
|
PySlot_FUNC(2, demo_releasebuffer),
|
|
PySlot_FUNC(3, demo_ass_subscript),
|
|
PySlot_FUNC(4, demo_length),
|
|
PySlot_SIZE(Py_tp_extra_basicsize, sizeof(int)),
|
|
PySlot_STATIC_DATA(Py_tp_members, ((PyMemberDef[]) {
|
|
{"buf_counter", Py_T_INT, 0, Py_READONLY | Py_RELATIVE_OFFSET},
|
|
{NULL},
|
|
})),
|
|
ENDCASE()
|
|
CASE("new_slot_numbers")
|
|
PySlot_FUNC(88, demo_getbuffer),
|
|
PySlot_FUNC(89, demo_releasebuffer),
|
|
PySlot_FUNC(90, demo_ass_subscript),
|
|
PySlot_FUNC(91, demo_length),
|
|
PySlot_SIZE(Py_tp_extra_basicsize, sizeof(int)),
|
|
PySlot_STATIC_DATA(Py_tp_members, ((PyMemberDef[]) {
|
|
{"buf_counter", Py_T_INT, 0, Py_READONLY | Py_RELATIVE_OFFSET},
|
|
{NULL},
|
|
})),
|
|
ENDCASE()
|
|
CASE("nonstatic_tp_members")
|
|
PySlot_SIZE(Py_tp_extra_basicsize, sizeof(int)),
|
|
PySlot_DATA(Py_tp_members, ((PyMemberDef[]) {
|
|
{"buf_counter", Py_T_INT, 0, Py_READONLY | Py_RELATIVE_OFFSET},
|
|
{NULL},
|
|
})),
|
|
ENDCASE()
|
|
CASE("intptr_flags_macro")
|
|
PySlot_PTR(Py_tp_flags, (void*)(intptr_t)Py_TPFLAGS_IMMUTABLETYPE),
|
|
ENDCASE()
|
|
CASE("intptr_flags_struct")
|
|
{.sl_id=Py_tp_flags,
|
|
.sl_flags=PySlot_INTPTR,
|
|
.sl_ptr=(void*)(intptr_t)Py_TPFLAGS_IMMUTABLETYPE,
|
|
},
|
|
ENDCASE()
|
|
CASE("intptr_static")
|
|
PySlot_SIZE(Py_tp_extra_basicsize, sizeof(int)),
|
|
PySlot_PTR_STATIC(Py_tp_members, ((PyMemberDef[]) {
|
|
{"attribute", Py_T_INT, 0, Py_READONLY | Py_RELATIVE_OFFSET},
|
|
{NULL},
|
|
})),
|
|
ENDCASE()
|
|
CASE("nested")
|
|
PySlot_FUNC(Py_nb_add, binop_123),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_FUNC(Py_nb_subtract, binop_234),
|
|
PySlot_END,
|
|
})),
|
|
ENDCASE()
|
|
CASE("nested_max")
|
|
PySlot_FUNC(Py_nb_add, binop_123),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_FUNC(Py_nb_subtract, binop_234),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_FUNC(Py_nb_multiply, binop_345),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_FUNC(Py_nb_true_divide, binop_456),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_FUNC(Py_nb_remainder, binop_567),
|
|
PySlot_END
|
|
})),
|
|
PySlot_END,
|
|
})),
|
|
PySlot_END,
|
|
})),
|
|
PySlot_END,
|
|
})),
|
|
ENDCASE()
|
|
CASE("nested_over_limit")
|
|
PySlot_FUNC(Py_nb_add, binop_123),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_FUNC(Py_nb_subtract, binop_234),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_FUNC(Py_nb_multiply, binop_345),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_FUNC(Py_nb_true_divide, binop_456),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_FUNC(Py_nb_remainder, binop_567),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_FUNC(Py_nb_xor, binop_678),
|
|
PySlot_END
|
|
})),
|
|
PySlot_END
|
|
})),
|
|
PySlot_END,
|
|
})),
|
|
PySlot_END,
|
|
})),
|
|
PySlot_END,
|
|
})),
|
|
ENDCASE()
|
|
CASE("nested_old")
|
|
PySlot_FUNC(Py_nb_add, binop_123),
|
|
PySlot_DATA(Py_tp_slots, ((PyType_Slot[]) {
|
|
{Py_nb_subtract, binop_234},
|
|
{0},
|
|
})),
|
|
ENDCASE()
|
|
CASE("nested_old_max")
|
|
PySlot_FUNC(Py_nb_add, binop_123),
|
|
PySlot_DATA(Py_tp_slots, ((PyType_Slot[]) {
|
|
{Py_nb_subtract, binop_234},
|
|
{Py_tp_slots, ((PyType_Slot[]) {
|
|
{Py_nb_multiply, binop_345},
|
|
{Py_tp_slots, ((PyType_Slot[]) {
|
|
{Py_nb_true_divide, binop_456},
|
|
{Py_tp_slots, ((PyType_Slot[]) {
|
|
{Py_nb_remainder, binop_567},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})),
|
|
ENDCASE()
|
|
CASE("nested_old_over_limit")
|
|
PySlot_FUNC(Py_nb_add, binop_123),
|
|
PySlot_DATA(Py_tp_slots, ((PyType_Slot[]) {
|
|
{Py_nb_subtract, binop_234},
|
|
{Py_tp_slots, ((PyType_Slot[]) {
|
|
{Py_nb_multiply, binop_345},
|
|
{Py_tp_slots, ((PyType_Slot[]) {
|
|
{Py_nb_true_divide, binop_456},
|
|
{Py_tp_slots, ((PyType_Slot[]) {
|
|
{Py_nb_remainder, binop_567},
|
|
{Py_tp_slots, ((PyType_Slot[]) {
|
|
{Py_nb_xor, binop_678},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})),
|
|
ENDCASE()
|
|
CASE("nested_pingpong")
|
|
PySlot_FUNC(Py_nb_add, binop_123),
|
|
PySlot_DATA(Py_tp_slots, ((PyType_Slot[]) {
|
|
{Py_nb_subtract, binop_234},
|
|
{Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_FUNC(Py_nb_multiply, binop_345),
|
|
PySlot_DATA(Py_tp_slots, ((PyType_Slot[]) {
|
|
{Py_nb_true_divide, binop_456},
|
|
{Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_FUNC(Py_nb_remainder, binop_567),
|
|
PySlot_END
|
|
})},
|
|
{0},
|
|
})),
|
|
PySlot_END,
|
|
})},
|
|
{0},
|
|
})),
|
|
ENDCASE()
|
|
CASE("repeat_add")
|
|
PySlot_FUNC(Py_nb_add, binop_123),
|
|
PySlot_FUNC(Py_nb_add, binop_456),
|
|
ENDCASE()
|
|
CASE("repeat_module")
|
|
PySlot_DATA(Py_tp_module, Py_True),
|
|
PySlot_DATA(Py_tp_module, Py_False),
|
|
ENDCASE()
|
|
|
|
#undef CASE
|
|
#undef ENDCASE
|
|
PyErr_Format(PyExc_SystemError, "bad case: %s", case_name);
|
|
return NULL;
|
|
}
|
|
|
|
static PyObject *
|
|
type_from_null_slot(PyObject* module, PyObject *args)
|
|
{
|
|
long slot_number;
|
|
if (!PyArg_ParseTuple(args, "l", &slot_number)) {
|
|
return NULL;
|
|
}
|
|
return PyType_FromSlots((PySlot[]) {
|
|
PySlot_DATA(Py_tp_name, "_testlimitedcapi.MyType"),
|
|
PySlot_DATA(Py_tp_module, module),
|
|
PySlot_PTR_STATIC((uint16_t)slot_number, NULL),
|
|
PySlot_END
|
|
});
|
|
}
|
|
|
|
static PyObject *
|
|
type_from_null_spec_slot(PyObject* Py_UNUSED(module), PyObject *args)
|
|
{
|
|
long slot_number;
|
|
if (!PyArg_ParseTuple(args, "l", &slot_number)) {
|
|
return NULL;
|
|
}
|
|
return PyType_FromSpec(&(PyType_Spec) {
|
|
.name = "_testlimitedcapi.MyType",
|
|
.slots = (PyType_Slot[]) {
|
|
{slot_number, NULL},
|
|
{0},
|
|
},
|
|
});
|
|
}
|
|
|
|
static PyObject *
|
|
demo_create(PyObject *spec, PyModuleDef *def)
|
|
{
|
|
assert(def == NULL);
|
|
return Py_NewRef(spec);
|
|
}
|
|
|
|
static int
|
|
demo_exec(PyObject *mod)
|
|
{
|
|
return PyModule_AddStringConstant(mod, "exec_done", "yes");
|
|
}
|
|
|
|
static PyMethodDef *TestMethods;
|
|
|
|
static PyObject *
|
|
module_from_slots(PyObject* Py_UNUSED(module), PyObject *args)
|
|
{
|
|
PyObject *spec;
|
|
char *case_name;
|
|
if (!PyArg_ParseTuple(args, "sO", &case_name, &spec)) {
|
|
return NULL;
|
|
}
|
|
PyObject *mod = NULL;
|
|
#define CASE(NAME) \
|
|
if (strcmp(case_name, NAME) == 0) { \
|
|
mod = PyModule_FromSlotsAndSpec((PySlot[]) { \
|
|
PySlot_DATA(Py_mod_abi, &abi_info), \
|
|
PySlot_DATA(Py_mod_gil, Py_MOD_GIL_NOT_USED), \
|
|
/////////////////////////////////////////////////////////////////////////
|
|
#define ENDCASE() \
|
|
PySlot_END \
|
|
}, spec); \
|
|
} \
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
CASE("basic")
|
|
ENDCASE()
|
|
CASE("foreign_slot")
|
|
PySlot_DATA(Py_tp_name, "this is not a type"),
|
|
ENDCASE()
|
|
CASE("state_size")
|
|
PySlot_SIZE(Py_mod_state_size, 42),
|
|
ENDCASE()
|
|
CASE("multi_interp")
|
|
PySlot_DATA(Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED),
|
|
ENDCASE()
|
|
CASE("exec")
|
|
PySlot_FUNC(Py_mod_exec, demo_exec),
|
|
ENDCASE()
|
|
CASE("optional_end")
|
|
{.sl_flags=PySlot_OPTIONAL},
|
|
ENDCASE()
|
|
CASE("invalid")
|
|
{.sl_id=Py_slot_invalid},
|
|
ENDCASE()
|
|
CASE("invalid_fbad")
|
|
{.sl_id=0xfbad},
|
|
ENDCASE()
|
|
CASE("optional_invalid")
|
|
{.sl_id=Py_slot_invalid, .sl_flags=PySlot_OPTIONAL},
|
|
PySlot_SIZE(Py_mod_exec, demo_exec),
|
|
ENDCASE()
|
|
CASE("optional_invalid_fbad")
|
|
{.sl_id=0xfbad, .sl_flags=PySlot_OPTIONAL},
|
|
PySlot_SIZE(Py_mod_exec, demo_exec),
|
|
ENDCASE()
|
|
CASE("old_slot_numbers")
|
|
// 1: see old_slot_number_create case
|
|
PySlot_FUNC(2, demo_exec),
|
|
PySlot_DATA(3, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED),
|
|
// 4: see module_from_gil_slot function
|
|
ENDCASE()
|
|
CASE("new_slot_numbers")
|
|
// 84: see new_slot_number_create case
|
|
PySlot_FUNC(85, demo_exec),
|
|
PySlot_FUNC(86, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED),
|
|
// 87: see module_from_gil_slot function
|
|
ENDCASE()
|
|
CASE("old_slot_number_create")
|
|
PySlot_FUNC(1, demo_create),
|
|
ENDCASE()
|
|
CASE("new_slot_number_create")
|
|
PySlot_FUNC(84, demo_create),
|
|
ENDCASE()
|
|
CASE("nonstatic_mod_methods")
|
|
PySlot_DATA(Py_mod_methods, TestMethods),
|
|
ENDCASE()
|
|
CASE("intptr_methods")
|
|
PySlot_PTR_STATIC(Py_mod_methods, TestMethods),
|
|
ENDCASE()
|
|
CASE("nested")
|
|
PySlot_FUNC(Py_mod_exec, demo_exec),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_DATA(Py_mod_doc, "doc"),
|
|
PySlot_END,
|
|
})),
|
|
ENDCASE()
|
|
CASE("nested_max")
|
|
PySlot_FUNC(Py_mod_exec, demo_exec),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_SIZE(Py_mod_state_size, 53),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_DATA(Py_mod_doc, "doc"),
|
|
PySlot_END
|
|
})),
|
|
PySlot_END,
|
|
})),
|
|
PySlot_END,
|
|
})),
|
|
PySlot_END,
|
|
})),
|
|
ENDCASE()
|
|
CASE("nested_over_limit")
|
|
PySlot_FUNC(Py_mod_exec, demo_exec),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_SIZE(Py_mod_state_size, 53),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_DATA(Py_mod_doc, "doc"),
|
|
PySlot_DATA(Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_END
|
|
})),
|
|
PySlot_END
|
|
})),
|
|
PySlot_END,
|
|
})),
|
|
PySlot_END,
|
|
})),
|
|
PySlot_END,
|
|
})),
|
|
ENDCASE()
|
|
CASE("nested_old")
|
|
PySlot_FUNC(Py_mod_exec, demo_exec),
|
|
PySlot_DATA(Py_mod_slots, ((PyModuleDef_Slot[]) {
|
|
{Py_mod_doc, "doc"},
|
|
{0},
|
|
})),
|
|
ENDCASE()
|
|
CASE("nested_old_max")
|
|
PySlot_FUNC(Py_mod_exec, demo_exec),
|
|
PySlot_DATA(Py_mod_slots, ((PyModuleDef_Slot[]) {
|
|
{Py_mod_slots, ((PyModuleDef_Slot[]) {
|
|
{Py_mod_state_size, (void*)(intptr_t)53},
|
|
{Py_mod_slots, ((PyModuleDef_Slot[]) {
|
|
{Py_mod_slots, ((PyModuleDef_Slot[]) {
|
|
{Py_mod_doc, "doc"},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})),
|
|
ENDCASE()
|
|
CASE("nested_old_over_limit")
|
|
PySlot_FUNC(Py_mod_exec, demo_exec),
|
|
PySlot_DATA(Py_mod_slots, ((PyModuleDef_Slot[]) {
|
|
{Py_mod_slots, ((PyModuleDef_Slot[]) {
|
|
{Py_mod_state_size, (void*)(intptr_t)53},
|
|
{Py_mod_slots, ((PyModuleDef_Slot[]) {
|
|
{Py_mod_slots, ((PyModuleDef_Slot[]) {
|
|
{Py_mod_slots, ((PyModuleDef_Slot[]) {
|
|
{Py_mod_doc, "doc"},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})},
|
|
{0},
|
|
})),
|
|
ENDCASE()
|
|
CASE("nested_pingpong")
|
|
PySlot_FUNC(Py_mod_exec, demo_exec),
|
|
PySlot_DATA(Py_mod_slots, ((PyModuleDef_Slot[]) {
|
|
{Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_DATA(Py_mod_slots, ((PyModuleDef_Slot[]) {
|
|
{Py_mod_state_size, (void*)(intptr_t)53},
|
|
{Py_slot_subslots, ((PySlot[]) {
|
|
PySlot_DATA(Py_mod_doc, "doc"),
|
|
PySlot_END
|
|
})},
|
|
{0},
|
|
})),
|
|
PySlot_END,
|
|
})},
|
|
{0},
|
|
})),
|
|
ENDCASE()
|
|
CASE("repeat_create")
|
|
PySlot_DATA(Py_mod_create, demo_create),
|
|
PySlot_DATA(Py_mod_create, demo_create),
|
|
PySlot_DATA(Py_mod_create, demo_create),
|
|
ENDCASE()
|
|
CASE("repeat_gil")
|
|
PySlot_DATA(Py_mod_gil, Py_MOD_GIL_NOT_USED),
|
|
PySlot_DATA(Py_mod_gil, Py_MOD_GIL_NOT_USED),
|
|
PySlot_DATA(Py_mod_gil, Py_MOD_GIL_NOT_USED),
|
|
ENDCASE()
|
|
CASE("repeat_exec")
|
|
PySlot_FUNC(Py_mod_exec, demo_exec),
|
|
PySlot_FUNC(Py_mod_exec, demo_exec),
|
|
ENDCASE()
|
|
|
|
#undef CASE
|
|
#undef ENDCASE
|
|
if (!mod) {
|
|
if (!PyErr_Occurred()) {
|
|
PyErr_Format(PyExc_SystemError, "bad case: %s", case_name);
|
|
return NULL;
|
|
}
|
|
return NULL;
|
|
}
|
|
if (PyModule_Check(mod)) {
|
|
Py_ssize_t size;
|
|
if (PyModule_GetStateSize(mod, &size) < 0) {
|
|
Py_DECREF(mod);
|
|
return NULL;
|
|
}
|
|
if (PyModule_AddIntConstant(mod, "state_size", (long)size) < 0) {
|
|
Py_DECREF(mod);
|
|
return NULL;
|
|
}
|
|
if (PyModule_Exec(mod) < 0) {
|
|
return NULL;
|
|
}
|
|
}
|
|
return mod;
|
|
}
|
|
|
|
static PyObject *
|
|
module_from_gil_slot(PyObject* Py_UNUSED(module), PyObject *args)
|
|
{
|
|
long slot_number;
|
|
PyObject *spec;
|
|
if (!PyArg_ParseTuple(args, "lO", &slot_number, &spec)) {
|
|
return NULL;
|
|
}
|
|
return PyModule_FromSlotsAndSpec((PySlot[]) {
|
|
PySlot_DATA(Py_mod_abi, &abi_info),
|
|
PySlot_PTR_STATIC((uint16_t)slot_number, Py_MOD_GIL_NOT_USED),
|
|
PySlot_END
|
|
}, spec);
|
|
}
|
|
|
|
static PyObject *
|
|
module_from_null_slot(PyObject* Py_UNUSED(module), PyObject *args)
|
|
{
|
|
long slot_number;
|
|
PyObject *spec;
|
|
if (!PyArg_ParseTuple(args, "lO", &slot_number, &spec)) {
|
|
return NULL;
|
|
}
|
|
uint16_t maybe_gil_slot = Py_mod_gil;
|
|
if ((slot_number == 4) || (slot_number == 87)) {
|
|
// Do not repeat the GIL slot
|
|
maybe_gil_slot = Py_slot_invalid;
|
|
}
|
|
return PyModule_FromSlotsAndSpec((PySlot[]) {
|
|
PySlot_DATA(Py_mod_abi, &abi_info),
|
|
PySlot_DATA(Py_mod_name, "mymod"),
|
|
PySlot_PTR_STATIC((uint16_t)slot_number, NULL),
|
|
{
|
|
.sl_id=maybe_gil_slot,
|
|
.sl_flags=PySlot_OPTIONAL,
|
|
.sl_ptr=Py_MOD_GIL_NOT_USED,
|
|
},
|
|
PySlot_END
|
|
}, spec);
|
|
}
|
|
|
|
static PyMethodDef _TestMethods[] = {
|
|
{"type_from_slots", type_from_slots, METH_VARARGS},
|
|
{"module_from_gil_slot", module_from_gil_slot, METH_VARARGS},
|
|
{"type_from_null_slot", type_from_null_slot, METH_VARARGS},
|
|
{"type_from_null_spec_slot", type_from_null_spec_slot, METH_VARARGS},
|
|
{"module_from_slots", module_from_slots, METH_VARARGS},
|
|
{"module_from_null_slot", module_from_null_slot, METH_VARARGS},
|
|
{NULL},
|
|
};
|
|
static PyMethodDef *TestMethods = _TestMethods;
|
|
|
|
int
|
|
_PyTestLimitedCAPI_Init_Slots(PyObject *m)
|
|
{
|
|
if (PyModule_AddFunctions(m, TestMethods) < 0) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|