summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorThomas Wouters <thomas@python.org>2000-08-17 22:37:32 (GMT)
committerThomas Wouters <thomas@python.org>2000-08-17 22:37:32 (GMT)
commit1d75a79c009e500923128716a02efbe86135e64e (patch)
tree9c978062db6b1e9c4c775a9d4b763fd115bd671e /Objects
parent68add2e9389e9cb2b74e448201ec101564391fe5 (diff)
downloadcpython-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.c37
-rw-r--r--Objects/classobject.c69
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;