mirror of https://github.com/python/cpython
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
|
@ -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:
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Isolate :mod:`!_collections` (apply :pep:`687`). Patch by Erlend E. Aasland.
|
|
@ -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
|
||||||
|
|
|
@ -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]*/
|
||||||
|
|
|
@ -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.
|
Loading…
Reference in New Issue