[pypy-svn] pypy collections-module: Write defaultdict... cheating.
arigo
commits-noreply at bitbucket.org
Tue Feb 15 18:31:42 CET 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: collections-module
Changeset: r41986:2a2352811697
Date: 2011-02-15 18:31 +0100
http://bitbucket.org/pypy/pypy/changeset/2a2352811697/
Log: Write defaultdict... cheating.
diff --git a/pypy/module/_collections/__init__.py b/pypy/module/_collections/__init__.py
--- a/pypy/module/_collections/__init__.py
+++ b/pypy/module/_collections/__init__.py
@@ -3,7 +3,9 @@
from pypy.interpreter.mixedmodule import MixedModule
class Module(MixedModule):
- appleveldefs = {}
+ appleveldefs = {
+ 'defaultdict': 'app_defaultdict.defaultdict',
+ }
interpleveldefs = {
'deque' : 'interp_deque.W_Deque',
diff --git a/pypy/module/_collections/app_defaultdict.py b/pypy/module/_collections/app_defaultdict.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_collections/app_defaultdict.py
@@ -0,0 +1,56 @@
+# NOT_RPYTHON
+
+# For now this is here, living at app-level.
+#
+# The issue is that for now we don't support writing interp-level
+# subclasses of Wrappable that inherit at app-level from a type like
+# 'dict'.
+
+
+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]) or args[0] is None):
+ 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, recurse=set()):
+ # XXX not thread-safe, but good enough
+ if id(self) in recurse:
+ return "defaultdict(...)"
+ try:
+ recurse.add(id(self))
+ return "defaultdict(%s, %s)" % (repr(self.default_factory), super(defaultdict, self).__repr__())
+ finally:
+ recurse.remove(id(self))
+
+ 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())
diff --git a/pypy/module/_collections/test/test_defaultdict.py b/pypy/module/_collections/test/test_defaultdict.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_collections/test/test_defaultdict.py
@@ -0,0 +1,18 @@
+import py
+from pypy.conftest import gettestobjspace
+
+class AppTestBasic:
+ def setup_class(cls):
+ cls.space = gettestobjspace(usemodules=['_collections'])
+
+ def test_basics(self):
+ from _collections import defaultdict
+ d = defaultdict(list)
+ l = d[5]
+ d[5].append(42)
+ d[5].append(43)
+ assert l == [42, 43]
+ l2 = []
+ d[5] = l2
+ d[5].append(44)
+ assert l == [42, 43] and l2 == [44]
More information about the Pypy-commit
mailing list