summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/ref/ref3.tex9
-rw-r--r--Lib/test/test_slice.py14
-rw-r--r--Objects/sliceobject.c35
3 files changed, 57 insertions, 1 deletions
diff --git a/Doc/ref/ref3.tex b/Doc/ref/ref3.tex
index d719db3..9f8d262 100644
--- a/Doc/ref/ref3.tex
+++ b/Doc/ref/ref3.tex
@@ -892,6 +892,15 @@ Special read-only attributes: \member{start} is the lower bound;
\ttindex{stop}
\ttindex{step}}
+Special method: \method{indices} takes an single integer argument
+\var{length} and computes information about the extended slice that
+the slice object would describe if applied to a sequence of
+\var{length}. It returns a tuple of three integers; respectively
+these are the \var{start} and \var{stop} indices and the \var{step} or
+stride length of the slice. Missing or out-of-bounds indices are
+handled in a manner consistent with regular slices.
+\versionadded{2.3}
+
\end{description} % Internal types
\end{description} % Types
diff --git a/Lib/test/test_slice.py b/Lib/test/test_slice.py
new file mode 100644
index 0000000..895238f
--- /dev/null
+++ b/Lib/test/test_slice.py
@@ -0,0 +1,14 @@
+# tests for slice objects; in particular the indices method.
+
+from test_support import vereq
+
+vereq(slice(None ).indices(10), (0, 10, 1))
+vereq(slice(None, None, 2).indices(10), (0, 10, 2))
+vereq(slice(1, None, 2).indices(10), (1, 10, 2))
+vereq(slice(None, None, -1).indices(10), (9, -1, -1))
+vereq(slice(None, None, -2).indices(10), (9, -1, -2))
+vereq(slice(3, None, -2).indices(10), (3, -1, -2))
+vereq(slice(-100, 100 ).indices(10), slice(None).indices(10))
+vereq(slice(100, -100, -1).indices(10), slice(None, None, -1).indices(10))
+vereq(slice(-100L, 100L, 2L).indices(10), (0, 10, 2))
+
diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c
index a43644d..f2d84da 100644
--- a/Objects/sliceobject.c
+++ b/Objects/sliceobject.c
@@ -221,6 +221,39 @@ static PyMemberDef slice_members[] = {
{0}
};
+static PyObject*
+slice_indices(PySliceObject* self, PyObject* len)
+{
+ int ilen, start, stop, step, slicelength;
+
+ ilen = PyInt_AsLong(len);
+
+ if (ilen == -1 && PyErr_Occurred()) {
+ return NULL;
+ }
+
+ if (PySlice_GetIndicesEx(self, ilen, &start, &stop,
+ &step, &slicelength) < 0) {
+ return NULL;
+ }
+
+ return Py_BuildValue("(lll)", start, stop, step);
+}
+
+PyDoc_STRVAR(slice_indices_doc,
+"S.indices(len) -> (start, stop, stride)\n\
+\n\
+Assuming a sequence of length len, calculate the start and stop\n\
+indices, and the stride length of the extended slice described by\n\
+S. Out of bounds indices are clipped in a manner consistent with the\n\
+handling of normal slices.");
+
+static PyMethodDef slice_methods[] = {
+ {"indices", (PyCFuntion)slice_indices,
+ METH_O, slice_indices_doc},
+ {NULL, NULL}
+};
+
static int
slice_compare(PySliceObject *v, PySliceObject *w)
{
@@ -271,7 +304,7 @@ PyTypeObject PySlice_Type = {
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
- 0, /* tp_methods */
+ slice_methods, /* tp_methods */
slice_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */