Skip to content

bpo-40077: Convert arraymodule to use heap types and establish module state #23124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jan 2, 2021
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Convert :mod:`array` to use heap types, and establish module state for these.
329 changes: 172 additions & 157 deletions Modules/arraymodule.c
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@

#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "structmember.h" // PyMemberDef
#include <stddef.h> // offsetof()

#ifdef STDC_HEADERS
@@ -21,6 +22,7 @@ module array
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7d1b8d7f5958fd83]*/

struct arrayobject; /* Forward */
static struct PyModuleDef arraymodule;

/* All possible arraydescr values are defined in the vector "descriptors"
* below. That's defined later because the appropriate get and set
@@ -46,18 +48,28 @@ typedef struct arrayobject {
Py_ssize_t ob_exports; /* Number of exported buffers */
} arrayobject;

static PyTypeObject Arraytype;

typedef struct {
PyObject_HEAD
Py_ssize_t index;
arrayobject *ao;
PyObject* (*getitem)(struct arrayobject *, Py_ssize_t);
} arrayiterobject;

static PyTypeObject PyArrayIter_Type;
typedef struct {
PyTypeObject *ArrayType;
PyTypeObject *ArrayIterType;
} array_state;

#define PyArrayIter_Check(op) PyObject_TypeCheck(op, &PyArrayIter_Type)
static array_state *
get_array_state(PyObject *module)
{
return (array_state *)PyModule_GetState(module);
}

#define find_array_state_by_type(tp) \
(get_array_state(_PyType_GetModuleByDef(tp, &arraymodule)))
#define get_array_state_by_class(cls) \
(get_array_state(PyType_GetModule(cls)))

enum machine_format_code {
UNKNOWN_FORMAT = -1,
@@ -105,8 +117,7 @@ enum machine_format_code {
*/
#include "clinic/arraymodule.c.h"

#define array_Check(op) PyObject_TypeCheck(op, &Arraytype)
#define array_CheckExact(op) Py_IS_TYPE(op, &Arraytype)
#define array_Check(op, state) PyObject_TypeCheck(op, state->ArrayType)

static int
array_resize(arrayobject *self, Py_ssize_t newsize)
@@ -562,9 +573,9 @@ static const struct arraydescr descriptors[] = {
Implementations of array object methods.
****************************************************************************/
/*[clinic input]
class array.array "arrayobject *" "&Arraytype"
class array.array "arrayobject *" "ArrayType"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ad43d37e942a8854]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a5c29edf59f176a3]*/

static PyObject *
newarrayobject(PyTypeObject *type, Py_ssize_t size, const struct arraydescr *descr)
@@ -607,8 +618,11 @@ newarrayobject(PyTypeObject *type, Py_ssize_t size, const struct arraydescr *des
static PyObject *
getarrayitem(PyObject *op, Py_ssize_t i)
{
#ifndef NDEBUG
array_state *state = find_array_state_by_type(Py_TYPE(op));
assert(array_Check(op, state));
#endif
arrayobject *ap;
assert(array_Check(op));
ap = (arrayobject *)op;
assert(i>=0 && i<Py_SIZE(ap));
return (*ap->ob_descr->getitem)(ap, i);
@@ -649,23 +663,27 @@ ins1(arrayobject *self, Py_ssize_t where, PyObject *v)
static void
array_dealloc(arrayobject *op)
{
PyTypeObject *tp = Py_TYPE(op);

if (op->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) op);
if (op->ob_item != NULL)
PyMem_Free(op->ob_item);
Py_TYPE(op)->tp_free((PyObject *)op);
tp->tp_free(op);
Py_DECREF(tp);
}

static PyObject *
array_richcompare(PyObject *v, PyObject *w, int op)
{
array_state *state = find_array_state_by_type(Py_TYPE(v));
arrayobject *va, *wa;
PyObject *vi = NULL;
PyObject *wi = NULL;
Py_ssize_t i, k;
PyObject *res;

if (!array_Check(v) || !array_Check(w))
if (!array_Check(v, state) || !array_Check(w, state))
Py_RETURN_NOTIMPLEMENTED;

va = (arrayobject *)v;
@@ -787,7 +805,9 @@ array_item(arrayobject *a, Py_ssize_t i)
static PyObject *
array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
{
array_state *state = find_array_state_by_type(Py_TYPE(a));
arrayobject *np;

if (ilow < 0)
ilow = 0;
else if (ilow > Py_SIZE(a))
@@ -798,7 +818,7 @@ array_slice(arrayobject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
ihigh = ilow;
else if (ihigh > Py_SIZE(a))
ihigh = Py_SIZE(a);
np = (arrayobject *) newarrayobject(&Arraytype, ihigh - ilow, a->ob_descr);
np = (arrayobject *) newarrayobject(state->ArrayType, ihigh - ilow, a->ob_descr);
if (np == NULL)
return NULL;
if (ihigh > ilow) {
@@ -841,9 +861,10 @@ array_array___deepcopy__(arrayobject *self, PyObject *unused)
static PyObject *
array_concat(arrayobject *a, PyObject *bb)
{
array_state *state = find_array_state_by_type(Py_TYPE(a));
Py_ssize_t size;
arrayobject *np;
if (!array_Check(bb)) {
if (!array_Check(bb, state)) {
PyErr_Format(PyExc_TypeError,
"can only append array (not \"%.200s\") to array",
Py_TYPE(bb)->tp_name);
@@ -858,7 +879,7 @@ array_concat(arrayobject *a, PyObject *bb)
return PyErr_NoMemory();
}
size = Py_SIZE(a) + Py_SIZE(b);
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
np = (arrayobject *) newarrayobject(state->ArrayType, size, a->ob_descr);
if (np == NULL) {
return NULL;
}
@@ -876,6 +897,7 @@ array_concat(arrayobject *a, PyObject *bb)
static PyObject *
array_repeat(arrayobject *a, Py_ssize_t n)
{
array_state *state = find_array_state_by_type(Py_TYPE(a));
Py_ssize_t size;
arrayobject *np;
Py_ssize_t oldbytes, newbytes;
@@ -885,7 +907,7 @@ array_repeat(arrayobject *a, Py_ssize_t n)
return PyErr_NoMemory();
}
size = Py_SIZE(a) * n;
np = (arrayobject *) newarrayobject(&Arraytype, size, a->ob_descr);
np = (arrayobject *) newarrayobject(state->ArrayType, size, a->ob_descr);
if (np == NULL)
return NULL;
if (size == 0)
@@ -958,7 +980,10 @@ array_ass_item(arrayobject *a, Py_ssize_t i, PyObject *v)
static int
setarrayitem(PyObject *a, Py_ssize_t i, PyObject *v)
{
assert(array_Check(a));
#ifndef NDEBUG
array_state *state = find_array_state_by_type(Py_TYPE(a));
assert(array_Check(a, state));
#endif
return array_ass_item((arrayobject *)a, i, v);
}

@@ -986,11 +1011,11 @@ array_iter_extend(arrayobject *self, PyObject *bb)
}

static int
array_do_extend(arrayobject *self, PyObject *bb)
array_do_extend(array_state *state, arrayobject *self, PyObject *bb)
{
Py_ssize_t size, oldsize, bbsize;

if (!array_Check(bb))
if (!array_Check(bb, state))
return array_iter_extend(self, bb);
#define b ((arrayobject *)bb)
if (self->ob_descr != b->ob_descr) {
@@ -1021,13 +1046,15 @@ array_do_extend(arrayobject *self, PyObject *bb)
static PyObject *
array_inplace_concat(arrayobject *self, PyObject *bb)
{
if (!array_Check(bb)) {
array_state *state = find_array_state_by_type(Py_TYPE(self));

if (!array_Check(bb, state)) {
PyErr_Format(PyExc_TypeError,
"can only extend array with array (not \"%.200s\")",
Py_TYPE(bb)->tp_name);
return NULL;
}
if (array_do_extend(self, bb) == -1)
if (array_do_extend(state, self, bb) == -1)
return NULL;
Py_INCREF(self);
return (PyObject *)self;
@@ -1232,17 +1259,20 @@ array_array_pop_impl(arrayobject *self, Py_ssize_t i)
/*[clinic input]
array.array.extend
cls: defining_class
bb: object
/
Append items to the end of the array.
[clinic start generated code]*/

static PyObject *
array_array_extend(arrayobject *self, PyObject *bb)
/*[clinic end generated code: output=bbddbc8e8bef871d input=43be86aba5c31e44]*/
array_array_extend_impl(arrayobject *self, PyTypeObject *cls, PyObject *bb)
/*[clinic end generated code: output=e65eb7588f0bc266 input=8eb6817ec4d2cb62]*/
{
if (array_do_extend(self, bb) == -1)
array_state *state = get_array_state_by_class(cls);

if (array_do_extend(state, self, bb) == -1)
return NULL;
Py_RETURN_NONE;
}
@@ -1928,6 +1958,7 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype,
PyObject *items)
/*[clinic end generated code: output=e05263141ba28365 input=2464dc8f4c7736b5]*/
{
array_state *state = get_array_state(module);
PyObject *converted_items;
PyObject *result;
const struct arraydescr *descr;
@@ -1938,10 +1969,10 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype,
Py_TYPE(arraytype)->tp_name);
return NULL;
}
if (!PyType_IsSubtype(arraytype, &Arraytype)) {
if (!PyType_IsSubtype(arraytype, state->ArrayType)) {
PyErr_Format(PyExc_TypeError,
"%.200s is not a subtype of %.200s",
arraytype->tp_name, Arraytype.tp_name);
arraytype->tp_name, state->ArrayType->tp_name);
return NULL;
}
for (descr = descriptors; descr->typecode != '\0'; descr++) {
@@ -2287,6 +2318,8 @@ array_repr(arrayobject *a)
static PyObject*
array_subscr(arrayobject* self, PyObject* item)
{
array_state *state = find_array_state_by_type(Py_TYPE(self));

if (PyIndex_Check(item)) {
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
if (i==-1 && PyErr_Occurred()) {
@@ -2310,10 +2343,10 @@ array_subscr(arrayobject* self, PyObject* item)
step);

if (slicelength <= 0) {
return newarrayobject(&Arraytype, 0, self->ob_descr);
return newarrayobject(state->ArrayType, 0, self->ob_descr);
}
else if (step == 1) {
PyObject *result = newarrayobject(&Arraytype,
PyObject *result = newarrayobject(state->ArrayType,
slicelength, self->ob_descr);
if (result == NULL)
return NULL;
@@ -2323,7 +2356,7 @@ array_subscr(arrayobject* self, PyObject* item)
return result;
}
else {
result = newarrayobject(&Arraytype, slicelength, self->ob_descr);
result = newarrayobject(state->ArrayType, slicelength, self->ob_descr);
if (!result) return NULL;

ar = (arrayobject*)result;
@@ -2349,6 +2382,7 @@ static int
array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
{
Py_ssize_t start, stop, step, slicelength, needed;
array_state* state = find_array_state_by_type(Py_TYPE(self));
arrayobject* other;
int itemsize;

@@ -2390,7 +2424,7 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
other = NULL;
needed = 0;
}
else if (array_Check(value)) {
else if (array_Check(value, state)) {
other = (arrayobject *)value;
needed = Py_SIZE(other);
if (self == other) {
@@ -2502,12 +2536,6 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
}
}

static PyMappingMethods array_as_mapping = {
(lenfunc)array_length,
(binaryfunc)array_subscr,
(objobjargproc)array_ass_subscr
};

static const void *emptybuf = "";


@@ -2558,32 +2586,15 @@ array_buffer_relbuf(arrayobject *self, Py_buffer *view)
self->ob_exports--;
}

static PySequenceMethods array_as_sequence = {
(lenfunc)array_length, /*sq_length*/
(binaryfunc)array_concat, /*sq_concat*/
(ssizeargfunc)array_repeat, /*sq_repeat*/
(ssizeargfunc)array_item, /*sq_item*/
0, /*sq_slice*/
(ssizeobjargproc)array_ass_item, /*sq_ass_item*/
0, /*sq_ass_slice*/
(objobjproc)array_contains, /*sq_contains*/
(binaryfunc)array_inplace_concat, /*sq_inplace_concat*/
(ssizeargfunc)array_inplace_repeat /*sq_inplace_repeat*/
};

static PyBufferProcs array_as_buffer = {
(getbufferproc)array_buffer_getbuf,
(releasebufferproc)array_buffer_relbuf
};

static PyObject *
array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
array_state *state = find_array_state_by_type(type);
int c;
PyObject *initial = NULL, *it = NULL;
const struct arraydescr *descr;

if (type == &Arraytype && !_PyArg_NoKeywords("array.array", kwds))
if (type == state->ArrayType && !_PyArg_NoKeywords("array.array", kwds))
return NULL;

if (!PyArg_ParseTuple(args, "C|O:array", &c, &initial))
@@ -2600,7 +2611,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
"an array with typecode '%c'", c);
return NULL;
}
else if (array_Check(initial) &&
else if (array_Check(initial, state) &&
((arrayobject*)initial)->ob_descr->typecode == 'u') {
PyErr_Format(PyExc_TypeError, "cannot use a unicode array to "
"initialize an array with typecode '%c'", c);
@@ -2613,7 +2624,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|| PyBytes_Check(initial)
|| PyTuple_Check(initial)
|| ((c=='u') && PyUnicode_Check(initial))
|| (array_Check(initial)
|| (array_Check(initial, state)
&& c == ((arrayobject*)initial)->ob_descr->typecode))) {
it = PyObject_GetIter(initial);
if (it == NULL)
@@ -2634,7 +2645,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
len = 0;
else if (PyList_Check(initial))
len = PyList_GET_SIZE(initial);
else if (PyTuple_Check(initial) || array_Check(initial))
else if (PyTuple_Check(initial) || array_Check(initial, state))
len = Py_SIZE(initial);
else
len = 0;
@@ -2643,7 +2654,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (a == NULL)
return NULL;

if (len > 0 && !array_Check(initial)) {
if (len > 0 && !array_Check(initial, state)) {
Py_ssize_t i;
for (i = 0; i < len; i++) {
PyObject *v =
@@ -2688,7 +2699,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
self->allocated = n;
}
}
else if (initial != NULL && array_Check(initial) && len > 0) {
else if (initial != NULL && array_Check(initial, state) && len > 0) {
arrayobject *self = (arrayobject *)a;
arrayobject *other = (arrayobject *)initial;
memcpy(self->ob_item, other->ob_item, len * other->ob_descr->itemsize);
@@ -2777,67 +2788,73 @@ itemsize -- the length in bytes of one array item\n\

static PyObject *array_iter(arrayobject *ao);

static PyTypeObject Arraytype = {
PyVarObject_HEAD_INIT(NULL, 0)
"array.array",
sizeof(arrayobject),
0,
(destructor)array_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
(reprfunc)array_repr, /* tp_repr */
0, /* tp_as_number*/
&array_as_sequence, /* tp_as_sequence*/
&array_as_mapping, /* tp_as_mapping*/
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
&array_as_buffer, /* tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
arraytype_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
array_richcompare, /* tp_richcompare */
offsetof(arrayobject, weakreflist), /* tp_weaklistoffset */
(getiterfunc)array_iter, /* tp_iter */
0, /* tp_iternext */
array_methods, /* tp_methods */
0, /* tp_members */
array_getsets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
array_new, /* tp_new */
PyObject_Del, /* tp_free */
static struct PyMemberDef array_members[] = {
{"__weaklistoffset__", T_PYSSIZET, offsetof(arrayobject, weakreflist), READONLY},
{NULL},
};

static PyType_Slot array_slots[] = {
{Py_tp_dealloc, array_dealloc},
{Py_tp_repr, array_repr},
{Py_tp_getattro, PyObject_GenericGetAttr},
{Py_tp_doc, (void *)arraytype_doc},
{Py_tp_richcompare, array_richcompare},
{Py_tp_iter, array_iter},
{Py_tp_methods, array_methods},
{Py_tp_members, array_members},
{Py_tp_getset, array_getsets},
{Py_tp_alloc, PyType_GenericAlloc},
{Py_tp_new, array_new},
{Py_tp_free, PyObject_Del},

/* as sequence */
{Py_sq_length, array_length},
{Py_sq_concat, array_concat},
{Py_sq_repeat, array_repeat},
{Py_sq_item, array_item},
{Py_sq_ass_item, array_ass_item},
{Py_sq_contains, array_contains},
{Py_sq_inplace_concat, array_inplace_concat},
{Py_sq_inplace_repeat, array_inplace_repeat},

/* as mapping */
{Py_mp_length, array_length},
{Py_mp_subscript, array_subscr},
{Py_mp_ass_subscript, array_ass_subscr},

/* as buffer */
{Py_bf_getbuffer, array_buffer_getbuf},
{Py_bf_releasebuffer, array_buffer_relbuf},

{0, NULL},
};

static PyType_Spec array_spec = {
.name = "array.array",
.basicsize = sizeof(arrayobject),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.slots = array_slots,
};

/*********************** Array Iterator **************************/

/*[clinic input]
class array.arrayiterator "arrayiterobject *" "&PyArrayIter_Type"
class array.arrayiterator "arrayiterobject *" "find_array_state_by_type(type)->ArrayIterType"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5aefd2d74d8c8e30]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=fb46d5ef98dd95ff]*/

static PyObject *
array_iter(arrayobject *ao)
{
array_state *state = find_array_state_by_type(Py_TYPE(ao));
arrayiterobject *it;

if (!array_Check(ao)) {
if (!array_Check(ao, state)) {
PyErr_BadInternalCall();
return NULL;
}

it = PyObject_GC_New(arrayiterobject, &PyArrayIter_Type);
it = PyObject_GC_New(arrayiterobject, state->ArrayIterType);
if (it == NULL)
return NULL;

@@ -2855,12 +2872,17 @@ arrayiter_next(arrayiterobject *it)
arrayobject *ao;

assert(it != NULL);
assert(PyArrayIter_Check(it));
#ifndef NDEBUG
array_state *state = find_array_state_by_type(Py_TYPE(it));
assert(PyObject_TypeCheck(it, state->ArrayIterType));
#endif
ao = it->ao;
if (ao == NULL) {
return NULL;
}
assert(array_Check(ao));
#ifndef NDEBUG
assert(array_Check(ao, state));
#endif
if (it->index < Py_SIZE(ao)) {
return (*it->getitem)(ao, it->index++);
}
@@ -2872,9 +2894,12 @@ arrayiter_next(arrayiterobject *it)
static void
arrayiter_dealloc(arrayiterobject *it)
{
PyTypeObject *tp = Py_TYPE(it);

PyObject_GC_UnTrack(it);
Py_XDECREF(it->ao);
PyObject_GC_Del(it);
Py_DECREF(tp);
}

static int
@@ -2932,36 +2957,21 @@ static PyMethodDef arrayiter_methods[] = {
{NULL, NULL} /* sentinel */
};

static PyTypeObject PyArrayIter_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"arrayiterator", /* tp_name */
sizeof(arrayiterobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)arrayiter_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
(traverseproc)arrayiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)arrayiter_next, /* tp_iternext */
arrayiter_methods, /* tp_methods */
static PyType_Slot arrayiter_slots[] = {
{Py_tp_dealloc, arrayiter_dealloc},
{Py_tp_getattro, PyObject_GenericGetAttr},
{Py_tp_traverse, arrayiter_traverse},
{Py_tp_iter, PyObject_SelfIter},
{Py_tp_iternext, arrayiter_next},
{Py_tp_methods, arrayiter_methods},
{0, NULL},
};

static PyType_Spec arrayiter_spec = {
.name = "array.arrayiterator",
.basicsize = sizeof(arrayiterobject),
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.slots = arrayiter_slots,
};


@@ -2973,45 +2983,53 @@ static PyMethodDef a_methods[] = {
{NULL, NULL, 0, NULL} /* Sentinel */
};

#define CREATE_TYPE(module, type, spec) \
do { \
type = (PyTypeObject *)PyType_FromModuleAndSpec(m, spec, NULL); \
if (type == NULL) { \
return -1; \
} \
} while (0)

static int
array_modexec(PyObject *m)
{
array_state *state = get_array_state(m);
char buffer[Py_ARRAY_LENGTH(descriptors)], *p;
PyObject *typecodes;
const struct arraydescr *descr;

if (PyType_Ready(&Arraytype) < 0)
return -1;
Py_SET_TYPE(&PyArrayIter_Type, &PyType_Type);
CREATE_TYPE(m, state->ArrayType, &array_spec);
CREATE_TYPE(m, state->ArrayIterType, &arrayiter_spec);
Py_SET_TYPE(state->ArrayIterType, &PyType_Type);

Py_INCREF((PyObject *)&Arraytype);
if (PyModule_AddObject(m, "ArrayType", (PyObject *)&Arraytype) < 0) {
Py_DECREF((PyObject *)&Arraytype);
Py_INCREF((PyObject *)state->ArrayType);
if (PyModule_AddObject(m, "ArrayType", (PyObject *)state->ArrayType) < 0) {
Py_DECREF((PyObject *)state->ArrayType);
return -1;
}

PyObject *abc_mod = PyImport_ImportModule("collections.abc");
if (!abc_mod) {
Py_DECREF((PyObject *)&Arraytype);
Py_DECREF((PyObject *)state->ArrayType);
return -1;
}
PyObject *mutablesequence = PyObject_GetAttrString(abc_mod, "MutableSequence");
Py_DECREF(abc_mod);
if (!mutablesequence) {
Py_DECREF((PyObject *)&Arraytype);
Py_DECREF((PyObject *)state->ArrayType);
return -1;
}
PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O", (PyObject *)&Arraytype);
PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O",
(PyObject *)state->ArrayType);
Py_DECREF(mutablesequence);
if (!res) {
Py_DECREF((PyObject *)&Arraytype);
Py_DECREF((PyObject *)state->ArrayType);
return -1;
}
Py_DECREF(res);

Py_INCREF((PyObject *)&Arraytype);
if (PyModule_AddObject(m, "array", (PyObject *)&Arraytype) < 0) {
Py_DECREF((PyObject *)&Arraytype);
if (PyModule_AddType(m, state->ArrayType) < 0) {
return -1;
}

@@ -3035,15 +3053,12 @@ static PyModuleDef_Slot arrayslots[] = {


static struct PyModuleDef arraymodule = {
PyModuleDef_HEAD_INIT,
"array",
module_doc,
0,
a_methods,
arrayslots,
NULL,
NULL,
NULL
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "array",
.m_size = sizeof(array_state),
.m_doc = module_doc,
.m_methods = a_methods,
.m_slots = arrayslots,
};


25 changes: 23 additions & 2 deletions Modules/clinic/arraymodule.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.