diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3064,6 +3064,106 @@ #endif /* WITH_THREAD */ +/* StructSequence */ +static PyStructSequence_Field struct_unnamed_end_fields[] = { + {"a", "letter"}, + {"b", "letter"}, + {"c", "letter"}, + {NULL, NULL}, + {NULL, NULL}, + {0} +}; + +static PyStructSequence_Field struct_unnamed_middle_fields[] = { + {"a", "letter"}, + {NULL, NULL}, + {NULL, NULL}, + {"b", "letter"}, + {"c", "letter"}, + {0} +}; + +static PyStructSequence_Field struct_unnamed_alternating_fields[] = { + {"a", "letter"}, + {NULL, NULL}, + {"b", "letter"}, + {NULL, NULL}, + {"c", "letter"}, + {0} +}; + +#define STRUCTSEQ_LEN 5 + +static PyStructSequence_Desc struct_unnamed_end_desc = { + "_testcapi.struct_unnamed_end", + "structseq with an unnamed block at the end", + struct_unnamed_end_fields, + STRUCTSEQ_LEN, +}; + +static PyStructSequence_Desc struct_unnamed_middle_desc = { + "_testcapi.struct_unnamed_middle", + "structseq with an unnamed block in the middle", + struct_unnamed_middle_fields, + STRUCTSEQ_LEN, +}; + +static PyStructSequence_Desc struct_unnamed_alternating_desc = { + "_testcapi.struct_unnamed_alternating", + "structseq with alternating named/unnamed fields", + struct_unnamed_alternating_fields, + STRUCTSEQ_LEN, +}; + +static int structseq_initialized = 0; +static PyTypeObject StructUnnamedEndType; +static PyTypeObject StructUnnamedMiddleType; +static PyTypeObject StructUnnamedAlternatingType; + +#define SET(i,val) PyStructSequence_SET_ITEM(v, i, PyLong_FromLong((long) val)) +static PyObject * +mk_structseq(PyObject *self, PyObject *args) +{ + PyObject *v; + char *s; + + if (!PyArg_ParseTuple(args, "s", &s)) { + return NULL; + } + + if (strcmp(s, "unnamed_end") == 0) { + v = PyStructSequence_New(&StructUnnamedEndType); + } + else if (strcmp(s, "unnamed_middle") == 0) { + v = PyStructSequence_New(&StructUnnamedMiddleType); + } + else if (strcmp(s, "unnamed_alternating") == 0) { + v = PyStructSequence_New(&StructUnnamedAlternatingType); + } + else { + PyErr_SetString(PyExc_ValueError, + "mk_structseq: invalid structseq type"); + return NULL; + } + + if (v == NULL) + return NULL; + + SET(0, 0); + SET(1, 1); + SET(2, 2); + SET(3, 3); + SET(4, 4); + + if (PyErr_Occurred()) { + Py_XDECREF(v); + return NULL; + } + + return v; +} + + static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, {"raise_memoryerror", (PyCFunction)raise_memoryerror, METH_NOARGS}, @@ -3198,6 +3298,7 @@ {"docstring_with_signature_with_defaults", (PyCFunction)test_with_docstring, METH_NOARGS, docstring_with_signature_with_defaults}, + {"mk_structseq", mk_structseq, METH_VARARGS, "make a struct sequence"}, #ifdef WITH_THREAD {"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_O, PyDoc_STR("set_error_class(error_class) -> None")}, @@ -3481,11 +3582,38 @@ PyInit__testcapi(void) { PyObject *m; + int i; m = PyModule_Create(&_testcapimodule); if (m == NULL) return NULL; + if (!structseq_initialized) { + for (i = 0; i < STRUCTSEQ_LEN; i++) { + if (struct_unnamed_end_fields[i].name == NULL) { + struct_unnamed_end_fields[i].name = PyStructSequence_UnnamedField; + } + if (struct_unnamed_middle_fields[i].name == NULL) { + struct_unnamed_middle_fields[i].name = PyStructSequence_UnnamedField; + } + if (struct_unnamed_alternating_fields[i].name == NULL) { + struct_unnamed_alternating_fields[i].name = PyStructSequence_UnnamedField; + } + } + if (PyStructSequence_InitType2(&StructUnnamedEndType, + &struct_unnamed_end_desc) < 0) { + return NULL; + } + if (PyStructSequence_InitType2(&StructUnnamedMiddleType, + &struct_unnamed_middle_desc) < 0) { + return NULL; + } + if (PyStructSequence_InitType2(&StructUnnamedAlternatingType, + &struct_unnamed_alternating_desc) < 0) { + return NULL; + } + } + Py_TYPE(&_HashInheritanceTester_Type)=&PyType_Type; Py_TYPE(&test_structmembersType)=&PyType_Type;