[Jython-checkins] jython: Convert iterators to both Object[] and primitive variants. Fixes #2279
jim.baker
jython-checkins at python.org
Wed Jan 6 20:40:28 EST 2016
https://hg.python.org/jython/rev/1e7c082d089d
changeset: 7853:1e7c082d089d
user: Jim Baker <jim.baker at rackspace.com>
date: Wed Jan 06 18:40:06 2016 -0700
summary:
Convert iterators to both Object[] and primitive variants. Fixes #2279
files:
Lib/test/test_array_jy.py | 10 +
src/org/python/core/PyArray.java | 66 +++++----
src/org/python/core/PyIterator.java | 4 +
src/org/python/core/PyXRange.java | 4 +
src/org/python/core/ReflectedArgs.java | 14 +-
tests/java/org/python/core/PyArrayTest.java | 12 +
6 files changed, 81 insertions(+), 29 deletions(-)
diff --git a/Lib/test/test_array_jy.py b/Lib/test/test_array_jy.py
--- a/Lib/test/test_array_jy.py
+++ b/Lib/test/test_array_jy.py
@@ -129,6 +129,16 @@
self.assertAsList(jarray.array([1, 2, 3, 4, 5], "i"), [1, 2, 3, 4, 5])
self.assertAsList(array("i", [1, 2, 3, 4, 5]), [1, 2, 3, 4, 5])
+ def test_auxillary_boxing(self):
+ "PyArray is internally used to support boxing of iterators/iterables"
+ self.assertAsList(xrange(5), [0, 1, 2, 3, 4])
+ self.assertAsList(iter(xrange(5)), [0, 1, 2, 3, 4])
+ self.assertAsList(list(xrange(5)), [0, 1, 2, 3, 4])
+ self.assertAsList((i * 2 for i in xrange(5)), [0, 2, 4, 6, 8])
+ self.assertAsList(iter((i * 2 for i in xrange(5))), [0, 2, 4, 6, 8])
+ self.assertAsList(iter((i * 2 for i in xrange(5))), [0, 2, 4, 6, 8])
+ self.assertAsList(itertools.chain('ABC', 'DEF'), ['A', 'B', 'C', 'D', 'E', 'F'])
+
def test_object_varargs(self):
"array.array objects can be used in the varargs position, with primitive boxing"
a = array('i', range(5, 10))
diff --git a/src/org/python/core/PyArray.java b/src/org/python/core/PyArray.java
--- a/src/org/python/core/PyArray.java
+++ b/src/org/python/core/PyArray.java
@@ -57,6 +57,15 @@
setup(type, data);
}
+ public PyArray(Class<?> type, PyObject initial) {
+ this(TYPE);
+ this.type = type;
+ typecode = class2char(type);
+ data = Array.newInstance(type, 0);
+ delegate = new ArrayDelegate();
+ useInitial(initial);
+ }
+
public PyArray(Class<?> type, int n) {
this(type, Array.newInstance(type, n));
}
@@ -77,6 +86,34 @@
delegate = new ArrayDelegate();
}
+ private void useInitial(PyObject initial) {
+ /*
+ * The initialiser may be omitted, or may validly be one of several types in the broad
+ * categories of a byte string (which is treated as a machine representation of the data) or
+ * an iterable yielding values assignable to the elements. There is special treatment for
+ * type 'u' Unicode.
+ */
+ if (initial == null) {
+ // Fall through
+
+ } else if (initial instanceof PyList) {
+ fromlist(initial);
+
+ } else if (initial instanceof PyString && !(initial instanceof PyUnicode)) {
+ fromstring(initial.toString());
+
+ } else if ("u".equals(typecode)) {
+ if (initial instanceof PyUnicode) {
+ extendArray(((PyUnicode)initial).toCodePoints());
+ } else {
+ extendUnicodeIter(initial);
+ }
+
+ } else {
+ extendInternal(initial);
+ }
+ }
+
@ExposedNew
static final PyObject array_new(PyNewWrapper new_, boolean init, PyType subtype,
PyObject[] args, String[] keywords) {
@@ -130,34 +167,7 @@
class2char(type);
self.setup(type, Array.newInstance(type, 0));
self.typecode = typecode;
-
- /*
- * The initialiser may be omitted, or may validly be one of several types in the broad
- * categories of a byte string (which is treated as a machine representation of the data) or
- * an iterable yielding values assignable to the elements. There is special treatment for
- * type 'u' Unicode.
- */
- PyObject initial = ap.getPyObject(1, null);
- if (initial == null) {
- // Fall through
-
- } else if (initial instanceof PyList) {
- self.fromlist(initial);
-
- } else if (initial instanceof PyString && !(initial instanceof PyUnicode)) {
- self.fromstring(initial.toString());
-
- } else if ("u".equals(typecode)) {
- if (initial instanceof PyUnicode) {
- self.extendArray(((PyUnicode)initial).toCodePoints());
- } else {
- self.extendUnicodeIter(initial);
- }
-
- } else {
- self.extendInternal(initial);
- }
-
+ self.useInitial(ap.getPyObject(1, null));
return self;
}
diff --git a/src/org/python/core/PyIterator.java b/src/org/python/core/PyIterator.java
--- a/src/org/python/core/PyIterator.java
+++ b/src/org/python/core/PyIterator.java
@@ -81,6 +81,10 @@
}
return list;
}
+ if (c.isArray()) {
+ PyArray array = new PyArray(c.getComponentType(), this);
+ return array.__tojava__(c);
+ }
return super.__tojava__(c);
}
diff --git a/src/org/python/core/PyXRange.java b/src/org/python/core/PyXRange.java
--- a/src/org/python/core/PyXRange.java
+++ b/src/org/python/core/PyXRange.java
@@ -210,6 +210,10 @@
}
return list;
}
+ if (c.isArray()) {
+ PyArray array = new PyArray(c.getComponentType(), this);
+ return array.__tojava__(c);
+ }
return super.__tojava__(c);
}
}
diff --git a/src/org/python/core/ReflectedArgs.java b/src/org/python/core/ReflectedArgs.java
--- a/src/org/python/core/ReflectedArgs.java
+++ b/src/org/python/core/ReflectedArgs.java
@@ -155,7 +155,19 @@
return pyArgs;
}
PyObject lastArg = pyArgs[pyArgs.length - 1];
- if (lastArg instanceof PySequenceList || lastArg instanceof PyArray) {
+ if (lastArg instanceof PySequenceList ||
+ lastArg instanceof PyArray ||
+ lastArg instanceof PyXRange ||
+ lastArg instanceof PyIterator) {
+ // NOTE that the check is against PySequenceList, not PySequence,
+ // because certain Java <=> Python semantics currently require this
+ // additional strictness. Perhaps this can be relaxed.
+
+ // Empirically this list is exhaustive against the Jython runtime,
+ // excluding only PyBaseString, PyMemoryView, Py2kBuffer, BaseBytes,
+ // and AstList, many/most of which seem likely to be problematic for
+ // varargs usage.
+
// FIXME also check if lastArg is sequence-like
return pyArgs; // will be boxed in an array once __tojava__ is called
}
diff --git a/tests/java/org/python/core/PyArrayTest.java b/tests/java/org/python/core/PyArrayTest.java
--- a/tests/java/org/python/core/PyArrayTest.java
+++ b/tests/java/org/python/core/PyArrayTest.java
@@ -1,6 +1,7 @@
package org.python.core;
import junit.framework.TestCase;
+import org.junit.Assert;
import org.python.util.PythonInterpreter;
/**
@@ -63,4 +64,15 @@
assertEquals(0.0, a[0]);
assertEquals(3.0, a[3]);
}
+
+ public void testToJava() {
+ PythonInterpreter interp = new PythonInterpreter();
+ PyObject pyobj = interp.eval("[i * 2 for i in xrange(5)]");
+ Assert.assertArrayEquals
+ (new int[] {0, 2, 4, 6, 8},
+ (int[])pyobj.__tojava__(int[].class));
+ Assert.assertArrayEquals(
+ new Integer[] { 0, 2, 4, 6, 8},
+ (Object[])pyobj.__tojava__(Object[].class));
+ }
}
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list