[Jython-checkins] jython: Fix concurrency issues with weakref dicts and update tests.

jim.baker jython-checkins at python.org
Wed Nov 19 06:36:36 CET 2014


https://hg.python.org/jython/rev/8fed9df0ccd8
changeset:   7414:8fed9df0ccd8
user:        Jim Baker <jim.baker at rackspace.com>
date:        Tue Nov 18 22:36:17 2014 -0700
summary:
  Fix concurrency issues with weakref dicts and update tests.

WeakKeyDictionary and WeakValueDictionary now build their dictionaries
by using Google Guava, as supported by jythonlib.dict_builder, which
now also supports providing such backing for dictionaries derived from
dict.

Update weakref tests to 2.7, with appropriate skips for Jython. Added
gc.collect() (with sleeps) as necessary so that weak reference
lifecycle can be observed in tests, including callbacks (sleeps allow
us to observe the reaper thread in action).

files:
  Lib/test/test_weakref.py                               |  490 ++++++---
  Lib/test/test_weakset.py                               |   12 +-
  Lib/weakref.py                                         |  358 +------
  src/org/python/core/PyDictionary.java                  |    5 +
  src/org/python/core/PyDictionaryDerived.java           |   10 +
  src/org/python/modules/_jythonlib/dict_builder.java    |   16 +-
  src/org/python/modules/_weakref/AbstractReference.java |   18 +
  src/org/python/modules/_weakref/ProxyType.java         |    6 +-
  src/org/python/modules/_weakref/ReferenceType.java     |    7 +
  9 files changed, 444 insertions(+), 478 deletions(-)


diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -11,7 +11,7 @@
     import time
 
     def extra_collect():
-        """Kick Java's GC into gear"""
+        """Kick Java's GC into gear; also callbacks need to be called by our reaper thread"""
         gc.collect()
         time.sleep(0.2)
         gc.collect()
@@ -19,7 +19,8 @@
         gc.collect()
 else:
     def extra_collect():
-        pass
+        gc.collect()
+
 
 # Used in ReferencesTestCase.test_ref_created_during_del() .
 ref_from_del = None
@@ -47,6 +48,27 @@
     return C.method
 
 
+class Object:
+    def __init__(self, arg):
+        self.arg = arg
+    def __repr__(self):
+        return "<Object %r>" % self.arg
+    def __eq__(self, other):
+        if isinstance(other, Object):
+            return self.arg == other.arg
+        return NotImplemented
+    def __ne__(self, other):
+        if isinstance(other, Object):
+            return self.arg != other.arg
+        return NotImplemented
+    def __hash__(self):
+        return hash(self.arg)
+
+class RefCycle:
+    def __init__(self):
+        self.cycle = self
+
+
 class TestBase(unittest.TestCase):
 
     def setUp(self):
@@ -71,6 +93,7 @@
         repr(wr)
         # Dead reference:
         del o
+        gc.collect()
         repr(wr)
 
     def test_basic_callback(self):
@@ -85,11 +108,11 @@
         ref2 = weakref.ref(o, self.callback)
         del o
         extra_collect()
-        self.assert_(ref1() is None,
+        self.assertTrue(ref1() is None,
                      "expected reference to be invalidated")
-        self.assert_(ref2() is None,
+        self.assertTrue(ref2() is None,
                      "expected reference to be invalidated")
-        self.assert_(self.cbcalled == 2,
+        self.assertTrue(self.cbcalled == 2,
                      "callback not called the right number of times")
 
     def test_multiple_selfref_callbacks(self):
@@ -109,6 +132,7 @@
         self.ref = weakref.ref(c, callback)
         ref1 = weakref.ref(c, callback)
         del c
+        gc.collect()
 
     def test_proxy_ref(self):
         o = C()
@@ -116,28 +140,31 @@
         ref1 = weakref.proxy(o, self.callback)
         ref2 = weakref.proxy(o, self.callback)
         del o
+        gc.collect()
 
         def check(proxy):
             proxy.bar
 
-        extra_collect()
         self.assertRaises(weakref.ReferenceError, check, ref1)
         self.assertRaises(weakref.ReferenceError, check, ref2)
-        # XXX: CPython GC collects C() immediately. use ref1 instead on
-        # Jython
-        if test_support.is_jython:
-            self.assertRaises(weakref.ReferenceError, bool, ref1)
-        else:
-            self.assertRaises(weakref.ReferenceError, bool, weakref.proxy(C()))
-        self.assert_(self.cbcalled == 2)
+
+        # Need to add extra step for Jython - in the orginal test, ref counting had already removed C()
+        # self.assertRaises(weakref.ReferenceError, bool, weakref.proxy(C()))
+        o2 = C()
+        ref3 = weakref.proxy(o2)
+        del o2
+        gc.collect()
+        self.assertRaises(weakref.ReferenceError, bool, ref3)
+
+        self.assertTrue(self.cbcalled == 2)
 
     def check_basic_ref(self, factory):
         o = factory()
         ref = weakref.ref(o)
-        self.assert_(ref() is not None,
+        self.assertTrue(ref() is not None,
                      "weak reference to live object should be live")
         o2 = ref()
-        self.assert_(o is o2,
+        self.assertTrue(o is o2,
                      "<ref>() should return original object if live")
 
     def check_basic_callback(self, factory):
@@ -145,10 +172,10 @@
         o = factory()
         ref = weakref.ref(o, self.callback)
         del o
-        extra_collect()
-        self.assert_(self.cbcalled == 1,
+        extra_collect()  # Jython - allow for the reaper to take care of the callback
+        self.assertTrue(self.cbcalled == 1,
                      "callback did not properly set 'cbcalled'")
-        self.assert_(ref() is None,
+        self.assertTrue(ref() is None,
                      "ref2 should be dead after deleting object reference")
 
     def test_ref_reuse(self):
@@ -158,20 +185,20 @@
         # between these two; it should make no difference
         proxy = weakref.proxy(o)
         ref2 = weakref.ref(o)
-        self.assert_(ref1 is ref2,
+        self.assertTrue(ref1 is ref2,
                      "reference object w/out callback should be re-used")
 
         o = C()
         proxy = weakref.proxy(o)
         ref1 = weakref.ref(o)
         ref2 = weakref.ref(o)
-        self.assert_(ref1 is ref2,
+        self.assertTrue(ref1 is ref2,
                      "reference object w/out callback should be re-used")
-        self.assert_(weakref.getweakrefcount(o) == 2,
+        self.assertTrue(weakref.getweakrefcount(o) == 2,
                      "wrong weak ref count for object")
         del proxy
-        extra_collect()
-        self.assert_(weakref.getweakrefcount(o) == 1,
+        gc.collect()
+        self.assertTrue(weakref.getweakrefcount(o) == 1,
                      "wrong weak ref count for object after deleting proxy")
 
     def test_proxy_reuse(self):
@@ -179,7 +206,7 @@
         proxy1 = weakref.proxy(o)
         ref = weakref.ref(o)
         proxy2 = weakref.proxy(o)
-        self.assert_(proxy1 is proxy2,
+        self.assertTrue(proxy1 is proxy2,
                      "proxy object w/out callback should have been re-used")
 
     def test_basic_proxy(self):
@@ -188,16 +215,15 @@
 
         L = UserList.UserList()
         p = weakref.proxy(L)
-        self.failIf(p, "proxy for empty UserList should be false")
+        self.assertFalse(p, "proxy for empty UserList should be false")
         p.append(12)
         self.assertEqual(len(L), 1)
-        self.failUnless(p, "proxy for non-empty UserList should be true")
+        self.assertTrue(p, "proxy for non-empty UserList should be true")
         with test_support.check_py3k_warnings():
             p[:] = [2, 3]
         self.assertEqual(len(L), 2)
         self.assertEqual(len(p), 2)
-        self.failUnless(3 in p,
-                        "proxy didn't support __contains__() properly")
+        self.assertIn(3, p, "proxy didn't support __contains__() properly")
         p[1] = 5
         self.assertEqual(L[1], 5)
         self.assertEqual(p[1], 5)
@@ -213,7 +239,6 @@
             self.assertEqual(L3[:5], p3[:5])
             self.assertEqual(L3[2:5], p3[2:5])
 
-    @unittest.skip("FIXME: broken")
     def test_proxy_unicode(self):
         # See bug 5037
         class C(object):
@@ -222,10 +247,9 @@
             def __unicode__(self):
                 return u"unicode"
         instance = C()
-        self.assertTrue("__unicode__" in dir(weakref.proxy(instance)))
+        self.assertIn("__unicode__", dir(weakref.proxy(instance)))
         self.assertEqual(unicode(weakref.proxy(instance)), u"unicode")
 
-    @unittest.skip("FIXME: broken")
     def test_proxy_index(self):
         class C:
             def __index__(self):
@@ -234,7 +258,6 @@
         p = weakref.proxy(o)
         self.assertEqual(operator.index(p), 10)
 
-    @unittest.skip("FIXME: broken")
     def test_proxy_div(self):
         class C:
             def __floordiv__(self, other):
@@ -265,19 +288,19 @@
         o = Object(1)
         p1 = makeref(o, None)
         p2 = makeref(o, None)
-        self.assert_(p1 is p2, "both callbacks were None in the C API")
+        self.assertTrue(p1 is p2, "both callbacks were None in the C API")
         del p1, p2
         p1 = makeref(o)
         p2 = makeref(o, None)
-        self.assert_(p1 is p2, "callbacks were NULL, None in the C API")
+        self.assertTrue(p1 is p2, "callbacks were NULL, None in the C API")
         del p1, p2
         p1 = makeref(o)
         p2 = makeref(o)
-        self.assert_(p1 is p2, "both callbacks were NULL in the C API")
+        self.assertTrue(p1 is p2, "both callbacks were NULL in the C API")
         del p1, p2
         p1 = makeref(o, None)
         p2 = makeref(o)
-        self.assert_(p1 is p2, "callbacks were None, NULL in the C API")
+        self.assertTrue(p1 is p2, "callbacks were None, NULL in the C API")
 
     def test_callable_proxy(self):
         o = Callable()
@@ -285,13 +308,13 @@
 
         self.check_proxy(o, ref1)
 
-        self.assert_(type(ref1) is weakref.CallableProxyType,
+        self.assertTrue(type(ref1) is weakref.CallableProxyType,
                      "proxy is not of callable type")
         ref1('twinkies!')
-        self.assert_(o.bar == 'twinkies!',
+        self.assertTrue(o.bar == 'twinkies!',
                      "call through proxy not passed through to original")
         ref1(x='Splat.')
-        self.assert_(o.bar == 'Splat.',
+        self.assertTrue(o.bar == 'Splat.',
                      "call through proxy not passed through to original")
 
         # expect due to too few args
@@ -302,24 +325,24 @@
 
     def check_proxy(self, o, proxy):
         o.foo = 1
-        self.assert_(proxy.foo == 1,
+        self.assertTrue(proxy.foo == 1,
                      "proxy does not reflect attribute addition")
         o.foo = 2
-        self.assert_(proxy.foo == 2,
+        self.assertTrue(proxy.foo == 2,
                      "proxy does not reflect attribute modification")
         del o.foo
-        self.assert_(not hasattr(proxy, 'foo'),
+        self.assertTrue(not hasattr(proxy, 'foo'),
                      "proxy does not reflect attribute removal")
 
         proxy.foo = 1
-        self.assert_(o.foo == 1,
+        self.assertTrue(o.foo == 1,
                      "object does not reflect attribute addition via proxy")
         proxy.foo = 2
-        self.assert_(
+        self.assertTrue(
             o.foo == 2,
             "object does not reflect attribute modification via proxy")
         del proxy.foo
-        self.assert_(not hasattr(o, 'foo'),
+        self.assertTrue(not hasattr(o, 'foo'),
                      "object does not reflect attribute removal via proxy")
 
     def test_proxy_deletion(self):
@@ -343,22 +366,22 @@
         o = C()
         ref1 = weakref.ref(o)
         ref2 = weakref.ref(o, self.callback)
-        self.assert_(weakref.getweakrefcount(o) == 2,
+        self.assertTrue(weakref.getweakrefcount(o) == 2,
                      "got wrong number of weak reference objects")
 
         proxy1 = weakref.proxy(o)
         proxy2 = weakref.proxy(o, self.callback)
-        self.assert_(weakref.getweakrefcount(o) == 4,
+        self.assertTrue(weakref.getweakrefcount(o) == 4,
                      "got wrong number of weak reference objects")
 
         del ref1, ref2, proxy1, proxy2
-        extra_collect()
-        self.assert_(weakref.getweakrefcount(o) == 0,
+        gc.collect()
+        self.assertTrue(weakref.getweakrefcount(o) == 0,
                      "weak reference objects not unlinked from"
                      " referent when discarded.")
 
         # assumes ints do not support weakrefs
-        self.assert_(weakref.getweakrefcount(1) == 0,
+        self.assertTrue(weakref.getweakrefcount(1) == 0,
                      "got wrong number of weak reference objects for int")
 
     def test_getweakrefs(self):
@@ -366,25 +389,25 @@
         ref1 = weakref.ref(o, self.callback)
         ref2 = weakref.ref(o, self.callback)
         del ref1
-        extra_collect()
-        self.assert_(weakref.getweakrefs(o) == [ref2],
+        gc.collect()
+        self.assertTrue(weakref.getweakrefs(o) == [ref2],
                      "list of refs does not match")
 
         o = C()
         ref1 = weakref.ref(o, self.callback)
         ref2 = weakref.ref(o, self.callback)
         del ref2
-        extra_collect()
-        self.assert_(weakref.getweakrefs(o) == [ref1],
+        gc.collect()
+        self.assertTrue(weakref.getweakrefs(o) == [ref1],
                      "list of refs does not match")
 
         del ref1
-        extra_collect()
-        self.assert_(weakref.getweakrefs(o) == [],
+        gc.collect()
+        self.assertTrue(weakref.getweakrefs(o) == [],
                      "list of refs not cleared")
 
         # assumes ints do not support weakrefs
-        self.assert_(weakref.getweakrefs(1) == [],
+        self.assertTrue(weakref.getweakrefs(1) == [],
                      "list of refs does not match for int")
 
     def test_newstyle_number_ops(self):
@@ -392,8 +415,8 @@
             pass
         f = F(2.0)
         p = weakref.proxy(f)
-        self.assert_(p + 1.0 == 3.0)
-        self.assert_(1.0 + p == 3.0)  # this used to SEGV
+        self.assertTrue(p + 1.0 == 3.0)
+        self.assertTrue(1.0 + p == 3.0)  # this used to SEGV
 
     def test_callbacks_protected(self):
         # Callbacks protected from already-set exceptions?
@@ -581,6 +604,7 @@
         del c1, c2, C, D
         gc.collect()
 
+    @unittest.skipIf(test_support.is_jython, "Not a valid test for Jython without significant rewriting")
     def test_callback_in_cycle_resurrection(self):
         import gc
 
@@ -627,6 +651,7 @@
         gc.collect()
         self.assertEqual(alist, [])
 
+    @unittest.skipIf(test_support.is_jython, "Not a valid test for Jython")
     def test_callbacks_on_callback(self):
         import gc
 
@@ -646,7 +671,7 @@
         c.wr = weakref.ref(d, callback)     # this won't trigger
         d.wr = weakref.ref(callback, d.cb)  # ditto
         external_wr = weakref.ref(callback, safe_callback)  # but this will
-        self.assert_(external_wr() is callback)
+        self.assertTrue(external_wr() is callback)
 
         # The weakrefs attached to c and d should get cleared, so that
         # C.cb is never called.  But external_wr isn't part of the cyclic
@@ -658,7 +683,6 @@
         del callback, c, d, C
         self.assertEqual(alist, [])  # del isn't enough to clean up cycles
         gc.collect()
-        extra_collect()
         self.assertEqual(alist, ["safe_callback called"])
         self.assertEqual(external_wr(), None)
 
@@ -666,17 +690,18 @@
         gc.collect()
         self.assertEqual(alist, [])
 
+    @unittest.skipIf(test_support.is_jython, "Not a valid test for Jython")
     def test_gc_during_ref_creation(self):
         self.check_gc_during_creation(weakref.ref)
 
+    @unittest.skipIf(test_support.is_jython, "Not a valid test for Jython")
     def test_gc_during_proxy_creation(self):
         self.check_gc_during_creation(weakref.proxy)
 
+    @unittest.skipIf(test_support.is_jython, "Not a valid test for Jython")
     def check_gc_during_creation(self, makeref):
-        # XXX: threshold not applicable to Jython
-        if not test_support.is_jython:
-            thresholds = gc.get_threshold()
-            gc.set_threshold(1, 1, 1)
+        thresholds = gc.get_threshold()
+        gc.set_threshold(1, 1, 1)
         gc.collect()
         class A:
             pass
@@ -697,9 +722,7 @@
             weakref.ref(referenced, callback)
 
         finally:
-            # XXX: threshold not applicable to Jython
-            if not test_support.is_jython:
-                gc.set_threshold(*thresholds)
+            gc.set_threshold(*thresholds)
 
     def test_ref_created_during_del(self):
         # Bug #1377858
@@ -713,7 +736,6 @@
 
         w = Target()
 
-    @unittest.skip("FIXME: broken")
     def test_init(self):
         # Issue 3634
         # <weakref to class>.__init__() doesn't check errors correctly
@@ -722,10 +744,98 @@
         # No exception should be raised here
         gc.collect()
 
+    def test_classes(self):
+        # Check that both old-style classes and new-style classes
+        # are weakrefable.
+        class A(object):
+            pass
+        class B:
+            pass
+        l = []
+        weakref.ref(int)
+        a = weakref.ref(A, l.append)
+        A = None
+        gc.collect()
+        self.assertEqual(a(), None)
+        self.assertEqual(l, [a])
+        b = weakref.ref(B, l.append)
+        B = None
+        gc.collect()
+        self.assertEqual(b(), None)
+        self.assertEqual(l, [a, b])
+
+    def test_equality(self):
+        # Alive weakrefs defer equality testing to their underlying object.
+        x = Object(1)
+        y = Object(1)
+        z = Object(2)
+        a = weakref.ref(x)
+        b = weakref.ref(y)
+        c = weakref.ref(z)
+        d = weakref.ref(x)
+        # Note how we directly test the operators here, to stress both
+        # __eq__ and __ne__.
+        self.assertTrue(a == b)
+        self.assertFalse(a != b)
+        self.assertFalse(a == c)
+        self.assertTrue(a != c)
+        self.assertTrue(a == d)
+        self.assertFalse(a != d)
+        del x, y, z
+        gc.collect()
+        for r in a, b, c:
+            # Sanity check
+            self.assertIs(r(), None)
+        # Dead weakrefs compare by identity: whether `a` and `d` are the
+        # same weakref object is an implementation detail, since they pointed
+        # to the same original object and didn't have a callback.
+        # (see issue #16453).
+        self.assertFalse(a == b)
+        self.assertTrue(a != b)
+        self.assertFalse(a == c)
+        self.assertTrue(a != c)
+        self.assertEqual(a == d, a is d)
+        self.assertEqual(a != d, a is not d)
+
+    def test_hashing(self):
+        # Alive weakrefs hash the same as the underlying object
+        x = Object(42)
+        y = Object(42)
+        a = weakref.ref(x)
+        b = weakref.ref(y)
+        self.assertEqual(hash(a), hash(42))
+        del x, y
+        gc.collect()
+        # Dead weakrefs:
+        # - retain their hash is they were hashed when alive;
+        # - otherwise, cannot be hashed.
+        self.assertEqual(hash(a), hash(42))
+        self.assertRaises(TypeError, hash, b)
+
+    def test_trashcan_16602(self):
+        # Issue #16602: when a weakref's target was part of a long
+        # deallocation chain, the trashcan mechanism could delay clearing
+        # of the weakref and make the target object visible from outside
+        # code even though its refcount had dropped to 0.  A crash ensued.
+        class C(object):
+            def __init__(self, parent):
+                if not parent:
+                    return
+                wself = weakref.ref(self)
+                def cb(wparent):
+                    o = wself()
+                self.wparent = weakref.ref(parent, cb)
+
+        d = weakref.WeakKeyDictionary()
+        root = c = C(None)
+        for n in range(100):
+            d[c] = c = C(c)
+        del root
+        gc.collect()
+
 
 class SubclassableWeakrefTestCase(TestBase):
 
-    @unittest.skip("FIXME: broken")
     def test_subclass_refs(self):
         class MyRef(weakref.ref):
             def __init__(self, ob, callback=None, value=42):
@@ -736,42 +846,41 @@
                 return super(MyRef, self).__call__()
         o = Object("foo")
         mr = MyRef(o, value=24)
-        self.assert_(mr() is o)
-        self.assert_(mr.called)
+        self.assertTrue(mr() is o)
+        self.assertTrue(mr.called)
         self.assertEqual(mr.value, 24)
         del o
-        self.assert_(mr() is None)
-        self.assert_(mr.called)
+        gc.collect()
+        self.assertTrue(mr() is None)
+        self.assertTrue(mr.called)
 
-    @unittest.skip("FIXME: broken")
     def test_subclass_refs_dont_replace_standard_refs(self):
         class MyRef(weakref.ref):
             pass
         o = Object(42)
         r1 = MyRef(o)
         r2 = weakref.ref(o)
-        self.assert_(r1 is not r2)
+        self.assertTrue(r1 is not r2)
         self.assertEqual(weakref.getweakrefs(o), [r2, r1])
         self.assertEqual(weakref.getweakrefcount(o), 2)
         r3 = MyRef(o)
         self.assertEqual(weakref.getweakrefcount(o), 3)
         refs = weakref.getweakrefs(o)
         self.assertEqual(len(refs), 3)
-        self.assert_(r2 is refs[0])
-        self.assert_(r1 in refs[1:])
-        self.assert_(r3 in refs[1:])
+        self.assertIn(r1, refs)
+        self.assertIn(r2, refs)
+        self.assertIn(r3, refs)
 
-    @unittest.skip("FIXME: broken")
     def test_subclass_refs_dont_conflate_callbacks(self):
         class MyRef(weakref.ref):
             pass
         o = Object(42)
         r1 = MyRef(o, id)
         r2 = MyRef(o, str)
-        self.assert_(r1 is not r2)
-        refs = weakref.getweakrefs(o)
-        self.assert_(r1 in refs)
-        self.assert_(r2 in refs)
+        self.assertTrue(r1 is not r2)
+        refs = list(weakref.getweakrefs(o))
+        self.assertIn(r1, refs)
+        self.assertIn(r2, refs)
 
     def test_subclass_refs_with_slots(self):
         class MyRef(weakref.ref):
@@ -788,7 +897,7 @@
         self.assertEqual(r.slot1, "abc")
         self.assertEqual(r.slot2, "def")
         self.assertEqual(r.meth(), "abcdef")
-        self.failIf(hasattr(r, "__dict__"))
+        self.assertFalse(hasattr(r, "__dict__"))
 
     def test_subclass_refs_with_cycle(self):
         # Bug #3110
@@ -829,48 +938,101 @@
         self.assertEqual(self.cbcalled, 0)
 
 
-class Object:
-    def __init__(self, arg):
-        self.arg = arg
-    def __repr__(self):
-        return "<Object %r>" % self.arg
-
-
 class MappingTestCase(TestBase):
 
     COUNT = 10
 
+    def check_len_cycles(self, dict_type, cons):
+        N = 20
+        items = [RefCycle() for i in range(N)]
+        dct = dict_type(cons(o) for o in items)
+        # Keep an iterator alive
+        it = dct.iteritems()
+        try:
+            next(it)
+        except StopIteration:
+            pass
+        del items
+        gc.collect()
+        n1 = len(list(dct))
+        del it
+        gc.collect()
+        n2 = len(list(dct))
+        # one or two items may be kept alive inside the iterator
+        self.assertIn(n1, (0, 1, 2))
+        self.assertEqual(n2, 0)
+
+    def test_weak_keyed_len_cycles(self):
+        self.check_len_cycles(weakref.WeakKeyDictionary, lambda k: (k, 1))
+
+    def test_weak_valued_len_cycles(self):
+        self.check_len_cycles(weakref.WeakValueDictionary, lambda k: (1, k))
+
+    def check_len_race(self, dict_type, cons):
+        # Extended sanity checks for len() in the face of cyclic collection
+        self.addCleanup(gc.set_threshold, *gc.get_threshold())
+        for th in range(1, 100):
+            N = 20
+            gc.collect(0)
+            gc.set_threshold(th, th, th)
+            items = [RefCycle() for i in range(N)]
+            dct = dict_type(cons(o) for o in items)
+            del items
+            # All items will be collected at next garbage collection pass
+            it = dct.iteritems()
+            try:
+                next(it)
+            except StopIteration:
+                pass
+            n1 = len(dct)
+            del it
+            n2 = len(dct)
+            self.assertGreaterEqual(n1, 0)
+            self.assertLessEqual(n1, N)
+            self.assertGreaterEqual(n2, 0)
+            self.assertLessEqual(n2, n1)
+
+    @unittest.skipIf(test_support.is_jython, "Not a valid test for Jython")
+    def test_weak_keyed_len_race(self):
+        self.check_len_race(weakref.WeakKeyDictionary, lambda k: (k, 1))
+
+    @unittest.skipIf(test_support.is_jython, "Not a valid test for Jython")
+    def test_weak_valued_len_race(self):
+        self.check_len_race(weakref.WeakValueDictionary, lambda k: (1, k))
+
     def test_weak_values(self):
         #
         #  This exercises d.copy(), d.items(), d[], del d[], len(d).
         #
         dict, objects = self.make_weak_valued_dict()
         for o in objects:
-            self.assert_(weakref.getweakrefcount(o) == 1,
-                         "wrong number of weak references to %r!" % o)
-            self.assert_(o is dict[o.arg],
+            if not test_support.is_jython:  # Such dictionaries now use MapMaker
+                self.assertTrue(weakref.getweakrefcount(o) == 1,
+                                "wrong number of weak references to %r!" % o)
+            self.assertTrue(o is dict[o.arg],
                          "wrong object returned by weak dict!")
         items1 = dict.items()
         items2 = dict.copy().items()
         items1.sort()
         items2.sort()
-        self.assert_(items1 == items2,
+        self.assertTrue(items1 == items2,
                      "cloning of weak-valued dictionary did not work!")
         del items1, items2
-        self.assert_(len(dict) == self.COUNT)
+        self.assertTrue(len(dict) == self.COUNT)
         del objects[0]
-        extra_collect()
-        self.assert_(len(dict) == (self.COUNT - 1),
+        gc.collect()
+        # underlying Map.size is guaranteed only to be eventually consistent for MapMaker
+        self.assertEqual(len(list(dict.iterkeys())), self.COUNT - 1,
                      "deleting object did not cause dictionary update")
         del objects, o
-        extra_collect()
-        self.assert_(len(dict) == 0,
+        gc.collect()
+        self.assertEqual(len(list(dict.iterkeys())), 0,
                      "deleting the values did not clear the dictionary")
         # regression on SF bug #447152:
         dict = weakref.WeakValueDictionary()
         self.assertRaises(KeyError, dict.__getitem__, 1)
         dict[2] = C()
-        extra_collect()
+        gc.collect()
         self.assertRaises(KeyError, dict.__getitem__, 2)
 
     def test_weak_keys(self):
@@ -880,28 +1042,29 @@
         #
         dict, objects = self.make_weak_keyed_dict()
         for o in objects:
-            self.assert_(weakref.getweakrefcount(o) == 1,
-                         "wrong number of weak references to %r!" % o)
-            self.assert_(o.arg is dict[o],
+            if not test_support.is_jython:  # Such dictionaries now use MapMaker
+                self.assertTrue(weakref.getweakrefcount(o) == 1,
+                                "wrong number of weak references to %r!" % o)
+            self.assertTrue(o.arg is dict[o],
                          "wrong object returned by weak dict!")
         items1 = dict.items()
         items2 = dict.copy().items()
-        self.assert_(set(items1) == set(items2),
+        self.assertTrue(set(items1) == set(items2),
                      "cloning of weak-keyed dictionary did not work!")
         del items1, items2
-        self.assert_(len(dict) == self.COUNT)
+        self.assertEqual(len(list(dict.iterkeys())), self.COUNT)
         del objects[0]
-        extra_collect()
-        self.assert_(len(dict) == (self.COUNT - 1),
+        gc.collect()
+        self.assertEqual(len(list(dict.iterkeys())), self.COUNT - 1,
                      "deleting object did not cause dictionary update")
         del objects, o
-        extra_collect()
-        self.assert_(len(dict) == 0,
+        gc.collect()
+        self.assertEqual(len(list(dict.iterkeys())), 0,
                      "deleting the keys did not clear the dictionary")
         o = Object(42)
         dict[o] = "What is the meaning of the universe?"
-        self.assertTrue(o in dict)
-        self.assertTrue(34 not in dict)
+        self.assertIn(o, dict)
+        self.assertNotIn(34, dict)
 
     def test_weak_keyed_iters(self):
         dict, objects = self.make_weak_keyed_dict()
@@ -913,7 +1076,7 @@
         objects2 = list(objects)
         for wr in refs:
             ob = wr()
-            self.assertTrue(ob in dict)
+            self.assertIn(ob, dict)
             self.assertEqual(ob.arg, dict[ob])
             objects2.remove(ob)
         self.assertEqual(len(objects2), 0)
@@ -923,7 +1086,7 @@
         self.assertEqual(len(list(dict.iterkeyrefs())), len(objects))
         for wr in dict.iterkeyrefs():
             ob = wr()
-            self.assertTrue(ob in dict)
+            self.assertIn(ob, dict)
             self.assertEqual(ob.arg, dict[ob])
             objects2.remove(ob)
         self.assertEqual(len(objects2), 0)
@@ -958,37 +1121,37 @@
         items = dict.items()
         for item in dict.iteritems():
             items.remove(item)
-        self.assert_(len(items) == 0, "iteritems() did not touch all items")
+        self.assertTrue(len(items) == 0, "iteritems() did not touch all items")
 
         # key iterator, via __iter__():
         keys = dict.keys()
         for k in dict:
             keys.remove(k)
-        self.assert_(len(keys) == 0, "__iter__() did not touch all keys")
+        self.assertTrue(len(keys) == 0, "__iter__() did not touch all keys")
 
         # key iterator, via iterkeys():
         keys = dict.keys()
         for k in dict.iterkeys():
             keys.remove(k)
-        self.assert_(len(keys) == 0, "iterkeys() did not touch all keys")
+        self.assertTrue(len(keys) == 0, "iterkeys() did not touch all keys")
 
         # value iterator:
         values = dict.values()
         for v in dict.itervalues():
             values.remove(v)
-        self.assert_(len(values) == 0,
+        self.assertTrue(len(values) == 0,
                      "itervalues() did not touch all values")
 
     def test_make_weak_keyed_dict_from_dict(self):
         o = Object(3)
         dict = weakref.WeakKeyDictionary({o:364})
-        self.assert_(dict[o] == 364)
+        self.assertTrue(dict[o] == 364)
 
     def test_make_weak_keyed_dict_from_weak_keyed_dict(self):
         o = Object(3)
         dict = weakref.WeakKeyDictionary({o:364})
         dict2 = weakref.WeakKeyDictionary(dict)
-        self.assert_(dict[o] == 364)
+        self.assertTrue(dict[o] == 364)
 
     def make_weak_keyed_dict(self):
         dict = weakref.WeakKeyDictionary()
@@ -1008,19 +1171,19 @@
         weakdict = klass()
         weakdict[key1] = value1
         weakdict[key2] = value2
-        self.assert_(len(weakdict) == 2)
+        self.assertTrue(len(weakdict) == 2)
         k, v = weakdict.popitem()
-        self.assert_(len(weakdict) == 1)
+        self.assertTrue(len(weakdict) == 1)
         if k is key1:
-            self.assert_(v is value1)
+            self.assertTrue(v is value1)
         else:
-            self.assert_(v is value2)
+            self.assertTrue(v is value2)
         k, v = weakdict.popitem()
-        self.assert_(len(weakdict) == 0)
+        self.assertTrue(len(weakdict) == 0)
         if k is key1:
-            self.assert_(v is value1)
+            self.assertTrue(v is value1)
         else:
-            self.assert_(v is value2)
+            self.assertTrue(v is value2)
 
     def test_weak_valued_dict_popitem(self):
         self.check_popitem(weakref.WeakValueDictionary,
@@ -1031,21 +1194,21 @@
                            C(), "value 1", C(), "value 2")
 
     def check_setdefault(self, klass, key, value1, value2):
-        self.assert_(value1 is not value2,
+        self.assertTrue(value1 is not value2,
                      "invalid test"
                      " -- value parameters must be distinct objects")
         weakdict = klass()
         o = weakdict.setdefault(key, value1)
-        self.assertTrue(o is value1)
-        self.assertTrue(key in weakdict)
-        self.assertTrue(weakdict.get(key) is value1)
-        self.assertTrue(weakdict[key] is value1)
+        self.assertIs(o, value1)
+        self.assertIn(key, weakdict)
+        self.assertIs(weakdict.get(key), value1)
+        self.assertIs(weakdict[key], value1)
 
         o = weakdict.setdefault(key, value2)
-        self.assertTrue(o is value1)
-        self.assertTrue(key in weakdict)
-        self.assertTrue(weakdict.get(key) is value1)
-        self.assertTrue(weakdict[key] is value1)
+        self.assertIs(o, value1)
+        self.assertIn(key, weakdict)
+        self.assertIs(weakdict.get(key), value1)
+        self.assertIs(weakdict[key], value1)
 
     def test_weak_valued_dict_setdefault(self):
         self.check_setdefault(weakref.WeakValueDictionary,
@@ -1064,17 +1227,17 @@
         weakdict.update(dict)
         self.assertEqual(len(weakdict), len(dict))
         for k in weakdict.keys():
-            self.assertTrue(k in dict,
+            self.assertIn(k, dict,
                          "mysterious new key appeared in weak dict")
             v = dict.get(k)
-            self.assertTrue(v is weakdict[k])
-            self.assertTrue(v is weakdict.get(k))
+            self.assertIs(v, weakdict[k])
+            self.assertIs(v, weakdict.get(k))
         for k in dict.keys():
-            self.assertTrue(k in weakdict,
+            self.assertIn(k, weakdict,
                          "original key disappeared in weak dict")
             v = dict[k]
-            self.assertTrue(v is weakdict[k])
-            self.assertTrue(v is weakdict.get(k))
+            self.assertIs(v, weakdict[k])
+            self.assertIs(v, weakdict.get(k))
 
     def test_weak_valued_dict_update(self):
         self.check_update(weakref.WeakValueDictionary,
@@ -1090,10 +1253,10 @@
         o2 = Object('2')
         d[o1] = 'something'
         d[o2] = 'something'
-        self.assert_(len(d) == 2)
+        self.assertTrue(len(d) == 2)
         del d[o1]
-        self.assert_(len(d) == 1)
-        self.assert_(d.keys() == [o2])
+        self.assertTrue(len(d) == 1)
+        self.assertTrue(d.keys() == [o2])
 
     def test_weak_valued_delitem(self):
         d = weakref.WeakValueDictionary()
@@ -1101,10 +1264,10 @@
         o2 = Object('2')
         d['something'] = o1
         d['something else'] = o2
-        self.assert_(len(d) == 2)
+        self.assertTrue(len(d) == 2)
         del d['something']
-        self.assert_(len(d) == 1)
-        self.assert_(d.items() == [('something else', o2)])
+        self.assertTrue(len(d) == 1)
+        self.assertTrue(d.items() == [('something else', o2)])
 
     def test_weak_keyed_bad_delitem(self):
         d = weakref.WeakKeyDictionary()
@@ -1114,14 +1277,15 @@
         self.assertRaises(KeyError, d.__delitem__, o)
         self.assertRaises(KeyError, d.__getitem__, o)
 
-        # If a key isn't of a weakly referencable type, __getitem__ and
-        # __setitem__ raise TypeError.  __delitem__ should too.
-        self.assertRaises(TypeError, d.__delitem__,  13)
-        self.assertRaises(TypeError, d.__getitem__,  13)
-        self.assertRaises(TypeError, d.__setitem__,  13, 13)
+        # In Jython, all objects can be weakly referenced.
+        self.assertRaises(KeyError, d.__delitem__,  13)
+        self.assertRaises(KeyError, d.__getitem__,  13)
 
+    # Using MapMaker means that __eq__ is not called given that such
+    # Google Collections based weak maps use identity, not equality.
+    @unittest.skipIf(test_support.is_jython, "Not a valid test for Jython")
     def test_weak_keyed_cascading_deletes(self):
-        # SF bug 742860.  For some reason, before 2.3 __delitem__ iterated
+        # SF bug 742860.  For some reason, bef1ore 2.3 __delitem__ iterated
         # over the keys via self.data.iterkeys().  If things vanished from
         # the dict during this (or got added), that caused a RuntimeError.
 
@@ -1202,7 +1366,8 @@
 >>> o is o2
 True
 >>> del o, o2
->>> extra_collect()
+>>> import gc  # Addition for Jython
+>>> gc.collect()
 >>> print r()
 None
 
@@ -1255,7 +1420,8 @@
 >>> id2obj(a_id) is a
 True
 >>> del a
->>> extra_collect()
+>>> import gc  # addition for Jython
+>>> gc.collect()
 >>> try:
 ...     id2obj(a_id)
 ... except KeyError:
@@ -1269,16 +1435,6 @@
 __test__ = {'libreftest' : libreftest}
 
 def test_main():
-    if test_support.is_jython:
-        # Probably CPython GC specific (possibly even Jython bugs)
-        del ReferencesTestCase.test_callback_in_cycle_resurrection
-        del ReferencesTestCase.test_callbacks_on_callback
-
-        # Jython allows types to be weakref'd that CPython doesn't
-        del MappingTestCase.test_weak_keyed_bad_delitem
-
-        # CPython GC specific
-        del MappingTestCase.test_weak_keyed_cascading_deletes
     test_support.run_unittest(
         ReferencesTestCase,
         MappingTestCase,
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
@@ -63,14 +63,14 @@
     def test_new_or_init(self):
         self.assertRaises(TypeError, WeakSet, [], 2)
 
-    @unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
+    #@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
         self.assertEqual(len(self.fs), 0)
 
-    @unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
+    #@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)
@@ -167,14 +167,14 @@
         self.assertFalse(set('a').issubset('cbs'))
         self.assertFalse(set('cbs').issuperset('a'))
 
-    @unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
+    #@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")
+    #@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 +229,7 @@
         self.assertEqual(self.s, dup)
         self.assertNotEqual(id(self.s), id(dup))
 
-    @unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
+    #@unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
     def test_add(self):
         x = SomeClass('Q')
         self.s.add(x)
@@ -356,7 +356,7 @@
         self.assertFalse(self.s == tuple(self.items))
         self.assertFalse(self.s == 1)
 
-    @unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
+    #@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
diff --git a/Lib/weakref.py b/Lib/weakref.py
--- a/Lib/weakref.py
+++ b/Lib/weakref.py
@@ -5,12 +5,12 @@
 http://www.python.org/dev/peps/pep-0205/
 """
 
+# Changed for Jython to use MapMaker in Google Collections
+
 # Naming convention: Variables named "wr" are weak reference objects;
 # they are called this instead of "ref" to avoid name collisions with
 # the module-global ref() function imported from _weakref.
 
-import UserDict
-
 from _weakref import (
      getweakrefcount,
      getweakrefs,
@@ -23,6 +23,7 @@
 from _weakrefset import WeakSet
 
 from exceptions import ReferenceError
+from jythonlib import MapMaker, dict_builder
 
 
 ProxyTypes = (ProxyType, CallableProxyType)
@@ -32,107 +33,15 @@
            "CallableProxyType", "ProxyTypes", "WeakValueDictionary", 'WeakSet']
 
 
-class WeakValueDictionary(UserDict.UserDict):
+class WeakValueDictionary(dict):
     """Mapping class that references values weakly.
 
     Entries in the dictionary will be discarded when no strong
     reference to the value exists anymore
     """
-    # We inherit the constructor without worrying about the input
-    # dictionary; since it uses our .update() method, we get the right
-    # checks (if the other dictionary is a WeakValueDictionary,
-    # objects are unwrapped on the way out, and we always wrap on the
-    # way in).
 
-    def __init__(self, *args, **kw):
-        def remove(wr, selfref=ref(self)):
-            self = selfref()
-            if self is not None:
-                try:
-                    del self.data[wr.key]
-                except KeyError:
-                    pass
-        self._remove = remove
-        UserDict.UserDict.__init__(self, *args, **kw)
-
-    def __getitem__(self, key):
-        o = self.data[key]()
-        if o is None:
-            raise KeyError, key
-        else:
-            return o
-
-    def __contains__(self, key):
-        try:
-            o = self.data[key]()
-        except KeyError:
-            return False
-        return o is not None
-
-    def has_key(self, key):
-        try:
-            o = self.data[key]()
-        except KeyError:
-            return False
-        return o is not None
-
-    def __repr__(self):
-        return "<WeakValueDictionary at %s>" % id(self)
-
-    def __setitem__(self, key, value):
-        self.data[key] = KeyedRef(value, self._remove, key)
-
-    def copy(self):
-        new = WeakValueDictionary()
-        for key, wr in self.data.items():
-            o = wr()
-            if o is not None:
-                new[key] = o
-        return new
-
-    __copy__ = copy
-
-    def __deepcopy__(self, memo):
-        from copy import deepcopy
-        new = self.__class__()
-        for key, wr in self.data.items():
-            o = wr()
-            if o is not None:
-                new[deepcopy(key, memo)] = o
-        return new
-
-    def get(self, key, default=None):
-        try:
-            wr = self.data[key]
-        except KeyError:
-            return default
-        else:
-            o = wr()
-            if o is None:
-                # This should only happen
-                return default
-            else:
-                return o
-
-    def items(self):
-        L = []
-        for key, wr in self.data.items():
-            o = wr()
-            if o is not None:
-                L.append((key, o))
-        return L
-
-    def iteritems(self):
-        for wr in self.data.itervalues():
-            value = wr()
-            if value is not None:
-                yield wr.key, value
-
-    def iterkeys(self):
-        return self.data.iterkeys()
-
-    def __iter__(self):
-        return self.data.iterkeys()
+    def __new__(cls, *args, **kw):
+        return WeakValueDictionaryBuilder(*args, **kw)
 
     def itervaluerefs(self):
         """Return an iterator that yields the weak references to the values.
@@ -144,51 +53,8 @@
         keep the values around longer than needed.
 
         """
-        return self.data.itervalues()
-
-    def itervalues(self):
-        for wr in self.data.itervalues():
-            obj = wr()
-            if obj is not None:
-                yield obj
-
-    def popitem(self):
-        while 1:
-            key, wr = self.data.popitem()
-            o = wr()
-            if o is not None:
-                return key, o
-
-    def pop(self, key, *args):
-        try:
-            o = self.data.pop(key)()
-        except KeyError:
-            if args:
-                return args[0]
-            raise
-        if o is None:
-            raise KeyError, key
-        else:
-            return o
-
-    def setdefault(self, key, default=None):
-        try:
-            wr = self.data[key]
-        except KeyError:
-            self.data[key] = KeyedRef(default, self._remove, key)
-            return default
-        else:
-            return wr()
-
-    def update(self, dict=None, **kwargs):
-        d = self.data
-        if dict is not None:
-            if not hasattr(dict, "items"):
-                dict = type({})(dict)
-            for key, o in dict.items():
-                d[key] = KeyedRef(o, self._remove, key)
-        if len(kwargs):
-            self.update(kwargs)
+        for value in self.itervalues():
+            yield ref(value) 
 
     def valuerefs(self):
         """Return a list of weak references to the values.
@@ -200,17 +66,56 @@
         keep the values around longer than needed.
 
         """
-        return self.data.values()
+        return [ref(value) for value in self.itervalues()]
 
-    def values(self):
-        L = []
-        for wr in self.data.values():
-            o = wr()
-            if o is not None:
-                L.append(o)
-        return L
+WeakValueDictionaryBuilder = dict_builder(MapMaker().weakValues().makeMap, WeakValueDictionary)
 
 
+class WeakKeyDictionary(dict):
+    """ Mapping class that references keys weakly.
+
+    Entries in the dictionary will be discarded when there is no
+    longer a strong reference to the key. This can be used to
+    associate additional data with an object owned by other parts of
+    an application without adding attributes to those objects. This
+    can be especially useful with objects that override attribute
+    accesses.
+    """
+
+    def __new__(cls, *args, **kw):
+        return WeakKeyDictionaryBuilder(*args, **kw)
+
+    def iterkeyrefs(self):
+        """Return an iterator that yields the weak references to the keys.
+
+        The references are not guaranteed to be 'live' at the time
+        they are used, so the result of calling the references needs
+        to be checked before being used.  This can be used to avoid
+        creating references that will cause the garbage collector to
+        keep the keys around longer than needed.
+
+        """
+        for key in self.iterkeys():
+            yield ref(key)
+
+    def keyrefs(self):
+        """Return a list of weak references to the keys.
+
+        The references are not guaranteed to be 'live' at the time
+        they are used, so the result of calling the references needs
+        to be checked before being used.  This can be used to avoid
+        creating references that will cause the garbage collector to
+        keep the keys around longer than needed.
+
+        """
+        return [ref(key) for key in self.iterkeys()]
+
+WeakKeyDictionaryBuilder = dict_builder(MapMaker().weakKeys().makeMap, WeakKeyDictionary)
+
+
+# Jython does not use below, however retaining in the case of any user code that might 
+# be using it. Note that it is not exported.
+
 class KeyedRef(ref):
     """Specialized reference that includes a key corresponding to the value.
 
@@ -230,156 +135,3 @@
 
     def __init__(self, ob, callback, key):
         super(KeyedRef,  self).__init__(ob, callback)
-
-
-class WeakKeyDictionary(UserDict.UserDict):
-    """ Mapping class that references keys weakly.
-
-    Entries in the dictionary will be discarded when there is no
-    longer a strong reference to the key. This can be used to
-    associate additional data with an object owned by other parts of
-    an application without adding attributes to those objects. This
-    can be especially useful with objects that override attribute
-    accesses.
-    """
-
-    def __init__(self, dict=None):
-        self.data = {}
-        def remove(k, selfref=ref(self)):
-            self = selfref()
-            if self is not None:
-                try:
-                    del self.data[k]
-                except KeyError:
-                    pass
-        self._remove = remove
-        if dict is not None: self.update(dict)
-
-    def __delitem__(self, key):
-        del self.data[ref(key)]
-
-    def __getitem__(self, key):
-        return self.data[ref(key)]
-
-    def __repr__(self):
-        return "<WeakKeyDictionary at %s>" % id(self)
-
-    def __setitem__(self, key, value):
-        self.data[ref(key, self._remove)] = value
-
-    def copy(self):
-        new = WeakKeyDictionary()
-        for key, value in self.data.items():
-            o = key()
-            if o is not None:
-                new[o] = value
-        return new
-
-    __copy__ = copy
-
-    def __deepcopy__(self, memo):
-        from copy import deepcopy
-        new = self.__class__()
-        for key, value in self.data.items():
-            o = key()
-            if o is not None:
-                new[o] = deepcopy(value, memo)
-        return new
-
-    def get(self, key, default=None):
-        return self.data.get(ref(key),default)
-
-    def has_key(self, key):
-        try:
-            wr = ref(key)
-        except TypeError:
-            return 0
-        return wr in self.data
-
-    def __contains__(self, key):
-        try:
-            wr = ref(key)
-        except TypeError:
-            return 0
-        return wr in self.data
-
-    def items(self):
-        L = []
-        for key, value in self.data.items():
-            o = key()
-            if o is not None:
-                L.append((o, value))
-        return L
-
-    def iteritems(self):
-        for wr, value in self.data.iteritems():
-            key = wr()
-            if key is not None:
-                yield key, value
-
-    def iterkeyrefs(self):
-        """Return an iterator that yields the weak references to the keys.
-
-        The references are not guaranteed to be 'live' at the time
-        they are used, so the result of calling the references needs
-        to be checked before being used.  This can be used to avoid
-        creating references that will cause the garbage collector to
-        keep the keys around longer than needed.
-
-        """
-        return self.data.iterkeys()
-
-    def iterkeys(self):
-        for wr in self.data.iterkeys():
-            obj = wr()
-            if obj is not None:
-                yield obj
-
-    def __iter__(self):
-        return self.iterkeys()
-
-    def itervalues(self):
-        return self.data.itervalues()
-
-    def keyrefs(self):
-        """Return a list of weak references to the keys.
-
-        The references are not guaranteed to be 'live' at the time
-        they are used, so the result of calling the references needs
-        to be checked before being used.  This can be used to avoid
-        creating references that will cause the garbage collector to
-        keep the keys around longer than needed.
-
-        """
-        return self.data.keys()
-
-    def keys(self):
-        L = []
-        for wr in self.data.keys():
-            o = wr()
-            if o is not None:
-                L.append(o)
-        return L
-
-    def popitem(self):
-        while 1:
-            key, value = self.data.popitem()
-            o = key()
-            if o is not None:
-                return o, value
-
-    def pop(self, key, *args):
-        return self.data.pop(ref(key), *args)
-
-    def setdefault(self, key, default=None):
-        return self.data.setdefault(ref(key, self._remove),default)
-
-    def update(self, dict=None, **kwargs):
-        d = self.data
-        if dict is not None:
-            if not hasattr(dict, "items"):
-                dict = type({})(dict)
-            for key, value in dict.items():
-                d[ref(key, self._remove)] = value
-        if len(kwargs):
-            self.update(kwargs)
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
@@ -79,6 +79,11 @@
         internalMap = backingMap;
     }
 
+    public PyDictionary(PyType type, ConcurrentMap<PyObject, PyObject> backingMap, boolean useBackingMap) {
+        super(type);
+        internalMap = backingMap;
+    }
+
     /**
      * Create a new dictionary which is populated with entries the given map.
      */
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
@@ -1,6 +1,7 @@
 /* Generated file, do not modify.  See jython/src/templates/gderived.py. */
 package org.python.core;
 
+import java.util.concurrent.ConcurrentMap;
 import java.io.Serializable;
 import org.python.core.finalization.FinalizeTrigger;
 import org.python.core.finalization.FinalizablePyObjectDerived;
@@ -66,6 +67,15 @@
         }
     }
 
+    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__");
diff --git a/src/org/python/modules/_jythonlib/dict_builder.java b/src/org/python/modules/_jythonlib/dict_builder.java
--- a/src/org/python/modules/_jythonlib/dict_builder.java
+++ b/src/org/python/modules/_jythonlib/dict_builder.java
@@ -2,6 +2,7 @@
 package org.python.modules._jythonlib;
 
 import org.python.core.PyDictionary;
+import org.python.core.PyDictionaryDerived;
 import org.python.core.PyObject;
 import org.python.core.PyType;
 
@@ -24,15 +25,28 @@
 
     public static final PyType TYPE = PyType.fromClass(dict_builder.class);
     private final PyObject factory;
+    private final PyType dict_type;
 
     public dict_builder(PyObject factory) {
         super();
         this.factory = factory;
+	this.dict_type = null;
+    }
+
+    public dict_builder(PyObject factory, PyType dict_type) {
+	super();
+	this.factory = factory;
+	this.dict_type = dict_type;
     }
 
     public PyObject __call__(PyObject[] args, String[] keywords) {
         ConcurrentMap map = (ConcurrentMap) (factory.__call__().__tojava__(ConcurrentMap.class));
-        PyDictionary dict = new PyDictionary(map, true);
+	PyDictionary dict;
+	if (dict_type == null) {
+	    dict = new PyDictionary(map, true);
+	} else {
+	    dict = new PyDictionaryDerived(dict_type, map, true);
+	}
         dict.updateCommon(args, keywords, "dict");
         return dict;
     }
diff --git a/src/org/python/modules/_weakref/AbstractReference.java b/src/org/python/modules/_weakref/AbstractReference.java
--- a/src/org/python/modules/_weakref/AbstractReference.java
+++ b/src/org/python/modules/_weakref/AbstractReference.java
@@ -39,6 +39,12 @@
         return o;
     }
 
+    // Differentiate reference equality (equals) with what is being referred to (__eq__)
+    @Override
+    public boolean equals(Object ob_other) {
+        return ob_other == this;
+    }
+
     public int hashCode() {
         return gref.pythonHashCode();
     }
@@ -54,4 +60,16 @@
         }
         return pythis._eq(pyother);
     }
+
+    public PyObject __ne__(PyObject other) {
+        if (other.getClass() != getClass()) {
+            return Py.True;
+        }
+        PyObject pythis = (PyObject)gref.get();
+        PyObject pyother = (PyObject)((AbstractReference)other).gref.get();
+        if (pythis == null || pyother == null) {
+            return this == other ? Py.False : Py.True;
+        }
+        return pythis._eq(pyother).__not__();
+    }
 }
diff --git a/src/org/python/modules/_weakref/ProxyType.java b/src/org/python/modules/_weakref/ProxyType.java
--- a/src/org/python/modules/_weakref/ProxyType.java
+++ b/src/org/python/modules/_weakref/ProxyType.java
@@ -6,6 +6,7 @@
 import org.python.core.PyObject;
 import org.python.core.PyString;
 import org.python.core.PyType;
+import org.python.core.PyUnicode;
 import org.python.expose.ExposedType;
 
 /**
@@ -47,6 +48,7 @@
 
     public PyObject __iter__() { return py().__iter__(); }
     public PyString __str__() { return py().__str__(); }
+    public PyUnicode __unicode__() { return py().__unicode__(); }
     public PyString __hex__() { return py().__hex__(); }
     public PyString __oct__() { return py().__oct__(); }
     public PyObject __int__() { return py().__int__(); }
@@ -60,6 +62,7 @@
 
 
     public boolean __contains__(PyObject o) { return py().__contains__(o); }
+    public PyObject __index__() { return py().__index__(); }
 
     public PyObject __add__(PyObject o) { return py().__add__(o); }
     public PyObject __radd__(PyObject o) { return py().__radd__(o); }
@@ -71,8 +74,10 @@
     public PyObject __rmul__(PyObject o) { return py().__rmul__(o); }
     public PyObject __imul__(PyObject o) { return py().__imul__(o); }
     public PyObject __div__(PyObject o) { return py().__div__(o); }
+    public PyObject __floordiv__(PyObject o) { return py().__floordiv__(o); }
     public PyObject __rdiv__(PyObject o) { return py().__rdiv__(o); }
     public PyObject __idiv__(PyObject o) { return py().__idiv__(o); }
+    public PyObject __ifloordiv__(PyObject o) { return py().__ifloordiv__(o); }
     public PyObject __mod__(PyObject o) { return py().__mod__(o); }
     public PyObject __rmod__(PyObject o) { return py().__rmod__(o); }
     public PyObject __imod__(PyObject o) { return py().__imod__(o); }
@@ -84,7 +89,6 @@
     public PyObject __lshift__(PyObject o) { return py().__lshift__(o); }
     public PyObject __rlshift__(PyObject o) { return py().__rlshift__(o);}
     public PyObject __ilshift__(PyObject o) { return py().__ilshift__(o);}
-
     public PyObject __rshift__(PyObject o) { return py().__rshift__(o); }
     public PyObject __rrshift__(PyObject o) { return py().__rrshift__(o);}
     public PyObject __irshift__(PyObject o) { return py().__irshift__(o);}
diff --git a/src/org/python/modules/_weakref/ReferenceType.java b/src/org/python/modules/_weakref/ReferenceType.java
--- a/src/org/python/modules/_weakref/ReferenceType.java
+++ b/src/org/python/modules/_weakref/ReferenceType.java
@@ -3,8 +3,10 @@
 
 import org.python.core.ArgParser;
 import org.python.core.Py;
+import org.python.core.PyList;
 import org.python.core.PyNewWrapper;
 import org.python.core.PyObject;
+import org.python.core.PyTuple;
 import org.python.core.PyType;
 import org.python.expose.ExposedMethod;
 import org.python.expose.ExposedNew;
@@ -57,6 +59,11 @@
         // Just ensure at least one arg, leaving other args alone
         ArgParser ap = parseInitArgs("__init__", args, keywords);
         ap.getPyObject(0);
+        int arglen = ap.getList(2).__len__();
+        if (arglen > 2) {
+            throw Py.TypeError(String.format("__init__ expected at most 2 arguments, got %d",
+                    arglen));
+        }
     }
 
     /**

-- 
Repository URL: https://hg.python.org/jython


More information about the Jython-checkins mailing list