summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Modules/arraymodule.c
diff options
context:
space:
mode:
authorshadchin <[email protected]>2022-04-18 12:39:32 +0300
committershadchin <[email protected]>2022-04-18 12:39:32 +0300
commitd4be68e361f4258cf0848fc70018dfe37a2acc24 (patch)
tree153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Modules/arraymodule.c
parent260c02f5ccf242d9d9b8a873afaf6588c00237d6 (diff)
IGNIETFERRO-1816 Update Python 3 from 3.9.12 to 3.10.4
ref:9f96be6d02ee8044fdd6f124b799b270c20ce641
Diffstat (limited to 'contrib/tools/python3/src/Modules/arraymodule.c')
-rw-r--r--contrib/tools/python3/src/Modules/arraymodule.c428
1 files changed, 253 insertions, 175 deletions
diff --git a/contrib/tools/python3/src/Modules/arraymodule.c b/contrib/tools/python3/src/Modules/arraymodule.c
index 7c7fc917454..72b90111a83 100644
--- a/contrib/tools/python3/src/Modules/arraymodule.c
+++ b/contrib/tools/python3/src/Modules/arraymodule.c
@@ -5,6 +5,8 @@
#define PY_SSIZE_T_CLEAN
#include "Python.h"
+#include "pycore_moduleobject.h" // _PyModule_GetState()
+#include "structmember.h" // PyMemberDef
#include <stddef.h> // offsetof()
#ifdef STDC_HEADERS
@@ -21,6 +23,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,8 +49,6 @@ typedef struct arrayobject {
Py_ssize_t ob_exports; /* Number of exported buffers */
} arrayobject;
-static PyTypeObject Arraytype;
-
typedef struct {
PyObject_HEAD
Py_ssize_t index;
@@ -55,9 +56,21 @@ typedef struct {
PyObject* (*getitem)(struct arrayobject *, Py_ssize_t);
} arrayiterobject;
-static PyTypeObject PyArrayIter_Type;
+typedef struct {
+ PyTypeObject *ArrayType;
+ PyTypeObject *ArrayIterType;
+} array_state;
+
+static array_state *
+get_array_state(PyObject *module)
+{
+ return (array_state *)_PyModule_GetState(module);
+}
-#define PyArrayIter_Check(op) PyObject_TypeCheck(op, &PyArrayIter_Type)
+#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 +118,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)
@@ -133,7 +145,7 @@ array_resize(arrayobject *self, Py_ssize_t newsize)
}
if (newsize == 0) {
- PyMem_FREE(self->ob_item);
+ PyMem_Free(self->ob_item);
self->ob_item = NULL;
Py_SET_SIZE(self, 0);
self->allocated = 0;
@@ -337,17 +349,6 @@ II_getitem(arrayobject *ap, Py_ssize_t i)
(unsigned long) ((unsigned int *)ap->ob_item)[i]);
}
-static PyObject *
-get_int_unless_float(PyObject *v)
-{
- if (PyFloat_Check(v)) {
- PyErr_SetString(PyExc_TypeError,
- "array item must be integer");
- return NULL;
- }
- return _PyLong_FromNbIndexOrNbInt(v);
-}
-
static int
II_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
{
@@ -355,7 +356,7 @@ II_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
int do_decref = 0; /* if nb_int was called */
if (!PyLong_Check(v)) {
- v = get_int_unless_float(v);
+ v = _PyNumber_Index(v);
if (NULL == v) {
return -1;
}
@@ -415,7 +416,7 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
int do_decref = 0; /* if nb_int was called */
if (!PyLong_Check(v)) {
- v = get_int_unless_float(v);
+ v = _PyNumber_Index(v);
if (NULL == v) {
return -1;
}
@@ -468,7 +469,7 @@ QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
int do_decref = 0; /* if nb_int was called */
if (!PyLong_Check(v)) {
- v = get_int_unless_float(v);
+ v = _PyNumber_Index(v);
if (NULL == v) {
return -1;
}
@@ -573,9 +574,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)
@@ -618,8 +619,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);
@@ -657,26 +661,38 @@ ins1(arrayobject *self, Py_ssize_t where, PyObject *v)
/* Methods */
+static int
+array_tp_traverse(arrayobject *op, visitproc visit, void *arg)
+{
+ Py_VISIT(Py_TYPE(op));
+ return 0;
+}
+
static void
array_dealloc(arrayobject *op)
{
+ PyTypeObject *tp = Py_TYPE(op);
+ PyObject_GC_UnTrack(op);
+
if (op->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) op);
if (op->ob_item != NULL)
- PyMem_DEL(op->ob_item);
- Py_TYPE(op)->tp_free((PyObject *)op);
+ PyMem_Free(op->ob_item);
+ 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;
@@ -798,7 +814,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))
@@ -809,7 +827,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) {
@@ -852,9 +870,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);
@@ -869,7 +888,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;
}
@@ -887,6 +906,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;
@@ -896,7 +916,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)
@@ -969,7 +989,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);
}
@@ -997,11 +1020,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) {
@@ -1032,13 +1055,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;
@@ -1120,18 +1145,32 @@ array_array_count(arrayobject *self, PyObject *v)
array.array.index
v: object
+ start: slice_index(accept={int}) = 0
+ stop: slice_index(accept={int}, c_default="PY_SSIZE_T_MAX") = sys.maxsize
/
Return index of first occurrence of v in the array.
+
+Raise ValueError if the value is not present.
[clinic start generated code]*/
static PyObject *
-array_array_index(arrayobject *self, PyObject *v)
-/*[clinic end generated code: output=d48498d325602167 input=cf619898c6649d08]*/
+array_array_index_impl(arrayobject *self, PyObject *v, Py_ssize_t start,
+ Py_ssize_t stop)
+/*[clinic end generated code: output=c45e777880c99f52 input=089dff7baa7e5a7e]*/
{
- Py_ssize_t i;
-
- for (i = 0; i < Py_SIZE(self); i++) {
+ if (start < 0) {
+ start += Py_SIZE(self);
+ if (start < 0) {
+ start = 0;
+ }
+ }
+ if (stop < 0) {
+ stop += Py_SIZE(self);
+ }
+ // Use Py_SIZE() for every iteration in case the array is mutated
+ // during PyObject_RichCompareBool()
+ for (Py_ssize_t i = start; i < stop && i < Py_SIZE(self); i++) {
PyObject *selfi;
int cmp;
@@ -1243,6 +1282,7 @@ array_array_pop_impl(arrayobject *self, Py_ssize_t i)
/*[clinic input]
array.array.extend
+ cls: defining_class
bb: object
/
@@ -1250,10 +1290,12 @@ 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;
}
@@ -1939,6 +1981,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;
@@ -1949,10 +1992,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++) {
@@ -2298,6 +2341,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()) {
@@ -2321,10 +2366,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;
@@ -2334,7 +2379,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;
@@ -2360,6 +2405,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;
@@ -2401,7 +2447,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) {
@@ -2513,12 +2559,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 = "";
@@ -2536,14 +2576,14 @@ array_buffer_getbuf(arrayobject *self, Py_buffer *view, int flags)
Py_INCREF(self);
if (view->buf == NULL)
view->buf = (void *)emptybuf;
- view->len = (Py_SIZE(self)) * self->ob_descr->itemsize;
+ view->len = Py_SIZE(self) * self->ob_descr->itemsize;
view->readonly = 0;
view->ndim = 1;
view->itemsize = self->ob_descr->itemsize;
view->suboffsets = NULL;
view->shape = NULL;
if ((flags & PyBUF_ND)==PyBUF_ND) {
- view->shape = &((Py_SIZE(self)));
+ view->shape = &((PyVarObject*)self)->ob_size;
}
view->strides = NULL;
if ((flags & PyBUF_STRIDES)==PyBUF_STRIDES)
@@ -2569,32 +2609,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))
@@ -2611,7 +2634,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);
@@ -2624,7 +2647,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)
@@ -2645,7 +2668,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;
@@ -2654,7 +2677,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 =
@@ -2699,7 +2722,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);
@@ -2788,67 +2811,75 @@ 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_traverse, array_tp_traverse},
+
+ /* 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 |
+ Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC |
+ Py_TPFLAGS_SEQUENCE),
+ .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;
@@ -2866,12 +2897,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++);
}
@@ -2883,14 +2919,18 @@ 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
arrayiter_traverse(arrayiterobject *it, visitproc visit, void *arg)
{
+ Py_VISIT(Py_TYPE(it));
Py_VISIT(it->ao);
return 0;
}
@@ -2943,66 +2983,104 @@ 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 |
+ Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE),
+ .slots = arrayiter_slots,
};
/*********************** Install Module **************************/
+static int
+array_traverse(PyObject *module, visitproc visit, void *arg)
+{
+ array_state *state = get_array_state(module);
+ Py_VISIT(state->ArrayType);
+ Py_VISIT(state->ArrayIterType);
+ return 0;
+}
+
+static int
+array_clear(PyObject *module)
+{
+ array_state *state = get_array_state(module);
+ Py_CLEAR(state->ArrayType);
+ Py_CLEAR(state->ArrayIterType);
+ return 0;
+}
+
+static void
+array_free(void *module)
+{
+ array_clear((PyObject *)module);
+}
+
/* No functions in array module. */
static PyMethodDef a_methods[] = {
ARRAY__ARRAY_RECONSTRUCTOR_METHODDEF
{NULL, NULL, 0, NULL} /* Sentinel */
};
+#define CREATE_TYPE(module, type, spec) \
+do { \
+ type = (PyTypeObject *)PyType_FromModuleAndSpec(module, 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)
+ CREATE_TYPE(m, state->ArrayType, &array_spec);
+ CREATE_TYPE(m, state->ArrayIterType, &arrayiter_spec);
+ Py_SET_TYPE(state->ArrayIterType, &PyType_Type);
+
+ Py_INCREF((PyObject *)state->ArrayType);
+ if (PyModule_AddObject(m, "ArrayType", (PyObject *)state->ArrayType) < 0) {
+ Py_DECREF((PyObject *)state->ArrayType);
return -1;
- Py_SET_TYPE(&PyArrayIter_Type, &PyType_Type);
+ }
- Py_INCREF((PyObject *)&Arraytype);
- if (PyModule_AddObject(m, "ArrayType", (PyObject *)&Arraytype) < 0) {
- Py_DECREF((PyObject *)&Arraytype);
+ PyObject *abc_mod = PyImport_ImportModule("collections.abc");
+ if (!abc_mod) {
+ Py_DECREF((PyObject *)state->ArrayType);
+ return -1;
+ }
+ PyObject *mutablesequence = PyObject_GetAttrString(abc_mod, "MutableSequence");
+ Py_DECREF(abc_mod);
+ if (!mutablesequence) {
+ Py_DECREF((PyObject *)state->ArrayType);
+ return -1;
+ }
+ PyObject *res = PyObject_CallMethod(mutablesequence, "register", "O",
+ (PyObject *)state->ArrayType);
+ Py_DECREF(mutablesequence);
+ if (!res) {
+ Py_DECREF((PyObject *)state->ArrayType);
return -1;
}
- Py_INCREF((PyObject *)&Arraytype);
- if (PyModule_AddObject(m, "array", (PyObject *)&Arraytype) < 0) {
- Py_DECREF((PyObject *)&Arraytype);
+ Py_DECREF(res);
+
+ if (PyModule_AddType(m, state->ArrayType) < 0) {
return -1;
}
@@ -3026,15 +3104,15 @@ 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,
+ .m_traverse = array_traverse,
+ .m_clear = array_clear,
+ .m_free = array_free,
};