[pypy-svn] r47826 - in pypy/dist/pypy/module/zipimport: . test

fijal at codespeak.net fijal at codespeak.net
Wed Oct 24 15:04:54 CEST 2007


Author: fijal
Date: Wed Oct 24 15:04:54 2007
New Revision: 47826

Added:
   pypy/dist/pypy/module/zipimport/test/__init__.py   (contents, props changed)
Modified:
   pypy/dist/pypy/module/zipimport/   (props changed)
   pypy/dist/pypy/module/zipimport/__init__.py
   pypy/dist/pypy/module/zipimport/app_zipimport.py
   pypy/dist/pypy/module/zipimport/interp_zipimport.py
   pypy/dist/pypy/module/zipimport/test/   (props changed)
   pypy/dist/pypy/module/zipimport/test/test_zipimport.py
Log:
More or less working zipimport. Packages are not working though.


Modified: pypy/dist/pypy/module/zipimport/__init__.py
==============================================================================
--- pypy/dist/pypy/module/zipimport/__init__.py	(original)
+++ pypy/dist/pypy/module/zipimport/__init__.py	Wed Oct 24 15:04:54 2007
@@ -10,6 +10,6 @@
     interpleveldefs = {'zipimporter':'interp_zipimport.W_ZipImporter'}
 
     appleveldefs = {
-        'ZipImporterError' : 'app_zipimport.ZipImporterError',
+        'ZipImportError' : 'app_zipimport.ZipImportError',
     }
     

Modified: pypy/dist/pypy/module/zipimport/app_zipimport.py
==============================================================================
--- pypy/dist/pypy/module/zipimport/app_zipimport.py	(original)
+++ pypy/dist/pypy/module/zipimport/app_zipimport.py	Wed Oct 24 15:04:54 2007
@@ -1,3 +1,3 @@
 
-class ZipImporterError(Exception):
+class ZipImportError(Exception):
     pass

Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py
==============================================================================
--- pypy/dist/pypy/module/zipimport/interp_zipimport.py	(original)
+++ pypy/dist/pypy/module/zipimport/interp_zipimport.py	Wed Oct 24 15:04:54 2007
@@ -8,9 +8,20 @@
 from pypy.interpreter.eval import Code
 from pypy.interpreter.module import Module
 from pypy.module.__builtin__ import importing
+from pypy.rlib.unroll import unrolling_iterable
 import os
 import stat
 
+zip_importer_cache = {}
+
+ENUMERATE_EXTS = unrolling_iterable(
+    [(True, True, os.path.sep + '__init__.pyc'),
+     (True, True, os.path.sep + '__init__.pyo'),
+     (False, True, os.path.sep + '__init__.py'),
+     (True, False, '.pyc'),
+     (True, False, '.pyo'),
+     (False, False, '.py')]
+
 class W_ZipImporter(Wrappable):
     def __init__(self, space, name, w_dir, w_zipfile):
         self.space = space
@@ -24,14 +35,31 @@
             space.call(space.getattr(w_dir, space.wrap('namelist')),
                        space.newlist([])))]
 
-    def import_py_file(self, space, modname, filename, w_buf):
+    def import_py_file(self, space, modname, filename, w_buf, pkgpath):
         buf = space.str_w(w_buf)
         w = space.wrap
         w_mod = w(Module(space, w(modname)))
-        importing._prepare_module(space, w_mod, filename, None)
-        return importing.load_source_module(space, w(modname), w_mod,
+        real_name = self.name + os.path.sep + filename
+        importing._prepare_module(space, w_mod, real_name, pkgpath)
+        result = importing.load_source_module(space, w(modname), w_mod,
                                             filename, buf, write_pyc=False)
-        return w_mod
+        space.setattr(w_mod, w('__loader__'), space.wrap(self))
+        return result
+
+    def import_pyc_file(self, space, modname, filename, w_buf, pkgpath):
+        w = space.wrap
+        buf = space.str_w(w_buf)
+        magic = importing._get_long(buf[:4])
+        timestamp = importing._get_long(buf[4:8])
+        buf = buf[8:] # XXX ugly copy, should use sequential read instead
+        w_mod = w(Module(space, w(modname)))
+        real_name = self.name + os.path.sep + filename
+        importing._prepare_module(space, w_mod, real_name, pkgpath)
+        result = importing.load_compiled_module(space, w(modname), w_mod,
+                                                filename, magic, timestamp,
+                                                buf)
+        space.setattr(w_mod, w('__loader__'), space.wrap(self))
+        return result
 
     def get_module(self, space, name):
         w = space.wrap
@@ -42,20 +70,48 @@
             if not e.match(space, space.w_KeyError):
                 # should never happen
                 raise e
+            return space.w_None
 
     def find_module(self, space, import_name, w_path=None):
         import_name = import_name.replace('.', os.path.sep)
-        for ext in ['.py', 'pyc', '.pyo']:
-            if self.get_module(space, import_name + ext):
+        for _, _, ext in ENUMERATE_EXTS:
+            if space.is_true(self.get_module(space, import_name + ext)):
                 return space.wrap(self)
     find_module.unwrap_spec = ['self', ObjSpace, str, W_Root]
 
     def load_module(self, space, name):
         w = space.wrap
-        filename = name.replace('.', os.path.sep) + '.py'
-        w_buf = space.call(space.getattr(self.w_dir, w('read')),
-                           space.newlist([w(filename)]))
-        return self.import_py_file(space, name, filename, w_buf)
+        w_modules = space.sys.get('modules')
+        try:
+            return space.getitem(w_modules, w(name))
+        except OperationError, e:
+            pass
+        filename = name.replace('.', os.path.sep)
+        w_ZipImportError = space.getattr(space.getbuiltinmodule('zipimport'),
+                                         w('ZipImportError'))
+        last_exc = None
+        for compiled, is_package, ext in ENUMERATE_EXTS:
+            try:
+                w_buf = space.call(space.getattr(self.w_dir, w('read')),
+                                   space.newlist([w(filename + ext)]))
+                if is_package:
+                    pkgpath = filename + os.path.sep
+                else:
+                    pkgpath = None
+                if compiled:
+                    return self.import_pyc_file(space, name, filename + ext,
+                                                w_buf, pkgpath)
+                else:
+                    return self.import_py_file(space, name, filename + ext,
+                                               w_buf, pkgpath)
+            except OperationError, e:
+                last_exc = e
+                w_mods = space.sys.get('modules')
+                space.call_method(w_mods,'pop', w(name), space.w_None)
+        if last_exc:
+            raise OperationError(w_ZipImportError, last_exc.w_value)
+        # should never happen I think
+        return space.w_None
     load_module.unwrap_spec = ['self', ObjSpace, str]
 
     def get_data(self, space):
@@ -76,6 +132,10 @@
 
 def descr_new_zipimporter(space, w_type, name):
     try:
+        return zip_importer_cache[name]
+    except KeyError:
+        pass
+    try:
         s = os.stat(name)
     except OSError:
         return space.w_None
@@ -93,7 +153,9 @@
     except OperationError: # we catch everything as this function
         # should not raise
         return space.w_None
-    return space.wrap(W_ZipImporter(space, name, w_dir, w_zipfile))
+    result = space.wrap(W_ZipImporter(space, name, w_dir, w_zipfile))
+    zip_importer_cache[name] = result
+    return result
     
 descr_new_zipimporter.unwrap_spec = [ObjSpace, W_Root, str]
 

Added: pypy/dist/pypy/module/zipimport/test/__init__.py
==============================================================================

Modified: pypy/dist/pypy/module/zipimport/test/test_zipimport.py
==============================================================================
--- pypy/dist/pypy/module/zipimport/test/test_zipimport.py	(original)
+++ pypy/dist/pypy/module/zipimport/test/test_zipimport.py	Wed Oct 24 15:04:54 2007
@@ -1,10 +1,11 @@
 
-import imp
 from pypy.conftest import gettestobjspace
 import marshal
 import py
 import time
 import struct
+from pypy.module.__builtin__.importing import get_pyc_magic, _w_long
+from StringIO import StringIO
 
 from pypy.tool.udir import udir
 from zipfile import ZIP_STORED, ZIP_DEFLATED, ZipInfo
@@ -13,7 +14,7 @@
     """ A bit structurized tests stolen and adapted from
     cpy's regression tests
     """
-    def make_pyc(cls, co, mtime):
+    def make_pyc(cls, space, co, mtime):
         data = marshal.dumps(co)
         if type(mtime) is type(0.0):
             # Mac mtimes need a bit of special casing
@@ -21,7 +22,13 @@
                 mtime = int(mtime)
             else:
                 mtime = int(-0x100000000L + long(mtime))
-        pyc = imp.get_magic() + struct.pack("<i", int(mtime)) + data
+        s = StringIO()
+        try:
+            _w_long(s, get_pyc_magic(space))
+        except AttributeError:
+            import imp
+            s.write(imp.get_magic())
+        pyc = s.getvalue() + struct.pack("<i", int(mtime)) + data
         return pyc
     make_pyc = classmethod(make_pyc)
 
@@ -37,28 +44,118 @@
         tmpdir = udir.ensure('zipimport', dir=1)
         now = time.time()
         cls.w_now = space.wrap(now)
-        test_pyc = cls.make_pyc(co, now)
+        test_pyc = cls.make_pyc(space, co, now)
         cls.w_test_pyc = space.wrap(test_pyc)
         cls.w_compression = space.wrap(ZIP_STORED)
         #ziptestmodule = tmpdir.ensure('ziptestmodule.zip').write(
         ziptestmodule = tmpdir.join("somezip.zip")
         cls.w_tmpzip = space.wrap(str(ziptestmodule))
         cls.tmpdir = tmpdir
+        cls.w_writefile = space.appexec([], """():
+        def writefile (self, filename, data):
+            import sys
+            import time
+            from zipfile import ZipFile, ZipInfo
+            z = ZipFile(self.zipfile, 'w')
+            write_files = getattr(self, 'write_files', [])
+            write_files.append((filename, data))
+            for filename, data in write_files:
+                zinfo = ZipInfo(filename, time.localtime(self.now))
+                zinfo.compress_type = self.compression
+                z.writestr(zinfo, data)
+            self.write_files = write_files
+            # XXX populates sys.path, but at applevel
+            if sys.path[0] != self.zipfile:
+                sys.path.insert(0, self.zipfile)
+            z.close()
+        return writefile
+        """)
+        #space.appexec([], 
 
     def setup_method(self, meth):
         space = self.space
-        name = "test_%s" % meth.__name__
-        self.w_zipfile = self.tmpdir.join(name)
+        name = "test_%s.zip" % meth.__name__
+        self.w_zipfile = space.wrap(str(self.tmpdir.join(name)))
+        space.appexec([space.wrap(self)], """(self):
+        self.write_files = []
+        """)
 
-    def test_py(self): #, expected_ext, files, *modules, **kw):
-        from zipfile import ZipFile, ZipInfo
+    def teardown_method(self, meth):
+        space = self.space
+        space.appexec([], """():
+        import sys
+        while sys.path[0].endswith('.zip'):
+            sys.path.pop(0)
+        """)
+
+    def test_py(self):
         import sys
-        import time
-        z = ZipFile(self.tmpzip, "w")
-        zinfo = ZipInfo("uuu.py", time.localtime(self.now))
-        zinfo.compress_type = self.compression
-        z.writestr(zinfo, "def f(x): return x")
-        sys.path.insert(0, self.tmpzip)
-        z.close()
+        self.writefile(self, "uuu.py", "def f(x): return x")
         mod = __import__('uuu', globals(), locals(), [])
         assert mod.f(3) == 3
+        expected = {
+            '__doc__' : None,
+            '__name__' : 'uuu',
+            'f': mod.f}
+        for key, val in expected.items():
+            assert mod.__dict__[key] == val
+        assert mod.__file__.endswith('.zip/uuu.py')
+        del sys.modules['uuu']
+    
+    def test_pyc(self):
+        import sys
+        self.writefile(self, "uuu.pyc", self.test_pyc)
+        mod = __import__('uuu', globals(), locals(), [])
+        expected = {
+            '__doc__' : None,
+            '__name__' : 'uuu',
+            'get_name' : mod.get_name,
+            'get_file' : mod.get_file
+        }
+        for key, val in expected.items():
+            assert mod.__dict__[key] == val
+        assert mod.__file__.endswith('.zip/uuu.pyc')
+        assert mod.get_file() == mod.__file__
+        assert mod.get_name() == mod.__name__
+        del sys.modules['uuu']
+                                
+    def test_bad_pyc(self):
+        import zipimport
+        import sys
+        m0 = ord(self.test_pyc[0])
+        m0 ^= 0x04
+        test_pyc = chr(m0) + self.test_pyc[1:]
+        self.writefile(self, "uu.pyc", test_pyc)
+        raises(zipimport.ZipImportError,
+               "__import__('uu', globals(), locals(), [])")
+        assert 'uu' not in sys.modules
+
+    def test_force_py(self):
+        m0 = ord(self.test_pyc[0])
+        m0 ^= 0x04
+        test_pyc = chr(m0) + self.test_pyc[1:]
+        self.writefile(self, "uu.pyc", test_pyc)
+        self.writefile(self, "uu.py", "def f(x): return x")
+        mod = __import__("uu", globals(), locals(), [])
+        assert mod.f(3) == 3
+
+    def test_sys_modules(self):
+        m0 = ord(self.test_pyc[0])
+        m0 ^= 0x04
+        test_pyc = chr(m0) + self.test_pyc[1:]
+        self.writefile(self, "uuu.pyc", test_pyc)
+        import sys
+        import zipimport
+        z = zipimport.zipimporter(self.zipfile)
+        sys.modules['uuu'] = lambda x : x + 1
+        mod = z.load_module('uuu')
+        assert mod(3) == 4
+
+    def test_package(self):
+        skip("Does not work, no idea why...")
+        self.writefile(self, "xx/__init__.py", "")
+        self.writefile(self, "xx/yy.py", "def f(x): return x")
+        mod = __import__("xx", globals(), locals(), ['yy'])
+        assert mod.__path__
+        assert mod.yy.f(3) == 3
+    



More information about the Pypy-commit mailing list