[pypy-commit] pypy py2-mappingproxy: Backport W_DictProxyObject from py3k

rlamy pypy.commits at gmail.com
Tue Aug 9 10:52:37 EDT 2016


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py2-mappingproxy
Changeset: r86110:786fadddf616
Date: 2016-08-09 15:15 +0100
http://bitbucket.org/pypy/pypy/changeset/786fadddf616/

Log:	Backport W_DictProxyObject from py3k

diff --git a/pypy/objspace/std/dictproxyobject.py b/pypy/objspace/std/dictproxyobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/objspace/std/dictproxyobject.py
@@ -0,0 +1,86 @@
+# Read-only proxy for mappings. PyPy does not have a separate type for
+# type.__dict__, so PyDictProxy_New has to use a custom read-only mapping.
+
+from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter.error import oefmt
+from pypy.interpreter.gateway import unwrap_spec, WrappedDefault
+from pypy.interpreter.typedef import TypeDef, interp2app
+
+class W_DictProxyObject(W_Root):
+    "Read-only proxy for mappings."
+
+    def __init__(self, w_mapping):
+        self.w_mapping = w_mapping
+
+    @staticmethod
+    def descr_new(space, w_type, w_mapping):
+        raise oefmt(space.w_TypeError, "Cannot create 'dictproxy' instances")
+
+    def descr_init(self, space, __args__):
+        pass
+
+    def descr_len(self, space):
+        return space.len(self.w_mapping)
+
+    def descr_getitem(self, space, w_key):
+        return space.getitem(self.w_mapping, w_key)
+
+    def descr_contains(self, space, w_key):
+        return space.contains(self.w_mapping, w_key)
+
+    def descr_iter(self, space):
+        return space.iter(self.w_mapping)
+
+    def descr_str(self, space):
+        return space.str(self.w_mapping)
+
+    def descr_repr(self, space):
+        return space.wrap("dict_proxy(%s)" %
+                                (space.str_w(space.repr(self.w_mapping)),))
+
+    @unwrap_spec(w_default=WrappedDefault(None))
+    def get_w(self, space, w_key, w_default):
+        return space.call_method(self.w_mapping, "get", w_key, w_default)
+
+    def keys_w(self, space):
+        return space.call_method(self.w_mapping, "keys")
+
+    def values_w(self, space):
+        return space.call_method(self.w_mapping, "values")
+
+    def items_w(self, space):
+        return space.call_method(self.w_mapping, "items")
+
+    def copy_w(self, space):
+        return space.call_method(self.w_mapping, "copy")
+
+cmp_methods = {}
+def make_cmp_method(op):
+    def descr_op(self, space, w_other):
+        return getattr(space, op)(self.w_mapping, w_other)
+    descr_name = 'descr_' + op
+    descr_op.__name__ = descr_name
+    setattr(W_DictProxyObject, descr_name, descr_op)
+    cmp_methods['__%s__' % op] = interp2app(getattr(W_DictProxyObject, descr_name))
+
+for op in ['eq', 'ne', 'gt', 'ge', 'lt', 'le']:
+    make_cmp_method(op)
+
+
+W_DictProxyObject.typedef = TypeDef(
+    'dictproxy',
+    __new__=interp2app(W_DictProxyObject.descr_new),
+    __init__=interp2app(W_DictProxyObject.descr_init),
+    __len__=interp2app(W_DictProxyObject.descr_len),
+    __getitem__=interp2app(W_DictProxyObject.descr_getitem),
+    __contains__=interp2app(W_DictProxyObject.descr_contains),
+    __iter__=interp2app(W_DictProxyObject.descr_iter),
+    __str__=interp2app(W_DictProxyObject.descr_str),
+    __repr__=interp2app(W_DictProxyObject.descr_repr),
+    get=interp2app(W_DictProxyObject.get_w),
+    keys=interp2app(W_DictProxyObject.keys_w),
+    values=interp2app(W_DictProxyObject.values_w),
+    items=interp2app(W_DictProxyObject.items_w),
+    copy=interp2app(W_DictProxyObject.copy_w),
+    **cmp_methods
+)
diff --git a/pypy/objspace/std/test/test_typeobject.py b/pypy/objspace/std/test/test_typeobject.py
--- a/pypy/objspace/std/test/test_typeobject.py
+++ b/pypy/objspace/std/test/test_typeobject.py
@@ -968,7 +968,6 @@
         raises(TypeError, setattr, list, 'foobar', 42)
         raises(TypeError, delattr, dict, 'keys')
         raises(TypeError, 'int.__dict__["a"] = 1')
-        raises(TypeError, 'int.__dict__.clear()')
 
     def test_nontype_in_mro(self):
         class OldStyle:
@@ -1026,10 +1025,9 @@
             pass
 
         a = A()
+        d = A.__dict__
         A.x = 1
-        assert A.__dict__["x"] == 1
-        A.__dict__['x'] = 5
-        assert A.x == 5
+        assert d["x"] == 1
 
     def test_we_already_got_one_1(self):
         # Issue #2079: highly obscure: CPython complains if we say
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -488,11 +488,13 @@
     def getdict(self, space): # returning a dict-proxy!
         from pypy.objspace.std.classdict import ClassDictStrategy
         from pypy.objspace.std.dictmultiobject import W_DictObject
+        from pypy.objspace.std.dictproxyobject import W_DictProxyObject
         if self.lazyloaders:
             self._cleanup_()    # force un-lazification
         strategy = space.fromcache(ClassDictStrategy)
         storage = strategy.erase(self)
-        return W_DictObject(space, strategy, storage)
+        w_dict = W_DictObject(space, strategy, storage)
+        return W_DictProxyObject(w_dict)
 
     def is_heaptype(self):
         return self.flag_heaptype


More information about the pypy-commit mailing list