Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Doc/c-api/tuple.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ objects, i.e. a sequence whose items can also be accessed through attributes.
To create a struct sequence, you first have to create a specific struct sequence
type.

.. c:function:: PyTypeObject* PyStructSequence_FromModuleAndDesc(PyObject *module, PyStructSequence_Desc *desc, unsigned long tp_flags)

Create and return a new struct sequence type from the *desc*.
This function is similar to :c:func:`PyStructSequence_NewType`.
Comment thread
shihai1991 marked this conversation as resolved.
The *module* argument is associated with the new type and can be retrieved
with :c:func:`PyType_GetModule`. It must be a module object or ``NULL``.
The *tp_flags* argument is used to set :c:member:`PyTypeObject.tp_flags`.

.. versionadded:: 3.11


.. c:function:: PyTypeObject* PyStructSequence_NewType(PyStructSequence_Desc *desc)

Create a new struct sequence type from the data in *desc*, described below. Instances
Expand Down
5 changes: 5 additions & 0 deletions Doc/data/refcounts.dat
Original file line number Diff line number Diff line change
Expand Up @@ -2089,6 +2089,11 @@ PyState_FindModule:PyModuleDef*:def::
PyState_RemoveModule:int:::
PyState_RemoveModule:PyModuleDef*:def::

PyStructSequence_FromModuleAndDesc:PyTypeObject*::+1:
PyStructSequence_FromModuleAndDesc:PyObject*:module:+1:
PyStructSequence_FromModuleAndDesc:PyStructSequence_Desc*:desc::
PyStructSequence_FromModuleAndDesc:unsigned long:tp_flags::

PyStructSequence_GET_ITEM:PyObject*::0:
PyStructSequence_GET_ITEM:PyObject*:p:0:
PyStructSequence_GET_ITEM:Py_ssize_t:pos::
Expand Down
1 change: 1 addition & 0 deletions Doc/data/stable_abi.dat
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,7 @@ function,PyState_FindModule,3.2,
function,PyState_RemoveModule,3.3,
type,PyStructSequence_Desc,3.2,
type,PyStructSequence_Field,3.2,
function,PyStructSequence_FromModuleAndDesc,3.11,
function,PyStructSequence_GetItem,3.2,
function,PyStructSequence_New,3.2,
function,PyStructSequence_NewType,3.2,
Expand Down
4 changes: 4 additions & 0 deletions Doc/whatsnew/3.11.rst
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,10 @@ New Features
suspend and resume tracing and profiling.
(Contributed by Victor Stinner in :issue:`43760`.)

* Add a new :c:func:`PyStructSequence_FromModuleAndDesc` function to create
a new struct sequence type from the desc.
(Contributed by Hai Shi in :issue:`45113`.)

Porting to Python 3.11
----------------------

Expand Down
4 changes: 4 additions & 0 deletions Include/structseq.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ typedef PyTupleObject PyStructSequence;

PyAPI_FUNC(void) PyStructSequence_SetItem(PyObject*, Py_ssize_t, PyObject*);
PyAPI_FUNC(PyObject*) PyStructSequence_GetItem(PyObject*, Py_ssize_t);
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030B0000
PyAPI_FUNC(PyTypeObject *) PyStructSequence_FromModuleAndDesc(
PyObject *, PyStructSequence_Desc *, unsigned long);
#endif

#ifdef __cplusplus
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add a new :c:func:`PyStructSequence_FromModuleAndDesc` function to create a new
struct sequence type on the heap.
2 changes: 2 additions & 0 deletions Misc/stable_abi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2151,6 +2151,8 @@ function PyType_GetQualName
added 3.11
data PyStructSequence_UnnamedField
added 3.11
function PyStructSequence_FromModuleAndDesc
added 3.11

# (Detailed comments aren't really needed for further entries: from here on
# we can use version control logs.)
26 changes: 26 additions & 0 deletions Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -4029,6 +4029,30 @@ test_structseq_newtype_null_descr_doc(PyObject *Py_UNUSED(self),
Py_RETURN_NONE;
}

static PyObject *
test_structseq_newtype_from_heap(PyObject *Py_UNUSED(self),
PyObject *Py_UNUSED(args))
{
PyStructSequence_Desc descr;
PyStructSequence_Field descr_fields[2];

descr_fields[0] = (PyStructSequence_Field){"foo", "foo value"};
descr_fields[1] = (PyStructSequence_Field){0, NULL};

descr.name = "_testcapi.test_descr";
descr.fields = descr_fields;
descr.doc = "This is used to test for creating a new type from heap";
descr.n_in_sequence = 1;

PyTypeObject* structseq_type =
(PyTypeObject *)PyStructSequence_FromModuleAndDesc(NULL, &descr, 0);
assert(structseq_type != NULL);
assert(PyType_Check(structseq_type));
Py_DECREF(structseq_type);

Py_RETURN_NONE;
}

static PyObject *
test_incref_decref_API(PyObject *ob, PyObject *Py_UNUSED(ignored))
{
Expand Down Expand Up @@ -5892,6 +5916,8 @@ static PyMethodDef TestMethods[] = {
test_structseq_newtype_doesnt_leak, METH_NOARGS},
{"test_structseq_newtype_null_descr_doc",
test_structseq_newtype_null_descr_doc, METH_NOARGS},
{"test_structseq_newtype_from_heap",
test_structseq_newtype_from_heap, METH_NOARGS},
{"test_incref_decref_API", test_incref_decref_API, METH_NOARGS},
{"test_long_and_overflow", test_long_and_overflow, METH_NOARGS},
{"test_long_as_double", test_long_as_double, METH_NOARGS},
Expand Down
15 changes: 12 additions & 3 deletions Objects/structseq.c
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,9 @@ PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
}

PyTypeObject *
PyStructSequence_NewType(PyStructSequence_Desc *desc)
PyStructSequence_FromModuleAndDesc(PyObject *module,
PyStructSequence_Desc *desc,
unsigned long tp_flags)
{
PyMemberDef *members;
PyTypeObject *type;
Expand Down Expand Up @@ -565,10 +567,11 @@ PyStructSequence_NewType(PyStructSequence_Desc *desc)
spec.name = desc->name;
spec.basicsize = sizeof(PyStructSequence) - sizeof(PyObject *);
spec.itemsize = sizeof(PyObject *);
spec.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC;
spec.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | tp_flags;
spec.slots = slots;

type = (PyTypeObject *)PyType_FromSpecWithBases(&spec, (PyObject *)&PyTuple_Type);
type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &spec,
(PyObject *)&PyTuple_Type);
PyMem_Free(members);
if (type == NULL) {
return NULL;
Expand All @@ -583,6 +586,12 @@ PyStructSequence_NewType(PyStructSequence_Desc *desc)
return type;
}

PyTypeObject *
PyStructSequence_NewType(PyStructSequence_Desc *desc)
{
return PyStructSequence_FromModuleAndDesc(NULL, desc, 0);
}

int _PyStructSequence_Init(void)
{
if (_PyUnicode_FromId(&PyId_n_sequence_fields) == NULL
Expand Down
1 change: 1 addition & 0 deletions PC/python3dll.c
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ EXPORT_FUNC(PySlice_Unpack)
EXPORT_FUNC(PyState_AddModule)
EXPORT_FUNC(PyState_FindModule)
EXPORT_FUNC(PyState_RemoveModule)
EXPORT_FUNC(PyStructSequence_FromModuleAndDesc)
EXPORT_FUNC(PyStructSequence_GetItem)
EXPORT_FUNC(PyStructSequence_New)
EXPORT_FUNC(PyStructSequence_NewType)
Expand Down