gh-103092: Isolate `_collections` (#103093)

Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
This commit is contained in:
Erlend E. Aasland 2023-04-12 14:51:28 +02:00 committed by GitHub
parent 411b169281
commit 52f96d3ea3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 286 additions and 282 deletions

View File

@ -45,6 +45,11 @@ except ImportError:
else:
_collections_abc.MutableSequence.register(deque)
try:
from _collections import _deque_iterator
except ImportError:
pass
try:
from _collections import defaultdict
except ImportError:

View File

@ -0,0 +1 @@
Isolate :mod:`!_collections` (apply :pep:`687`). Patch by Erlend E. Aasland.

View File

@ -1,17 +1,56 @@
#include "Python.h"
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_typeobject.h" // _PyType_GetModuleState()
#include "structmember.h" // PyMemberDef
#include <stddef.h>
typedef struct {
PyTypeObject *deque_type;
PyTypeObject *defdict_type;
PyTypeObject *dequeiter_type;
PyTypeObject *dequereviter_type;
PyTypeObject *tuplegetter_type;
} collections_state;
static inline collections_state *
get_module_state(PyObject *mod)
{
void *state = _PyModule_GetState(mod);
assert(state != NULL);
return (collections_state *)state;
}
static inline collections_state *
get_module_state_by_cls(PyTypeObject *cls)
{
void *state = _PyType_GetModuleState(cls);
assert(state != NULL);
return (collections_state *)state;
}
static struct PyModuleDef _collectionsmodule;
static inline collections_state *
find_module_state_by_def(PyTypeObject *type)
{
PyObject *mod = PyType_GetModuleByDef(type, &_collectionsmodule);
assert(mod != NULL);
return get_module_state(mod);
}
/*[clinic input]
module _collections
class _tuplegetter "_tuplegetterobject *" "&tuplegetter_type"
class _tuplegetter "_tuplegetterobject *" "clinic_state()->tuplegetter_type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a8ece4ccad7e30ac]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7356042a89862e0e]*/
static PyTypeObject tuplegetter_type;
/* We can safely assume type to be the defining class,
* since tuplegetter is not a base type */
#define clinic_state() (get_module_state_by_cls(type))
#include "clinic/_collectionsmodule.c.h"
#undef clinic_state
/* collections module implementation of a deque() datatype
Written and maintained by Raymond D. Hettinger <python@rcn.com>
@ -94,8 +133,6 @@ typedef struct {
PyObject *weakreflist;
} dequeobject;
static PyTypeObject deque_type;
/* For debug builds, add error checking to track the endpoints
* in the chain of links. The goal is to make sure that link
* assignments only take place at endpoints so that links already
@ -484,11 +521,13 @@ deque_copy(PyObject *deque, PyObject *Py_UNUSED(ignored))
{
PyObject *result;
dequeobject *old_deque = (dequeobject *)deque;
if (Py_IS_TYPE(deque, &deque_type)) {
collections_state *state = find_module_state_by_def(Py_TYPE(deque));
if (Py_IS_TYPE(deque, state->deque_type)) {
dequeobject *new_deque;
PyObject *rv;
new_deque = (dequeobject *)deque_new(&deque_type, (PyObject *)NULL, (PyObject *)NULL);
new_deque = (dequeobject *)deque_new(state->deque_type,
(PyObject *)NULL, (PyObject *)NULL);
if (new_deque == NULL)
return NULL;
new_deque->maxlen = old_deque->maxlen;
@ -511,7 +550,7 @@ deque_copy(PyObject *deque, PyObject *Py_UNUSED(ignored))
else
result = PyObject_CallFunction((PyObject *)(Py_TYPE(deque)), "Oi",
deque, old_deque->maxlen, NULL);
if (result != NULL && !PyObject_TypeCheck(result, &deque_type)) {
if (result != NULL && !PyObject_TypeCheck(result, state->deque_type)) {
PyErr_Format(PyExc_TypeError,
"%.200s() must return a deque, not %.200s",
Py_TYPE(deque)->tp_name, Py_TYPE(result)->tp_name);
@ -529,7 +568,8 @@ deque_concat(dequeobject *deque, PyObject *other)
PyObject *new_deque, *result;
int rv;
rv = PyObject_IsInstance(other, (PyObject *)&deque_type);
collections_state *state = find_module_state_by_def(Py_TYPE(deque));
rv = PyObject_IsInstance(other, (PyObject *)state->deque_type);
if (rv <= 0) {
if (rv == 0) {
PyErr_Format(PyExc_TypeError,
@ -1288,6 +1328,7 @@ deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v)
static void
deque_dealloc(dequeobject *deque)
{
PyTypeObject *tp = Py_TYPE(deque);
Py_ssize_t i;
PyObject_GC_UnTrack(deque);
@ -1303,12 +1344,15 @@ deque_dealloc(dequeobject *deque)
for (i=0 ; i < deque->numfreeblocks ; i++) {
PyMem_Free(deque->freeblocks[i]);
}
Py_TYPE(deque)->tp_free(deque);
tp->tp_free(deque);
Py_DECREF(tp);
}
static int
deque_traverse(dequeobject *deque, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(deque));
block *b;
PyObject *item;
Py_ssize_t index;
@ -1393,8 +1437,9 @@ deque_richcompare(PyObject *v, PyObject *w, int op)
Py_ssize_t vs, ws;
int b, cmp=-1;
if (!PyObject_TypeCheck(v, &deque_type) ||
!PyObject_TypeCheck(w, &deque_type)) {
collections_state *state = find_module_state_by_def(Py_TYPE(v));
if (!PyObject_TypeCheck(v, state->deque_type) ||
!PyObject_TypeCheck(w, state->deque_type)) {
Py_RETURN_NOTIMPLEMENTED;
}
@ -1537,19 +1582,6 @@ static PyGetSetDef deque_getset[] = {
{0}
};
static PySequenceMethods deque_as_sequence = {
(lenfunc)deque_len, /* sq_length */
(binaryfunc)deque_concat, /* sq_concat */
(ssizeargfunc)deque_repeat, /* sq_repeat */
(ssizeargfunc)deque_item, /* sq_item */
0, /* sq_slice */
(ssizeobjargproc)deque_ass_item, /* sq_ass_item */
0, /* sq_ass_slice */
(objobjproc)deque_contains, /* sq_contains */
(binaryfunc)deque_inplace_concat, /* sq_inplace_concat */
(ssizeargfunc)deque_inplace_repeat, /* sq_inplace_repeat */
};
static PyObject *deque_iter(dequeobject *deque);
static PyObject *deque_reviter(dequeobject *deque, PyObject *Py_UNUSED(ignored));
PyDoc_STRVAR(reversed_doc,
@ -1597,54 +1629,53 @@ static PyMethodDef deque_methods[] = {
{NULL, NULL} /* sentinel */
};
static PyMemberDef deque_members[] = {
{"__weaklistoffset__", T_PYSSIZET, offsetof(dequeobject, weakreflist), READONLY},
{NULL},
};
PyDoc_STRVAR(deque_doc,
"deque([iterable[, maxlen]]) --> deque object\n\
\n\
A list-like sequence optimized for data accesses near its endpoints.");
static PyTypeObject deque_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"collections.deque", /* tp_name */
sizeof(dequeobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)deque_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
deque_repr, /* tp_repr */
0, /* tp_as_number */
&deque_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
PyObject_HashNotImplemented, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SEQUENCE,
/* tp_flags */
deque_doc, /* tp_doc */
(traverseproc)deque_traverse, /* tp_traverse */
(inquiry)deque_clear, /* tp_clear */
(richcmpfunc)deque_richcompare, /* tp_richcompare */
offsetof(dequeobject, weakreflist), /* tp_weaklistoffset*/
(getiterfunc)deque_iter, /* tp_iter */
0, /* tp_iternext */
deque_methods, /* tp_methods */
0, /* tp_members */
deque_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)deque_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
deque_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
static PyType_Slot deque_slots[] = {
{Py_tp_dealloc, deque_dealloc},
{Py_tp_repr, deque_repr},
{Py_tp_hash, PyObject_HashNotImplemented},
{Py_tp_getattro, PyObject_GenericGetAttr},
{Py_tp_doc, (void *)deque_doc},
{Py_tp_traverse, deque_traverse},
{Py_tp_clear, deque_clear},
{Py_tp_richcompare, deque_richcompare},
{Py_tp_iter, deque_iter},
{Py_tp_getset, deque_getset},
{Py_tp_init, deque_init},
{Py_tp_alloc, PyType_GenericAlloc},
{Py_tp_new, deque_new},
{Py_tp_free, PyObject_GC_Del},
{Py_tp_methods, deque_methods},
{Py_tp_members, deque_members},
// Sequence protocol
{Py_sq_length, deque_len},
{Py_sq_concat, deque_concat},
{Py_sq_repeat, deque_repeat},
{Py_sq_item, deque_item},
{Py_sq_ass_item, deque_ass_item},
{Py_sq_contains, deque_contains},
{Py_sq_inplace_concat, deque_inplace_concat},
{Py_sq_inplace_repeat, deque_inplace_repeat},
{0, NULL},
};
static PyType_Spec deque_spec = {
.name = "collections.deque",
.basicsize = sizeof(dequeobject),
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_SEQUENCE |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = deque_slots,
};
/*********************** Deque Iterator **************************/
@ -1658,14 +1689,13 @@ typedef struct {
Py_ssize_t counter; /* number of items remaining for iteration */
} dequeiterobject;
static PyTypeObject dequeiter_type;
static PyObject *
deque_iter(dequeobject *deque)
{
dequeiterobject *it;
it = PyObject_GC_New(dequeiterobject, &dequeiter_type);
collections_state *state = find_module_state_by_def(Py_TYPE(deque));
it = PyObject_GC_New(dequeiterobject, state->dequeiter_type);
if (it == NULL)
return NULL;
it->b = deque->leftblock;
@ -1680,17 +1710,27 @@ deque_iter(dequeobject *deque)
static int
dequeiter_traverse(dequeiterobject *dio, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(dio));
Py_VISIT(dio->deque);
return 0;
}
static int
dequeiter_clear(dequeiterobject *dio)
{
Py_CLEAR(dio->deque);
return 0;
}
static void
dequeiter_dealloc(dequeiterobject *dio)
{
/* bpo-31095: UnTrack is needed before calling any callbacks */
PyTypeObject *tp = Py_TYPE(dio);
PyObject_GC_UnTrack(dio);
Py_XDECREF(dio->deque);
(void)dequeiter_clear(dio);
PyObject_GC_Del(dio);
Py_DECREF(tp);
}
static PyObject *
@ -1726,9 +1766,10 @@ dequeiter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Py_ssize_t i, index=0;
PyObject *deque;
dequeiterobject *it;
if (!PyArg_ParseTuple(args, "O!|n", &deque_type, &deque, &index))
collections_state *state = get_module_state_by_cls(type);
if (!PyArg_ParseTuple(args, "O!|n", state->deque_type, &deque, &index))
return NULL;
assert(type == &dequeiter_type);
assert(type == state->dequeiter_type);
it = (dequeiterobject*)deque_iter((dequeobject *)deque);
if (!it)
@ -1769,59 +1810,35 @@ static PyMethodDef dequeiter_methods[] = {
{NULL, NULL} /* sentinel */
};
static PyTypeObject dequeiter_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_collections._deque_iterator", /* tp_name */
sizeof(dequeiterobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)dequeiter_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)dequeiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)dequeiter_next, /* tp_iternext */
dequeiter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
dequeiter_new, /* tp_new */
0,
static PyType_Slot dequeiter_slots[] = {
{Py_tp_dealloc, dequeiter_dealloc},
{Py_tp_getattro, PyObject_GenericGetAttr},
{Py_tp_traverse, dequeiter_traverse},
{Py_tp_clear, dequeiter_clear},
{Py_tp_iter, PyObject_SelfIter},
{Py_tp_iternext, dequeiter_next},
{Py_tp_methods, dequeiter_methods},
{Py_tp_new, dequeiter_new},
{0, NULL},
};
static PyType_Spec dequeiter_spec = {
.name = "collections._deque_iterator",
.basicsize = sizeof(dequeiterobject),
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = dequeiter_slots,
};
/*********************** Deque Reverse Iterator **************************/
static PyTypeObject dequereviter_type;
static PyObject *
deque_reviter(dequeobject *deque, PyObject *Py_UNUSED(ignored))
{
dequeiterobject *it;
collections_state *state = find_module_state_by_def(Py_TYPE(deque));
it = PyObject_GC_New(dequeiterobject, &dequereviter_type);
it = PyObject_GC_New(dequeiterobject, state->dequereviter_type);
if (it == NULL)
return NULL;
it->b = deque->rightblock;
@ -1866,9 +1883,10 @@ dequereviter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Py_ssize_t i, index=0;
PyObject *deque;
dequeiterobject *it;
if (!PyArg_ParseTuple(args, "O!|n", &deque_type, &deque, &index))
collections_state *state = get_module_state_by_cls(type);
if (!PyArg_ParseTuple(args, "O!|n", state->deque_type, &deque, &index))
return NULL;
assert(type == &dequereviter_type);
assert(type == state->dequereviter_type);
it = (dequeiterobject*)deque_reviter((dequeobject *)deque, NULL);
if (!it)
@ -1889,47 +1907,24 @@ dequereviter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return (PyObject*)it;
}
static PyTypeObject dequereviter_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_collections._deque_reverse_iterator", /* tp_name */
sizeof(dequeiterobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)dequeiter_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)dequeiter_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)dequereviter_next, /* tp_iternext */
dequeiter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
dequereviter_new, /* tp_new */
0,
static PyType_Slot dequereviter_slots[] = {
{Py_tp_dealloc, dequeiter_dealloc},
{Py_tp_getattro, PyObject_GenericGetAttr},
{Py_tp_traverse, dequeiter_traverse},
{Py_tp_clear, dequeiter_clear},
{Py_tp_iter, PyObject_SelfIter},
{Py_tp_iternext, dequereviter_next},
{Py_tp_methods, dequeiter_methods},
{Py_tp_new, dequereviter_new},
{0, NULL},
};
static PyType_Spec dequereviter_spec = {
.name = "collections._deque_reverse_iterator",
.basicsize = sizeof(dequeiterobject),
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = dequereviter_slots,
};
/* defaultdict type *********************************************************/
@ -1939,8 +1934,6 @@ typedef struct {
PyObject *default_factory;
} defdictobject;
static PyTypeObject defdict_type; /* Forward */
PyDoc_STRVAR(defdict_missing_doc,
"__missing__(key) # Called by __getitem__ for missing key; pseudo-code:\n\
if self.default_factory is None: raise KeyError((key,))\n\
@ -2071,9 +2064,11 @@ static void
defdict_dealloc(defdictobject *dd)
{
/* bpo-31095: UnTrack is needed before calling any callbacks */
PyTypeObject *tp = Py_TYPE(dd);
PyObject_GC_UnTrack(dd);
Py_CLEAR(dd->default_factory);
PyDict_Type.tp_dealloc((PyObject *)dd);
Py_DECREF(tp);
}
static PyObject *
@ -2117,11 +2112,24 @@ static PyObject*
defdict_or(PyObject* left, PyObject* right)
{
PyObject *self, *other;
if (PyObject_TypeCheck(left, &defdict_type)) {
// Find module state
PyTypeObject *tp = Py_TYPE(left);
PyObject *mod = PyType_GetModuleByDef(tp, &_collectionsmodule);
if (mod == NULL) {
PyErr_Clear();
tp = Py_TYPE(right);
mod = PyType_GetModuleByDef(tp, &_collectionsmodule);
}
assert(mod != NULL);
collections_state *state = get_module_state(mod);
if (PyObject_TypeCheck(left, state->defdict_type)) {
self = left;
other = right;
}
else {
assert(PyObject_TypeCheck(right, state->defdict_type));
self = right;
other = left;
}
@ -2141,13 +2149,10 @@ defdict_or(PyObject* left, PyObject* right)
return new;
}
static PyNumberMethods defdict_as_number = {
.nb_or = defdict_or,
};
static int
defdict_traverse(PyObject *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
Py_VISIT(((defdictobject *)self)->default_factory);
return PyDict_Type.tp_traverse(self, visit, arg);
}
@ -2203,48 +2208,28 @@ passed to the dict constructor, including keyword arguments.\n\
/* See comment in xxsubtype.c */
#define DEFERRED_ADDRESS(ADDR) 0
static PyTypeObject defdict_type = {
PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
"collections.defaultdict", /* tp_name */
sizeof(defdictobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)defdict_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
(reprfunc)defdict_repr, /* tp_repr */
&defdict_as_number, /* 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_BASETYPE | Py_TPFLAGS_HAVE_GC,
/* tp_flags */
defdict_doc, /* tp_doc */
defdict_traverse, /* tp_traverse */
(inquiry)defdict_tp_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset*/
0, /* tp_iter */
0, /* tp_iternext */
defdict_methods, /* tp_methods */
defdict_members, /* tp_members */
0, /* tp_getset */
DEFERRED_ADDRESS(&PyDict_Type), /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
defdict_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
0, /* tp_new */
PyObject_GC_Del, /* tp_free */
static PyType_Slot defdict_slots[] = {
{Py_tp_dealloc, defdict_dealloc},
{Py_tp_repr, defdict_repr},
{Py_nb_or, defdict_or},
{Py_tp_getattro, PyObject_GenericGetAttr},
{Py_tp_doc, (void *)defdict_doc},
{Py_tp_traverse, defdict_traverse},
{Py_tp_clear, defdict_tp_clear},
{Py_tp_methods, defdict_methods},
{Py_tp_members, defdict_members},
{Py_tp_init, defdict_init},
{Py_tp_alloc, PyType_GenericAlloc},
{Py_tp_free, PyObject_GC_Del},
{0, NULL},
};
static PyType_Spec defdict_spec = {
.name = "collections.defaultdict",
.basicsize = sizeof(defdictobject),
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = defdict_slots,
};
/* helper function for Counter *********************************************/
@ -2442,6 +2427,7 @@ static int
tuplegetter_traverse(PyObject *self, visitproc visit, void *arg)
{
_tuplegetterobject *tuplegetter = (_tuplegetterobject *)self;
Py_VISIT(Py_TYPE(tuplegetter));
Py_VISIT(tuplegetter->doc);
return 0;
}
@ -2457,9 +2443,11 @@ tuplegetter_clear(PyObject *self)
static void
tuplegetter_dealloc(_tuplegetterobject *self)
{
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
tuplegetter_clear((PyObject*)self);
Py_TYPE(self)->tp_free((PyObject*)self);
tp->tp_free((PyObject*)self);
Py_DECREF(tp);
}
static PyObject*
@ -2487,52 +2475,60 @@ static PyMethodDef tuplegetter_methods[] = {
{NULL},
};
static PyTypeObject tuplegetter_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_collections._tuplegetter", /* tp_name */
sizeof(_tuplegetterobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)tuplegetter_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
(reprfunc)tuplegetter_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
(traverseproc)tuplegetter_traverse, /* tp_traverse */
(inquiry)tuplegetter_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
tuplegetter_methods, /* tp_methods */
tuplegetter_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
tuplegetter_descr_get, /* tp_descr_get */
tuplegetter_descr_set, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
tuplegetter_new, /* tp_new */
0,
static PyType_Slot tuplegetter_slots[] = {
{Py_tp_dealloc, tuplegetter_dealloc},
{Py_tp_repr, tuplegetter_repr},
{Py_tp_traverse, tuplegetter_traverse},
{Py_tp_clear, tuplegetter_clear},
{Py_tp_methods, tuplegetter_methods},
{Py_tp_members, tuplegetter_members},
{Py_tp_descr_get, tuplegetter_descr_get},
{Py_tp_descr_set, tuplegetter_descr_set},
{Py_tp_new, tuplegetter_new},
{0, NULL},
};
static PyType_Spec tuplegetter_spec = {
.name = "collections._tuplegetter",
.basicsize = sizeof(_tuplegetterobject),
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = tuplegetter_slots,
};
/* module level code ********************************************************/
static int
collections_traverse(PyObject *mod, visitproc visit, void *arg)
{
collections_state *state = get_module_state(mod);
Py_VISIT(state->deque_type);
Py_VISIT(state->defdict_type);
Py_VISIT(state->dequeiter_type);
Py_VISIT(state->dequereviter_type);
Py_VISIT(state->tuplegetter_type);
return 0;
}
static int
collections_clear(PyObject *mod)
{
collections_state *state = get_module_state(mod);
Py_CLEAR(state->deque_type);
Py_CLEAR(state->defdict_type);
Py_CLEAR(state->dequeiter_type);
Py_CLEAR(state->dequereviter_type);
Py_CLEAR(state->tuplegetter_type);
return 0;
}
static void
collections_free(void *module)
{
collections_clear((PyObject *)module);
}
PyDoc_STRVAR(collections_doc,
"High performance data structures.\n\
- deque: ordered collection accessible from endpoints only\n\
@ -2544,43 +2540,50 @@ static struct PyMethodDef collections_methods[] = {
{NULL, NULL} /* sentinel */
};
#define ADD_TYPE(MOD, SPEC, TYPE, BASE) do { \
TYPE = (PyTypeObject *)PyType_FromMetaclass(NULL, MOD, SPEC, \
(PyObject *)BASE); \
if (TYPE == NULL) { \
return -1; \
} \
if (PyModule_AddType(MOD, TYPE) < 0) { \
return -1; \
} \
} while (0)
static int
collections_exec(PyObject *module) {
PyTypeObject *typelist[] = {
&deque_type,
&defdict_type,
&PyODict_Type,
&dequeiter_type,
&dequereviter_type,
&tuplegetter_type
};
collections_state *state = get_module_state(module);
ADD_TYPE(module, &deque_spec, state->deque_type, NULL);
ADD_TYPE(module, &defdict_spec, state->defdict_type, &PyDict_Type);
ADD_TYPE(module, &dequeiter_spec, state->dequeiter_type, NULL);
ADD_TYPE(module, &dequereviter_spec, state->dequereviter_type, NULL);
ADD_TYPE(module, &tuplegetter_spec, state->tuplegetter_type, NULL);
defdict_type.tp_base = &PyDict_Type;
for (size_t i = 0; i < Py_ARRAY_LENGTH(typelist); i++) {
if (PyModule_AddType(module, typelist[i]) < 0) {
return -1;
}
if (PyModule_AddType(module, &PyODict_Type) < 0) {
return -1;
}
return 0;
}
#undef ADD_TYPE
static struct PyModuleDef_Slot collections_slots[] = {
{Py_mod_exec, collections_exec},
{0, NULL}
};
static struct PyModuleDef _collectionsmodule = {
PyModuleDef_HEAD_INIT,
"_collections",
collections_doc,
0,
collections_methods,
collections_slots,
NULL,
NULL,
NULL
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "_collections",
.m_doc = collections_doc,
.m_size = sizeof(collections_state),
.m_methods = collections_methods,
.m_slots = collections_slots,
.m_traverse = collections_traverse,
.m_clear = collections_clear,
.m_free = collections_free,
};
PyMODINIT_FUNC

View File

@ -46,7 +46,7 @@ static PyObject *
tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
PyTypeObject *base_tp = &tuplegetter_type;
PyTypeObject *base_tp = clinic_state()->tuplegetter_type;
Py_ssize_t index;
PyObject *doc;
@ -75,4 +75,4 @@ tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
exit:
return return_value;
}
/*[clinic end generated code: output=91a0f221c7b1f96c input=a9049054013a1b77]*/
/*[clinic end generated code: output=00e516317d2b8bed input=a9049054013a1b77]*/

View File

@ -316,11 +316,6 @@ Python/instrumentation.c - _PyInstrumentation_MISSING -
##-----------------------
## static types
Modules/_collectionsmodule.c - defdict_type -
Modules/_collectionsmodule.c - deque_type -
Modules/_collectionsmodule.c - dequeiter_type -
Modules/_collectionsmodule.c - dequereviter_type -
Modules/_collectionsmodule.c - tuplegetter_type -
Modules/_io/bufferedio.c - PyBufferedIOBase_Type -
Modules/_io/bytesio.c - _PyBytesIOBuffer_Type -
Modules/_io/iobase.c - PyIOBase_Type -

Can't render this file because it has a wrong number of fields in line 4.