[pypy-commit] pypy py3.3: Rewrite the DictProxy type, so that it does not depend on

amauryfa noreply at buildbot.pypy.org
Sat Apr 12 10:36:57 CEST 2014


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3.3
Changeset: r70600:bb19ba3f6538
Date: 2014-04-12 10:35 +0200
http://bitbucket.org/pypy/pypy/changeset/bb19ba3f6538/

Log:	Rewrite the DictProxy type, so that it does not depend on
	collections.abc which imports (and freezes) a lot of stdlib modules.

	+Translation fixes.

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
@@ -5,8 +5,8 @@
 from pypy.module.cpyext.pyobject import PyObject, PyObjectP, borrow_from
 from pypy.module.cpyext.pyobject import RefcountState
 from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
+from pypy.module.cpyext.dictproxyobject import W_DictProxyObject
 from pypy.interpreter.error import OperationError
-from rpython.rlib.objectmodel import specialize
 
 @cpython_api([], PyObject)
 def PyDict_New(space):
@@ -195,25 +195,9 @@
         return 0
     return 1
 
- at specialize.memo()
-def make_frozendict(space):
-    return space.appexec([], '''():
-    from collections.abc import Mapping
-    class FrozenDict(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''')
-
 @cpython_api([PyObject], PyObject)
 def PyDictProxy_New(space, w_dict):
-    w_frozendict = make_frozendict(space)
-    return space.call_function(w_frozendict, w_dict)
+    return space.wrap(W_DictProxyObject(w_dict))
 
 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
 def _PyDict_HasOnlyStringKeys(space, w_dict):
diff --git a/pypy/module/cpyext/dictproxyobject.py b/pypy/module/cpyext/dictproxyobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/dictproxyobject.py
@@ -0,0 +1,61 @@
+# 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.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
+
+    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.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")
+
+W_DictProxyObject.typedef = TypeDef(
+    'mappingproxy',
+    __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)
+    )
diff --git a/pypy/module/cpyext/import_.py b/pypy/module/cpyext/import_.py
--- a/pypy/module/cpyext/import_.py
+++ b/pypy/module/cpyext/import_.py
@@ -53,8 +53,9 @@
 
 @cpython_api([PyObject], PyObject)
 def PyImport_ReloadModule(space, w_mod):
-    from pypy.module.imp.importing import reload
-    return reload(space, w_mod)
+    w_import = space.builtin.get('__import__')
+    w_imp = space.call_function(w_import, space.wrap('imp'))
+    return space.call_method(w_imp, 'reload', w_mod)
 
 @cpython_api([CONST_STRING], PyObject)
 def PyImport_AddModule(space, name):
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -129,6 +129,14 @@
     find_module=interp2app(W_NullImporter.find_module_w),
     )
 
+def _prepare_module(space, w_mod, filename, pkgdir):
+    w = space.wrap
+    space.sys.setmodule(w_mod)
+    space.setattr(w_mod, w('__file__'), space.wrap(filename))
+    space.setattr(w_mod, w('__doc__'), space.w_None)
+    if pkgdir is not None:
+        space.setattr(w_mod, w('__path__'), space.newlist([w(pkgdir)]))
+
 def add_module(space, w_name):
     w_mod = check_sys_modules(space, w_name)
     if w_mod is None:
@@ -377,6 +385,15 @@
         if const is not None and isinstance(const, PyCode):
             update_code_filenames(space, const, pathname, oldname)
 
+def _get_long(s):
+    a = ord(s[0])
+    b = ord(s[1])
+    c = ord(s[2])
+    d = ord(s[3])
+    if d >= 0x80:
+        d -= 0x100
+    return a | (b<<8) | (c<<16) | (d<<24)
+
 def read_compiled_module(space, cpathname, strbuf):
     """ Read a code object from a file and check it for validity """
 
@@ -386,3 +403,25 @@
         raise oefmt(space.w_ImportError, "Non-code object in %s", cpathname)
     return w_code
 
+ at jit.dont_look_inside
+def load_compiled_module(space, w_modulename, w_mod, cpathname, magic,
+                         timestamp, source, write_paths=True):
+    """
+    Load a module from a compiled file, execute it, and return its
+    module object.
+    """
+    if magic != get_pyc_magic(space):
+        raise oefmt(space.w_ImportError, "Bad magic number in %s", cpathname)
+    #print "loading pyc file:", cpathname
+    code_w = read_compiled_module(space, cpathname, source)
+    try:
+        optimize = space.sys.get_flag('optimize')
+    except RuntimeError:
+        # during bootstrapping
+        optimize = 0
+    if optimize >= 2:
+        code_w.remove_docstrings(space)
+
+    exec_code_module(space, w_mod, code_w, cpathname, cpathname, write_paths)
+
+    return w_mod
diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -68,7 +68,13 @@
     if not space.config.objspace.usemodules.cpyext:
         raise OperationError(space.w_ImportError, space.wrap(
             "Not implemented"))
-    importing.load_c_extension(space, filename, space.str_w(w_modulename))
+
+    # the next line is mandatory to init cpyext
+    space.getbuiltinmodule("cpyext")
+
+    from pypy.module.cpyext.api import load_extension_module
+    load_extension_module(space, filename, space.str_w(w_modulename))
+
     return importing.check_sys_modules(space, w_modulename)
 
 def new_module(space, w_name):


More information about the pypy-commit mailing list