[Python-checkins] r57172 - sandbox/trunk/import_in_py/NOTES sandbox/trunk/import_in_py/_importlib.py

brett.cannon python-checkins at python.org
Sat Aug 18 04:33:12 CEST 2007


Author: brett.cannon
Date: Sat Aug 18 04:32:42 2007
New Revision: 57172

Modified:
   sandbox/trunk/import_in_py/NOTES
   sandbox/trunk/import_in_py/_importlib.py
Log:
Untested implementation of new source handler.


Modified: sandbox/trunk/import_in_py/NOTES
==============================================================================
--- sandbox/trunk/import_in_py/NOTES	(original)
+++ sandbox/trunk/import_in_py/NOTES	Sat Aug 18 04:32:42 2007
@@ -2,13 +2,12 @@
 * mod_time(module_name) -> int
     Find out the modification time for a source module.  If no source module
     exists, raise XXX.
-* source(module_name) -> str
-    Return the text for a source module.
-    XXX Consider just using get_source from PEP 302 optional extensions.
-* bytecode(module_name) -> bytes
+* get_source(module_name) -> str
+    Return the text for a source module.  Defined as part of PEP 302's optional
+    extensions.
+* get_bytecode(module_name) -> bytes
     Return the bytes for a bytecode-stored module (including timestamp and
     cookie).
-    XXX Rename to get_bytecode if get_source is viable for source().
 * write_bytecode(module_name, data:bytes) -> bool
     Write out the new representation of a bytecode module.  Returns a boolean
     representing whether the bytes were actually written out or not.

Modified: sandbox/trunk/import_in_py/_importlib.py
==============================================================================
--- sandbox/trunk/import_in_py/_importlib.py	(original)
+++ sandbox/trunk/import_in_py/_importlib.py	Sat Aug 18 04:32:42 2007
@@ -273,7 +273,64 @@
 
 def handle_py(loader, name, path, source_exists, bytecode_exists, is_pkg):
     """Handle the initialization of a module by Python source or bytecode."""
-    raise NotImplementedError
+    assert source_exists or bytecode_exists
+    source_timestamp = None
+    module = sys.modules.get(name)
+    if module is None:
+        module = self.new_module(name)
+        sys.modules[mod_name] = module
+    # __file__, __path__, and __loader__ *must* be set on the module before
+    # any code is executed by the import.  __name__ is set by new_module.
+    module.__loader__ = loader
+    # XXX Will always be to the source if it exists, even if the module is
+    # initialized from source thanks to the importer always searching for
+    # source first.
+    module.__file__ = path
+    if is_pkg:
+        module.__path__  = [path.rsplit(path_sep, 1)[0]]
+    # Try to use bytecode if it is available.
+    if bytecode_exists:
+        pyc_data = loader.get_bytecode(name)
+        magic, pyc_timestamp, bytecode = data[:4], _r_long(data[4:8]), data[8:]
+        try:
+            # Verify that the magic number is valid.
+            if imp.get_magic() != magic:
+                raise ImportError("bad magic number")
+            # Verify that the bytecode is not stale.
+            if source_exists:
+                # Keep in a variable so that if bytecode turns out to be bad
+                # then the value can be reused when re-generating bytecode.
+                source_timestamp = loader.mod_time(name)
+                if pyc_timestamp < source_timestamp:
+                    raise ImportError("bytcode is stale")
+            # Bytecode seems fine, so try to use it.
+            try:
+                exec marshal.loads(bytecode) in module.__dict__
+                return module
+            except ValueError:
+                # XXX Does this have to be true?
+                # Since bad bytecode halts the import entirely, having the
+                # source code is useless.  Signal this fact by setting
+                # bytecode_exists to None.
+                bytecode_exists = None
+                raise ImportError('Non-code object in %s' %
+        except ImportError:
+            # If the exception is from the bytecode being corrupt, let it
+            # propagate.
+            if not source_exists or bytecode_exists is None:
+                raise
+    # Use the source.
+    source = loader.get_source(name)
+    code_object = compile(source, path, 'exec')
+    exec code_object in module.__dict__
+    # Generate bytecode and write it out.
+    if source_timestamp is None:  # May have from bytecode verification.
+        source_timestamp = loader.mod_time(source_path)
+    data = imp.get_magic()
+    data += _w_long(source_timestamp)
+    data += marshal.dumps(code_object)
+    loader.write_bytecode(name, data)
+    return module
 
 
 class _PyFileLoader(object):


More information about the Python-checkins mailing list