[pypy-svn] r17420 - in pypy/dist/pypy/rpython: . test

arigo at codespeak.net arigo at codespeak.net
Fri Sep 9 18:16:05 CEST 2005


Author: arigo
Date: Fri Sep  9 18:16:03 2005
New Revision: 17420

Added:
   pypy/dist/pypy/rpython/test/test_objectmodel.py   (contents, props changed)
Modified:
   pypy/dist/pypy/rpython/objectmodel.py
Log:
An r_dict() class that will work a bit like a dict at interp-level, but
containing keys over which we have control for hashing and comparison,
via subclassing and overriding the key_eq() and key_hash() methods.

The idea is to use it to replace the dictobject.py table lookup algorithms 
altogether, then annotate r_dict almost like regular dictionaries, in the same
way that we annotate r_int almost like regular ints.



Modified: pypy/dist/pypy/rpython/objectmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/objectmodel.py	(original)
+++ pypy/dist/pypy/rpython/objectmodel.py	Fri Sep  9 18:16:03 2005
@@ -29,3 +29,96 @@
     assert not getattr(obj.__class__, "_alloc_flavor_", 'gc').startswith('gc'), "trying to free gc object"
     obj.__dict__ = {}
     obj.__class__ = FREED_OBJECT
+
+# ____________________________________________________________
+
+
+class r_dict(object):
+    """An RPython dict-like object.
+    Only provides the interface supported by RPython.
+    The methods key_eq() and key_hash() are used by the key comparison
+    algorithm and can be subclassed."""
+
+    def __init__(self):
+        self._dict = {}
+
+    def __getitem__(self, key):
+        return self._dict[_r_dictkey(self, key)]
+
+    def __setitem__(self, key, value):
+        self._dict[_r_dictkey(self, key)] = value
+
+    def __delitem__(self, key):
+        del self._dict[_r_dictkey(self, key)]
+
+    def __len__(self):
+        return len(self._dict)
+
+    def __iter__(self):
+        for dk in self._dict:
+            yield dk.key
+
+    def __contains__(self, key):
+        return _r_dictkey(self, key) in self._dict
+
+    def get(self, key, default):
+        return self._dict.get(_r_dictkey(self, key), default)
+
+    def copy(self):
+        result = self.__class__()
+        result.update(self)
+        return result
+
+    def update(self, other):
+        for key, value in other.items():
+            self[key] = value
+
+    def keys(self):
+        return [dk.key for dk in self._dict]
+
+    def values(self):
+        return self._dict.values()
+
+    def items(self):
+        return [(dk.key, value) for dk, value in self._dict.items()]
+
+    iterkeys = __iter__
+
+    def itervalues(self):
+        return self._dict.itervalues()
+
+    def iteritems(self):
+        for dk, value in self._dict.items():
+            yield dk.key, value
+
+    def clear(self):
+        self._dict.clear()
+
+    def key_eq(self, key1, key2):
+        "Called to compare two keys.  Can be overridden in subclasses."
+        return key1 == key2
+
+    def key_hash(self, key):
+        "Called to compute the hash of a key.  Can be overridden in subclasses."
+        return hash(key)
+
+    def __repr__(self):
+        "Representation for debugging purposes."
+        return 'r_dict(%r)' % (dict(self.items()),)
+
+
+class _r_dictkey(object):
+    __slots__ = ['dic', 'key']
+    def __init__(self, dic, key):
+        self.dic = dic
+        self.key = key
+    def __eq__(self, other):
+        if not isinstance(other, _r_dictkey):
+            return NotImplemented
+        return self.dic.key_eq(self.key, other.key)
+    def __ne__(self, other):
+        if not isinstance(other, _r_dictkey):
+            return NotImplemented
+        return not self.dic.key_eq(self.key, other.key)
+    def __hash__(self):
+        return self.dic.key_hash(self.key)

Added: pypy/dist/pypy/rpython/test/test_objectmodel.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/test/test_objectmodel.py	Fri Sep  9 18:16:03 2005
@@ -0,0 +1,40 @@
+import py
+from pypy.rpython.objectmodel import *
+from pypy.rpython.test.test_llinterp import interpret
+
+
+def test_we_are_translated():
+    assert we_are_translated() == False
+
+    def fn():
+        return we_are_translated()
+    res = interpret(fn, [])
+    assert res is True
+
+def test_r_dict():
+    class StrangeDict(r_dict):
+        def key_eq(self, key1, key2):
+            return key1[0] == key2[0]   # only the 1st character is relevant
+        def key_hash(self, key):
+            return ord(key[0])
+    d = StrangeDict()
+    d['hello'] = 42
+    assert d['hi there'] == 42
+    py.test.raises(KeyError, 'd["dumb"]')
+    assert len(d) == 1
+    assert 'oops' not in d
+    assert list(d) == ['hello']
+    assert d.get('hola', -1) == 42
+    assert d.get('salut', -1) == -1
+    d1 = d.copy()
+    del d['hu!']
+    assert len(d) == 0
+    assert d1.keys() == ['hello']
+    d.update(d1)
+    assert d.values() == [42]
+    assert d.items() == [('hello', 42)]
+    assert list(d.iterkeys()) == ['hello']
+    assert list(d.itervalues()) == [42]
+    assert list(d.iteritems()) == [('hello', 42)]
+    d.clear()
+    assert d.keys() == []



More information about the Pypy-commit mailing list