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

View File

@ -46,7 +46,7 @@ static PyObject *
tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{ {
PyObject *return_value = NULL; PyObject *return_value = NULL;
PyTypeObject *base_tp = &tuplegetter_type; PyTypeObject *base_tp = clinic_state()->tuplegetter_type;
Py_ssize_t index; Py_ssize_t index;
PyObject *doc; PyObject *doc;
@ -75,4 +75,4 @@ tuplegetter_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
exit: exit:
return return_value; 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 ## 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/bufferedio.c - PyBufferedIOBase_Type -
Modules/_io/bytesio.c - _PyBytesIOBuffer_Type - Modules/_io/bytesio.c - _PyBytesIOBuffer_Type -
Modules/_io/iobase.c - PyIOBase_Type - Modules/_io/iobase.c - PyIOBase_Type -

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