Skip to content

Commit b5d770b

Browse files
committed
Add PyStructSequence_FromModuleAndDesc() to create a new struct sequence type.
1 parent 7834ff2 commit b5d770b

10 files changed

Lines changed: 67 additions & 3 deletions

File tree

Doc/c-api/tuple.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,14 @@ objects, i.e. a sequence whose items can also be accessed through attributes.
119119
To create a struct sequence, you first have to create a specific struct sequence
120120
type.
121121
122+
.. c:function:: PyTypeObject* PyStructSequence_FromModuleAndDesc(PyObject *module, PyStructSequence_Desc *desc, unsigned long tp_flags)
123+
124+
Create and return a new struct sequence type from the *desc*.
125+
This function is similar to :c:func:`PyStructSequence_NewType`.
126+
127+
.. versionadded:: 3.11
128+
129+
122130
.. c:function:: PyTypeObject* PyStructSequence_NewType(PyStructSequence_Desc *desc)
123131
124132
Create a new struct sequence type from the data in *desc*, described below. Instances

Doc/data/refcounts.dat

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,6 +2089,11 @@ PyState_FindModule:PyModuleDef*:def::
20892089
PyState_RemoveModule:int:::
20902090
PyState_RemoveModule:PyModuleDef*:def::
20912091

2092+
PyStructSequence_FromModuleAndDesc:PyTypeObject*::+1:
2093+
PyStructSequence_FromModuleAndDesc:PyObject*:module:+1:
2094+
PyStructSequence_FromModuleAndDesc:PyStructSequence_Desc*:desc::
2095+
PyStructSequence_FromModuleAndDesc:unsigned long:tp_flags::
2096+
20922097
PyStructSequence_GET_ITEM:PyObject*::0:
20932098
PyStructSequence_GET_ITEM:PyObject*:p:0:
20942099
PyStructSequence_GET_ITEM:Py_ssize_t:pos::

Doc/data/stable_abi.dat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ function,PyState_FindModule,3.2,
565565
function,PyState_RemoveModule,3.3,
566566
type,PyStructSequence_Desc,3.2,
567567
type,PyStructSequence_Field,3.2,
568+
function,PyStructSequence_FromModuleAndDesc,3.11,
568569
function,PyStructSequence_GetItem,3.2,
569570
function,PyStructSequence_New,3.2,
570571
function,PyStructSequence_NewType,3.2,

Doc/whatsnew/3.11.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,10 @@ New Features
455455
* Add a new :c:func:`PyType_GetQualName` function to get type's qualified name.
456456
(Contributed by Hai Shi in :issue:`42035`.)
457457

458+
* Add a new :c:func:`PyStructSequence_FromModuleAndDesc` function to create
459+
a new struct sequence type from the desc.
460+
(Contributed by Hai Shi in :issue:`45113`.)
461+
458462
Porting to Python 3.11
459463
----------------------
460464

Include/structseq.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ typedef PyTupleObject PyStructSequence;
4242

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

4650
#ifdef __cplusplus
4751
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add a new :c:func:`PyStructSequence_FromModuleAndDesc` function to create a new
2+
struct sequence type in heap.

Misc/stable_abi.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2149,6 +2149,8 @@ function PyType_GetName
21492149
added 3.11
21502150
function PyType_GetQualName
21512151
added 3.11
2152+
function PyStructSequence_FromModuleAndDesc
2153+
added 3.11
21522154

21532155
# (Detailed comments aren't really needed for further entries: from here on
21542156
# we can use version control logs.)

Modules/_testcapimodule.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3919,6 +3919,30 @@ test_structseq_newtype_null_descr_doc(PyObject *Py_UNUSED(self),
39193919
Py_RETURN_NONE;
39203920
}
39213921

3922+
static PyObject *
3923+
test_structseq_newtype_from_heap(PyObject *Py_UNUSED(self),
3924+
PyObject *Py_UNUSED(args))
3925+
{
3926+
PyStructSequence_Desc descr;
3927+
PyStructSequence_Field descr_fields[2];
3928+
3929+
descr_fields[0] = (PyStructSequence_Field){"foo", "foo value"};
3930+
descr_fields[1] = (PyStructSequence_Field){0, NULL};
3931+
3932+
descr.name = "_testcapi.test_descr";
3933+
descr.fields = descr_fields;
3934+
descr.doc = "This is used to test for creating a new type from heap";
3935+
descr.n_in_sequence = 1;
3936+
3937+
PyTypeObject* structseq_type =
3938+
(PyTypeObject *)PyStructSequence_FromModuleAndDesc(NULL, &descr, 0);
3939+
assert(structseq_type != NULL);
3940+
assert(PyType_Check(structseq_type));
3941+
Py_DECREF(structseq_type);
3942+
3943+
Py_RETURN_NONE;
3944+
}
3945+
39223946
static PyObject *
39233947
test_incref_decref_API(PyObject *ob, PyObject *Py_UNUSED(ignored))
39243948
{
@@ -5691,6 +5715,8 @@ static PyMethodDef TestMethods[] = {
56915715
test_structseq_newtype_doesnt_leak, METH_NOARGS},
56925716
{"test_structseq_newtype_null_descr_doc",
56935717
test_structseq_newtype_null_descr_doc, METH_NOARGS},
5718+
{"test_structseq_newtype_from_heap",
5719+
test_structseq_newtype_from_heap, METH_NOARGS},
56945720
{"test_incref_decref_API", test_incref_decref_API, METH_NOARGS},
56955721
{"test_long_and_overflow", test_long_and_overflow, METH_NOARGS},
56965722
{"test_long_as_double", test_long_as_double, METH_NOARGS},

Objects/structseq.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,9 @@ PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
532532
}
533533

534534
PyTypeObject *
535-
PyStructSequence_NewType(PyStructSequence_Desc *desc)
535+
PyStructSequence_FromModuleAndDesc(PyObject *module,
536+
PyStructSequence_Desc *desc,
537+
unsigned long tp_flags)
536538
{
537539
PyMemberDef *members;
538540
PyTypeObject *type;
@@ -565,14 +567,17 @@ PyStructSequence_NewType(PyStructSequence_Desc *desc)
565567
spec.name = desc->name;
566568
spec.basicsize = sizeof(PyStructSequence) - sizeof(PyObject *);
567569
spec.itemsize = sizeof(PyObject *);
568-
spec.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC;
570+
spec.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | tp_flags;
569571
spec.slots = slots;
570572

571-
type = (PyTypeObject *)PyType_FromSpecWithBases(&spec, (PyObject *)&PyTuple_Type);
573+
type = (PyTypeObject *)PyType_FromSpecWithBases(&spec,
574+
(PyObject *)&PyTuple_Type);
572575
PyMem_Free(members);
573576
if (type == NULL) {
574577
return NULL;
575578
}
579+
Py_XINCREF(module);
580+
((PyHeapTypeObject *)type)->ht_module = module;
576581

577582
if (initialize_structseq_dict(
578583
desc, type->tp_dict, n_members, n_unnamed_members) < 0) {
@@ -583,6 +588,12 @@ PyStructSequence_NewType(PyStructSequence_Desc *desc)
583588
return type;
584589
}
585590

591+
PyTypeObject *
592+
PyStructSequence_NewType(PyStructSequence_Desc *desc)
593+
{
594+
return PyStructSequence_FromModuleAndDesc(NULL, desc, 0);
595+
}
596+
586597
int _PyStructSequence_Init(void)
587598
{
588599
if (_PyUnicode_FromId(&PyId_n_sequence_fields) == NULL

PC/python3dll.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ EXPORT_FUNC(PySlice_Unpack)
519519
EXPORT_FUNC(PyState_AddModule)
520520
EXPORT_FUNC(PyState_FindModule)
521521
EXPORT_FUNC(PyState_RemoveModule)
522+
EXPORT_FUNC(PyStructSequence_FromModuleAndDesc)
522523
EXPORT_FUNC(PyStructSequence_GetItem)
523524
EXPORT_FUNC(PyStructSequence_New)
524525
EXPORT_FUNC(PyStructSequence_NewType)

0 commit comments

Comments
 (0)