mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	gh-103092: Isolate _collections (#103093)
				
					
				
			Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									411b169281
								
							
						
					
					
						commit
						52f96d3ea3
					
				
					 5 changed files with 286 additions and 282 deletions
				
			
		| 
						 | 
				
			
			@ -45,6 +45,11 @@
 | 
			
		|||
else:
 | 
			
		||||
    _collections_abc.MutableSequence.register(deque)
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    from _collections import _deque_iterator
 | 
			
		||||
except ImportError:
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    from _collections import defaultdict
 | 
			
		||||
except ImportError:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
Isolate :mod:`!_collections` (apply :pep:`687`). Patch by Erlend E. Aasland.
 | 
			
		||||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
    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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								Modules/clinic/_collectionsmodule.c.h
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								Modules/clinic/_collectionsmodule.c.h
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -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]*/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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. 
		
	 | 
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue