[pypy-svn] r68351 - in pypy/branch/gc-hash/pypy/rlib: . test
arigo at codespeak.net
arigo at codespeak.net
Mon Oct 12 19:47:12 CEST 2009
Author: arigo
Date: Mon Oct 12 19:47:12 2009
New Revision: 68351
Modified:
pypy/branch/gc-hash/pypy/rlib/objectmodel.py
pypy/branch/gc-hash/pypy/rlib/test/test_objectmodel.py
Log:
Update the docstring of compute_hash() & friends,
to only promize to work on RPython-level objects.
Tests.
Modified: pypy/branch/gc-hash/pypy/rlib/objectmodel.py
==============================================================================
--- pypy/branch/gc-hash/pypy/rlib/objectmodel.py (original)
+++ pypy/branch/gc-hash/pypy/rlib/objectmodel.py Mon Oct 12 19:47:12 2009
@@ -136,12 +136,9 @@
def compute_hash(x):
"""RPython equivalent of hash(x), where 'x' is an immutable
- RPython-level or low-level object. For strings or unicodes it
- computes the hash as in Python. For tuples it calls compute_hash()
- recursively. For instances it uses compute_identity_hash().
- For low-level objects it returns the hash of the original RPython-
- level object, if any, or just compute_identity_hash() otherwise.
- It cannot be used on llmemory.GCREF.
+ RPython-level. For strings or unicodes it computes the hash as
+ in Python. For tuples it calls compute_hash() recursively.
+ For instances it uses compute_identity_hash().
Note that this can return 0 or -1 too.
@@ -170,9 +167,9 @@
"""RPython equivalent of object.__hash__(x). This returns the
so-called 'identity hash', which is the non-overridable default hash
of Python. Can be called for any RPython-level object that turns
- into a GC object, or for any low-level GC object, including
- llmemory.GCREF. The value is not guaranteed to be the same before
- and after translation, except for RPython instances on the lltypesystem.
+ into a GC object, but not NULL. The value is not guaranteed to be the
+ same before and after translation, except for RPython instances on the
+ lltypesystem.
"""
result = object.__hash__(x)
try:
@@ -206,14 +203,13 @@
from pypy.rlib.rarithmetic import intmask
length = len(s)
if length == 0:
- x = 0
- else:
- x = ord(s[0]) << 7
- i = 0
- while i < length:
- x = (1000003*x) ^ ord(s[i])
- i += 1
- x ^= length
+ return 0
+ x = ord(s[0]) << 7
+ i = 0
+ while i < length:
+ x = (1000003*x) ^ ord(s[i])
+ i += 1
+ x ^= length
return intmask(x)
def _hash_float(f):
@@ -222,12 +218,13 @@
except the fact that the integer case is not treated specially.
In RPython, floats cannot be used with ints in dicts, anyway.
"""
+ from pypy.rlib.rarithmetic import intmask
v, expo = math.frexp(f)
v *= TAKE_NEXT
hipart = int(v)
v = (v - float(hipart)) * TAKE_NEXT
x = hipart + int(v) + (expo << 15)
- return x
+ return intmask(x)
TAKE_NEXT = float(2**31)
def _hash_tuple(t):
@@ -237,10 +234,11 @@
that nested tuples are very uncommon in RPython, making the case
unlikely.
"""
+ from pypy.rlib.rarithmetic import intmask
x = 0x345678
for item in t:
y = compute_hash(item)
- x = (1000003 * x) ^ y
+ x = intmask((1000003 * x) ^ y)
return x
# ----------
Modified: pypy/branch/gc-hash/pypy/rlib/test/test_objectmodel.py
==============================================================================
--- pypy/branch/gc-hash/pypy/rlib/test/test_objectmodel.py (original)
+++ pypy/branch/gc-hash/pypy/rlib/test/test_objectmodel.py Mon Oct 12 19:47:12 2009
@@ -141,6 +141,45 @@
py.test.raises(TypeError, "s1 < s2")
py.test.raises(TypeError, "hash(s1)")
+def test_compute_hash():
+ from pypy.rlib.objectmodel import _hash_string, _hash_float, _hash_tuple
+ assert compute_hash("Hello") == _hash_string("Hello")
+ assert compute_hash(7) == 7
+ assert compute_hash(-3.5) == _hash_float(-3.5)
+ assert compute_hash(None) == 0
+ assert compute_hash(("world", None, 7)) == _hash_tuple(("world", None, 7))
+ #
+ class Foo(object):
+ def __hash__(self):
+ return 42
+ foo = Foo()
+ h = compute_hash(foo)
+ assert h == object.__hash__(foo)
+ assert h == getattr(foo, '__precomputed_identity_hash')
+ assert compute_hash(None) == 0
+
+def test_compute_identity_hash():
+ class Foo(object):
+ def __hash__(self):
+ return 42
+ foo = Foo()
+ h = compute_identity_hash(foo)
+ assert h == object.__hash__(foo)
+ assert h == getattr(foo, '__precomputed_identity_hash')
+
+def test_compute_unique_id():
+ class Foo(object):
+ pass
+ foo = Foo()
+ assert compute_unique_id(foo) == id(foo)
+
+def test_current_object_addr_as_int():
+ from pypy.rlib.rarithmetic import intmask
+ class Foo(object):
+ pass
+ foo = Foo()
+ assert current_object_addr_as_int(foo) == intmask(id(foo))
+
class BaseTestObjectModel(BaseRtypingTest):
def test_we_are_translated(self):
@@ -270,6 +309,27 @@
res = self.interpret(g, [3])
assert res == 77
+ def test_compute_hash(self):
+ class Foo(object):
+ pass
+ def f(i):
+ assert compute_hash(i) == compute_hash(42)
+ assert compute_hash(i+1.0) == compute_hash(43.0)
+ assert compute_hash("Hello" + str(i)) == compute_hash("Hello42")
+ if i == 42:
+ p = None
+ else:
+ p = Foo()
+ assert compute_hash(p) == compute_hash(None)
+ assert (compute_hash(("world", None, i, 7.5)) ==
+ compute_hash(("world", None, 42, 7.5)))
+ q = Foo()
+ assert compute_hash(q) == compute_identity_hash(q)
+ return i*2
+ res = self.interpret(f, [42])
+ assert res == 84
+
+
class TestLLtype(BaseTestObjectModel, LLRtypeMixin):
def test_rtype_keepalive(self):
@@ -283,6 +343,33 @@
res = self.interpret(f, [])
assert res == 1
+ def test_compute_hash_across_translation(self):
+ class Foo(object):
+ pass
+ q = Foo()
+
+ def f(i):
+ assert compute_hash(i) == h_42
+ assert compute_hash(i+1.0) == h_43_dot_0
+ assert compute_hash("Hello" + str(i)) == h_Hello42
+ if i == 42:
+ p = None
+ else:
+ p = Foo()
+ assert compute_hash(p) == h_None
+ assert compute_hash(("world", None, i, 7.5)) == h_tuple
+ assert compute_hash(q) == h_q
+ return i*2
+ h_42 = compute_hash(42)
+ h_43_dot_0 = compute_hash(43.0)
+ h_Hello42 = compute_hash("Hello42")
+ h_None = compute_hash(None)
+ h_tuple = compute_hash(("world", None, 42, 7.5))
+ h_q = compute_hash(q)
+
+ res = self.interpret(f, [42])
+ assert res == 84
+
class TestOOtype(BaseTestObjectModel, OORtypeMixin):
pass
More information about the Pypy-commit
mailing list