Index: Objects/structseq.c =================================================================== --- Objects/structseq.c (.../p3yk) (revision 53047) +++ Objects/structseq.c (.../p3yk-noslice) (revision 53047) @@ -90,6 +90,54 @@ } static PyObject * +structseq_subscript(PyStructSequence *self, PyObject *item) +{ + if (PyIndex_Check(item)) { + Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) + return NULL; + + if (i < 0) + i += VISIBLE_SIZE(self); + + if (i < 0 || i >= VISIBLE_SIZE(self)) { + PyErr_SetString(PyExc_IndexError, + "tuple index out of range"); + return NULL; + } + Py_INCREF(self->ob_item[i]); + return self->ob_item[i]; + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelen, cur, i; + PyObject *result; + + if (PySlice_GetIndicesEx((PySliceObject *)item, + VISIBLE_SIZE(self), &start, &stop, + &step, &slicelen) < 0) { + return NULL; + } + if (slicelen <= 0) + return PyTuple_New(0); + result = PyTuple_New(slicelen); + if (result == NULL) + return NULL; + for (cur = start, i = 0; i < slicelen; + cur += step, i++) { + PyObject *v = self->ob_item[cur]; + Py_INCREF(v); + PyTuple_SET_ITEM(result, i, v); + } + return result; + } + else { + PyErr_SetString(PyExc_TypeError, + "structseq indices must be integers"); + return NULL; + } +} + +static PyObject * structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *arg = NULL; @@ -298,6 +346,11 @@ (objobjproc)structseq_contains, /* sq_contains */ }; +static PyMappingMethods structseq_as_mapping = { + (lenfunc)structseq_length, + (binaryfunc)structseq_subscript, +}; + static PyMethodDef structseq_methods[] = { {"__reduce__", (PyCFunction)structseq_reduce, METH_NOARGS, NULL}, @@ -318,7 +371,7 @@ (reprfunc)structseq_repr, /* tp_repr */ 0, /* tp_as_number */ &structseq_as_sequence, /* tp_as_sequence */ - 0, /* tp_as_mapping */ + &structseq_as_mapping, /* tp_as_mapping */ structseq_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ Index: Lib/test/test_structseq.py =================================================================== --- Lib/test/test_structseq.py (.../p3yk) (revision 53047) +++ Lib/test/test_structseq.py (.../p3yk-noslice) (revision 53047) @@ -97,6 +97,18 @@ t = time.gmtime() x = t.__reduce__() + def test_extended_getslice(self): + # Test extended slicing by comparing with list slicing. + t = time.gmtime() + L = list(t) + indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300) + for start in indices: + for stop in indices: + # Skip step 0 (invalid) + for step in indices[1:]: + self.assertEqual(list(t[start:stop:step]), + L[start:stop:step]) + def test_main(): test_support.run_unittest(StructSeqTest)