[pypy-commit] pypy default: cpyext: Implement PyDictProxy_New(), as a read-only dict.

amauryfa noreply at buildbot.pypy.org
Wed Feb 15 23:48:48 CET 2012


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: 
Changeset: r52528:94882d5e1677
Date: 2012-02-15 22:06 +0100
http://bitbucket.org/pypy/pypy/changeset/94882d5e1677/

Log:	cpyext: Implement PyDictProxy_New(), as a read-only dict. I don't
	know if there is a better way; PyPy does not have a separate type
	for int.__dict__.

diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py
--- a/pypy/module/cpyext/dictobject.py
+++ b/pypy/module/cpyext/dictobject.py
@@ -6,6 +6,7 @@
 from pypy.module.cpyext.pyobject import RefcountState
 from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
 from pypy.interpreter.error import OperationError
+from pypy.rlib.objectmodel import specialize
 
 @cpython_api([], PyObject)
 def PyDict_New(space):
@@ -191,3 +192,24 @@
             raise
         return 0
     return 1
+
+ at specialize.memo()
+def make_frozendict(space):
+    return space.appexec([], '''():
+    import collections
+    class FrozenDict(collections.Mapping):
+        def __init__(self, *args, **kwargs):
+            self._d = dict(*args, **kwargs)
+        def __iter__(self):
+            return iter(self._d)
+        def __len__(self):
+            return len(self._d)
+        def __getitem__(self, key):
+            return self._d[key]
+    return FrozenDict''')
+
+ at cpython_api([PyObject], PyObject)
+def PyDictProxy_New(space, w_dict):
+    w_frozendict = make_frozendict(space)
+    return space.call_function(w_frozendict, w_dict)
+
diff --git a/pypy/module/cpyext/test/test_dictobject.py b/pypy/module/cpyext/test/test_dictobject.py
--- a/pypy/module/cpyext/test/test_dictobject.py
+++ b/pypy/module/cpyext/test/test_dictobject.py
@@ -2,6 +2,7 @@
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.module.cpyext.api import Py_ssize_tP, PyObjectP
 from pypy.module.cpyext.pyobject import make_ref, from_ref
+from pypy.interpreter.error import OperationError
 
 class TestDictObject(BaseApiTest):
     def test_dict(self, space, api):
@@ -110,3 +111,13 @@
 
         assert space.eq_w(space.len(w_copy), space.len(w_dict))
         assert space.eq_w(w_copy, w_dict)
+
+    def test_dictproxy(self, space, api):
+        w_dict = space.sys.get('modules')
+        w_proxy = api.PyDictProxy_New(w_dict)
+        assert space.is_true(space.contains(w_proxy, space.wrap('sys')))
+        raises(OperationError, space.setitem,
+               w_proxy, space.wrap('sys'), space.w_None)
+        raises(OperationError, space.delitem,
+               w_proxy, space.wrap('sys'))
+        raises(OperationError, space.call_method, w_proxy, 'clear')


More information about the pypy-commit mailing list