From: <cg...@us...> - 2009-01-17 20:56:34
|
Revision: 5941 http://jython.svn.sourceforge.net/jython/?rev=5941&view=rev Author: cgroves Date: 2009-01-17 20:56:28 +0000 (Sat, 17 Jan 2009) Log Message: ----------- Implement Iterable in PyIterator. This means generators are usable in foreach loops. The implementation could be moved up to PyObject, but I feel like implementing the interface says that the object will be iterable, and not all PyObjects provide an __iter__. Modified Paths: -------------- trunk/jython/Lib/test/test_java_visibility.py trunk/jython/src/org/python/core/BytecodeLoader.java trunk/jython/src/org/python/core/PyIterator.java trunk/jython/src/org/python/core/PyList.java trunk/jython/src/org/python/core/PyObject.java trunk/jython/src/org/python/core/PySequence.java trunk/jython/src/org/python/core/codecs.java trunk/jython/src/org/python/core/imp.java trunk/jython/tests/java/org/python/tests/Coercions.java Added Paths: ----------- trunk/jython/src/org/python/core/WrappedIterIterator.java Modified: trunk/jython/Lib/test/test_java_visibility.py =================================================================== --- trunk/jython/Lib/test/test_java_visibility.py 2009-01-17 20:35:09 UTC (rev 5940) +++ trunk/jython/Lib/test/test_java_visibility.py 2009-01-17 20:56:28 UTC (rev 5941) @@ -193,9 +193,7 @@ yield 2 yield 3 self.assertEquals(6, Coercions.takeIterable(simple_gen())) - self.assertEquals(True, Coercions.takeBoolIterable(simple_gen())) - def test_class_coercion(self): c = Coercions() from java.util import Hashtable, HashMap Modified: trunk/jython/src/org/python/core/BytecodeLoader.java =================================================================== --- trunk/jython/src/org/python/core/BytecodeLoader.java 2009-01-17 20:35:09 UTC (rev 5940) +++ trunk/jython/src/org/python/core/BytecodeLoader.java 2009-01-17 20:56:28 UTC (rev 5941) @@ -8,7 +8,7 @@ import org.python.util.Generic; /** - * Utility class for loading of compiled python modules and java classes defined in python modules. + * Utility class for loading compiled python modules and java classes defined in python modules. */ public class BytecodeLoader { Modified: trunk/jython/src/org/python/core/PyIterator.java =================================================================== --- trunk/jython/src/org/python/core/PyIterator.java 2009-01-17 20:35:09 UTC (rev 5940) +++ trunk/jython/src/org/python/core/PyIterator.java 2009-01-17 20:56:28 UTC (rev 5941) @@ -1,6 +1,8 @@ // Copyright 2000 Finn Bock package org.python.core; +import java.util.Iterator; + /** * An abstract helper class useful when implementing an iterator object. This implementation supply * a correct __iter__() and a next() method based on the __iternext__() implementation. The @@ -9,7 +11,7 @@ * If the implementation raises a StopIteration exception, it should be stored in stopException so * the correct exception can be thrown to preserve the line numbers in the traceback. */ -public abstract class PyIterator extends PyObject { +public abstract class PyIterator extends PyObject implements Iterable<Object> { protected PyException stopException; @@ -51,4 +53,13 @@ } return ret; } + + public Iterator<Object> iterator() { + return new WrappedIterIterator<Object>(this) { + @Override + public Object next() { + return getNext().__tojava__(Object.class); + } + }; + } } Modified: trunk/jython/src/org/python/core/PyList.java =================================================================== --- trunk/jython/src/org/python/core/PyList.java 2009-01-17 20:35:09 UTC (rev 5940) +++ trunk/jython/src/org/python/core/PyList.java 2009-01-17 20:56:28 UTC (rev 5941) @@ -3,13 +3,13 @@ import java.util.Collection; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import org.python.expose.ExposedMethod; import org.python.expose.ExposedNew; import org.python.expose.ExposedType; import org.python.expose.MethodType; +import org.python.util.Generic; /** * A builtin python list. @@ -51,7 +51,7 @@ } private static List<PyObject> listify(Iterator<PyObject> iter) { - final List<PyObject> list = new LinkedList<PyObject>(); + List<PyObject> list = Generic.list(); while (iter.hasNext()) { list.add(iter.next()); } Modified: trunk/jython/src/org/python/core/PyObject.java =================================================================== --- trunk/jython/src/org/python/core/PyObject.java 2009-01-17 20:35:09 UTC (rev 5940) +++ trunk/jython/src/org/python/core/PyObject.java 2009-01-17 20:56:28 UTC (rev 5941) @@ -7,8 +7,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.NoSuchElementException; - import org.python.expose.ExposedDelete; import org.python.expose.ExposedGet; import org.python.expose.ExposedMethod; @@ -765,37 +763,11 @@ */ public Iterable<PyObject> asIterable() { return new Iterable<PyObject>() { - public Iterator<PyObject> iterator() { - return new Iterator<PyObject>() { - - private PyObject iter = __iter__(); - - private PyObject next; - - private boolean checkedForNext; - - public boolean hasNext() { - if (!checkedForNext) { - next = iter.__iternext__(); - checkedForNext = true; - } - return next != null; - } - + return new WrappedIterIterator<PyObject>(__iter__()) { public PyObject next() { - if (!hasNext()) { - throw new NoSuchElementException("End of the line, bub"); - } - PyObject toReturn = next; - checkedForNext = false; - next = null; - return toReturn; + return getNext(); } - - public void remove() { - throw new UnsupportedOperationException("Can't remove from a Python iterator"); - } }; } }; @@ -1894,8 +1866,8 @@ where1 = where[0]; PyObject impl2 = t2.lookup_where(right, where); where2 = where[0]; - if (impl2 != null && impl1 != null && where1 != where2 && - (t2.isSubType(t1) && !Py.isSubClass(where1, where2) + if (impl2 != null && impl1 != null && where1 != where2 && + (t2.isSubType(t1) && !Py.isSubClass(where1, where2) && !Py.isSubClass(t1, where2) || isStrUnicodeSpecialCase(t1, t2, op))) { PyObject tmp = o1; Modified: trunk/jython/src/org/python/core/PySequence.java =================================================================== --- trunk/jython/src/org/python/core/PySequence.java 2009-01-17 20:35:09 UTC (rev 5940) +++ trunk/jython/src/org/python/core/PySequence.java 2009-01-17 20:56:28 UTC (rev 5941) @@ -14,9 +14,6 @@ */ public abstract class PySequence extends PyObject { - /** - * This constructor is used by PyJavaClass.init() - */ public PySequence() {} public int gListAllocatedStatus = -1; Added: trunk/jython/src/org/python/core/WrappedIterIterator.java =================================================================== --- trunk/jython/src/org/python/core/WrappedIterIterator.java (rev 0) +++ trunk/jython/src/org/python/core/WrappedIterIterator.java 2009-01-17 20:56:28 UTC (rev 5941) @@ -0,0 +1,48 @@ +package org.python.core; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * Exposes a Python iter as a Java Iterator. + */ +public abstract class WrappedIterIterator<E> implements Iterator<E> { + + private final PyObject iter; + + private PyObject next; + + private boolean checkedForNext; + + public WrappedIterIterator(PyObject iter) { + this.iter = iter; + } + + public boolean hasNext() { + if (!checkedForNext) { + next = iter.__iternext__(); + checkedForNext = true; + } + return next != null; + } + + /** + * Subclasses must implement this to turn the type returned by the iter to the type expected by + * Java. + */ + public abstract E next(); + + public PyObject getNext() { + if (!hasNext()) { + throw new NoSuchElementException("End of the line, bub"); + } + PyObject toReturn = next; + checkedForNext = false; + next = null; + return toReturn; + } + + public void remove() { + throw new UnsupportedOperationException("Can't remove from a Python iterator"); + } +} Modified: trunk/jython/src/org/python/core/codecs.java =================================================================== --- trunk/jython/src/org/python/core/codecs.java 2009-01-17 20:35:09 UTC (rev 5940) +++ trunk/jython/src/org/python/core/codecs.java 2009-01-17 20:56:28 UTC (rev 5941) @@ -245,14 +245,14 @@ if (Py.isInstance(exc, Py.UnicodeDecodeError)) { PyObject object = exc.__getattr__("object"); if (!Py.isInstance(object, PyString.TYPE) || Py.isInstance(object, PyUnicode.TYPE)) { - throw Py.TypeError("object attribute must be str"); + throw Py.TypeError("object attribute must be str"); } PyObject end = exc.__getattr__("end"); return new PyTuple(new PyUnicode(Py_UNICODE_REPLACEMENT_CHARACTER), end); } else if (Py.isInstance(exc, Py.UnicodeEncodeError)) { PyObject object = exc.__getattr__("object"); if (!Py.isInstance(object, PyUnicode.TYPE)) { - throw Py.TypeError("object attribute must be unicode"); + throw Py.TypeError("object attribute must be unicode"); } PyObject end = exc.__getattr__("end"); return new PyTuple(Py.java2py("?"), end); @@ -388,9 +388,9 @@ XMLCHARREFREPLACE, BACKSLASHREPLACE }; - for (int i = 0; i < builtinErrorHandlers.length; i++) { - register_error(builtinErrorHandlers[i], Py.newJavaFunc(codecs.class, - builtinErrorHandlers[i] + "_errors")); + for (String builtinErrorHandler : builtinErrorHandlers) { + register_error(builtinErrorHandler, Py.newJavaFunc(codecs.class, + builtinErrorHandler + "_errors")); } import_encodings(); } @@ -414,9 +414,9 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 1 , - + }; - + private static boolean SPECIAL(char c, boolean encodeO, boolean encodeWS){ return (c>127 || utf7_special[(c)] == 1) || (encodeWS && (utf7_special[(c)] == 2)) || @@ -447,7 +447,6 @@ int bitsInCharsleft = 0; long charsleft = 0; boolean surrogate = false; - char highOrderSurrogate = 0; StringBuilder unicode = new StringBuilder(e); while (s < e) { // restart: @@ -470,7 +469,6 @@ surrogate = false; } else if (0xDC00 <= outCh && outCh <= 0xDFFF) { surrogate = true; - highOrderSurrogate = outCh; } else { unicode.append(outCh); } @@ -537,7 +535,6 @@ "code pairs are not supported"); } else if (0xDC00 <= outCh && outCh <= 0xDFFF) { surrogate = true; - highOrderSurrogate = outCh; } else { unicode.append(outCh); } @@ -631,7 +628,7 @@ bitsleft -= 6; } /* If the next character is special then we dont' need to terminate - the shift sequence. If the next character is not a BASE64 character + the shift sequence. If the next character is not a BASE64 character or '-' then the shift sequence will be terminated implicitly and we don't have to insert a '-'. */ @@ -1280,7 +1277,7 @@ this.start = start; this.stop = stop; this.step = step; - + // this bounds checking is necessary to convert between use of code units elsewhere, and codepoints here // it would be nice if it were unnecessary! int count = getCodePointCount(s); @@ -1290,7 +1287,7 @@ else if (stop >= count) { this.stop = count; } - + for (int i = 0; i < start; i++) { nextCodePoint(); } @@ -1303,7 +1300,7 @@ private static int getCodePointCount(String s) { return s.codePointCount(0, s.length()); } - + public boolean hasNext() { return current < stop; } Modified: trunk/jython/src/org/python/core/imp.java =================================================================== --- trunk/jython/src/org/python/core/imp.java 2009-01-17 20:35:09 UTC (rev 5940) +++ trunk/jython/src/org/python/core/imp.java 2009-01-17 20:56:28 UTC (rev 5941) @@ -9,6 +9,7 @@ import java.io.InputStream; import java.util.concurrent.locks.ReentrantLock; +import org.python.compiler.Module; import org.python.core.util.FileUtil; /** @@ -189,9 +190,7 @@ } } - public static byte[] compileSource(String name, - InputStream fp, - String filename) { + public static byte[] compileSource(String name, InputStream fp, String filename) { ByteArrayOutputStream ofp = new ByteArrayOutputStream(); try { if(filename == null) { @@ -203,13 +202,7 @@ } finally { fp.close(); } - org.python.compiler.Module.compile(node, - ofp, - name + "$py", - filename, - true, - false, - null); + Module.compile(node, ofp, name + "$py", filename, true, false, null); return ofp.toByteArray(); } catch(Throwable t) { throw ParserFacade.fixParseError(null, t, filename); Modified: trunk/jython/tests/java/org/python/tests/Coercions.java =================================================================== --- trunk/jython/tests/java/org/python/tests/Coercions.java 2009-01-17 20:35:09 UTC (rev 5940) +++ trunk/jython/tests/java/org/python/tests/Coercions.java 2009-01-17 20:56:28 UTC (rev 5941) @@ -83,4 +83,21 @@ public static String take(byte bt) { return "take with byte arg: " + bt; } + + public static int takeIterable(Iterable<Integer> it) { + int sum = 0; + for (Integer integer : it) { + sum += integer; + } + return sum; + } + + public static boolean takeBoolIterable(Iterable<Boolean> it) { + for (Boolean integer : it) { + if (!integer) { + return false; + } + } + return true; + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |