Coverage Report

Created: 2025-07-11 06:59

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