[Python-checkins] r57267 - sandbox/trunk/import_in_py/_importlib.py sandbox/trunk/import_in_py/controlled_importlib.py
brett.cannon
python-checkins at python.org
Tue Aug 21 23:09:22 CEST 2007
Author: brett.cannon
Date: Tue Aug 21 23:09:21 2007
New Revision: 57267
Modified:
sandbox/trunk/import_in_py/_importlib.py
sandbox/trunk/import_in_py/controlled_importlib.py
Log:
Reimplement get_code for the source loader so as to return the code object that
load_module would have used had it been called.
This led to handle_py becoming handle_code to make this situation much easier.
Also introduced init_module which takes the code object and relevant
information and initializes a module for the import.
Modified: sandbox/trunk/import_in_py/_importlib.py
==============================================================================
--- sandbox/trunk/import_in_py/_importlib.py (original)
+++ sandbox/trunk/import_in_py/_importlib.py Tue Aug 21 23:09:21 2007
@@ -266,21 +266,28 @@
if suffix[2] == suffix_type]
-def handle_py(loader, name, source_path, bytecode_path, is_pkg):
- """Handle the initialization of a module by Python source or bytecode."""
- assert source_path or bytecode_path
- source_timestamp = None
+def init_module(loader, code_object, name, path, is_pkg):
+ """Return an initialized module."""
module = sys.modules.get(name)
if module is None:
module = imp.new_module(name)
sys.modules[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
- # Just so that the attribute has some value to start with.
- module.__file__ = source_path or bytecode_path
+ module.__name__ = name
+ module.__file__ = path
if is_pkg:
module.__path__ = [module.__file__.rsplit(path_sep, 1)[0]]
+ exec code_object in module.__dict__
+ return module
+
+
+def handle_code(loader, name, source_path, bytecode_path):
+ """Return the code object and the location of the code used to create the
+ code object in a two-item sequence."""
+ # Request paths instead of just booleans since 'compile' needs it for
+ # source.
+ assert source_path or bytecode_path
+ source_timestamp = None
# Try to use bytecode if it is available.
if bytecode_path:
magic, pyc_timestamp, bytecode = loader.get_bytecode(name)
@@ -297,9 +304,7 @@
raise ImportError("bytcode is stale")
# Bytecode seems fine, so try to use it.
try:
- exec marshal.loads(bytecode) in module.__dict__
- module.__file__ = bytecode_path
- return module
+ return marshal.loads(bytecode), bytecode_path
except ValueError:
# XXX Does this have to be true?
# Since bad bytecode halts the import entirely, having the
@@ -315,27 +320,28 @@
# Use the source.
source = loader.get_source(name)
code_object = compile(source, source_path, 'exec')
- exec code_object in module.__dict__
- module.__file__ = source_path
# Generate bytecode and write it out.
if source_timestamp is None: # May have from bytecode verification.
source_timestamp = loader.mod_time(name)
data = marshal.dumps(code_object)
loader.write_bytecode(name, source_timestamp, data)
- return module
+ return code_object, source_path
class _PyFileLoader(object):
"""Load a Python source or bytecode file."""
- _handler = handle_py
+ _handler = handle_code
+ _module_init = init_module
# XXX Take in fullname from importer to make sure loader is not called for
# another module?
def __init__(self, name, path, is_pkg):
self._name = name
self._is_pkg = is_pkg
+ self._source_path = None
+ self._bytecode_path = None
# Figure out whether source and/or bytecode exists.
for suffix in suffix_list(imp.PY_SOURCE):
if path.endswith(suffix):
@@ -359,17 +365,10 @@
@check_name
def load_module(self, fullname):
"""Load a Python source or bytecode file."""
- if hasattr(self, '_source_path'):
- source_path = self._source_path
- else:
- source_path = None
- if hasattr(self, '_bytecode_path'):
- bytecode_path = self._bytecode_path
- else:
- bytecode_path = None
+ code_object, path = self._handler(fullname, self._source_path,
+ self._bytecode_path)
try:
- return self._handler(fullname, source_path, bytecode_path,
- self._is_pkg)
+ return self._module_init(code_object, fullname, path, self._is_pkg)
except:
# Don't leave a partially initialized module in sys.modules.
if fullname in sys.modules:
@@ -384,10 +383,10 @@
if the loader cannot handle the module.
"""
- try:
+ if self._source_path:
return int(_os.stat(self._source_path).st_mtime)
- except AttributeError:
- return ValueError('no source for %s' % name)
+ else:
+ raise ValueError('no source for %s' % name)
@check_name
def get_source(self, fullname):
@@ -397,14 +396,12 @@
Raises ImportError if the loader cannot handle the module.
"""
- try:
+ if self._source_path and _path_exists(self._source_path):
return open(self._source_path, 'U').read()
- except (IOError, AttributeError):
- if (hasattr(self, '_bytecode_path') and
- _path_exists(self._bytecode_path)):
- return None
- else:
- raise ImportError('no source or bytecode available')
+ elif self._bytecode_path and _path_exists(self._bytecode_path):
+ return None
+ else:
+ raise ImportError('no source or bytecode available')
@check_name
def get_bytecode(self, name):
@@ -432,9 +429,9 @@
cannot be handled by the loader.
"""
- try:
+ if self._bytecode_path:
bytecode_path = self._bytecode_path
- except AttributeError:
+ else:
base_path = _path_without_ext(self._source_path)
bytecode_path = base_path + suffix_list(imp.PY_COMPILED)[0]
try:
@@ -471,14 +468,7 @@
specified module.
"""
- source = self.get_source(fullname)
- if source is not None:
- return compile(source, self._source_path, 'exec')
- else:
- magic, mtime, bytecode = self.get_bytecode(fullname)
- if imp.get_magic() != magic:
- raise ImportError('no source and bytecode bad')
- return marshal.loads(bytecode)
+ return self._handler(fullname, self._source_path, self._bytecode_path)[0]
class FileImporter(object):
Modified: sandbox/trunk/import_in_py/controlled_importlib.py
==============================================================================
--- sandbox/trunk/import_in_py/controlled_importlib.py (original)
+++ sandbox/trunk/import_in_py/controlled_importlib.py Tue Aug 21 23:09:21 2007
@@ -81,10 +81,7 @@
def __init__(self, *args, **kwargs):
"""Remove the bytecode path."""
super(PyOnlyFileLoader, self).__init__(*args, **kwargs)
- try:
- del self._bytecode_path
- except AttributeError:
- pass
+ self._bytecode_path = None
def write_bytecode(self, *args, **kwargs):
"""Do not write out any bytecode."""
More information about the Python-checkins
mailing list