[Jython-checkins] jython: Now uses java.util.WeakHashMap to back weakref.WeakSet

Stefan Richthofer Stefan.Richthofer at gmx.de
Sat Nov 29 05:49:00 CET 2014


Hello Jim,

I recently re-generated the *Derived classes and this results in the following build-error now (I suspect due to your changes):

/modules/_collections/PyDefaultDictDerived.java:1144: error: invalid method declaration; return type required
    [javac]     public PyDictionaryDerived(PyType subtype,ConcurrentMap backingMap,boolean useBackingMap) {
    [javac]            ^
    [javac] 1 error

BUILD FAILED

It is easy to repair modules._collections.PyDefaultDictDerived.java manually by changing the erroneous lines as follows:

from
public PyDictionaryDerived(PyType subtype,ConcurrentMap backingMap,boolean useBackingMap) {
    super(subtype,backingMap,useBackingMap);
    ...

to
public PyDefaultDictDerived(PyType subtype,ConcurrentMap backingMap) {//,boolean useBackingMap) {
    super(subtype,backingMap);//,useBackingMap);
    ...

However, it is still a bug in the generator and should be fixed there, but I am spontaneously not sure how to do this. Do you see an easy fix, or should I create an issue for this?

-Stefan



> Gesendet: Freitag, 21. November 2014 um 03:18 Uhr
> Von: "jim.baker" <jython-checkins at python.org>
> An: jython-checkins at python.org
> Betreff: [Jython-checkins] jython: Now uses java.util.WeakHashMap to back weakref.WeakSet
>
> https://hg.python.org/jython/rev/f51940218cf2
> changeset:   7420:f51940218cf2
> user:        Jim Baker <jim.baker at rackspace.com>
> date:        Thu Nov 20 19:17:46 2014 -0700
> summary:
>   Now uses java.util.WeakHashMap to back weakref.WeakSet
> 
> Adds jythonlib.set_builder so that Python sets/derived sets can be
> built with an arbitrary backing java.util.Set.  Updates test_weakset
> to 2.7 and fixes all outstanding skips. Updates gderived.py so that it
> can include arbitrary additional imports, based on a new import
> directive.
> 
> files:
>   Lib/_weakrefset.py                                 |  213 +---------
>   Lib/test/test_set.py                               |    3 +-
>   Lib/test/test_weakset.py                           |   71 ++-
>   src/org/python/core/BaseSet.java                   |    8 +-
>   src/org/python/core/PyDictionaryDerived.java       |   18 +-
>   src/org/python/core/PySet.java                     |    9 +
>   src/org/python/core/PySetDerived.java              |   10 +
>   src/org/python/modules/_jythonlib/_jythonlib.java  |    2 +
>   src/org/python/modules/_jythonlib/set_builder.java |   48 ++
>   src/templates/dict.derived                         |   10 +
>   src/templates/gderived.py                          |   25 +
>   src/templates/set.derived                          |   11 +
>   12 files changed, 186 insertions(+), 242 deletions(-)
> 
> 
> diff --git a/Lib/_weakrefset.py b/Lib/_weakrefset.py
> --- a/Lib/_weakrefset.py
> +++ b/Lib/_weakrefset.py
> @@ -2,211 +2,20 @@
>  # This code is separated-out because it is needed
>  # by abc.py to load everything else at startup.
>  
> -from _weakref import ref
> +from java.util import WeakHashMap
> +from java.util.Collections import newSetFromMap, synchronizedMap
> +from jythonlib import set_builder, MapMaker
>  
>  __all__ = ['WeakSet']
>  
>  
> -class _IterationGuard(object):
> -    # This context manager registers itself in the current iterators of the
> -    # weak container, such as to delay all removals until the context manager
> -    # exits.
> -    # This technique should be relatively thread-safe (since sets are).
> +class WeakSet(set):
>  
> -    def __init__(self, weakcontainer):
> -        # Don't create cycles
> -        self.weakcontainer = ref(weakcontainer)
> +    def __new__(cls, data=None):
> +        def _build():
> +            # Although not specified in the docs, WeakSet supports equality on
> +            # keys, as seen in test_weakset and its use of testing class
> +            # SomeClass. Therefore we cannot use MapMaker in this case.
> +            return newSetFromMap(synchronizedMap(WeakHashMap()))
>  
> -    def __enter__(self):
> -        w = self.weakcontainer()
> -        if w is not None:
> -            w._iterating.add(self)
> -        return self
> -
> -    def __exit__(self, e, t, b):
> -        w = self.weakcontainer()
> -        if w is not None:
> -            s = w._iterating
> -            s.remove(self)
> -            if not s:
> -                w._commit_removals()
> -
> -
> -class WeakSet(object):
> -    def __init__(self, data=None):
> -        self.data = set()
> -        def _remove(item, selfref=ref(self)):
> -            self = selfref()
> -            if self is not None:
> -                if self._iterating:
> -                    self._pending_removals.append(item)
> -                else:
> -                    self.data.discard(item)
> -        self._remove = _remove
> -        # A list of keys to be removed
> -        self._pending_removals = []
> -        self._iterating = set()
> -        if data is not None:
> -            self.update(data)
> -
> -    def _commit_removals(self):
> -        l = self._pending_removals
> -        discard = self.data.discard
> -        while l:
> -            discard(l.pop())
> -
> -    def __iter__(self):
> -        with _IterationGuard(self):
> -            for itemref in self.data:
> -                item = itemref()
> -                if item is not None:
> -                    yield item
> -
> -    def __len__(self):
> -        return sum(x() is not None for x in self.data)
> -
> -    def __contains__(self, item):
> -        return ref(item) in self.data
> -
> -    def __reduce__(self):
> -        return (self.__class__, (list(self),),
> -                getattr(self, '__dict__', None))
> -
> -    __hash__ = None
> -
> -    def add(self, item):
> -        if self._pending_removals:
> -            self._commit_removals()
> -        self.data.add(ref(item, self._remove))
> -
> -    def clear(self):
> -        if self._pending_removals:
> -            self._commit_removals()
> -        self.data.clear()
> -
> -    def copy(self):
> -        return self.__class__(self)
> -
> -    def pop(self):
> -        if self._pending_removals:
> -            self._commit_removals()
> -        while True:
> -            try:
> -                itemref = self.data.pop()
> -            except KeyError:
> -                raise KeyError('pop from empty WeakSet')
> -            item = itemref()
> -            if item is not None:
> -                return item
> -
> -    def remove(self, item):
> -        if self._pending_removals:
> -            self._commit_removals()
> -        self.data.remove(ref(item))
> -
> -    def discard(self, item):
> -        if self._pending_removals:
> -            self._commit_removals()
> -        self.data.discard(ref(item))
> -
> -    def update(self, other):
> -        if self._pending_removals:
> -            self._commit_removals()
> -        if isinstance(other, self.__class__):
> -            self.data.update(other.data)
> -        else:
> -            for element in other:
> -                self.add(element)
> -
> -    def __ior__(self, other):
> -        self.update(other)
> -        return self
> -
> -    # Helper functions for simple delegating methods.
> -    def _apply(self, other, method):
> -        if not isinstance(other, self.__class__):
> -            other = self.__class__(other)
> -        newdata = method(other.data)
> -        newset = self.__class__()
> -        newset.data = newdata
> -        return newset
> -
> -    def difference(self, other):
> -        return self._apply(other, self.data.difference)
> -    __sub__ = difference
> -
> -    def difference_update(self, other):
> -        if self._pending_removals:
> -            self._commit_removals()
> -        if self is other:
> -            self.data.clear()
> -        else:
> -            self.data.difference_update(ref(item) for item in other)
> -    def __isub__(self, other):
> -        if self._pending_removals:
> -            self._commit_removals()
> -        if self is other:
> -            self.data.clear()
> -        else:
> -            self.data.difference_update(ref(item) for item in other)
> -        return self
> -
> -    def intersection(self, other):
> -        return self._apply(other, self.data.intersection)
> -    __and__ = intersection
> -
> -    def intersection_update(self, other):
> -        if self._pending_removals:
> -            self._commit_removals()
> -        self.data.intersection_update(ref(item) for item in other)
> -    def __iand__(self, other):
> -        if self._pending_removals:
> -            self._commit_removals()
> -        self.data.intersection_update(ref(item) for item in other)
> -        return self
> -
> -    def issubset(self, other):
> -        return self.data.issubset(ref(item) for item in other)
> -    __lt__ = issubset
> -
> -    def __le__(self, other):
> -        return self.data <= set(ref(item) for item in other)
> -
> -    def issuperset(self, other):
> -        return self.data.issuperset(ref(item) for item in other)
> -    __gt__ = issuperset
> -
> -    def __ge__(self, other):
> -        return self.data >= set(ref(item) for item in other)
> -
> -    def __eq__(self, other):
> -        if not isinstance(other, self.__class__):
> -            return NotImplemented
> -        return self.data == set(ref(item) for item in other)
> -
> -    def symmetric_difference(self, other):
> -        return self._apply(other, self.data.symmetric_difference)
> -    __xor__ = symmetric_difference
> -
> -    def symmetric_difference_update(self, other):
> -        if self._pending_removals:
> -            self._commit_removals()
> -        if self is other:
> -            self.data.clear()
> -        else:
> -            self.data.symmetric_difference_update(ref(item) for item in other)
> -    def __ixor__(self, other):
> -        if self._pending_removals:
> -            self._commit_removals()
> -        if self is other:
> -            self.data.clear()
> -        else:
> -            self.data.symmetric_difference_update(ref(item) for item in other)
> -        return self
> -
> -    def union(self, other):
> -        return self._apply(other, self.data.union)
> -    __or__ = union
> -
> -    def isdisjoint(self, other):
> -        return len(self.intersection(other)) == 0
> +        return set_builder(_build, cls)(data)
> diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py
> --- a/Lib/test/test_set.py
> +++ b/Lib/test/test_set.py
> @@ -310,7 +310,7 @@
>              fo.close()
>              test_support.unlink(test_support.TESTFN)
>  
> -    @unittest.skipIf(test_support.is_jython, "FIXME: Not yet sure how to fix this")
> +    @unittest.skipIf(test_support.is_jython, "Not meaningful for Jython")
>      def test_do_not_rehash_dict_keys(self):
>          n = 10
>          d = dict.fromkeys(map(HashCountingInt, xrange(n)))
> @@ -917,6 +917,7 @@
>          set('abc')
>          set(gooditer())
>  
> +    @unittest.skipIf(test_support.is_jython, "Jython provides stronger support for concurrent updates")
>      def test_changingSizeWhileIterating(self):
>          s = set([1,2,3])
>          try:
> diff --git a/Lib/test/test_weakset.py b/Lib/test/test_weakset.py
> --- a/Lib/test/test_weakset.py
> +++ b/Lib/test/test_weakset.py
> @@ -1,5 +1,18 @@
> +# Jython specific notes:
> +#
> +# 1. Deletion (del) or reliance on going out of scope must be followed
> +#    by a gc.collect(); use extra_collect() if a callback will be
> +#    tested as well.
> +#
> +# 2. Avoid eventual consistency issues in the length computation by
> +#    computing the len of the list of the WeakSet
> +#
> +# 3. Jython can weakly refer to any object, unlike CPython, so don't
> +#    test for nonexistent TypeErrors
> +
>  import unittest
>  from test import test_support
> +from test.test_weakref import extra_collect
>  from weakref import proxy, ref, WeakSet
>  import operator
>  import copy
> @@ -30,6 +43,9 @@
>      def __hash__(self):
>          return hash((SomeClass, self.value))
>  
> +    def __repr__(self):
> +        return "SC(%s,%s)" % (self.value, id(self.value))
> +
>  class RefCycle(object):
>      def __init__(self):
>          self.cycle = self
> @@ -63,14 +79,13 @@
>      def test_new_or_init(self):
>          self.assertRaises(TypeError, WeakSet, [], 2)
>  
> -    #@unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
>      def test_len(self):
>          self.assertEqual(len(self.s), len(self.d))
>          self.assertEqual(len(self.fs), 1)
>          del self.obj
> +        gc.collect()
>          self.assertEqual(len(self.fs), 0)
>  
> -    #@unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
>      def test_contains(self):
>          for c in self.letters:
>              self.assertEqual(c in self.s, c in self.d)
> @@ -78,6 +93,7 @@
>          self.assertNotIn(1, self.s)
>          self.assertIn(self.obj, self.fs)
>          del self.obj
> +        gc.collect()
>          self.assertNotIn(SomeClass('F'), self.fs)
>  
>      def test_union(self):
> @@ -92,10 +108,11 @@
>              c = C(self.items2)
>              self.assertEqual(self.s.union(c), x)
>              del c
> -        self.assertEqual(len(u), len(self.items) + len(self.items2))
> +            gc.collect()
> +        self.assertEqual(len(list(u)), len(list(self.items)) + len(list(self.items2)))
>          self.items2.pop()
>          gc.collect()
> -        self.assertEqual(len(u), len(self.items) + len(self.items2))
> +        self.assertEqual(len(list(u)), len(list(self.items)) + len(list(self.items2)))
>  
>      def test_or(self):
>          i = self.s.union(self.items2)
> @@ -115,7 +132,7 @@
>          self.assertEqual(len(i), len(self.items2))
>          self.items2.pop()
>          gc.collect()
> -        self.assertEqual(len(i), len(self.items2))
> +        self.assertEqual(len(list(i)), len(list(self.items2)))
>  
>      def test_isdisjoint(self):
>          self.assertTrue(self.s.isdisjoint(WeakSet(self.items2)))
> @@ -149,7 +166,7 @@
>          self.assertEqual(len(i), len(self.items) + len(self.items2))
>          self.items2.pop()
>          gc.collect()
> -        self.assertEqual(len(i), len(self.items) + len(self.items2))
> +        self.assertEqual(len(list(i)), len(list(self.items)) + len(list(self.items2)))
>  
>      def test_xor(self):
>          i = self.s.symmetric_difference(self.items2)
> @@ -167,14 +184,12 @@
>          self.assertFalse(set('a').issubset('cbs'))
>          self.assertFalse(set('cbs').issuperset('a'))
>  
> -    #@unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
>      def test_lt(self):
>          self.assertTrue(self.ab_weakset < self.abcde_weakset)
>          self.assertFalse(self.abcde_weakset < self.def_weakset)
>          self.assertFalse(self.ab_weakset < self.ab_weakset)
>          self.assertFalse(WeakSet() < WeakSet())
>  
> -    #@unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
>      def test_gt(self):
>          self.assertTrue(self.abcde_weakset > self.ab_weakset)
>          self.assertFalse(self.abcde_weakset > self.def_weakset)
> @@ -229,7 +244,6 @@
>          self.assertEqual(self.s, dup)
>          self.assertNotEqual(id(self.s), id(dup))
>  
> -    #@unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
>      def test_add(self):
>          x = SomeClass('Q')
>          self.s.add(x)
> @@ -237,25 +251,29 @@
>          dup = self.s.copy()
>          self.s.add(x)
>          self.assertEqual(self.s, dup)
> -        self.assertRaises(TypeError, self.s.add, [])
> +        if not test_support.is_jython:  # Jython/JVM can weakly reference list and other objects
> +            self.assertRaises(TypeError, self.s.add, [])
>          self.fs.add(Foo())
> -        self.assertTrue(len(self.fs) == 1)
> +        gc.collect()  # CPython assumes Foo() went out of scope and was collected, so ensure the same
> +        self.assertEqual(len(list(self.fs)), 1)
>          self.fs.add(self.obj)
> -        self.assertTrue(len(self.fs) == 1)
> +        self.assertEqual(len(list(self.fs)), 1)
>  
>      def test_remove(self):
>          x = SomeClass('a')
>          self.s.remove(x)
>          self.assertNotIn(x, self.s)
>          self.assertRaises(KeyError, self.s.remove, x)
> -        self.assertRaises(TypeError, self.s.remove, [])
> +        if not test_support.is_jython:  # Jython/JVM can weakly reference list and other objects
> +            self.assertRaises(TypeError, self.s.remove, [])
>  
>      def test_discard(self):
>          a, q = SomeClass('a'), SomeClass('Q')
>          self.s.discard(a)
>          self.assertNotIn(a, self.s)
>          self.s.discard(q)
> -        self.assertRaises(TypeError, self.s.discard, [])
> +        if not test_support.is_jython:  # Jython/JVM can weakly reference list and other objects
> +            self.assertRaises(TypeError, self.s.discard, [])
>  
>      def test_pop(self):
>          for i in range(len(self.s)):
> @@ -306,8 +324,9 @@
>                  self.assertIn(c, self.s)
>              else:
>                  self.assertNotIn(c, self.s)
> -        self.assertRaises(TypeError, self.s.difference_update, [[]])
> -        self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]])
> +        if not test_support.is_jython:  # Jython/JVM can weakly reference list and other objects
> +            self.assertRaises(TypeError, self.s.difference_update, [[]])
> +            self.assertRaises(TypeError, self.s.symmetric_difference_update, [[]])
>  
>      def test_isub(self):
>          self.s -= set(self.items2)
> @@ -348,15 +367,17 @@
>          self.assertEqual(t, WeakSet())
>  
>      def test_eq(self):
> -        # issue 5964
> -        self.assertTrue(self.s == self.s)
> -        self.assertTrue(self.s == WeakSet(self.items))
> -        self.assertFalse(self.s == set(self.items))
> -        self.assertFalse(self.s == list(self.items))
> -        self.assertFalse(self.s == tuple(self.items))
> -        self.assertFalse(self.s == 1)
> +        # issue 5964 (http://bugs.python.org/issue5964)
> +        self.assertEqual(self.s, self.s)
> +        self.assertEqual(self.s, WeakSet(self.items))
> +        # Jython diverges here in the next test because it constructs
> +        # WeakSet as a subclass of set; this seems to be the proper
> +        # thing to do given what is the typical comparison
> +        self.assertEqual(self.s, set(self.items))
> +        self.assertNotEqual(self.s, list(self.items))
> +        self.assertNotEqual(self.s, tuple(self.items))
> +        self.assertNotEqual(self.s, 1)
>  
> -    #@unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
>      def test_weak_destroy_while_iterating(self):
>          # Issue #7105: iterators shouldn't crash when a key is implicitly removed
>          # Create new items to be sure no-one else holds a reference
> @@ -370,6 +391,7 @@
>          # We have removed either the first consumed items, or another one
>          self.assertIn(len(list(it)), [len(items), len(items) - 1])
>          del it
> +        gc.collect()
>          # The removal has been committed
>          self.assertEqual(len(s), len(items))
>  
> @@ -410,6 +432,7 @@
>          items = [RefCycle() for i in range(N)]
>          s = WeakSet(items)
>          del items
> +        gc.collect()
>          it = iter(s)
>          try:
>              next(it)
> diff --git a/src/org/python/core/BaseSet.java b/src/org/python/core/BaseSet.java
> --- a/src/org/python/core/BaseSet.java
> +++ b/src/org/python/core/BaseSet.java
> @@ -231,9 +231,6 @@
>  
>              @Override
>              public PyObject __iternext__() {
> -                if (size != size()) {
> -                    throw Py.RuntimeError("set changed size during iteration");
> -                }
>                  if (iterator.hasNext()) {
>                      return iterator.next();
>                  }
> @@ -481,7 +478,7 @@
>      }
>  
>      /**
> -     * Create a new <et of type from iterable.
> +     * Create a new set of type from iterable.
>       *
>       * @param type a set type
>       * @param iterable an iterable or null
> @@ -494,8 +491,7 @@
>          } else if (type == PyFrozenSet.TYPE) {
>              so = new PyFrozenSet(iterable);
>          } else if (Py.isSubClass(type, PySet.TYPE)) {
> -            so = new PySetDerived(type);
> -            so._update(iterable);
> +            so = (BaseSet)(type.__call__(iterable == null ? Py.EmptyTuple : iterable));
>          } else {
>              so = new PyFrozenSetDerived(type, iterable);
>          }
> diff --git a/src/org/python/core/PyDictionaryDerived.java b/src/org/python/core/PyDictionaryDerived.java
> --- a/src/org/python/core/PyDictionaryDerived.java
> +++ b/src/org/python/core/PyDictionaryDerived.java
> @@ -67,15 +67,6 @@
>          }
>      }
>  
> -    public PyDictionaryDerived(PyType subtype, ConcurrentMap<PyObject, PyObject> backingMap, boolean useBackingMap) {
> -        super(subtype, backingMap, useBackingMap);
> -        slots=new PyObject[subtype.getNumSlots()];
> -        dict=subtype.instDict();
> -        if (subtype.needsFinalizer()) {
> -            finalizeTrigger=FinalizeTrigger.makeTrigger(this);
> -        }
> -    }
> -
>      public PyString __str__() {
>          PyType self_type=getType();
>          PyObject impl=self_type.lookup("__str__");
> @@ -1149,6 +1140,15 @@
>          return super.__coerce_ex__(o);
>      }
>  
> +    public PyDictionaryDerived(PyType subtype,ConcurrentMap backingMap,boolean useBackingMap) {
> +        super(subtype,backingMap,useBackingMap);
> +        slots=new PyObject[subtype.getNumSlots()];
> +        dict=subtype.instDict();
> +        if (subtype.needsFinalizer()) {
> +            finalizeTrigger=FinalizeTrigger.makeTrigger(this);
> +        }
> +    }
> +
>      public String toString() {
>          PyType self_type=getType();
>          PyObject impl=self_type.lookup("__repr__");
> 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
> @@ -2,6 +2,7 @@
>  
>  import java.util.Iterator;
>  import java.util.NoSuchElementException;
> +import java.util.Set;
>  
>  import org.python.expose.ExposedMethod;
>  import org.python.expose.ExposedNew;
> @@ -34,6 +35,14 @@
>          super(TYPE, _update(Generic.<PyObject>concurrentSet(), data));
>      }
>  
> +    public PySet(Set backing_set, PyObject data) {
> +        super(TYPE, _update(backing_set, data));
> +    }
> +
> +    public PySet(PyType type, Set backing_set, PyObject data) {
> +        super(type, _update(backing_set, data));
> +    }
> +
>      @ExposedNew
>      @ExposedMethod(doc = BuiltinDocs.set___init___doc)
>      final void set___init__(PyObject[] args, String[] kwds) {
> diff --git a/src/org/python/core/PySetDerived.java b/src/org/python/core/PySetDerived.java
> --- a/src/org/python/core/PySetDerived.java
> +++ b/src/org/python/core/PySetDerived.java
> @@ -1,6 +1,7 @@
>  /* Generated file, do not modify.  See jython/src/templates/gderived.py. */
>  package org.python.core;
>  
> +import java.util.Set;
>  import java.io.Serializable;
>  import org.python.core.finalization.FinalizeTrigger;
>  import org.python.core.finalization.FinalizablePyObjectDerived;
> @@ -1139,6 +1140,15 @@
>          return super.__coerce_ex__(o);
>      }
>  
> +    public PySetDerived(PyType subtype,Set backing_set,PyObject data) {
> +        super(subtype,backing_set,data);
> +        slots=new PyObject[subtype.getNumSlots()];
> +        dict=subtype.instDict();
> +        if (subtype.needsFinalizer()) {
> +            finalizeTrigger=FinalizeTrigger.makeTrigger(this);
> +        }
> +    }
> +
>      public String toString() {
>          PyType self_type=getType();
>          PyObject impl=self_type.lookup("__repr__");
> diff --git a/src/org/python/modules/_jythonlib/_jythonlib.java b/src/org/python/modules/_jythonlib/_jythonlib.java
> --- a/src/org/python/modules/_jythonlib/_jythonlib.java
> +++ b/src/org/python/modules/_jythonlib/_jythonlib.java
> @@ -15,6 +15,8 @@
>          dict.__setitem__("__doc__", __doc__);
>          dict.__setitem__("__module__", new PyString("_jythonlib"));
>          dict.__setitem__("dict_builder", dict_builder.TYPE);
> +        dict.__setitem__("set_builder", set_builder.TYPE);
> +
>  
>          // Hide from Python
>          dict.__setitem__("classDictInit", null);
> diff --git a/src/org/python/modules/_jythonlib/set_builder.java b/src/org/python/modules/_jythonlib/set_builder.java
> new file mode 100644
> --- /dev/null
> +++ b/src/org/python/modules/_jythonlib/set_builder.java
> @@ -0,0 +1,48 @@
> +/* Copyright (c) Jython Developers */
> +package org.python.modules._jythonlib;
> +
> +import org.python.core.Py;
> +import org.python.core.PyObject;
> +import org.python.core.PySet;
> +import org.python.core.PySetDerived;
> +import org.python.core.PyType;
> +
> +import java.util.Set;
> +
> +
> +/* Support building PySet objects with arbitrary backing Set objects
> + * Uses a factory for efficiency.
> + *
> + * See the very similar dict_builder for more insight. But note that we do not
> + * impose the restriction that the set be concurrent, although this is generally
> + * what we would want.
> + */
> +
> +public class set_builder extends PyObject {
> +
> +    public static final PyType TYPE = PyType.fromClass(set_builder.class);
> +    private final PyObject factory;
> +    private final PyType set_type;
> +
> +    public set_builder(PyObject factory) {
> +        super();
> +        this.factory = factory;
> +        this.set_type = null;
> +    }
> +
> +    public set_builder(PyObject factory, PyType set_type) {
> +        super();
> +        this.factory = factory;
> +        this.set_type = set_type;
> +    }
> +
> +    public PyObject __call__(PyObject iterable) {
> +        Set backing_set = (Set) (factory.__call__().__tojava__(Set.class));
> +        if (set_type == null) {
> +            return new PySet(backing_set, iterable == Py.None ? null : iterable);
> +        } else {
> +            return new PySetDerived(set_type, backing_set, iterable == Py.None ? null : iterable);
> +        }
> +    }
> +
> +}
> diff --git a/src/templates/dict.derived b/src/templates/dict.derived
> --- a/src/templates/dict.derived
> +++ b/src/templates/dict.derived
> @@ -2,3 +2,13 @@
>  want_dict: true
>  ctr:
>  incl: object
> +import: java.util.concurrent.ConcurrentMap
> +rest:
> +    public PyDictionaryDerived(PyType subtype, ConcurrentMap backingMap, boolean useBackingMap) {
> +        super(subtype, backingMap, useBackingMap);
> +        slots=new PyObject[subtype.getNumSlots()];
> +        dict=subtype.instDict();
> +        if (subtype.needsFinalizer()) {
> +            finalizeTrigger=FinalizeTrigger.makeTrigger(this);
> +        }
> +    }
> diff --git a/src/templates/gderived.py b/src/templates/gderived.py
> --- a/src/templates/gderived.py
> +++ b/src/templates/gderived.py
> @@ -25,6 +25,8 @@
>  
>  modif_re = re.compile(r"(?:\((\w+)\))?(\w+)")
>  
> +added_imports = []
> +
>  # os.path.samefile unavailable on Windows before Python v3.2
>  if hasattr(os.path, "samefile"):
>      # Good: available on this platform
> @@ -43,6 +45,7 @@
>                        'unary1',
>                        'binary', 'ibinary',
>                        'rest',
> +                      'import',
>                        'no_toString'
>                        ]
>  
> @@ -82,6 +85,10 @@
>              self.auxiliary = aux_gen.global_bindings
>          return self.auxiliary[name]
>  
> +    def dire_import(self, name, parm, body):
> +        global added_imports
> +        added_imports = [x.strip() for x in parm.split(",")]
> +
>      def dire_require(self, name, parm, body):
>          if body is not None:
>              self.invalid('require', 'non-empty body')
> @@ -217,6 +224,7 @@
>      directives.execute(directives.load(fn), gen)
>      result = gen.generate()
>      result = hack_derived_header(outfile, result)
> +    result = add_imports(outfile, result)
>      print >> open(outfile, 'w'), result
>      #gen.debug()
>  
> @@ -245,6 +253,23 @@
>      
>      return '\n'.join(result)
>  
> +def add_imports(fn, result):
> +    if not added_imports:
> +        return result
> +    print 'Adding imports for: %s' % fn
> +    result = result.splitlines()
> +
> +    def f():
> +        added = False
> +        for line in result:
> +            if not added and line.startswith("import "):
> +                added = True
> +                for addition in added_imports:
> +                    yield "import %s;" % (addition,)
> +            yield line
> +    
> +    return '\n'.join(f())
> +        
>  
>  if __name__ == '__main__':
>      from gexpose import load_mappings, usage
> diff --git a/src/templates/set.derived b/src/templates/set.derived
> --- a/src/templates/set.derived
> +++ b/src/templates/set.derived
> @@ -2,3 +2,14 @@
>  want_dict: true
>  ctr:
>  incl: object
> +import: java.util.Set
> +rest:
> +    public PySetDerived(PyType subtype, Set backing_set, PyObject data) {
> +        super(subtype, backing_set, data);
> +        slots=new PyObject[subtype.getNumSlots()];
> +        dict=subtype.instDict();
> +        if (subtype.needsFinalizer()) {
> +            finalizeTrigger=FinalizeTrigger.makeTrigger(this);
> +        }
> +    }
> +
> 
> -- 
> Repository URL: https://hg.python.org/jython
> _______________________________________________
> Jython-checkins mailing list
> Jython-checkins at python.org
> https://mail.python.org/mailman/listinfo/jython-checkins
> 


More information about the Jython-checkins mailing list