Branch data Line data Source code
1 : : /* enumerate object */
2 : :
3 : : #include "Python.h"
4 : : #include "pycore_call.h" // _PyObject_CallNoArgs()
5 : : #include "pycore_long.h" // _PyLong_GetOne()
6 : : #include "pycore_object.h" // _PyObject_GC_TRACK()
7 : :
8 : : #include "clinic/enumobject.c.h"
9 : :
10 : : /*[clinic input]
11 : : class enumerate "enumobject *" "&PyEnum_Type"
12 : : class reversed "reversedobject *" "&PyReversed_Type"
13 : : [clinic start generated code]*/
14 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=d2dfdf1a88c88975]*/
15 : :
16 : : typedef struct {
17 : : PyObject_HEAD
18 : : Py_ssize_t en_index; /* current index of enumeration */
19 : : PyObject* en_sit; /* secondary iterator of enumeration */
20 : : PyObject* en_result; /* result tuple */
21 : : PyObject* en_longindex; /* index for sequences >= PY_SSIZE_T_MAX */
22 : : PyObject* one; /* borrowed reference */
23 : : } enumobject;
24 : :
25 : :
26 : : /*[clinic input]
27 : : @classmethod
28 : : enumerate.__new__ as enum_new
29 : :
30 : : iterable: object
31 : : an object supporting iteration
32 : : start: object = 0
33 : :
34 : : Return an enumerate object.
35 : :
36 : : The enumerate object yields pairs containing a count (from start, which
37 : : defaults to zero) and a value yielded by the iterable argument.
38 : :
39 : : enumerate is useful for obtaining an indexed list:
40 : : (0, seq[0]), (1, seq[1]), (2, seq[2]), ...
41 : : [clinic start generated code]*/
42 : :
43 : : static PyObject *
44 : 354625 : enum_new_impl(PyTypeObject *type, PyObject *iterable, PyObject *start)
45 : : /*[clinic end generated code: output=e95e6e439f812c10 input=782e4911efcb8acf]*/
46 : : {
47 : : enumobject *en;
48 : :
49 : 354625 : en = (enumobject *)type->tp_alloc(type, 0);
50 [ - + ]: 354625 : if (en == NULL)
51 : 0 : return NULL;
52 [ + + ]: 354625 : if (start != NULL) {
53 : 41722 : start = PyNumber_Index(start);
54 [ + + ]: 41722 : if (start == NULL) {
55 : 7 : Py_DECREF(en);
56 : 7 : return NULL;
57 : : }
58 : : assert(PyLong_Check(start));
59 : 41715 : en->en_index = PyLong_AsSsize_t(start);
60 [ + + + + ]: 41715 : if (en->en_index == -1 && PyErr_Occurred()) {
61 : 33 : PyErr_Clear();
62 : 33 : en->en_index = PY_SSIZE_T_MAX;
63 : 33 : en->en_longindex = start;
64 : : } else {
65 : 41682 : en->en_longindex = NULL;
66 : 41682 : Py_DECREF(start);
67 : : }
68 : : } else {
69 : 312903 : en->en_index = 0;
70 : 312903 : en->en_longindex = NULL;
71 : : }
72 : 354618 : en->en_sit = PyObject_GetIter(iterable);
73 [ + + ]: 354618 : if (en->en_sit == NULL) {
74 : 26 : Py_DECREF(en);
75 : 26 : return NULL;
76 : : }
77 : 354592 : en->en_result = PyTuple_Pack(2, Py_None, Py_None);
78 [ - + ]: 354592 : if (en->en_result == NULL) {
79 : 0 : Py_DECREF(en);
80 : 0 : return NULL;
81 : : }
82 : 354592 : en->one = _PyLong_GetOne(); /* borrowed reference */
83 : 354592 : return (PyObject *)en;
84 : : }
85 : :
86 : 726 : static int check_keyword(PyObject *kwnames, int index,
87 : : const char *name)
88 : : {
89 : 726 : PyObject *kw = PyTuple_GET_ITEM(kwnames, index);
90 [ + + ]: 726 : if (!_PyUnicode_EqualToASCIIString(kw, name)) {
91 : 16 : PyErr_Format(PyExc_TypeError,
92 : : "'%S' is an invalid keyword argument for enumerate()", kw);
93 : 16 : return 0;
94 : : }
95 : 710 : return 1;
96 : : }
97 : :
98 : : // TODO: Use AC when bpo-43447 is supported
99 : : static PyObject *
100 : 354611 : enumerate_vectorcall(PyObject *type, PyObject *const *args,
101 : : size_t nargsf, PyObject *kwnames)
102 : : {
103 : 354611 : PyTypeObject *tp = _PyType_CAST(type);
104 : 354611 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
105 : 354611 : Py_ssize_t nkwargs = 0;
106 [ + + ]: 354611 : if (kwnames != NULL) {
107 : 718 : nkwargs = PyTuple_GET_SIZE(kwnames);
108 : : }
109 : :
110 : : // Manually implement enumerate(iterable, start=...)
111 [ + + ]: 354611 : if (nargs + nkwargs == 2) {
112 [ + + ]: 41712 : if (nkwargs == 1) {
113 [ - + ]: 690 : if (!check_keyword(kwnames, 0, "start")) {
114 : 0 : return NULL;
115 : : }
116 [ + + ]: 41022 : } else if (nkwargs == 2) {
117 : 20 : PyObject *kw0 = PyTuple_GET_ITEM(kwnames, 0);
118 [ + + ]: 20 : if (_PyUnicode_EqualToASCIIString(kw0, "start")) {
119 [ + + ]: 8 : if (!check_keyword(kwnames, 1, "iterable")) {
120 : 4 : return NULL;
121 : : }
122 : 4 : return enum_new_impl(tp, args[1], args[0]);
123 : : }
124 [ + + + + ]: 20 : if (!check_keyword(kwnames, 0, "iterable") ||
125 : 8 : !check_keyword(kwnames, 1, "start")) {
126 : 8 : return NULL;
127 : : }
128 : :
129 : : }
130 : 41696 : return enum_new_impl(tp, args[0], args[1]);
131 : : }
132 : :
133 [ + + ]: 312899 : if (nargs + nkwargs == 1) {
134 [ + + + + ]: 312891 : if (nkwargs == 1 && !check_keyword(kwnames, 0, "iterable")) {
135 : 4 : return NULL;
136 : : }
137 : 312887 : return enum_new_impl(tp, args[0], NULL);
138 : : }
139 : :
140 [ + + ]: 8 : if (nargs == 0) {
141 : 4 : PyErr_SetString(PyExc_TypeError,
142 : : "enumerate() missing required argument 'iterable'");
143 : 4 : return NULL;
144 : : }
145 : :
146 : 4 : PyErr_Format(PyExc_TypeError,
147 : : "enumerate() takes at most 2 arguments (%d given)", nargs + nkwargs);
148 : 4 : return NULL;
149 : : }
150 : :
151 : : static void
152 : 354625 : enum_dealloc(enumobject *en)
153 : : {
154 : 354625 : PyObject_GC_UnTrack(en);
155 : 354625 : Py_XDECREF(en->en_sit);
156 : 354625 : Py_XDECREF(en->en_result);
157 : 354625 : Py_XDECREF(en->en_longindex);
158 : 354625 : Py_TYPE(en)->tp_free(en);
159 : 354625 : }
160 : :
161 : : static int
162 : 64258 : enum_traverse(enumobject *en, visitproc visit, void *arg)
163 : : {
164 [ + + - + ]: 64258 : Py_VISIT(en->en_sit);
165 [ + + - + ]: 64258 : Py_VISIT(en->en_result);
166 [ + + - + ]: 64258 : Py_VISIT(en->en_longindex);
167 : 64258 : return 0;
168 : : }
169 : :
170 : : static PyObject *
171 : 52 : enum_next_long(enumobject *en, PyObject* next_item)
172 : : {
173 : 52 : PyObject *result = en->en_result;
174 : : PyObject *next_index;
175 : : PyObject *stepped_up;
176 : : PyObject *old_index;
177 : : PyObject *old_item;
178 : :
179 [ - + ]: 52 : if (en->en_longindex == NULL) {
180 : 0 : en->en_longindex = PyLong_FromSsize_t(PY_SSIZE_T_MAX);
181 [ # # ]: 0 : if (en->en_longindex == NULL) {
182 : 0 : Py_DECREF(next_item);
183 : 0 : return NULL;
184 : : }
185 : : }
186 : 52 : next_index = en->en_longindex;
187 : : assert(next_index != NULL);
188 : 52 : stepped_up = PyNumber_Add(next_index, en->one);
189 [ - + ]: 52 : if (stepped_up == NULL) {
190 : 0 : Py_DECREF(next_item);
191 : 0 : return NULL;
192 : : }
193 : 52 : en->en_longindex = stepped_up;
194 : :
195 [ + + ]: 52 : if (Py_REFCNT(result) == 1) {
196 : 24 : Py_INCREF(result);
197 : 24 : old_index = PyTuple_GET_ITEM(result, 0);
198 : 24 : old_item = PyTuple_GET_ITEM(result, 1);
199 : 24 : PyTuple_SET_ITEM(result, 0, next_index);
200 : 24 : PyTuple_SET_ITEM(result, 1, next_item);
201 : 24 : Py_DECREF(old_index);
202 : 24 : Py_DECREF(old_item);
203 : : // bpo-42536: The GC may have untracked this result tuple. Since we're
204 : : // recycling it, make sure it's tracked again:
205 [ + + ]: 24 : if (!_PyObject_GC_IS_TRACKED(result)) {
206 : 1 : _PyObject_GC_TRACK(result);
207 : : }
208 : 24 : return result;
209 : : }
210 : 28 : result = PyTuple_New(2);
211 [ - + ]: 28 : if (result == NULL) {
212 : 0 : Py_DECREF(next_index);
213 : 0 : Py_DECREF(next_item);
214 : 0 : return NULL;
215 : : }
216 : 28 : PyTuple_SET_ITEM(result, 0, next_index);
217 : 28 : PyTuple_SET_ITEM(result, 1, next_item);
218 : 28 : return result;
219 : : }
220 : :
221 : : static PyObject *
222 : 5004691 : enum_next(enumobject *en)
223 : : {
224 : : PyObject *next_index;
225 : : PyObject *next_item;
226 : 5004691 : PyObject *result = en->en_result;
227 : 5004691 : PyObject *it = en->en_sit;
228 : : PyObject *old_index;
229 : : PyObject *old_item;
230 : :
231 : 5004691 : next_item = (*Py_TYPE(it)->tp_iternext)(it);
232 [ + + ]: 5004691 : if (next_item == NULL)
233 : 352267 : return NULL;
234 : :
235 [ + + ]: 4652424 : if (en->en_index == PY_SSIZE_T_MAX)
236 : 52 : return enum_next_long(en, next_item);
237 : :
238 : 4652372 : next_index = PyLong_FromSsize_t(en->en_index);
239 [ - + ]: 4652372 : if (next_index == NULL) {
240 : 0 : Py_DECREF(next_item);
241 : 0 : return NULL;
242 : : }
243 : 4652372 : en->en_index++;
244 : :
245 [ + + ]: 4652372 : if (Py_REFCNT(result) == 1) {
246 : 4442220 : Py_INCREF(result);
247 : 4442220 : old_index = PyTuple_GET_ITEM(result, 0);
248 : 4442220 : old_item = PyTuple_GET_ITEM(result, 1);
249 : 4442220 : PyTuple_SET_ITEM(result, 0, next_index);
250 : 4442220 : PyTuple_SET_ITEM(result, 1, next_item);
251 : 4442220 : Py_DECREF(old_index);
252 : 4442220 : Py_DECREF(old_item);
253 : : // bpo-42536: The GC may have untracked this result tuple. Since we're
254 : : // recycling it, make sure it's tracked again:
255 [ + + ]: 4442220 : if (!_PyObject_GC_IS_TRACKED(result)) {
256 : 497 : _PyObject_GC_TRACK(result);
257 : : }
258 : 4442220 : return result;
259 : : }
260 : 210152 : result = PyTuple_New(2);
261 [ - + ]: 210152 : if (result == NULL) {
262 : 0 : Py_DECREF(next_index);
263 : 0 : Py_DECREF(next_item);
264 : 0 : return NULL;
265 : : }
266 : 210152 : PyTuple_SET_ITEM(result, 0, next_index);
267 : 210152 : PyTuple_SET_ITEM(result, 1, next_item);
268 : 210152 : return result;
269 : : }
270 : :
271 : : static PyObject *
272 : 78 : enum_reduce(enumobject *en, PyObject *Py_UNUSED(ignored))
273 : : {
274 [ + + ]: 78 : if (en->en_longindex != NULL)
275 : 12 : return Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en->en_longindex);
276 : : else
277 : 66 : return Py_BuildValue("O(On)", Py_TYPE(en), en->en_sit, en->en_index);
278 : : }
279 : :
280 : : PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
281 : :
282 : : static PyMethodDef enum_methods[] = {
283 : : {"__reduce__", (PyCFunction)enum_reduce, METH_NOARGS, reduce_doc},
284 : : {"__class_getitem__", Py_GenericAlias,
285 : : METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
286 : : {NULL, NULL} /* sentinel */
287 : : };
288 : :
289 : : PyTypeObject PyEnum_Type = {
290 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
291 : : "enumerate", /* tp_name */
292 : : sizeof(enumobject), /* tp_basicsize */
293 : : 0, /* tp_itemsize */
294 : : /* methods */
295 : : (destructor)enum_dealloc, /* tp_dealloc */
296 : : 0, /* tp_vectorcall_offset */
297 : : 0, /* tp_getattr */
298 : : 0, /* tp_setattr */
299 : : 0, /* tp_as_async */
300 : : 0, /* tp_repr */
301 : : 0, /* tp_as_number */
302 : : 0, /* tp_as_sequence */
303 : : 0, /* tp_as_mapping */
304 : : 0, /* tp_hash */
305 : : 0, /* tp_call */
306 : : 0, /* tp_str */
307 : : PyObject_GenericGetAttr, /* tp_getattro */
308 : : 0, /* tp_setattro */
309 : : 0, /* tp_as_buffer */
310 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
311 : : Py_TPFLAGS_BASETYPE, /* tp_flags */
312 : : enum_new__doc__, /* tp_doc */
313 : : (traverseproc)enum_traverse, /* tp_traverse */
314 : : 0, /* tp_clear */
315 : : 0, /* tp_richcompare */
316 : : 0, /* tp_weaklistoffset */
317 : : PyObject_SelfIter, /* tp_iter */
318 : : (iternextfunc)enum_next, /* tp_iternext */
319 : : enum_methods, /* tp_methods */
320 : : 0, /* tp_members */
321 : : 0, /* tp_getset */
322 : : 0, /* tp_base */
323 : : 0, /* tp_dict */
324 : : 0, /* tp_descr_get */
325 : : 0, /* tp_descr_set */
326 : : 0, /* tp_dictoffset */
327 : : 0, /* tp_init */
328 : : PyType_GenericAlloc, /* tp_alloc */
329 : : enum_new, /* tp_new */
330 : : PyObject_GC_Del, /* tp_free */
331 : : .tp_vectorcall = (vectorcallfunc)enumerate_vectorcall
332 : : };
333 : :
334 : : /* Reversed Object ***************************************************************/
335 : :
336 : : typedef struct {
337 : : PyObject_HEAD
338 : : Py_ssize_t index;
339 : : PyObject* seq;
340 : : } reversedobject;
341 : :
342 : : /*[clinic input]
343 : : @classmethod
344 : : reversed.__new__ as reversed_new
345 : :
346 : : sequence as seq: object
347 : : /
348 : :
349 : : Return a reverse iterator over the values of the given sequence.
350 : : [clinic start generated code]*/
351 : :
352 : : static PyObject *
353 : 135331 : reversed_new_impl(PyTypeObject *type, PyObject *seq)
354 : : /*[clinic end generated code: output=f7854cc1df26f570 input=aeb720361e5e3f1d]*/
355 : : {
356 : : Py_ssize_t n;
357 : : PyObject *reversed_meth;
358 : : reversedobject *ro;
359 : :
360 : 135331 : reversed_meth = _PyObject_LookupSpecial(seq, &_Py_ID(__reversed__));
361 [ + + ]: 135331 : if (reversed_meth == Py_None) {
362 : 2 : Py_DECREF(reversed_meth);
363 : 2 : PyErr_Format(PyExc_TypeError,
364 : : "'%.200s' object is not reversible",
365 : 2 : Py_TYPE(seq)->tp_name);
366 : 2 : return NULL;
367 : : }
368 [ + + ]: 135329 : if (reversed_meth != NULL) {
369 : 125894 : PyObject *res = _PyObject_CallNoArgs(reversed_meth);
370 : 125894 : Py_DECREF(reversed_meth);
371 : 125894 : return res;
372 : : }
373 [ + + ]: 9435 : else if (PyErr_Occurred())
374 : 1 : return NULL;
375 : :
376 [ + + ]: 9434 : if (!PySequence_Check(seq)) {
377 : 11 : PyErr_Format(PyExc_TypeError,
378 : : "'%.200s' object is not reversible",
379 : 11 : Py_TYPE(seq)->tp_name);
380 : 11 : return NULL;
381 : : }
382 : :
383 : 9423 : n = PySequence_Size(seq);
384 [ + + ]: 9423 : if (n == -1)
385 : 1 : return NULL;
386 : :
387 : 9422 : ro = (reversedobject *)type->tp_alloc(type, 0);
388 [ - + ]: 9422 : if (ro == NULL)
389 : 0 : return NULL;
390 : :
391 : 9422 : ro->index = n-1;
392 : 9422 : Py_INCREF(seq);
393 : 9422 : ro->seq = seq;
394 : 9422 : return (PyObject *)ro;
395 : : }
396 : :
397 : : static PyObject *
398 : 135334 : reversed_vectorcall(PyObject *type, PyObject * const*args,
399 : : size_t nargsf, PyObject *kwnames)
400 : : {
401 [ + + + - ]: 135334 : if (!_PyArg_NoKwnames("reversed", kwnames)) {
402 : 1 : return NULL;
403 : : }
404 : :
405 : 135333 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
406 [ + + + + : 135333 : if (!_PyArg_CheckPositional("reversed", nargs, 1, 1)) {
+ - ]
407 : 2 : return NULL;
408 : : }
409 : :
410 : 135331 : return reversed_new_impl(_PyType_CAST(type), args[0]);
411 : : }
412 : :
413 : : static void
414 : 9422 : reversed_dealloc(reversedobject *ro)
415 : : {
416 : 9422 : PyObject_GC_UnTrack(ro);
417 : 9422 : Py_XDECREF(ro->seq);
418 : 9422 : Py_TYPE(ro)->tp_free(ro);
419 : 9422 : }
420 : :
421 : : static int
422 : 150 : reversed_traverse(reversedobject *ro, visitproc visit, void *arg)
423 : : {
424 [ + + - + ]: 150 : Py_VISIT(ro->seq);
425 : 150 : return 0;
426 : : }
427 : :
428 : : static PyObject *
429 : 23581 : reversed_next(reversedobject *ro)
430 : : {
431 : : PyObject *item;
432 : 23581 : Py_ssize_t index = ro->index;
433 : :
434 [ + + ]: 23581 : if (index >= 0) {
435 : 15829 : item = PySequence_GetItem(ro->seq, index);
436 [ + - ]: 15829 : if (item != NULL) {
437 : 15829 : ro->index--;
438 : 15829 : return item;
439 : : }
440 [ # # # # ]: 0 : if (PyErr_ExceptionMatches(PyExc_IndexError) ||
441 : 0 : PyErr_ExceptionMatches(PyExc_StopIteration))
442 : 0 : PyErr_Clear();
443 : : }
444 : 7752 : ro->index = -1;
445 [ + + ]: 7752 : Py_CLEAR(ro->seq);
446 : 7752 : return NULL;
447 : : }
448 : :
449 : : static PyObject *
450 : 1662 : reversed_len(reversedobject *ro, PyObject *Py_UNUSED(ignored))
451 : : {
452 : : Py_ssize_t position, seqsize;
453 : :
454 [ + + ]: 1662 : if (ro->seq == NULL)
455 : 15 : return PyLong_FromLong(0);
456 : 1647 : seqsize = PySequence_Size(ro->seq);
457 [ + + ]: 1647 : if (seqsize == -1)
458 : 1 : return NULL;
459 : 1646 : position = ro->index + 1;
460 [ + - ]: 1646 : return PyLong_FromSsize_t((seqsize < position) ? 0 : position);
461 : : }
462 : :
463 : : PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
464 : :
465 : : static PyObject *
466 : 348 : reversed_reduce(reversedobject *ro, PyObject *Py_UNUSED(ignored))
467 : : {
468 [ + + ]: 348 : if (ro->seq)
469 : 270 : return Py_BuildValue("O(O)n", Py_TYPE(ro), ro->seq, ro->index);
470 : : else
471 : 78 : return Py_BuildValue("O(())", Py_TYPE(ro));
472 : : }
473 : :
474 : : static PyObject *
475 : 282 : reversed_setstate(reversedobject *ro, PyObject *state)
476 : : {
477 : 282 : Py_ssize_t index = PyLong_AsSsize_t(state);
478 [ + + - + ]: 282 : if (index == -1 && PyErr_Occurred())
479 : 0 : return NULL;
480 [ + - ]: 282 : if (ro->seq != 0) {
481 : 282 : Py_ssize_t n = PySequence_Size(ro->seq);
482 [ - + ]: 282 : if (n < 0)
483 : 0 : return NULL;
484 [ - + ]: 282 : if (index < -1)
485 : 0 : index = -1;
486 [ - + ]: 282 : else if (index > n-1)
487 : 0 : index = n-1;
488 : 282 : ro->index = index;
489 : : }
490 : 282 : Py_RETURN_NONE;
491 : : }
492 : :
493 : : PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
494 : :
495 : : static PyMethodDef reversediter_methods[] = {
496 : : {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc},
497 : : {"__reduce__", (PyCFunction)reversed_reduce, METH_NOARGS, reduce_doc},
498 : : {"__setstate__", (PyCFunction)reversed_setstate, METH_O, setstate_doc},
499 : : {NULL, NULL} /* sentinel */
500 : : };
501 : :
502 : : PyTypeObject PyReversed_Type = {
503 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
504 : : "reversed", /* tp_name */
505 : : sizeof(reversedobject), /* tp_basicsize */
506 : : 0, /* tp_itemsize */
507 : : /* methods */
508 : : (destructor)reversed_dealloc, /* tp_dealloc */
509 : : 0, /* tp_vectorcall_offset */
510 : : 0, /* tp_getattr */
511 : : 0, /* tp_setattr */
512 : : 0, /* tp_as_async */
513 : : 0, /* tp_repr */
514 : : 0, /* tp_as_number */
515 : : 0, /* tp_as_sequence */
516 : : 0, /* tp_as_mapping */
517 : : 0, /* tp_hash */
518 : : 0, /* tp_call */
519 : : 0, /* tp_str */
520 : : PyObject_GenericGetAttr, /* tp_getattro */
521 : : 0, /* tp_setattro */
522 : : 0, /* tp_as_buffer */
523 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
524 : : Py_TPFLAGS_BASETYPE, /* tp_flags */
525 : : reversed_new__doc__, /* tp_doc */
526 : : (traverseproc)reversed_traverse,/* tp_traverse */
527 : : 0, /* tp_clear */
528 : : 0, /* tp_richcompare */
529 : : 0, /* tp_weaklistoffset */
530 : : PyObject_SelfIter, /* tp_iter */
531 : : (iternextfunc)reversed_next, /* tp_iternext */
532 : : reversediter_methods, /* tp_methods */
533 : : 0, /* tp_members */
534 : : 0, /* tp_getset */
535 : : 0, /* tp_base */
536 : : 0, /* tp_dict */
537 : : 0, /* tp_descr_get */
538 : : 0, /* tp_descr_set */
539 : : 0, /* tp_dictoffset */
540 : : 0, /* tp_init */
541 : : PyType_GenericAlloc, /* tp_alloc */
542 : : reversed_new, /* tp_new */
543 : : PyObject_GC_Del, /* tp_free */
544 : : .tp_vectorcall = (vectorcallfunc)reversed_vectorcall,
545 : : };
|