[Jython-checkins] jython: Now uses java.util.WeakHashMap to back weakref.WeakSet
jim.baker
jython-checkins at python.org
Fri Nov 21 03:18:25 CET 2014
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
More information about the Jython-checkins
mailing list