Index: Objects/enumobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/enumobject.c,v retrieving revision 1.8 diff -c -r1.8 enumobject.c *** Objects/enumobject.c 2 Nov 2003 05:37:44 -0000 1.8 --- Objects/enumobject.c 2 Nov 2003 08:59:47 -0000 *************** *** 155,157 **** --- 155,282 ---- enum_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; + + /* Reversed Object ***************************************************************/ + + typedef struct { + PyObject_HEAD + long index; + PyObject* seq; + } reversedobject; + + static PyObject * + reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds) + { + long n; + PyObject *seq; + reversedobject *ro; + + if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq)) + return NULL; + + if (PyObject_HasAttrString(seq, "__reversed__")) + return PyObject_CallMethod(seq, "__reversed__", NULL); + + if (!PySequence_Check(seq)) { + PyErr_SetString(PyExc_TypeError, + "argument to reversed() must be a sequence"); + return NULL; + + } + + n = PySequence_Size(seq); + if (n == -1) + return NULL; + + ro = (reversedobject *)type->tp_alloc(type, 0); + if (ro == NULL) + return NULL; + + ro->index = n-1; + Py_INCREF(seq); + ro->seq = seq; + return (PyObject *)ro; + } + + static void + reversed_dealloc(reversedobject *ro) + { + PyObject_GC_UnTrack(ro); + Py_XDECREF(ro->seq); + ro->ob_type->tp_free(ro); + } + + static int + reversed_traverse(reversedobject *ro, visitproc visit, void *arg) + { + if (ro->seq) + return visit((PyObject *)(ro->seq), arg); + return 0; + } + + static PyObject * + reversed_next(reversedobject *ro) + { + PyObject *item; + + if (ro->index < 0) + return NULL; + + assert(PySequence_Check(ro->seq)); + item = PySequence_GetItem(ro->seq, ro->index); + if (item == NULL) + return NULL; + + ro->index--; + return item; + } + + PyDoc_STRVAR(reversed_doc, + "reverse(sequence) -> reverse iterator over values of the sequence\n" + "\n" + "Return a reverse iterator"); + + PyTypeObject PyReversed_Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /* ob_size */ + "reversed", /* tp_name */ + sizeof(reversedobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)reversed_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + reversed_doc, /* tp_doc */ + (traverseproc)reversed_traverse,/* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)reversed_next, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + reversed_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ + }; Index: Include/enumobject.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/enumobject.h,v retrieving revision 2.2 diff -c -r2.2 enumobject.h *** Include/enumobject.h 12 Aug 2002 07:21:56 -0000 2.2 --- Include/enumobject.h 2 Nov 2003 08:59:47 -0000 *************** *** 8,13 **** --- 8,14 ---- #endif PyAPI_DATA(PyTypeObject) PyEnum_Type; + PyAPI_DATA(PyTypeObject) PyReversed_Type; #ifdef __cplusplus } Index: Python/bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.301 diff -c -r2.301 bltinmodule.c *** Python/bltinmodule.c 25 Oct 2003 23:24:14 -0000 2.301 --- Python/bltinmodule.c 2 Nov 2003 08:59:49 -0000 *************** *** 2121,2126 **** --- 2121,2127 ---- SETBUILTIN("list", &PyList_Type); SETBUILTIN("long", &PyLong_Type); SETBUILTIN("object", &PyBaseObject_Type); + SETBUILTIN("reversed", &PyReversed_Type); SETBUILTIN("slice", &PySlice_Type); SETBUILTIN("staticmethod", &PyStaticMethod_Type); SETBUILTIN("str", &PyString_Type); Index: Lib/test/test_enumerate.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_enumerate.py,v retrieving revision 1.6 diff -c -r1.6 test_enumerate.py *** Lib/test/test_enumerate.py 29 May 2003 07:20:29 -0000 1.6 --- Lib/test/test_enumerate.py 2 Nov 2003 08:59:49 -0000 *************** *** 124,132 **** seq = range(10,20000,2) res = zip(range(20000), seq) def test_main(verbose=None): ! testclasses = (EnumerateTestCase, SubclassTestCase, TestEmpty, TestBig) test_support.run_unittest(*testclasses) # verify reference counting --- 124,154 ---- seq = range(10,20000,2) res = zip(range(20000), seq) + class TestReversed(unittest.TestCase): + + def test_simple(self): + class A: + def __getitem__(self, i): + if i < 5: + return str(i) + raise StopIteration + def __len__(self): + return 5 + for data in 'abc', range(5), tuple(enumerate('abc')), A(): + self.assertEqual(list(data)[::-1], list(reversed(data))) + self.assertRaises(TypeError, reversed, {}) + + def test_custom_reversed(self): + class A: + def __reversed__(self): + for i in xrange(5): + yield i + self.assertEqual(list(reversed(A())), range(5)) + def test_main(verbose=None): ! testclasses = (EnumerateTestCase, SubclassTestCase, TestEmpty, TestBig, ! TestReversed) test_support.run_unittest(*testclasses) # verify reference counting Index: Doc/lib/libfuncs.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libfuncs.tex,v retrieving revision 1.150 diff -c -r1.150 libfuncs.tex *** Doc/lib/libfuncs.tex 13 Oct 2003 17:52:35 -0000 1.150 --- Doc/lib/libfuncs.tex 2 Nov 2003 08:59:49 -0000 *************** *** 880,885 **** --- 880,895 ---- when passed to \function{eval()}. \end{funcdesc} + \begin{funcdesc}{reversed}{iterable} + Return a reverse iterator. \var{iterable} must be an object which + supports the sequence protocol (the __len__() and the + \method{__getitem__()} method with integer arguments starting at + \code{0}). Alternatively, the \var{iterable} argument may be an + object defining a \method{__reverse__()} method which returns an + iterator. + \versionadded{2.4} + \end{funcdesc} + \begin{funcdesc}{round}{x\optional{, n}} Return the floating point value \var{x} rounded to \var{n} digits after the decimal point. If \var{n} is omitted, it defaults to zero.