Index: Objects/typeobject.c =================================================================== --- Objects/typeobject.c (revision 47124) +++ Objects/typeobject.c (working copy) @@ -5766,6 +5766,96 @@ } } +static Py_ssize_t +super_length(PyObject *self) +{ + Py_ssize_t result; + PyObject *len_meth; + PyObject *py_result; + PyObject *attr = PyString_FromString("__len__"); + if (NULL == attr) + return -1; + + len_meth = super_getattro(self, attr); + Py_DECREF(attr); + if (NULL == len_meth) + return -1; + + py_result = PyObject_CallObject(len_meth, (PyObject *)NULL); + Py_DECREF(len_meth); + if (NULL == py_result) + result = -1; + else { + result = PyInt_AsSsize_t(py_result); + Py_DECREF(py_result); + } + return result; +} + +static PyObject * +super_subscript(PyObject *self, PyObject *key) +{ + PyObject *subscript_meth; + PyObject *result; + PyObject *attr = PyString_FromString("__getitem__"); + if (NULL == attr) + return NULL; + + subscript_meth = super_getattro(self, attr); + Py_DECREF(attr); + if (NULL == subscript_meth) + return NULL; + + result = PyObject_CallFunctionObjArgs(subscript_meth, key, NULL); + Py_DECREF(subscript_meth); + return result; +} + +int +super_ass_sub(PyObject *self, PyObject *key, PyObject *item) +{ + int result; + PyObject *py_result; + PyObject *subscript_meth; + PyObject *attr; + + attr = PyString_FromString(item ? "__setitem__" : "__delitem__"); + if (NULL == attr) + return -1; + + subscript_meth = super_getattro(self, attr); + Py_DECREF(attr); + if (NULL == subscript_meth) + return -1; + + py_result = PyObject_CallFunctionObjArgs(subscript_meth, key, item, NULL); + result = (NULL == py_result) ? -1 : 0; + Py_DECREF(subscript_meth); + Py_XDECREF(py_result); + return result; +} + +static long +super_hash(PyObject *self) +{ + PyObject *py_result; + PyObject *hash_meth; + PyObject *attr = PyString_FromString("__hash__"); + if (NULL == attr) + return -1; + + hash_meth = super_getattro(self, attr); + Py_DECREF(attr); + if (NULL == hash_meth) + return -1; + + py_result = PyObject_CallObject(hash_meth, (PyObject *)NULL); + Py_DECREF(hash_meth); + if (NULL == py_result) + return -1; + return PyInt_AsLong(py_result); +} + static int super_init(PyObject *self, PyObject *args, PyObject *kwds) { @@ -5812,6 +5902,12 @@ return 0; } +static PyMappingMethods super_as_mapping = { + (lenfunc)super_length, /*mp_length*/ + (binaryfunc)super_subscript, /*mp_subscript*/ + (objobjargproc)super_ass_sub, /*mp_ass_subscript*/ +}; + PyTypeObject PySuper_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, /* ob_size */ @@ -5822,13 +5918,13 @@ super_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ - 0, /* tp_setattr */ + 0, /* tp_setattr */ 0, /* tp_compare */ super_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ + &super_as_mapping, /* tp_as_mapping */ + (hashfunc)super_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ super_getattro, /* tp_getattro */ Index: Doc/lib/libfuncs.tex =================================================================== --- Doc/lib/libfuncs.tex (revision 47124) +++ Doc/lib/libfuncs.tex (working copy) @@ -1065,12 +1065,12 @@ super(C, self).meth(arg) \end{verbatim} - Note that \function{super} is implemented as part of the binding process for - explicit dotted attribute lookups such as - \samp{super(C, self).__getitem__(name)}. Accordingly, \function{super} is - undefined for implicit lookups using statements or operators such as - \samp{super(C, self)[name]}. + Note that \function{super} is works with some implicit lookups using + statements or operators such as \samp{super(C, self)[name]}. Currently + \function{super} works with implicit calls to \code{__getitem__}, + \code{__setitem__}, \code{__delitem__}, \code{__len__} and \code{__hash__}. \versionadded{2.2} +\versionchanged[Support for implicit lookups added]{2.5} \end{funcdesc} \begin{funcdesc}{tuple}{\optional{sequence}} Index: Lib/test/test_descr.py =================================================================== --- Lib/test/test_descr.py (revision 47124) +++ Lib/test/test_descr.py (working copy) @@ -2131,6 +2131,78 @@ return super(Sub,klass).aProp veris(Sub.test(), Base.aProp) + + # Ensure that subscripting (__getitem__) works with super() + + class Base(object): + def __getitem__(self, key): + return 88 + + class Sub(Base): + def __getitem__(self, key): + return 77 + + vereq(super(Sub, Sub())['foo'], 88) + + # Ensure that subscript assignment (__setitem__) works with super() + + class Base(object): + def __setitem__(self, key, obj): + raise TypeError("Base", key, obj) + + class Sub(Base): + def __setitem__(self, key, obj): + raise TypeError("Sub", key, obj) + + o = super(Sub, Sub()) + try: + o['foo'] = 88 + except TypeError, e: + vereq(e.args, ("Base", "foo", 88)) + else: + raise TestFailed, "TypeError not raised" + + # Ensure that subscript deletion (__delitem__) works with super() + + class Base(object): + def __delitem__(self, key): + raise KeyError("Base", key) + + class Sub(Base): + def __delitem__(self, key): + raise KeyError("Sub", key) + + o = super(Sub, Sub()) + try: + del o['foo'] + except KeyError, e: + vereq(e.args, ("Base", "foo")) + else: + raise TestFailed, "KeyError not raised" + + # Ensure that len() (__len__) works with super() + + class Base(object): + def __len__(self): + return 88 + + class Sub(Base): + def __len__(self): + return 77 + + vereq(len(super(Sub, Sub())), 88) + + # Ensure that hash() (__hash__) works on super() objects + + class Base(object): + def __hash__(self): + return 88 + + class Sub(Base): + def __hash__(self): + return 77 + + vereq(hash(super(Sub, Sub())), 88) def inherits():