/home/mdboom/Work/builds/cpython/Objects/enumobject.c
Line | Count | Source (jump to first uncovered line) |
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 | enum_new_impl(PyTypeObject *type, PyObject *iterable, PyObject *start) |
45 | /*[clinic end generated code: output=e95e6e439f812c10 input=782e4911efcb8acf]*/ |
46 | { |
47 | enumobject *en; |
48 | |
49 | en = (enumobject *)type->tp_alloc(type, 0); |
50 | if (en == NULL) Branch (50:9): [True: 0, False: 129k]
|
51 | return NULL; |
52 | if (start != NULL) { Branch (52:9): [True: 3.63k, False: 125k]
|
53 | start = PyNumber_Index(start); |
54 | if (start == NULL) { Branch (54:13): [True: 7, False: 3.63k]
|
55 | Py_DECREF(en); |
56 | return NULL; |
57 | } |
58 | assert(PyLong_Check(start)); |
59 | en->en_index = PyLong_AsSsize_t(start); |
60 | if (en->en_index == -1 && PyErr_Occurred()109 ) { Branch (60:13): [True: 109, False: 3.52k]
Branch (60:35): [True: 33, False: 76]
|
61 | PyErr_Clear(); |
62 | en->en_index = PY_SSIZE_T_MAX; |
63 | en->en_longindex = start; |
64 | } else { |
65 | en->en_longindex = NULL; |
66 | Py_DECREF(start); |
67 | } |
68 | } else { |
69 | en->en_index = 0; |
70 | en->en_longindex = NULL; |
71 | } |
72 | en->en_sit = PyObject_GetIter(iterable); |
73 | if (en->en_sit == NULL) { Branch (73:9): [True: 26, False: 129k]
|
74 | Py_DECREF(en); |
75 | return NULL; |
76 | } |
77 | en->en_result = PyTuple_Pack(2, Py_None, Py_None); |
78 | if (en->en_result == NULL) { Branch (78:9): [True: 0, False: 129k]
|
79 | Py_DECREF(en); |
80 | return NULL; |
81 | } |
82 | en->one = _PyLong_GetOne(); /* borrowed reference */ |
83 | return (PyObject *)en; |
84 | } |
85 | |
86 | static int check_keyword(PyObject *kwnames, int index, |
87 | const char *name) |
88 | { |
89 | PyObject *kw = PyTuple_GET_ITEM(kwnames, index); |
90 | if (!_PyUnicode_EqualToASCIIString(kw, name)) { Branch (90:9): [True: 16, False: 704]
|
91 | PyErr_Format(PyExc_TypeError, |
92 | "'%S' is an invalid keyword argument for enumerate()", kw); |
93 | return 0; |
94 | } |
95 | return 1; |
96 | } |
97 | |
98 | // TODO: Use AC when bpo-43447 is supported |
99 | static PyObject * |
100 | enumerate_vectorcall(PyObject *type, PyObject *const *args, |
101 | size_t nargsf, PyObject *kwnames) |
102 | { |
103 | PyTypeObject *tp = _PyType_CAST(type); |
104 | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
105 | Py_ssize_t nkwargs = 0; |
106 | if (kwnames != NULL) { Branch (106:9): [True: 712, False: 128k]
|
107 | nkwargs = PyTuple_GET_SIZE(kwnames); |
108 | } |
109 | |
110 | // Manually implement enumerate(iterable, start=...) |
111 | if (nargs + nkwargs == 2) { Branch (111:9): [True: 3.62k, False: 125k]
|
112 | if (nkwargs == 1) { Branch (112:13): [True: 684, False: 2.94k]
|
113 | if (!check_keyword(kwnames, 0, "start")) { Branch (113:17): [True: 0, False: 684]
|
114 | return NULL; |
115 | } |
116 | } else if (nkwargs == 2) { Branch (116:20): [True: 20, False: 2.92k]
|
117 | PyObject *kw0 = PyTuple_GET_ITEM(kwnames, 0); |
118 | if (_PyUnicode_EqualToASCIIString(kw0, "start")) { Branch (118:17): [True: 8, False: 12]
|
119 | if (!check_keyword(kwnames, 1, "iterable")) { Branch (119:21): [True: 4, False: 4]
|
120 | return NULL; |
121 | } |
122 | return enum_new_impl(tp, args[1], args[0]); |
123 | } |
124 | if (!check_keyword(kwnames, 0, "iterable") || Branch (124:17): [True: 4, False: 8]
|
125 | !check_keyword(kwnames, 1, "start")8 ) { Branch (125:17): [True: 4, False: 4]
|
126 | return NULL; |
127 | } |
128 | |
129 | } |
130 | return enum_new_impl(tp, args[0], args[1]); |
131 | } |
132 | |
133 | if (nargs + nkwargs == 1) { Branch (133:9): [True: 125k, False: 8]
|
134 | if (nkwargs == 1 && !check_keyword(kwnames, 0, "iterable")8 ) { Branch (134:13): [True: 8, False: 125k]
Branch (134:29): [True: 4, False: 4]
|
135 | return NULL; |
136 | } |
137 | return enum_new_impl(tp, args[0], NULL); |
138 | } |
139 | |
140 | if (nargs == 0) { Branch (140:9): [True: 4, False: 4]
|
141 | PyErr_SetString(PyExc_TypeError, |
142 | "enumerate() missing required argument 'iterable'"); |
143 | return NULL; |
144 | } |
145 | |
146 | PyErr_Format(PyExc_TypeError, |
147 | "enumerate() takes at most 2 arguments (%d given)", nargs + nkwargs); |
148 | return NULL; |
149 | } |
150 | |
151 | static void |
152 | enum_dealloc(enumobject *en) |
153 | { |
154 | PyObject_GC_UnTrack(en); |
155 | Py_XDECREF(en->en_sit); |
156 | Py_XDECREF(en->en_result); |
157 | Py_XDECREF(en->en_longindex); |
158 | Py_TYPE(en)->tp_free(en); |
159 | } |
160 | |
161 | static int |
162 | enum_traverse(enumobject *en, visitproc visit, void *arg) |
163 | { |
164 | Py_VISIT(en->en_sit); |
165 | Py_VISIT(en->en_result); |
166 | Py_VISIT(en->en_longindex); |
167 | return 0; |
168 | } |
169 | |
170 | static PyObject * |
171 | enum_next_long(enumobject *en, PyObject* next_item) |
172 | { |
173 | PyObject *result = en->en_result; |
174 | PyObject *next_index; |
175 | PyObject *stepped_up; |
176 | PyObject *old_index; |
177 | PyObject *old_item; |
178 | |
179 | if (en->en_longindex == NULL) { Branch (179:9): [True: 0, False: 52]
|
180 | en->en_longindex = PyLong_FromSsize_t(PY_SSIZE_T_MAX); |
181 | if (en->en_longindex == NULL) { Branch (181:13): [True: 0, False: 0]
|
182 | Py_DECREF(next_item); |
183 | return NULL; |
184 | } |
185 | } |
186 | next_index = en->en_longindex; |
187 | assert(next_index != NULL); |
188 | stepped_up = PyNumber_Add(next_index, en->one); |
189 | if (stepped_up == NULL) { Branch (189:9): [True: 0, False: 52]
|
190 | Py_DECREF(next_item); |
191 | return NULL; |
192 | } |
193 | en->en_longindex = stepped_up; |
194 | |
195 | if (Py_REFCNT(result) == 1) { Branch (195:9): [True: 24, False: 28]
|
196 | Py_INCREF(result); |
197 | old_index = PyTuple_GET_ITEM(result, 0); |
198 | old_item = PyTuple_GET_ITEM(result, 1); |
199 | PyTuple_SET_ITEM(result, 0, next_index); |
200 | PyTuple_SET_ITEM(result, 1, next_item); |
201 | Py_DECREF(old_index); |
202 | 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 | if (!_PyObject_GC_IS_TRACKED(result)) { Branch (205:13): [True: 1, False: 23]
|
206 | _PyObject_GC_TRACK(result); |
207 | } |
208 | return result; |
209 | } |
210 | result = PyTuple_New(2); |
211 | if (result == NULL) { Branch (211:9): [True: 0, False: 28]
|
212 | Py_DECREF(next_index); |
213 | Py_DECREF(next_item); |
214 | return NULL; |
215 | } |
216 | PyTuple_SET_ITEM(result, 0, next_index); |
217 | PyTuple_SET_ITEM(result, 1, next_item); |
218 | return result; |
219 | } |
220 | |
221 | static PyObject * |
222 | enum_next(enumobject *en) |
223 | { |
224 | PyObject *next_index; |
225 | PyObject *next_item; |
226 | PyObject *result = en->en_result; |
227 | PyObject *it = en->en_sit; |
228 | PyObject *old_index; |
229 | PyObject *old_item; |
230 | |
231 | next_item = (*Py_TYPE(it)->tp_iternext)(it); |
232 | if (next_item == NULL) Branch (232:9): [True: 127k, False: 2.87M]
|
233 | return NULL; |
234 | |
235 | if (en->en_index == PY_SSIZE_T_MAX) Branch (235:9): [True: 52, False: 2.87M]
|
236 | return enum_next_long(en, next_item); |
237 | |
238 | next_index = PyLong_FromSsize_t(en->en_index); |
239 | if (next_index == NULL) { Branch (239:9): [True: 0, False: 2.87M]
|
240 | Py_DECREF(next_item); |
241 | return NULL; |
242 | } |
243 | en->en_index++; |
244 | |
245 | if (Py_REFCNT(result) == 1) { Branch (245:9): [True: 2.66M, False: 210k]
|
246 | Py_INCREF(result); |
247 | old_index = PyTuple_GET_ITEM(result, 0); |
248 | old_item = PyTuple_GET_ITEM(result, 1); |
249 | PyTuple_SET_ITEM(result, 0, next_index); |
250 | PyTuple_SET_ITEM(result, 1, next_item); |
251 | Py_DECREF(old_index); |
252 | 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 | if (!_PyObject_GC_IS_TRACKED(result)) { Branch (255:13): [True: 527, False: 2.66M]
|
256 | _PyObject_GC_TRACK(result); |
257 | } |
258 | return result; |
259 | } |
260 | result = PyTuple_New(2); |
261 | if (result == NULL) { Branch (261:9): [True: 0, False: 210k]
|
262 | Py_DECREF(next_index); |
263 | Py_DECREF(next_item); |
264 | return NULL; |
265 | } |
266 | PyTuple_SET_ITEM(result, 0, next_index); |
267 | PyTuple_SET_ITEM(result, 1, next_item); |
268 | return result; |
269 | } |
270 | |
271 | static PyObject * |
272 | enum_reduce(enumobject *en, PyObject *Py_UNUSED(ignored)) |
273 | { |
274 | if (en->en_longindex != NULL) Branch (274:9): [True: 12, False: 66]
|
275 | return Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en->en_longindex); |
276 | else |
277 | 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 | 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 | reversed_meth = _PyObject_LookupSpecial(seq, &_Py_ID(__reversed__)); |
361 | if (reversed_meth == Py_None) { Branch (361:9): [True: 2, False: 118k]
|
362 | Py_DECREF(reversed_meth); |
363 | PyErr_Format(PyExc_TypeError, |
364 | "'%.200s' object is not reversible", |
365 | Py_TYPE(seq)->tp_name); |
366 | return NULL; |
367 | } |
368 | if (reversed_meth != NULL) { Branch (368:9): [True: 114k, False: 4.39k]
|
369 | PyObject *res = _PyObject_CallNoArgs(reversed_meth); |
370 | Py_DECREF(reversed_meth); |
371 | return res; |
372 | } |
373 | else if (PyErr_Occurred()) Branch (373:14): [True: 1, False: 4.39k]
|
374 | return NULL; |
375 | |
376 | if (!PySequence_Check(seq)) { Branch (376:9): [True: 11, False: 4.38k]
|
377 | PyErr_Format(PyExc_TypeError, |
378 | "'%.200s' object is not reversible", |
379 | Py_TYPE(seq)->tp_name); |
380 | return NULL; |
381 | } |
382 | |
383 | n = PySequence_Size(seq); |
384 | if (n == -1) Branch (384:9): [True: 1, False: 4.38k]
|
385 | return NULL; |
386 | |
387 | ro = (reversedobject *)type->tp_alloc(type, 0); |
388 | if (ro == NULL) Branch (388:9): [True: 0, False: 4.38k]
|
389 | return NULL; |
390 | |
391 | ro->index = n-1; |
392 | Py_INCREF(seq); |
393 | ro->seq = seq; |
394 | return (PyObject *)ro; |
395 | } |
396 | |
397 | static PyObject * |
398 | reversed_vectorcall(PyObject *type, PyObject * const*args, |
399 | size_t nargsf, PyObject *kwnames) |
400 | { |
401 | if (!_PyArg_NoKwnames("reversed", kwnames)) { |
402 | return NULL; |
403 | } |
404 | |
405 | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
406 | if (!_PyArg_CheckPositional("reversed", nargs, 1, 1)) { |
407 | return NULL; |
408 | } |
409 | |
410 | return reversed_new_impl(_PyType_CAST(type), args[0]); |
411 | } |
412 | |
413 | static void |
414 | reversed_dealloc(reversedobject *ro) |
415 | { |
416 | PyObject_GC_UnTrack(ro); |
417 | Py_XDECREF(ro->seq); |
418 | Py_TYPE(ro)->tp_free(ro); |
419 | } |
420 | |
421 | static int |
422 | reversed_traverse(reversedobject *ro, visitproc visit, void *arg) |
423 | { |
424 | Py_VISIT(ro->seq); |
425 | return 0; |
426 | } |
427 | |
428 | static PyObject * |
429 | reversed_next(reversedobject *ro) |
430 | { |
431 | PyObject *item; |
432 | Py_ssize_t index = ro->index; |
433 | |
434 | if (index >= 0) { Branch (434:9): [True: 5.40k, False: 3.98k]
|
435 | item = PySequence_GetItem(ro->seq, index); |
436 | if (item != NULL) { Branch (436:13): [True: 5.40k, False: 0]
|
437 | ro->index--; |
438 | return item; |
439 | } |
440 | if (PyErr_ExceptionMatches(PyExc_IndexError) || Branch (440:13): [True: 0, False: 0]
|
441 | PyErr_ExceptionMatches(PyExc_StopIteration)) Branch (441:13): [True: 0, False: 0]
|
442 | PyErr_Clear(); |
443 | } |
444 | ro->index = -1; |
445 | Py_CLEAR(ro->seq); |
446 | return NULL; |
447 | } |
448 | |
449 | static PyObject * |
450 | reversed_len(reversedobject *ro, PyObject *Py_UNUSED(ignored)) |
451 | { |
452 | Py_ssize_t position, seqsize; |
453 | |
454 | if (ro->seq == NULL) Branch (454:9): [True: 15, False: 1.64k]
|
455 | return PyLong_FromLong(0); |
456 | seqsize = PySequence_Size(ro->seq); |
457 | if (seqsize == -1) Branch (457:9): [True: 1, False: 1.64k]
|
458 | return NULL; |
459 | position = ro->index + 1; |
460 | return PyLong_FromSsize_t((seqsize < position) ? 00 : position); Branch (460:31): [True: 0, False: 1.64k]
|
461 | } |
462 | |
463 | PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); |
464 | |
465 | static PyObject * |
466 | reversed_reduce(reversedobject *ro, PyObject *Py_UNUSED(ignored)) |
467 | { |
468 | if (ro->seq) Branch (468:9): [True: 270, False: 78]
|
469 | return Py_BuildValue("O(O)n", Py_TYPE(ro), ro->seq, ro->index); |
470 | else |
471 | return Py_BuildValue("O(())", Py_TYPE(ro)); |
472 | } |
473 | |
474 | static PyObject * |
475 | reversed_setstate(reversedobject *ro, PyObject *state) |
476 | { |
477 | Py_ssize_t index = PyLong_AsSsize_t(state); |
478 | if (index == -1 && PyErr_Occurred()78 ) Branch (478:9): [True: 78, False: 204]
Branch (478:24): [True: 0, False: 78]
|
479 | return NULL; |
480 | if (ro->seq != 0) { Branch (480:9): [True: 282, False: 0]
|
481 | Py_ssize_t n = PySequence_Size(ro->seq); |
482 | if (n < 0) Branch (482:13): [True: 0, False: 282]
|
483 | return NULL; |
484 | if (index < -1) Branch (484:13): [True: 0, False: 282]
|
485 | index = -1; |
486 | else if (index > n-1) Branch (486:18): [True: 0, False: 282]
|
487 | index = n-1; |
488 | ro->index = index; |
489 | } |
490 | Py_RETURN_NONE0 ; |
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 | }; |