ยปCore Development>Code coverage>Objects/sliceobject.c

Python code coverage for Objects/sliceobject.c

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