1 /*
2 Written by Jim Hugunin and Chris Chase.
3
4 This includes both the singular ellipsis object and slice objects.
5
6 Guido, feel free to do whatever you want in the way of copyrights
7 for this file.
8 */
9
10 /*
11 Py_Ellipsis encodes the '...' rubber index token. It is similar to
12 the Py_NoneStruct in that there is no way to create other objects of
13 this type and there is exactly one in existence.
14 */
15
16 #include "Python.h"
17 #include "pycore_abstract.h" // _PyIndex_Check()
18 #include "pycore_long.h" // _PyLong_GetZero()
19 #include "pycore_modsupport.h" // _PyArg_NoKeywords()
20 #include "pycore_object.h" // _PyObject_GC_TRACK()
21
22
23 static PyObject *
ellipsis_new(PyTypeObject * type,PyObject * args,PyObject * kwargs)24 ellipsis_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
25 {
26 if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) {
27 PyErr_SetString(PyExc_TypeError, "EllipsisType takes no arguments");
28 return NULL;
29 }
30 return Py_Ellipsis;
31 }
32
33 static void
ellipsis_dealloc(PyObject * ellipsis)34 ellipsis_dealloc(PyObject *ellipsis)
35 {
36 /* This should never get called, but we also don't want to SEGV if
37 * we accidentally decref Ellipsis out of existence. Instead,
38 * since Ellipsis is an immortal object, re-set the reference count.
39 */
40 _Py_SetImmortal(ellipsis);
41 }
42
43 static PyObject *
ellipsis_repr(PyObject * op)44 ellipsis_repr(PyObject *op)
45 {
46 return PyUnicode_FromString("Ellipsis");
47 }
48
49 static PyObject *
ellipsis_reduce(PyObject * op,PyObject * Py_UNUSED (ignored))50 ellipsis_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
51 {
52 return PyUnicode_FromString("Ellipsis");
53 }
54
55 static PyMethodDef ellipsis_methods[] = {
56 {"__reduce__", ellipsis_reduce, METH_NOARGS, NULL},
57 {NULL, NULL}
58 };
59
60 PyDoc_STRVAR(ellipsis_doc,
61 "ellipsis()\n"
62 "--\n\n"
63 "The type of the Ellipsis singleton.");
64
65 PyTypeObject PyEllipsis_Type = {
66 PyVarObject_HEAD_INIT(&PyType_Type, 0)
67 "ellipsis", /* tp_name */
68 0, /* tp_basicsize */
69 0, /* tp_itemsize */
70 ellipsis_dealloc, /* tp_dealloc */
71 0, /* tp_vectorcall_offset */
72 0, /* tp_getattr */
73 0, /* tp_setattr */
74 0, /* tp_as_async */
75 ellipsis_repr, /* tp_repr */
76 0, /* tp_as_number */
77 0, /* tp_as_sequence */
78 0, /* tp_as_mapping */
79 0, /* tp_hash */
80 0, /* tp_call */
81 0, /* tp_str */
82 PyObject_GenericGetAttr, /* tp_getattro */
83 0, /* tp_setattro */
84 0, /* tp_as_buffer */
85 Py_TPFLAGS_DEFAULT, /* tp_flags */
86 ellipsis_doc, /* tp_doc */
87 0, /* tp_traverse */
88 0, /* tp_clear */
89 0, /* tp_richcompare */
90 0, /* tp_weaklistoffset */
91 0, /* tp_iter */
92 0, /* tp_iternext */
93 ellipsis_methods, /* tp_methods */
94 0, /* tp_members */
95 0, /* tp_getset */
96 0, /* tp_base */
97 0, /* tp_dict */
98 0, /* tp_descr_get */
99 0, /* tp_descr_set */
100 0, /* tp_dictoffset */
101 0, /* tp_init */
102 0, /* tp_alloc */
103 ellipsis_new, /* tp_new */
104 };
105
106 PyObject _Py_EllipsisObject = _PyObject_HEAD_INIT(&PyEllipsis_Type);
107
108
109 /* Slice object implementation */
110
_PySlice_ClearFreeList(struct _Py_object_freelists * freelists,int is_finalization)111 void _PySlice_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization)
112 {
113 if (!is_finalization) {
114 return;
115 }
116 #ifdef WITH_FREELISTS
117 PySliceObject *obj = freelists->slices.slice_cache;
118 if (obj != NULL) {
119 freelists->slices.slice_cache = NULL;
120 PyObject_GC_Del(obj);
121 }
122 #endif
123 }
124
125 /* start, stop, and step are python objects with None indicating no
126 index is present.
127 */
128
129 static PySliceObject *
_PyBuildSlice_Consume2(PyObject * start,PyObject * stop,PyObject * step)130 _PyBuildSlice_Consume2(PyObject *start, PyObject *stop, PyObject *step)
131 {
132 assert(start != NULL && stop != NULL && step != NULL);
133 PySliceObject *obj;
134 #ifdef WITH_FREELISTS
135 struct _Py_object_freelists *freelists = _Py_object_freelists_GET();
136 if (freelists->slices.slice_cache != NULL) {
137 obj = freelists->slices.slice_cache;
138 freelists->slices.slice_cache = NULL;
139 _Py_NewReference((PyObject *)obj);
140 }
141 else
142 #endif
143 {
144 obj = PyObject_GC_New(PySliceObject, &PySlice_Type);
145 if (obj == NULL) {
146 goto error;
147 }
148 }
149
150 obj->start = start;
151 obj->stop = stop;
152 obj->step = Py_NewRef(step);
153
154 _PyObject_GC_TRACK(obj);
155 return obj;
156 error:
157 Py_DECREF(start);
158 Py_DECREF(stop);
159 return NULL;
160 }
161
162 PyObject *
PySlice_New(PyObject * start,PyObject * stop,PyObject * step)163 PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
164 {
165 if (step == NULL) {
166 step = Py_None;
167 }
168 if (start == NULL) {
169 start = Py_None;
170 }
171 if (stop == NULL) {
172 stop = Py_None;
173 }
174 return (PyObject *)_PyBuildSlice_Consume2(Py_NewRef(start),
175 Py_NewRef(stop), step);
176 }
177
178 PyObject *
_PyBuildSlice_ConsumeRefs(PyObject * start,PyObject * stop)179 _PyBuildSlice_ConsumeRefs(PyObject *start, PyObject *stop)
180 {
181 assert(start != NULL && stop != NULL);
182 return (PyObject *)_PyBuildSlice_Consume2(start, stop, Py_None);
183 }
184
185 PyObject *
_PySlice_FromIndices(Py_ssize_t istart,Py_ssize_t istop)186 _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)
187 {
188 PyObject *start, *end, *slice;
189 start = PyLong_FromSsize_t(istart);
190 if (!start)
191 return NULL;
192 end = PyLong_FromSsize_t(istop);
193 if (!end) {
194 Py_DECREF(start);
195 return NULL;
196 }
197
198 slice = PySlice_New(start, end, NULL);
199 Py_DECREF(start);
200 Py_DECREF(end);
201 return slice;
202 }
203
204 int
PySlice_GetIndices(PyObject * _r,Py_ssize_t length,Py_ssize_t * start,Py_ssize_t * stop,Py_ssize_t * step)205 PySlice_GetIndices(PyObject *_r, Py_ssize_t length,
206 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
207 {
208 PySliceObject *r = (PySliceObject*)_r;
209 /* XXX support long ints */
210 if (r->step == Py_None) {
211 *step = 1;
212 } else {
213 if (!PyLong_Check(r->step)) return -1;
214 *step = PyLong_AsSsize_t(r->step);
215 }
216 if (r->start == Py_None) {
217 *start = *step < 0 ? length-1 : 0;
218 } else {
219 if (!PyLong_Check(r->start)) return -1;
220 *start = PyLong_AsSsize_t(r->start);
221 if (*start < 0) *start += length;
222 }
223 if (r->stop == Py_None) {
224 *stop = *step < 0 ? -1 : length;
225 } else {
226 if (!PyLong_Check(r->stop)) return -1;
227 *stop = PyLong_AsSsize_t(r->stop);
228 if (*stop < 0) *stop += length;
229 }
230 if (*stop > length) return -1;
231 if (*start >= length) return -1;
232 if (*step == 0) return -1;
233 return 0;
234 }
235
236 int
PySlice_Unpack(PyObject * _r,Py_ssize_t * start,Py_ssize_t * stop,Py_ssize_t * step)237 PySlice_Unpack(PyObject *_r,
238 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
239 {
240 PySliceObject *r = (PySliceObject*)_r;
241 /* this is harder to get right than you might think */
242
243 static_assert(PY_SSIZE_T_MIN + 1 <= -PY_SSIZE_T_MAX,
244 "-PY_SSIZE_T_MAX < PY_SSIZE_T_MIN + 1");
245
246 if (r->step == Py_None) {
247 *step = 1;
248 }
249 else {
250 if (!_PyEval_SliceIndex(r->step, step)) return -1;
251 if (*step == 0) {
252 PyErr_SetString(PyExc_ValueError,
253 "slice step cannot be zero");
254 return -1;
255 }
256 /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it
257 * with -PY_SSIZE_T_MAX. This doesn't affect the semantics, and it
258 * guards against later undefined behaviour resulting from code that
259 * does "step = -step" as part of a slice reversal.
260 */
261 if (*step < -PY_SSIZE_T_MAX)
262 *step = -PY_SSIZE_T_MAX;
263 }
264
265 if (r->start == Py_None) {
266 *start = *step < 0 ? PY_SSIZE_T_MAX : 0;
267 }
268 else {
269 if (!_PyEval_SliceIndex(r->start, start)) return -1;
270 }
271
272 if (r->stop == Py_None) {
273 *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
274 }
275 else {
276 if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
277 }
278
279 return 0;
280 }
281
282 Py_ssize_t
PySlice_AdjustIndices(Py_ssize_t length,Py_ssize_t * start,Py_ssize_t * stop,Py_ssize_t step)283 PySlice_AdjustIndices(Py_ssize_t length,
284 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step)
285 {
286 /* this is harder to get right than you might think */
287
288 assert(step != 0);
289 assert(step >= -PY_SSIZE_T_MAX);
290
291 if (*start < 0) {
292 *start += length;
293 if (*start < 0) {
294 *start = (step < 0) ? -1 : 0;
295 }
296 }
297 else if (*start >= length) {
298 *start = (step < 0) ? length - 1 : length;
299 }
300
301 if (*stop < 0) {
302 *stop += length;
303 if (*stop < 0) {
304 *stop = (step < 0) ? -1 : 0;
305 }
306 }
307 else if (*stop >= length) {
308 *stop = (step < 0) ? length - 1 : length;
309 }
310
311 if (step < 0) {
312 if (*stop < *start) {
313 return (*start - *stop - 1) / (-step) + 1;
314 }
315 }
316 else {
317 if (*start < *stop) {
318 return (*stop - *start - 1) / step + 1;
319 }
320 }
321 return 0;
322 }
323
324 #undef PySlice_GetIndicesEx
325
326 int
PySlice_GetIndicesEx(PyObject * _r,Py_ssize_t length,Py_ssize_t * start,Py_ssize_t * stop,Py_ssize_t * step,Py_ssize_t * slicelength)327 PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length,
328 Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
329 Py_ssize_t *slicelength)
330 {
331 if (PySlice_Unpack(_r, start, stop, step) < 0)
332 return -1;
333 *slicelength = PySlice_AdjustIndices(length, start, stop, *step);
334 return 0;
335 }
336
337 static PyObject *
slice_new(PyTypeObject * type,PyObject * args,PyObject * kw)338 slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
339 {
340 PyObject *start, *stop, *step;
341
342 start = stop = step = NULL;
343
344 if (!_PyArg_NoKeywords("slice", kw))
345 return NULL;
346
347 if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
348 return NULL;
349
350 /* This swapping of stop and start is to maintain similarity with
351 range(). */
352 if (stop == NULL) {
353 stop = start;
354 start = NULL;
355 }
356 return PySlice_New(start, stop, step);
357 }
358
359 PyDoc_STRVAR(slice_doc,
360 "slice(stop)\n\
361 slice(start, stop[, step])\n\
362 \n\
363 Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).");
364
365 static void
slice_dealloc(PySliceObject * r)366 slice_dealloc(PySliceObject *r)
367 {
368 _PyObject_GC_UNTRACK(r);
369 Py_DECREF(r->step);
370 Py_DECREF(r->start);
371 Py_DECREF(r->stop);
372 #ifdef WITH_FREELISTS
373 struct _Py_object_freelists *freelists = _Py_object_freelists_GET();
374 if (freelists->slices.slice_cache == NULL) {
375 freelists->slices.slice_cache = r;
376 }
377 else
378 #endif
379 {
380 PyObject_GC_Del(r);
381 }
382 }
383
384 static PyObject *
slice_repr(PySliceObject * r)385 slice_repr(PySliceObject *r)
386 {
387 return PyUnicode_FromFormat("slice(%R, %R, %R)", r->start, r->stop, r->step);
388 }
389
390 static PyMemberDef slice_members[] = {
391 {"start", _Py_T_OBJECT, offsetof(PySliceObject, start), Py_READONLY},
392 {"stop", _Py_T_OBJECT, offsetof(PySliceObject, stop), Py_READONLY},
393 {"step", _Py_T_OBJECT, offsetof(PySliceObject, step), Py_READONLY},
394 {0}
395 };
396
397 /* Helper function to convert a slice argument to a PyLong, and raise TypeError
398 with a suitable message on failure. */
399
400 static PyObject*
evaluate_slice_index(PyObject * v)401 evaluate_slice_index(PyObject *v)
402 {
403 if (_PyIndex_Check(v)) {
404 return PyNumber_Index(v);
405 }
406 else {
407 PyErr_SetString(PyExc_TypeError,
408 "slice indices must be integers or "
409 "None or have an __index__ method");
410 return NULL;
411 }
412 }
413
414 /* Compute slice indices given a slice and length. Return -1 on failure. Used
415 by slice.indices and rangeobject slicing. Assumes that `len` is a
416 nonnegative instance of PyLong. */
417
418 int
_PySlice_GetLongIndices(PySliceObject * self,PyObject * length,PyObject ** start_ptr,PyObject ** stop_ptr,PyObject ** step_ptr)419 _PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
420 PyObject **start_ptr, PyObject **stop_ptr,
421 PyObject **step_ptr)
422 {
423 PyObject *start=NULL, *stop=NULL, *step=NULL;
424 PyObject *upper=NULL, *lower=NULL;
425 int step_is_negative, cmp_result;
426
427 /* Convert step to an integer; raise for zero step. */
428 if (self->step == Py_None) {
429 step = _PyLong_GetOne();
430 step_is_negative = 0;
431 }
432 else {
433 int step_sign;
434 step = evaluate_slice_index(self->step);
435 if (step == NULL)
436 goto error;
437 step_sign = _PyLong_Sign(step);
438 if (step_sign == 0) {
439 PyErr_SetString(PyExc_ValueError,
440 "slice step cannot be zero");
441 goto error;
442 }
443 step_is_negative = step_sign < 0;
444 }
445
446 /* Find lower and upper bounds for start and stop. */
447 if (step_is_negative) {
448 lower = PyLong_FromLong(-1L);
449 if (lower == NULL)
450 goto error;
451
452 upper = PyNumber_Add(length, lower);
453 if (upper == NULL)
454 goto error;
455 }
456 else {
457 lower = _PyLong_GetZero();
458 upper = Py_NewRef(length);
459 }
460
461 /* Compute start. */
462 if (self->start == Py_None) {
463 start = Py_NewRef(step_is_negative ? upper : lower);
464 }
465 else {
466 start = evaluate_slice_index(self->start);
467 if (start == NULL)
468 goto error;
469
470 if (_PyLong_IsNegative((PyLongObject *)start)) {
471 /* start += length */
472 PyObject *tmp = PyNumber_Add(start, length);
473 Py_SETREF(start, tmp);
474 if (start == NULL)
475 goto error;
476
477 cmp_result = PyObject_RichCompareBool(start, lower, Py_LT);
478 if (cmp_result < 0)
479 goto error;
480 if (cmp_result) {
481 Py_SETREF(start, Py_NewRef(lower));
482 }
483 }
484 else {
485 cmp_result = PyObject_RichCompareBool(start, upper, Py_GT);
486 if (cmp_result < 0)
487 goto error;
488 if (cmp_result) {
489 Py_SETREF(start, Py_NewRef(upper));
490 }
491 }
492 }
493
494 /* Compute stop. */
495 if (self->stop == Py_None) {
496 stop = Py_NewRef(step_is_negative ? lower : upper);
497 }
498 else {
499 stop = evaluate_slice_index(self->stop);
500 if (stop == NULL)
501 goto error;
502
503 if (_PyLong_IsNegative((PyLongObject *)stop)) {
504 /* stop += length */
505 PyObject *tmp = PyNumber_Add(stop, length);
506 Py_SETREF(stop, tmp);
507 if (stop == NULL)
508 goto error;
509
510 cmp_result = PyObject_RichCompareBool(stop, lower, Py_LT);
511 if (cmp_result < 0)
512 goto error;
513 if (cmp_result) {
514 Py_SETREF(stop, Py_NewRef(lower));
515 }
516 }
517 else {
518 cmp_result = PyObject_RichCompareBool(stop, upper, Py_GT);
519 if (cmp_result < 0)
520 goto error;
521 if (cmp_result) {
522 Py_SETREF(stop, Py_NewRef(upper));
523 }
524 }
525 }
526
527 *start_ptr = start;
528 *stop_ptr = stop;
529 *step_ptr = step;
530 Py_DECREF(upper);
531 Py_DECREF(lower);
532 return 0;
533
534 error:
535 *start_ptr = *stop_ptr = *step_ptr = NULL;
536 Py_XDECREF(start);
537 Py_XDECREF(stop);
538 Py_XDECREF(step);
539 Py_XDECREF(upper);
540 Py_XDECREF(lower);
541 return -1;
542 }
543
544 /* Implementation of slice.indices. */
545
546 static PyObject*
slice_indices(PySliceObject * self,PyObject * len)547 slice_indices(PySliceObject* self, PyObject* len)
548 {
549 PyObject *start, *stop, *step;
550 PyObject *length;
551 int error;
552
553 /* Convert length to an integer if necessary; raise for negative length. */
554 length = PyNumber_Index(len);
555 if (length == NULL)
556 return NULL;
557
558 if (_PyLong_IsNegative((PyLongObject *)length)) {
559 PyErr_SetString(PyExc_ValueError,
560 "length should not be negative");
561 Py_DECREF(length);
562 return NULL;
563 }
564
565 error = _PySlice_GetLongIndices(self, length, &start, &stop, &step);
566 Py_DECREF(length);
567 if (error == -1)
568 return NULL;
569 else
570 return Py_BuildValue("(NNN)", start, stop, step);
571 }
572
573 PyDoc_STRVAR(slice_indices_doc,
574 "S.indices(len) -> (start, stop, stride)\n\
575 \n\
576 Assuming a sequence of length len, calculate the start and stop\n\
577 indices, and the stride length of the extended slice described by\n\
578 S. Out of bounds indices are clipped in a manner consistent with the\n\
579 handling of normal slices.");
580
581 static PyObject *
slice_reduce(PySliceObject * self,PyObject * Py_UNUSED (ignored))582 slice_reduce(PySliceObject* self, PyObject *Py_UNUSED(ignored))
583 {
584 return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);
585 }
586
587 PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
588
589 static PyMethodDef slice_methods[] = {
590 {"indices", (PyCFunction)slice_indices,
591 METH_O, slice_indices_doc},
592 {"__reduce__", (PyCFunction)slice_reduce,
593 METH_NOARGS, reduce_doc},
594 {NULL, NULL}
595 };
596
597 static PyObject *
slice_richcompare(PyObject * v,PyObject * w,int op)598 slice_richcompare(PyObject *v, PyObject *w, int op)
599 {
600 if (!PySlice_Check(v) || !PySlice_Check(w))
601 Py_RETURN_NOTIMPLEMENTED;
602
603 if (v == w) {
604 PyObject *res;
605 /* XXX Do we really need this shortcut?
606 There's a unit test for it, but is that fair? */
607 switch (op) {
608 case Py_EQ:
609 case Py_LE:
610 case Py_GE:
611 res = Py_True;
612 break;
613 default:
614 res = Py_False;
615 break;
616 }
617 return Py_NewRef(res);
618 }
619
620
621 PyObject *t1 = PyTuple_Pack(3,
622 ((PySliceObject *)v)->start,
623 ((PySliceObject *)v)->stop,
624 ((PySliceObject *)v)->step);
625 if (t1 == NULL) {
626 return NULL;
627 }
628
629 PyObject *t2 = PyTuple_Pack(3,
630 ((PySliceObject *)w)->start,
631 ((PySliceObject *)w)->stop,
632 ((PySliceObject *)w)->step);
633 if (t2 == NULL) {
634 Py_DECREF(t1);
635 return NULL;
636 }
637
638 PyObject *res = PyObject_RichCompare(t1, t2, op);
639 Py_DECREF(t1);
640 Py_DECREF(t2);
641 return res;
642 }
643
644 static int
slice_traverse(PySliceObject * v,visitproc visit,void * arg)645 slice_traverse(PySliceObject *v, visitproc visit, void *arg)
646 {
647 Py_VISIT(v->start);
648 Py_VISIT(v->stop);
649 Py_VISIT(v->step);
650 return 0;
651 }
652
653 /* code based on tuplehash() of Objects/tupleobject.c */
654 #if SIZEOF_PY_UHASH_T > 4
655 #define _PyHASH_XXPRIME_1 ((Py_uhash_t)11400714785074694791ULL)
656 #define _PyHASH_XXPRIME_2 ((Py_uhash_t)14029467366897019727ULL)
657 #define _PyHASH_XXPRIME_5 ((Py_uhash_t)2870177450012600261ULL)
658 #define _PyHASH_XXROTATE(x) ((x << 31) | (x >> 33)) /* Rotate left 31 bits */
659 #else
660 #define _PyHASH_XXPRIME_1 ((Py_uhash_t)2654435761UL)
661 #define _PyHASH_XXPRIME_2 ((Py_uhash_t)2246822519UL)
662 #define _PyHASH_XXPRIME_5 ((Py_uhash_t)374761393UL)
663 #define _PyHASH_XXROTATE(x) ((x << 13) | (x >> 19)) /* Rotate left 13 bits */
664 #endif
665
666 static Py_hash_t
slicehash(PySliceObject * v)667 slicehash(PySliceObject *v)
668 {
669 Py_uhash_t acc = _PyHASH_XXPRIME_5;
670 #define _PyHASH_SLICE_PART(com) { \
671 Py_uhash_t lane = PyObject_Hash(v->com); \
672 if(lane == (Py_uhash_t)-1) { \
673 return -1; \
674 } \
675 acc += lane * _PyHASH_XXPRIME_2; \
676 acc = _PyHASH_XXROTATE(acc); \
677 acc *= _PyHASH_XXPRIME_1; \
678 }
679 _PyHASH_SLICE_PART(start);
680 _PyHASH_SLICE_PART(stop);
681 _PyHASH_SLICE_PART(step);
682 #undef _PyHASH_SLICE_PART
683 if(acc == (Py_uhash_t)-1) {
684 return 1546275796;
685 }
686 return acc;
687 }
688
689 PyTypeObject PySlice_Type = {
690 PyVarObject_HEAD_INIT(&PyType_Type, 0)
691 "slice", /* Name of this type */
692 sizeof(PySliceObject), /* Basic object size */
693 0, /* Item size for varobject */
694 (destructor)slice_dealloc, /* tp_dealloc */
695 0, /* tp_vectorcall_offset */
696 0, /* tp_getattr */
697 0, /* tp_setattr */
698 0, /* tp_as_async */
699 (reprfunc)slice_repr, /* tp_repr */
700 0, /* tp_as_number */
701 0, /* tp_as_sequence */
702 0, /* tp_as_mapping */
703 (hashfunc)slicehash, /* tp_hash */
704 0, /* tp_call */
705 0, /* tp_str */
706 PyObject_GenericGetAttr, /* tp_getattro */
707 0, /* tp_setattro */
708 0, /* tp_as_buffer */
709 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
710 slice_doc, /* tp_doc */
711 (traverseproc)slice_traverse, /* tp_traverse */
712 0, /* tp_clear */
713 slice_richcompare, /* tp_richcompare */
714 0, /* tp_weaklistoffset */
715 0, /* tp_iter */
716 0, /* tp_iternext */
717 slice_methods, /* tp_methods */
718 slice_members, /* tp_members */
719 0, /* tp_getset */
720 0, /* tp_base */
721 0, /* tp_dict */
722 0, /* tp_descr_get */
723 0, /* tp_descr_set */
724 0, /* tp_dictoffset */
725 0, /* tp_init */
726 0, /* tp_alloc */
727 slice_new, /* tp_new */
728 };
729