diff options
author | Thomas Wouters <thomas@python.org> | 2000-08-17 22:37:32 (GMT) |
---|---|---|
committer | Thomas Wouters <thomas@python.org> | 2000-08-17 22:37:32 (GMT) |
commit | 1d75a79c009e500923128716a02efbe86135e64e (patch) | |
tree | 9c978062db6b1e9c4c775a9d4b763fd115bd671e /Objects | |
parent | 68add2e9389e9cb2b74e448201ec101564391fe5 (diff) | |
download | cpython-1d75a79c009e500923128716a02efbe86135e64e.zip cpython-1d75a79c009e500923128716a02efbe86135e64e.tar.gz cpython-1d75a79c009e500923128716a02efbe86135e64e.tar.bz2 |
Apply SF patch #101029: call __getitem__ with a proper slice object if there
is no __getslice__ available. Also does the same for C extension types.
Includes rudimentary documentation (it could use a cross reference to the
section on slice objects, I couldn't figure out how to do that) and a test
suite for all Python __hooks__ I could think of, including the new
behaviour.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/abstract.c | 37 | ||||
-rw-r--r-- | Objects/classobject.c | 69 |
2 files changed, 97 insertions, 9 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c index 4a64daa..8044d86 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -876,10 +876,29 @@ PySequence_GetItem(PyObject *s, int i) return type_error("unindexable object"); } +static PyObject * +sliceobj_from_intint(int i, int j) +{ + PyObject *start, *end, *slice; + start = PyInt_FromLong((long)i); + if (!start) + return NULL; + end = PyInt_FromLong((long)j); + if (!end) { + Py_DECREF(start); + return NULL; + } + slice = PySlice_New(start, end, NULL); + Py_DECREF(start); + Py_DECREF(end); + return slice; +} + PyObject * PySequence_GetSlice(PyObject *s, int i1, int i2) { PySequenceMethods *m; + PyMappingMethods *mp; if (!s) return null_error(); @@ -897,6 +916,14 @@ PySequence_GetSlice(PyObject *s, int i1, int i2) } } return m->sq_slice(s, i1, i2); + } else if ((mp = s->ob_type->tp_as_mapping) && mp->mp_subscript) { + PyObject *res; + PyObject *slice = sliceobj_from_intint(i1, i2); + if (!slice) + return NULL; + res = mp->mp_subscript(s, slice); + Py_DECREF(slice); + return res; } return type_error("unsliceable object"); @@ -960,6 +987,7 @@ int PySequence_SetSlice(PyObject *s, int i1, int i2, PyObject *o) { PySequenceMethods *m; + PyMappingMethods *mp; if (s == NULL) { null_error(); @@ -980,7 +1008,16 @@ PySequence_SetSlice(PyObject *s, int i1, int i2, PyObject *o) } } return m->sq_ass_slice(s, i1, i2, o); + } else if ((mp = s->ob_type->tp_as_mapping) && mp->mp_ass_subscript) { + int res; + PyObject *slice = sliceobj_from_intint(i1, i2); + if (!slice) + return -1; + res = mp->mp_ass_subscript(s, slice, o); + Py_DECREF(slice); + return res; } + type_error("object doesn't support slice assignment"); return -1; } diff --git a/Objects/classobject.c b/Objects/classobject.c index 3b97a02..66d1080 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -972,6 +972,27 @@ instance_item(PyInstanceObject *inst, int i) } static PyObject * +sliceobj_from_intint(int i, int j) +{ + PyObject *start, *end, *res; + + start = PyInt_FromLong((long)i); + if (!start) + return NULL; + + end = PyInt_FromLong((long)j); + if (!end) { + Py_DECREF(start); + return NULL; + } + res = PySlice_New(start, end, NULL); + Py_DECREF(start); + Py_DECREF(end); + return res; +} + + +static PyObject * instance_slice(PyInstanceObject *inst, int i, int j) { PyObject *func, *arg, *res; @@ -980,9 +1001,19 @@ instance_slice(PyInstanceObject *inst, int i, int j) if (getslicestr == NULL) getslicestr = PyString_InternFromString("__getslice__"); func = instance_getattr(inst, getslicestr); - if (func == NULL) - return NULL; - arg = Py_BuildValue("(ii)", i, j); + + if (func == NULL) { + PyErr_Clear(); + + if (getitemstr == NULL) + getitemstr = PyString_InternFromString("__getitem__"); + func = instance_getattr(inst, getitemstr); + if (func == NULL) + return NULL; + arg = Py_BuildValue("(N)", sliceobj_from_intint(i, j)); + } else + arg = Py_BuildValue("(ii)", i, j); + if (arg == NULL) { Py_DECREF(func); return NULL; @@ -1038,19 +1069,39 @@ instance_ass_slice(PyInstanceObject *inst, int i, int j, PyObject *value) delslicestr = PyString_InternFromString("__delslice__"); func = instance_getattr(inst, delslicestr); + if (func == NULL) { + PyErr_Clear(); + if (delitemstr == NULL) + delitemstr = + PyString_InternFromString("__delitem__"); + func = instance_getattr(inst, delitemstr); + if (func == NULL) + return -1; + + arg = Py_BuildValue("(N)", + sliceobj_from_intint(i, j)); + } else + arg = Py_BuildValue("(ii)", i, j); } else { if (setslicestr == NULL) setslicestr = PyString_InternFromString("__setslice__"); func = instance_getattr(inst, setslicestr); + if (func == NULL) { + PyErr_Clear(); + if (setitemstr == NULL) + setitemstr = + PyString_InternFromString("__setitem__"); + func = instance_getattr(inst, setitemstr); + if (func == NULL) + return -1; + + arg = Py_BuildValue("(NO)", + sliceobj_from_intint(i, j), value); + } else + arg = Py_BuildValue("(iiO)", i, j, value); } - if (func == NULL) - return -1; - if (value == NULL) - arg = Py_BuildValue("(ii)", i, j); - else - arg = Py_BuildValue("(iiO)", i, j, value); if (arg == NULL) { Py_DECREF(func); return -1; |