Issue1622207

classification
Title: _weakref.ref(o) only works if the argument is hasheable
Type: Severity: normal
Components: None Versions:
Milestone:
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: cgroves, codepage, leosoto, leouserz, lheuer
Priority: normal Keywords:

Created on 2006-12-26.03:45:50 by leosoto, last changed 2007-06-19.07:13:44 by cgroves.

Files
File name Uploaded Description Edit Remove
jython_weakref_hashcode_fix.patch leosoto, 2006-12-26.03:45:50 Simple Patch
surprising_assignment.py cgroves, 2007-04-25.08:08:43 example of a flaw in the patch
Messages
msg1378 (view) Author: Leonardo Soto (leosoto) Date: 2006-12-26.03:45:50
Jython seems to impose a non standard restriction here, as CPython doesn't have any problem with this code:

>>> import _weakref, UserDict
>>> _weakref.ref(UserDict.UserDict())

But it raises TypeError on Jython (2.3 branch at least).

I'm attaching a simple patch, but I don't know if that's the "right way" or not.
msg1379 (view) Author: Deleted User leouserz (leouserz) Date: 2007-01-16.00:20:23
ugh, it almost seems like a bug to me that something so basic as hashCode is throwing Exceptions.  The patch is probably going to cover up something else that's more maniacal.
msg1380 (view) Author: Mr. Codepage (codepage) Date: 2007-02-06.03:10:09
The attached patch solved my problem with weakref. My repro case is below.

from weakref import *
wvd = WeakValueDictionary()
try:
    wvd_hash = hash(wvd)
except Exception,e:
    print e, "this was expected"

try:
    wvd_ref = ref(wvd)
    print wvd_ref
except Exception, e:
    print e, "this exception was NOT expected, running under jython"



foo@foo-desktop:~/jython_dev$ python weakref_bug.py 
unhashable instance this was expected
<weakref at 0xb7dbdfcc; to 'instance' at 0xb7dbbcec>
foo@foo-desktop:~/jython_dev$ jython weakref_bug.py 
unhashable instance this was expected
<weakref 1; to 'instance' object>

If we could get any comments from a core jython dev on this bug that would be great.
msg1381 (view) Author: Charlie Groves (cgroves) Date: 2007-04-25.08:08:43
The patch makes the hash value for all unhashable PyObjects 0.  Combined with the way GlobalRefs are used in a hashtable, this means that creating refs for two equal but distinct objects will only make a single ref.  This is undesirable as illustrated in the example I'm attaching: calling the second ref returns the first object.  

The only solution I can think of is to use System.identityHashCode(object) instead of object.hashCode().  As long as there isn't a case where Jython creates two separate Objects that refer to the same underlying Python object that should be fine.  I can't think of anything like that off the top of my head.
File Added: surprising_assignment.py
msg1382 (view) Author: Lars Heuer (lheuer) Date: 2007-05-11.10:06:45
Even if the object defines a __hash__ method, the WeakValueDictionary does not work:

>>> class X(object):
       def __init__(self, id):
           self.id = id
       def __hash__(self):
           return hash(self.id)

>>> # Code taken from the CPython example:
>>> import weakref
>>> _id2obj_dict = weakref.WeakValueDictionary()
>>> def remember(obj):
       oid = id(obj)
       _id2obj_dict[oid] = obj
       return oid
>>> x = X(123)
>>> remember(x)
Traceback (innermost last):
...
TypeError: unhashable instance


msg1383 (view) Author: Charlie Groves (cgroves) Date: 2007-06-19.07:13:44
This is fixed in r3259.
History
Date User Action Args
2006-12-26 03:45:50leosotocreate