[pypy-svn] r8578 - in pypy/dist/pypy/objspace: . std test

hpk at codespeak.net hpk at codespeak.net
Tue Jan 25 17:43:08 CET 2005


Author: hpk
Date: Tue Jan 25 17:43:08 2005
New Revision: 8578

Modified:
   pypy/dist/pypy/objspace/descroperation.py
   pypy/dist/pypy/objspace/std/objecttype.py
   pypy/dist/pypy/objspace/std/objspace.py
   pypy/dist/pypy/objspace/test/test_descriptor.py
Log:
(Jacek and holger) 

- after some discussion with Samuele we decided 
  that new style classes should be stricter 
  with respect to __hash__ operations: 
  in CPython only old-style classes would 
  raise TypeError("unhashable object") on code like: 

    class A: 
        def __eq__(self, other): 
            pass 

    hash(A()) 

  and that was specifically tested in test_class.py  
  However, in PyPy which so far only has 
  new style classes we didn't do this 
  although it's probably a good idea. 



Modified: pypy/dist/pypy/objspace/descroperation.py
==============================================================================
--- pypy/dist/pypy/objspace/descroperation.py	(original)
+++ pypy/dist/pypy/objspace/descroperation.py	Tue Jan 25 17:43:08 2005
@@ -228,6 +228,20 @@
             if space.is_true(space.eq(w_next, w_item)):
                 return space.w_True
     
+    def hash(space, w_obj):
+        w_hash = space.lookup(w_obj, '__hash__')
+        if w_hash is None:
+            if space.lookup(w_obj, '__eq__') is not None or \
+               space.lookup(w_obj, '__cmp__') is not None: 
+                raise OperationError(space.w_TypeError, 
+                                     space.wrap("unhashable type"))
+            return space.id(w_obj) 
+        w_result = space.get_and_call_function(w_hash, w_obj)
+        if space.is_true(space.isinstance(w_result, space.w_int)): 
+            return w_result 
+        else: 
+            raise OperationError(space.w_TypeError, 
+                     space.wrap("__hash__() should return an int"))
 
     # xxx round, ord
 

Modified: pypy/dist/pypy/objspace/std/objecttype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/objecttype.py	(original)
+++ pypy/dist/pypy/objspace/std/objecttype.py	Tue Jan 25 17:43:08 2005
@@ -14,11 +14,6 @@
 def descr__str__(space, w_obj):
     return space.repr(w_obj)
 
-def descr__hash__(space, w_obj):
-    # XXX detect non-hashable instances (the ones overriding comparison only)
-    # XXX ids could be long
-    return space.id(w_obj)
-
 def descr__class__(space, w_obj):
     return space.type(w_obj)
 
@@ -49,7 +44,6 @@
     __delattr__ = gateway.interp2app(Object.descr__delattr__.im_func),
     __str__ = gateway.interp2app(descr__str__),
     __repr__ = gateway.interp2app(descr__repr__),
-    __hash__ = gateway.interp2app(descr__hash__),
     __class__ = GetSetProperty(descr__class__),
     __new__ = newmethod(descr__new__),
     __init__ = gateway.interp2app(descr__init__),

Modified: pypy/dist/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/std/objspace.py	(original)
+++ pypy/dist/pypy/objspace/std/objspace.py	Tue Jan 25 17:43:08 2005
@@ -364,21 +364,6 @@
         else:
             return DescrOperation.is_true(self, w_obj)
 
-    def hash(space, w_obj):
-        w = space.wrap
-        eq = '__eq__'
-        ne = '__ne__'
-        hash_s = '__hash__'
-
-        for w_t in space.type(w_obj).mro_w:
-            d = w_t.dict_w
-            if hash_s in d:
-                w_descr = d[hash_s]
-                return space.get_and_call_function(w_descr, w_obj)
-            if eq in d:                
-                raise OperationError(space.w_TypeError, w("unhashable type"))
-        return space.id(w_obj)
-        
 # add all regular multimethods to StdObjSpace
 for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable:
     if not hasattr(StdObjSpace.MM, _name):

Modified: pypy/dist/pypy/objspace/test/test_descriptor.py
==============================================================================
--- pypy/dist/pypy/objspace/test/test_descriptor.py	(original)
+++ pypy/dist/pypy/objspace/test/test_descriptor.py	Tue Jan 25 17:43:08 2005
@@ -50,3 +50,26 @@
         raises(TypeError, oct, inst) 
         raises(TypeError, hex, inst) 
         assert A.seen == [1,2,3,4]
+
+class TestDesciprtorOnStd: 
+    objspacename = 'std' 
+    def test_hash(self): 
+        class A:
+            pass 
+        hash(A()) 
+        class B: 
+            def __eq__(self, other): pass 
+        raises(TypeError, hash, B()) 
+        class C: 
+            def __cmp__(self, other): pass 
+        raises(TypeError, "hash(C())")
+
+        class D: 
+            def __hash__(self): 
+                return 23L
+        raises(TypeError, hash, D())
+
+        class E: 
+            def __hash__(self): 
+                return "something"
+        raises(TypeError, hash, E())



More information about the Pypy-commit mailing list