Index: src/org/python/core/PyReversedIterator.java =================================================================== --- src/org/python/core/PyReversedIterator.java (revision 0) +++ src/org/python/core/PyReversedIterator.java (revision 0) @@ -0,0 +1,22 @@ +package org.python.core; + +public class PyReversedIterator extends PyIterator { + + private PyObject seq; + private int idx; + + public PyReversedIterator(PyObject seq) { + this.seq = seq; + idx = seq.__len__(); + if (idx > 0 ) + idx = idx - 1; + } + + public PyObject __iternext__() { + //System.out.println("element at = " + idx); + if (idx >= 0) + return seq.__finditem__(idx--); + else + return null; + } +} Index: src/org/python/core/__builtin__.java =================================================================== --- src/org/python/core/__builtin__.java (revision 3318) +++ src/org/python/core/__builtin__.java (working copy) @@ -110,6 +110,8 @@ return fancyCall(new PyObject[] { arg1 }); case 43: return fancyCall(new PyObject[] { arg1 }); + case 45: + return __builtin__.reversed(arg1); default: throw info.unexpectedCall(1, false); } @@ -386,9 +388,8 @@ dict.__setitem__("vars", new BuiltinFunctions("vars", 41, 0, 1)); dict.__setitem__("xrange", new BuiltinFunctions("xrange", 42, 1, 3)); dict.__setitem__("zip", new BuiltinFunctions("zip", 43, 1, -1)); - + dict.__setitem__("reversed", new BuiltinFunctions("reversed", 45, 1)); dict.__setitem__("__import__", new ImportFunction()); - } public static PyObject abs(PyObject o) { @@ -1016,7 +1017,18 @@ } return result; } - + + public static PyObject reversed(PyObject seq) { + if (hasattr(seq, "__getitem__") && + hasattr(seq, "__len__") && + !(seq instanceof PyDictionary)) { + + return new PyReversedIterator(seq); + } else { + throw Py.TypeError("argument to reversed() must be a sequence"); + } + } + public static PyObject sum(PyObject seq) { return sum(seq, Py.Zero); } Index: Lib/test/test_enumerate.py =================================================================== --- Lib/test/test_enumerate.py (revision 3318) +++ Lib/test/test_enumerate.py (working copy) @@ -131,9 +131,31 @@ 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, {}) + +# This part is needed when we have obj that has __reversed__ method +# 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) + testclasses = (EnumerateTestCase, SubclassTestCase, TestEmpty, TestBig, + TestReversed) for test in testclasses: test_support.run_unittest(test)