lookup __reversed__ correctly as a special method

This commit is contained in:
Benjamin Peterson 2009-05-09 02:07:04 +00:00
parent 84ad84e0bb
commit 809e22543f
2 changed files with 11 additions and 3 deletions

View file

@ -1676,12 +1676,15 @@ order (MRO) for bases """
return self return self
def hello(self): def hello(self):
return "hello" return "hello"
def empty_seq(self):
return []
# It would be nice to have every special method tested here, but I'm # It would be nice to have every special method tested here, but I'm
# only listing the ones I can remember outside of typeobject.c, since it # only listing the ones I can remember outside of typeobject.c, since it
# does it right. # does it right.
specials = [ specials = [
("__unicode__", unicode, hello), ("__unicode__", unicode, hello),
("__reversed__", reversed, empty_seq),
# These two fail because the compiler generates LOAD_ATTR to look # These two fail because the compiler generates LOAD_ATTR to look
# them up. We'd have to add a new opcode to fix this, and it's # them up. We'd have to add a new opcode to fix this, and it's
# probably not worth it. # probably not worth it.

View file

@ -222,7 +222,8 @@ static PyObject *
reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds) reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
Py_ssize_t n; Py_ssize_t n;
PyObject *seq; PyObject *seq, *reversed_meth;
static PyObject *reversed_cache = NULL;
reversedobject *ro; reversedobject *ro;
if (type == &PyReversed_Type && !_PyArg_NoKeywords("reversed()", kwds)) if (type == &PyReversed_Type && !_PyArg_NoKeywords("reversed()", kwds))
@ -231,8 +232,12 @@ reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq) ) if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq) )
return NULL; return NULL;
if (PyObject_HasAttrString(seq, "__reversed__")) reversed_meth = _PyObject_LookupSpecial(seq, "__reversed__", &reversed_cache);
return PyObject_CallMethod(seq, "__reversed__", NULL); if (reversed_meth != NULL) {
PyObject *res = PyObject_CallFunctionObjArgs(reversed_meth, NULL);
Py_DECREF(reversed_meth);
return res;
}
if (!PySequence_Check(seq)) { if (!PySequence_Check(seq)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,