[pypy-commit] pypy kwargsdict-strategy: add a kwargs dict strategy based on two lists

cfbolz noreply at buildbot.pypy.org
Sat Apr 7 15:04:17 CEST 2012


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: kwargsdict-strategy
Changeset: r54226:3275a7dffd64
Date: 2012-04-05 23:20 +0200
http://bitbucket.org/pypy/pypy/changeset/3275a7dffd64/

Log:	add a kwargs dict strategy based on two lists

diff --git a/pypy/objspace/std/kwargsdict.py b/pypy/objspace/std/kwargsdict.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/kwargsdict.py
@@ -0,0 +1,136 @@
+## ----------------------------------------------------------------------------
+## dict strategy (see dictmultiobject.py)
+
+from pypy.rlib import rerased, jit
+from pypy.objspace.std.dictmultiobject import (DictStrategy,
+                                               IteratorImplementation,
+                                               ObjectDictStrategy)
+
+
+class KwargsDictStrategy(DictStrategy):
+    erase, unerase = rerased.new_erasing_pair("kwargsdict")
+    erase = staticmethod(erase)
+    unerase = staticmethod(unerase)
+
+    def wrap(self, key):
+        return self.space.wrap(key)
+
+    def unwrap(self, wrapped):
+        return self.space.str_w(wrapped)
+
+    def get_empty_storage(self):
+        d = ([], [])
+        return self.erase(d)
+
+    def is_correct_type(self, w_obj):
+        space = self.space
+        return space.is_w(space.type(w_obj), space.w_str)
+
+    def _never_equal_to(self, w_lookup_type):
+        return False
+
+    def iter(self, w_dict):
+        return KwargsDictIterator(self.space, self, w_dict)
+
+    def w_keys(self, w_dict):
+        return self.space.newlist([self.space.wrap(key) for key in self.unerase(w_dict.dstorage)[0]])
+
+    def setitem(self, w_dict, w_key, w_value):
+        space = self.space
+        if self.is_correct_type(w_key):
+            self.setitem_str(w_dict, self.unwrap(w_key), w_value)
+            return
+        else:
+            self.switch_to_object_strategy(w_dict)
+            w_dict.setitem(w_key, w_value)
+
+    @jit.look_inside_iff(lambda self, w_dict, key, w_value:
+            jit.is_constant(self.length(w_dict)) and jit.is_constant(key))
+    def setitem_str(self, w_dict, key, w_value):
+        keys, values_w = self.unerase(w_dict.dstorage)
+        result = []
+        for i in range(len(keys)):
+            if keys[i] == key:
+                values_w[i] = w_value
+                break
+        else:
+            keys.append(key)
+            values_w.append(w_value)
+
+    def setdefault(self, w_dict, w_key, w_default):
+        # XXX could do better, but is it worth it?
+        self.switch_to_object_strategy(w_dict)
+        return w_dict.setdefault(w_key, w_default)
+
+    def delitem(self, w_dict, w_key):
+        # XXX could do better, but is it worth it?
+        self.switch_to_object_strategy(w_dict)
+        return w_dict.delitem(w_key)
+
+    def length(self, w_dict):
+        return len(self.unerase(w_dict.dstorage)[0])
+
+    @jit.look_inside_iff(lambda self, w_dict, key: jit.is_constant(self.length(w_dict)) and jit.is_constant(key))
+    def getitem_str(self, w_dict, key):
+        keys, values_w = self.unerase(w_dict.dstorage)
+        result = []
+        for i in range(len(keys)):
+            if keys[i] == key:
+                return values_w[i]
+        return None
+
+    def getitem(self, w_dict, w_key):
+        space = self.space
+        if self.is_correct_type(w_key):
+            return self.getitem_str(w_dict, self.unwrap(w_key))
+        elif self._never_equal_to(space.type(w_key)):
+            return None
+        else:
+            self.switch_to_object_strategy(w_dict)
+            return w_dict.getitem(w_key)
+
+    def w_keys(self, w_dict):
+        l = [self.wrap(key) for key in self.unerase(w_dict.dstorage)[0]]
+        return self.space.newlist(l)
+
+    def values(self, w_dict):
+        return self.unerase(w_dict.dstorage)[1][:] # to make non-resizable
+
+    def items(self, w_dict):
+        space = self.space
+        keys, values_w = self.unerase(w_dict.dstorage)
+        result = []
+        for i in range(len(keys)):
+            result.append(space.newtuple([self.wrap(keys[i]), values_w[i]]))
+        return result
+
+    def popitem(self, w_dict):
+        keys, values_w = self.unerase(w_dict.dstorage)
+        key = keys.pop()
+        w_value = values_w.pop()
+        return (self.wrap(key), w_value)
+
+    def clear(self, w_dict):
+        w_dict.dstorage = self.get_empty_storage()
+
+    def switch_to_object_strategy(self, w_dict):
+        strategy = self.space.fromcache(ObjectDictStrategy)
+        keys, values_w = self.unerase(w_dict.dstorage)
+        d_new = strategy.unerase(strategy.get_empty_storage())
+        for i in range(len(keys)):
+            d_new[self.wrap(keys[i])] = values_w[i]
+        w_dict.strategy = strategy
+        w_dict.dstorage = strategy.erase(d_new)
+
+class KwargsDictIterator(IteratorImplementation):
+    def __init__(self, space, strategy, dictimplementation):
+        IteratorImplementation.__init__(self, space, strategy, dictimplementation)
+        self.iterator = iter(range(len(strategy.unerase(dictimplementation.dstorage)[0])))
+
+    def next_entry(self):
+        # note that this 'for' loop only runs once, at most
+        keys, values_w = self.strategy.unerase(self.dictimplementation.dstorage)
+        for i in self.iterator:
+            return self.space.wrap(keys[i]), values_w[i]
+        else:
+            return None, None
diff --git a/pypy/objspace/std/test/test_kwargsdict.py b/pypy/objspace/std/test/test_kwargsdict.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/test/test_kwargsdict.py
@@ -0,0 +1,84 @@
+from pypy.conftest import gettestobjspace, option
+from pypy.objspace.std.test.test_dictmultiobject import FakeSpace, W_DictMultiObject
+from pypy.objspace.std.kwargsdict import *
+
+space = FakeSpace()
+strategy = KwargsDictStrategy(space)
+
+def test_create():
+    keys = ["a", "b", "c"]
+    values = [1, 2, 3]
+    storage = strategy.erase((keys, values))
+    d = W_DictMultiObject(space, strategy, storage)
+    assert d.getitem_str("a") == 1
+    assert d.getitem_str("b") == 2
+    assert d.getitem_str("c") == 3
+    assert d.getitem(space.wrap("a")) == 1
+    assert d.getitem(space.wrap("b")) == 2
+    assert d.getitem(space.wrap("c")) == 3
+    assert d.w_keys() == keys
+    assert d.values() == values
+
+def test_set_existing():
+    keys = ["a", "b", "c"]
+    values = [1, 2, 3]
+    storage = strategy.erase((keys, values))
+    d = W_DictMultiObject(space, strategy, storage)
+    assert d.getitem_str("a") == 1
+    assert d.getitem_str("b") == 2
+    assert d.getitem_str("c") == 3
+    assert d.setitem_str("a", 4) is None
+    assert d.getitem_str("a") == 4
+    assert d.getitem_str("b") == 2
+    assert d.getitem_str("c") == 3
+    assert d.setitem_str("b", 5) is None
+    assert d.getitem_str("a") == 4
+    assert d.getitem_str("b") == 5
+    assert d.getitem_str("c") == 3
+    assert d.setitem_str("c", 6) is None
+    assert d.getitem_str("a") == 4
+    assert d.getitem_str("b") == 5
+    assert d.getitem_str("c") == 6
+    assert d.getitem(space.wrap("a")) == 4
+    assert d.getitem(space.wrap("b")) == 5
+    assert d.getitem(space.wrap("c")) == 6
+    assert d.w_keys() == keys
+    assert d.values() == values
+    assert keys == ["a", "b", "c"]
+    assert values == [4, 5, 6]
+
+
+def test_set_new():
+    keys = ["a", "b", "c"]
+    values = [1, 2, 3]
+    storage = strategy.erase((keys, values))
+    d = W_DictMultiObject(space, strategy, storage)
+    assert d.getitem_str("a") == 1
+    assert d.getitem_str("b") == 2
+    assert d.getitem_str("c") == 3
+    assert d.getitem_str("d") is None
+    assert d.setitem_str("d", 4) is None
+    assert d.getitem_str("a") == 1
+    assert d.getitem_str("b") == 2
+    assert d.getitem_str("c") == 3
+    assert d.getitem_str("d") == 4
+    assert d.w_keys() == keys
+    assert d.values() == values
+    assert keys == ["a", "b", "c", "d"]
+    assert values == [1, 2, 3, 4]
+
+
+from pypy.objspace.std.test.test_dictmultiobject import BaseTestRDictImplementation, BaseTestDevolvedDictImplementation
+def get_impl(self):
+    storage = strategy.erase(([], []))
+    return W_DictMultiObject(space, strategy, storage)
+class TestKwargsDictImplementation(BaseTestRDictImplementation):
+    StrategyClass = KwargsDictStrategy
+    get_impl = get_impl
+    def test_delitem(self):
+        pass # delitem devolves for now
+
+class TestDevolvedKwargsDictImplementation(BaseTestDevolvedDictImplementation):
+    get_impl = get_impl
+    StrategyClass = KwargsDictStrategy
+


More information about the pypy-commit mailing list