[pypy-svn] r54356 - in pypy/branch/2.5-features/pypy/lib: . app_test

bgola at codespeak.net bgola at codespeak.net
Sat May 3 00:38:23 CEST 2008


Author: bgola
Date: Sat May  3 00:38:21 2008
New Revision: 54356

Added:
   pypy/branch/2.5-features/pypy/lib/app_test/test_defaultdict.py   (contents, props changed)
Modified:
   pypy/branch/2.5-features/pypy/lib/collections.py
Log:
defaultdict implementation in collections module

Added: pypy/branch/2.5-features/pypy/lib/app_test/test_defaultdict.py
==============================================================================
--- (empty file)
+++ pypy/branch/2.5-features/pypy/lib/app_test/test_defaultdict.py	Sat May  3 00:38:21 2008
@@ -0,0 +1,110 @@
+# defaultdict Tests
+# from CPython2.5
+
+import copy
+
+# for passing the test on top of 2.3
+from py.builtin import reversed
+import pypy.lib.collections
+pypy.lib.collections.reversed = reversed
+
+from pypy.lib.collections import defaultdict
+
+def foobar():
+    return list
+
+class Test_defaultdict:
+    
+    def test_basic(self):
+        d1 = defaultdict()
+        assert d1.default_factory is None
+        d1.default_factory = list
+        d1[12].append(42)
+        assert d1 == {12: [42]}
+        d1[12].append(24)
+        assert d1 == {12: [42, 24]}
+        d1[13]
+        d1[14]
+        assert d1 == {12: [42, 24], 13: [], 14: []}
+        assert d1[12] is not d1[13] is not d1[14]
+        d2 = defaultdict(list, foo=1, bar=2)
+        assert d2.default_factory == list
+        assert d2 == {"foo": 1, "bar": 2}
+        assert d2["foo"] == 1
+        assert d2["bar"] == 2
+        assert d2[42] == []
+        assert "foo" in d2
+        assert "foo" in d2.keys()
+        assert "bar" in d2
+        assert "bar" in d2.keys()
+        assert 42 in d2
+        assert 42 in d2.keys()
+        assert 12 not in d2
+        assert 12 not in d2.keys()
+        d2.default_factory = None
+        assert d2.default_factory == None
+        raises(KeyError, d2.__getitem__, 15)
+        raises(TypeError, defaultdict, 1)
+
+    def test_missing(self):
+        d1 = defaultdict()
+        raises(KeyError, d1.__missing__, 42)
+        d1.default_factory = list
+        assert d1.__missing__(42) == []
+
+    def test_repr(self):
+        d1 = defaultdict()
+        assert d1.default_factory == None
+        assert repr(d1) == "defaultdict(None, {})"
+        d1[11] = 41
+        assert repr(d1) == "defaultdict(None, {11: 41})"
+        d2 = defaultdict(int)
+        assert d2.default_factory == int
+        d2[12] = 42
+        assert repr(d2), "defaultdict(<type 'int'>, {12: 42})"
+        def foo(): return 43
+        d3 = defaultdict(foo)
+        assert d3.default_factory is foo
+        d3[13]
+        assert repr(d3), "defaultdict(%s, {13: 43})" % repr(foo)
+
+    def test_copy(self):
+        d1 = defaultdict()
+        d2 = d1.copy()
+        assert type(d2) == defaultdict
+        assert d2.default_factory == None
+        assert d2 == {}
+        d1.default_factory = list
+        d3 = d1.copy()
+        assert type(d3) == defaultdict
+        assert d3.default_factory == list
+        assert d3 == {}
+        d1[42]
+        d4 = d1.copy()
+        assert type(d4) == defaultdict
+        assert d4.default_factory == list
+        assert d4 == {42: []}
+        d4[12]
+        assert d4 == {42: [], 12: []}
+
+    def test_shallow_copy(self):
+        d1 = defaultdict(foobar, {1: 1})
+        d2 = copy.copy(d1)
+        assert d2.default_factory == foobar
+        assert d2 == d1
+        d1.default_factory = list
+        d2 = copy.copy(d1)
+        assert d2.default_factory == list
+        assert d2 == d1
+
+    def test_deep_copy(self):
+        d1 = defaultdict(foobar, {1: [1]})
+        d2 = copy.deepcopy(d1)
+        assert d2.default_factory == foobar
+        assert d2 == d1
+        assert d1[1] is not d2[1]
+        d1.default_factory = list
+        d2 = copy.deepcopy(d1)
+        assert d2.default_factory == list
+        assert d2 == d1
+

Modified: pypy/branch/2.5-features/pypy/lib/collections.py
==============================================================================
--- pypy/branch/2.5-features/pypy/lib/collections.py	(original)
+++ pypy/branch/2.5-features/pypy/lib/collections.py	Sat May  3 00:38:21 2008
@@ -308,4 +308,45 @@
 
     def __len__(self):
         return self.counter
-        
+
+class defaultdict(dict):
+    
+    def __init__(self, *args, **kwds):
+        self.default_factory = None
+        if 'default_factory' in kwds:
+            self.default_factory = kwds.pop('default_factory')
+        elif len(args) > 0 and callable(args[0]):
+            self.default_factory = args[0]
+            args = args[1:]
+        super(defaultdict, self).__init__(*args, **kwds)
+ 
+    def __missing__(self, key):
+        # from defaultdict docs
+        if self.default_factory is None: 
+            raise KeyError((key,))
+        self[key] = value = self.default_factory()
+        return value
+
+    def __repr__(self):
+        return "defaultdict(%s, %s)" % (repr(self.default_factory), super(defaultdict, self).__repr__())
+
+    def copy(self):
+        return type(self)(self, default_factory=self.default_factory)
+    
+    def __copy__(self):
+        return self.copy()
+
+    def __reduce__(self):
+        """
+        __reduce__ must return a 5-tuple as follows:
+
+           - factory function
+           - tuple of args for the factory function
+           - additional state (here None)
+           - sequence iterator (here None)
+           - dictionary iterator (yielding successive (key, value) pairs
+
+           This API is used by pickle.py and copy.py.
+        """
+        return (type(self), (self.default_factory,), None, None, self.iteritems())
+



More information about the Pypy-commit mailing list