[Jython-checkins] jython: Fixed ABC support, including for Java interfaces.
jim.baker
jython-checkins at python.org
Sun Sep 14 05:37:09 CEST 2014
http://hg.python.org/jython/rev/5d0fd036d08b
changeset: 7374:5d0fd036d08b
user: Jim Baker <jim.baker at rackspace.com>
date: Sat Sep 13 21:35:36 2014 -0600
summary:
Fixed ABC support, including for Java interfaces.
No longer skips some collection tests, in part by ensuring dict, list,
set are not Hashable by having __hash__ set to None.
java.util.{Map, List, Set} are now treated as subclasses of the
corresponding Python abstract base classes.
files:
Lib/_abcoll.py | 17 +-
Lib/test/test_collections.py | 6 +-
Lib/test/test_collections_jy.py | 125 ++++++++++++++
src/org/python/core/PyDictionary.java | 5 +
src/org/python/core/PyList.java | 16 +-
src/org/python/core/PySet.java | 4 +
6 files changed, 162 insertions(+), 11 deletions(-)
diff --git a/Lib/_abcoll.py b/Lib/_abcoll.py
--- a/Lib/_abcoll.py
+++ b/Lib/_abcoll.py
@@ -19,6 +19,8 @@
"Sequence", "MutableSequence",
]
+_is_jython = sys.platform.startswith("java")
+
### ONE-TRICK PONIES ###
def _hasattr(C, attr):
@@ -82,7 +84,7 @@
@classmethod
def __subclasshook__(cls, C):
if cls is Iterator:
- if _hasattr(C, "next"):
+ if _hasattr(C, "next") and _hasattr(C, "__iter__"):
return True
return NotImplemented
@@ -556,8 +558,7 @@
Sequence.register(tuple)
Sequence.register(basestring)
-if sys.platform[:4] != "java":
- Sequence.register(buffer)
+Sequence.register(buffer)
Sequence.register(xrange)
@@ -600,3 +601,13 @@
return self
MutableSequence.register(list)
+
+if _is_jython:
+ from org.python.core import PyFastSequenceIter
+ import java
+
+ MutableSequence.register(java.util.List)
+ MutableMapping.register(java.util.Map)
+ MutableSet.register(java.util.Set)
+ Iterator.register(PyFastSequenceIter)
+
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
--- a/Lib/test/test_collections.py
+++ b/Lib/test/test_collections.py
@@ -295,10 +295,8 @@
# Check some non-hashables
non_samples = [list(), set(), dict()]
for x in non_samples:
- #FIXME: we need to get __hash__ to be None in non_samples for Jython.
- pass
- #self.assertNotIsInstance(x, Hashable)
- #self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
+ self.assertNotIsInstance(x, Hashable)
+ self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
# Check some hashables
samples = [None,
int(), float(), complex(),
diff --git a/Lib/test/test_collections_jy.py b/Lib/test/test_collections_jy.py
new file mode 100644
--- /dev/null
+++ b/Lib/test/test_collections_jy.py
@@ -0,0 +1,125 @@
+from test import test_support
+from test.test_collections import ABCTestCase
+from collections import (
+ Hashable, Iterable, Iterator,
+ Sized, Container, Callable,
+ Set, MutableSet,
+ Mapping, MutableMapping,
+ Sequence, MutableSequence)
+import sys
+
+import java
+
+
+class TestJavaInterfaces(ABCTestCase):
+
+ def test_Iterable(self):
+ # Check some non-iterables
+ non_samples = [
+ java.lang.Integer(42),
+ java.lang.Long(sys.maxint+1)]
+ for x in non_samples:
+ self.assertNotIsInstance(x, Iterable)
+ self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
+ # Check some iterables
+ samples = [
+ java.util.HashMap(),
+ java.util.ArrayList(),
+ java.util.LinkedList(),
+ java.util.HashMap().keys(),
+ java.util.HashMap().items(),
+ java.util.HashMap().values()]
+ for x in samples:
+ self.assertIsInstance(x, Iterable)
+ self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
+
+ def test_Container(self):
+ # Check some objects that are not containers
+ non_samples = [
+ java.lang.String(),
+ java.lang.Integer(42),
+ java.lang.Long(sys.maxint+1)]
+ for x in non_samples:
+ self.assertNotIsInstance(x, Container)
+ self.assertFalse(issubclass(type(x), Container), repr(type(x)))
+ # Check some containers
+ samples = [
+ java.util.HashMap(),
+ java.util.ArrayList(),
+ java.util.LinkedList(),
+ java.util.HashMap().keys(),
+ java.util.HashMap().items(),
+ java.util.HashMap().values()]
+ for x in samples:
+ self.assertIsInstance(x, Container)
+ self.assertTrue(issubclass(type(x), Container), repr(type(x)))
+
+ def test_MutableMapping(self):
+ # Check some objects that do not support MutableMapping
+ non_samples = [
+ java.util.ArrayList(),
+ java.util.HashMap().keys(),
+ java.util.HashSet(),
+ java.util.LinkedList(),
+ java.util.TreeSet(),
+ ]
+ for x in non_samples:
+ self.assertNotIsInstance(x, MutableMapping)
+ self.assertFalse(issubclass(type(x), MutableMapping), repr(type(x)))
+ # Check some mappables
+ samples = [
+ java.util.HashMap(),
+ java.util.concurrent.ConcurrentSkipListMap(),
+ ]
+ for x in samples:
+ self.assertIsInstance(x, MutableMapping)
+ self.assertTrue(issubclass(type(x), MutableMapping), repr(type(x)))
+
+ def test_MutableSequence(self):
+ # Check some objects that do not support MutableSequence
+ non_samples = [
+ java.util.HashMap(),
+ java.util.HashSet(),
+ java.util.TreeSet(),
+ java.util.concurrent.ConcurrentSkipListMap(),
+ ]
+ for x in non_samples:
+ self.assertNotIsInstance(x, MutableSequence)
+ self.assertFalse(issubclass(type(x), MutableSequence), repr(type(x)))
+ # Check some mappables
+ samples = [
+ java.util.ArrayList(),
+ java.util.LinkedList(),
+ java.util.HashMap().keys(),
+ ]
+ for x in samples:
+ self.assertIsInstance(x, MutableSequence)
+ self.assertTrue(issubclass(type(x), MutableSequence), repr(type(x)))
+
+ def test_MutableSet(self):
+ # Check some objects that are not sets
+ non_samples = [
+ java.util.ArrayList(),
+ java.util.LinkedList(),
+ java.util.HashMap(),
+ java.util.concurrent.ConcurrentSkipListMap(),
+ ]
+ for x in non_samples:
+ self.assertNotIsInstance(x, MutableSet)
+ self.assertFalse(issubclass(type(x), MutableSet), repr(type(x)))
+ # Check some sets
+ samples = [
+ java.util.HashSet(),
+ java.util.TreeSet(),
+ ]
+ for x in samples:
+ self.assertIsInstance(x, MutableSet)
+ self.assertTrue(issubclass(type(x), MutableSet), repr(type(x)))
+
+
+def test_main():
+ test_classes = [TestJavaInterfaces]
+ test_support.run_unittest(*test_classes)
+
+if __name__ == "__main__":
+ test_main()
diff --git a/src/org/python/core/PyDictionary.java b/src/org/python/core/PyDictionary.java
--- a/src/org/python/core/PyDictionary.java
+++ b/src/org/python/core/PyDictionary.java
@@ -16,6 +16,7 @@
import java.util.concurrent.ConcurrentHashMap;
import org.python.expose.ExposedClassMethod;
+import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -31,6 +32,10 @@
public class PyDictionary extends PyObject implements ConcurrentMap {
public static final PyType TYPE = PyType.fromClass(PyDictionary.class);
+ {
+ // Ensure dict is not Hashable
+ TYPE.object___setattr__("__hash__", Py.None);
+ }
private final ConcurrentMap<PyObject, PyObject> internalMap;
diff --git a/src/org/python/core/PyList.java b/src/org/python/core/PyList.java
--- a/src/org/python/core/PyList.java
+++ b/src/org/python/core/PyList.java
@@ -3,6 +3,8 @@
import java.util.ArrayList;
import java.util.Arrays;
+
+import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@@ -23,6 +25,11 @@
public class PyList extends PySequenceList implements List {
public static final PyType TYPE = PyType.fromClass(PyList.class);
+ {
+ // Ensure list is not Hashable
+ TYPE.object___setattr__("__hash__", Py.None);
+ }
+
private final List<PyObject> list;
public volatile int gListAllocatedStatus = -1;
@@ -918,12 +925,13 @@
}
public int hashCode() {
- return list___hash__();
+ throw Py.TypeError(String.format("unhashable type: '%.200s'", getType().fastGetName()));
}
- @ExposedMethod(doc = BuiltinDocs.list___hash___doc)
- final synchronized int list___hash__() {
- throw Py.TypeError(String.format("unhashable type: '%.200s'", getType().fastGetName()));
+ //@ExposedMethod(doc = BuiltinDocs.list___hash___doc)
+ @ExposedGet(name = "__hash__")
+ public PyObject list___hash__() {
+ return Py.None;
}
@Override
diff --git a/src/org/python/core/PySet.java b/src/org/python/core/PySet.java
--- a/src/org/python/core/PySet.java
+++ b/src/org/python/core/PySet.java
@@ -13,6 +13,10 @@
public class PySet extends BaseSet {
public static final PyType TYPE = PyType.fromClass(PySet.class);
+ {
+ // Ensure set is not Hashable
+ TYPE.object___setattr__("__hash__", Py.None);
+ }
public PySet() {
this(TYPE);
--
Repository URL: http://hg.python.org/jython
More information about the Jython-checkins
mailing list