diff options
author | Thomas Wouters <thomas@python.org> | 2006-04-21 10:40:58 (GMT) |
---|---|---|
committer | Thomas Wouters <thomas@python.org> | 2006-04-21 10:40:58 (GMT) |
commit | 49fd7fa4431da299196d74087df4a04f99f9c46f (patch) | |
tree | 35ace5fe78d3d52c7a9ab356ab9f6dbf8d4b71f4 /Lib/runpy.py | |
parent | 9ada3d6e29d5165dadacbe6be07bcd35cfbef59d (diff) | |
download | cpython-49fd7fa4431da299196d74087df4a04f99f9c46f.zip cpython-49fd7fa4431da299196d74087df4a04f99f9c46f.tar.gz cpython-49fd7fa4431da299196d74087df4a04f99f9c46f.tar.bz2 |
Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
number of tests, all because of the codecs/_multibytecodecs issue described
here (it's not a Py3K issue, just something Py3K discovers):
http://mail.python.org/pipermail/python-dev/2006-April/064051.html
Hye-Shik Chang promised to look for a fix, so no need to fix it here. The
tests that are expected to break are:
test_codecencodings_cn
test_codecencodings_hk
test_codecencodings_jp
test_codecencodings_kr
test_codecencodings_tw
test_codecs
test_multibytecodec
This merge fixes an actual test failure (test_weakref) in this branch,
though, so I believe merging is the right thing to do anyway.
Diffstat (limited to 'Lib/runpy.py')
-rwxr-xr-x | Lib/runpy.py | 377 |
1 files changed, 25 insertions, 352 deletions
diff --git a/Lib/runpy.py b/Lib/runpy.py index afb0098..8290dfe 100755 --- a/Lib/runpy.py +++ b/Lib/runpy.py @@ -11,349 +11,15 @@ importers when locating support scripts as well as when importing modules. import sys import imp +try: + from imp import get_loader +except ImportError: + from pkgutil import get_loader __all__ = [ "run_module", ] -try: - _get_loader = imp.get_loader -except AttributeError: - # get_loader() is not provided by the imp module, so emulate it - # as best we can using the PEP 302 import machinery exposed since - # Python 2.3. The emulation isn't perfect, but the differences - # in the way names are shadowed shouldn't matter in practice. - import os.path - import marshal # Handle compiled Python files - - # This helper is needed in order for the PEP 302 emulation to - # correctly handle compiled files - def _read_compiled_file(compiled_file): - magic = compiled_file.read(4) - if magic != imp.get_magic(): - return None - try: - compiled_file.read(4) # Skip timestamp - return marshal.load(compiled_file) - except Exception: - return None - - class _AbsoluteImporter(object): - """PEP 302 importer wrapper for top level import machinery""" - def find_module(self, mod_name, path=None): - if path is not None: - return None - try: - file, filename, mod_info = imp.find_module(mod_name) - except ImportError: - return None - suffix, mode, mod_type = mod_info - if mod_type == imp.PY_SOURCE: - loader = _SourceFileLoader(mod_name, file, - filename, mod_info) - elif mod_type == imp.PY_COMPILED: - loader = _CompiledFileLoader(mod_name, file, - filename, mod_info) - elif mod_type == imp.PKG_DIRECTORY: - loader = _PackageDirLoader(mod_name, file, - filename, mod_info) - elif mod_type == imp.C_EXTENSION: - loader = _FileSystemLoader(mod_name, file, - filename, mod_info) - else: - loader = _BasicLoader(mod_name, file, - filename, mod_info) - return loader - - - class _FileSystemImporter(object): - """PEP 302 importer wrapper for filesystem based imports""" - def __init__(self, path_item=None): - if path_item is not None: - if path_item != '' and not os.path.isdir(path_item): - raise ImportError("%s is not a directory" % path_item) - self.path_dir = path_item - else: - raise ImportError("Filesystem importer requires " - "a directory name") - - def find_module(self, mod_name, path=None): - if path is not None: - return None - path_dir = self.path_dir - if path_dir == '': - path_dir = os.getcwd() - sub_name = mod_name.rsplit(".", 1)[-1] - try: - file, filename, mod_info = imp.find_module(sub_name, - [path_dir]) - except ImportError: - return None - if not filename.startswith(path_dir): - return None - suffix, mode, mod_type = mod_info - if mod_type == imp.PY_SOURCE: - loader = _SourceFileLoader(mod_name, file, - filename, mod_info) - elif mod_type == imp.PY_COMPILED: - loader = _CompiledFileLoader(mod_name, file, - filename, mod_info) - elif mod_type == imp.PKG_DIRECTORY: - loader = _PackageDirLoader(mod_name, file, - filename, mod_info) - elif mod_type == imp.C_EXTENSION: - loader = _FileSystemLoader(mod_name, file, - filename, mod_info) - else: - loader = _BasicLoader(mod_name, file, - filename, mod_info) - return loader - - - class _BasicLoader(object): - """PEP 302 loader wrapper for top level import machinery""" - def __init__(self, mod_name, file, filename, mod_info): - self.mod_name = mod_name - self.file = file - self.filename = filename - self.mod_info = mod_info - - def _fix_name(self, mod_name): - if mod_name is None: - mod_name = self.mod_name - elif mod_name != self.mod_name: - raise ImportError("Loader for module %s cannot handle " - "module %s" % (self.mod_name, mod_name)) - return mod_name - - def load_module(self, mod_name=None): - mod_name = self._fix_name(mod_name) - mod = imp.load_module(mod_name, self.file, - self.filename, self.mod_info) - mod.__loader__ = self # for introspection - return mod - - def get_code(self, mod_name=None): - return None - - def get_source(self, mod_name=None): - return None - - def is_package(self, mod_name=None): - return False - - def close(self): - if self.file: - self.file.close() - - def __del__(self): - self.close() - - - class _FileSystemLoader(_BasicLoader): - """PEP 302 loader wrapper for filesystem based imports""" - def get_code(self, mod_name=None): - mod_name = self._fix_name(mod_name) - return self._get_code(mod_name) - - def get_data(self, pathname): - return open(pathname, "rb").read() - - def get_filename(self, mod_name=None): - mod_name = self._fix_name(mod_name) - return self._get_filename(mod_name) - - def get_source(self, mod_name=None): - mod_name = self._fix_name(mod_name) - return self._get_source(mod_name) - - def is_package(self, mod_name=None): - mod_name = self._fix_name(mod_name) - return self._is_package(mod_name) - - def _get_code(self, mod_name): - return None - - def _get_filename(self, mod_name): - return self.filename - - def _get_source(self, mod_name): - return None - - def _is_package(self, mod_name): - return False - - class _PackageDirLoader(_FileSystemLoader): - """PEP 302 loader wrapper for PKG_DIRECTORY directories""" - def _is_package(self, mod_name): - return True - - - class _SourceFileLoader(_FileSystemLoader): - """PEP 302 loader wrapper for PY_SOURCE modules""" - def _get_code(self, mod_name): - return compile(self._get_source(mod_name), - self.filename, 'exec') - - def _get_source(self, mod_name): - f = self.file - f.seek(0) - return f.read() - - - class _CompiledFileLoader(_FileSystemLoader): - """PEP 302 loader wrapper for PY_COMPILED modules""" - def _get_code(self, mod_name): - f = self.file - f.seek(0) - return _read_compiled_file(f) - - - def _get_importer(path_item): - """Retrieve a PEP 302 importer for the given path item - - The returned importer is cached in sys.path_importer_cache - if it was newly created by a path hook. - - If there is no importer, a wrapper around the basic import - machinery is returned. This wrapper is never inserted into - the importer cache (None is inserted instead). - - The cache (or part of it) can be cleared manually if a - rescan of sys.path_hooks is necessary. - """ - try: - importer = sys.path_importer_cache[path_item] - except KeyError: - for path_hook in sys.path_hooks: - try: - importer = path_hook(path_item) - break - except ImportError: - pass - else: - importer = None - sys.path_importer_cache[path_item] = importer - if importer is None: - try: - importer = _FileSystemImporter(path_item) - except ImportError: - pass - return importer - - - def _get_path_loader(mod_name, path=None): - """Retrieve a PEP 302 loader using a path importer""" - if path is None: - path = sys.path - absolute_loader = _AbsoluteImporter().find_module(mod_name) - if isinstance(absolute_loader, _FileSystemLoader): - # Found in filesystem, so scan path hooks - # before accepting this one as the right one - loader = None - else: - # Not found in filesystem, so use top-level loader - loader = absolute_loader - else: - loader = absolute_loader = None - if loader is None: - for path_item in path: - importer = _get_importer(path_item) - if importer is not None: - loader = importer.find_module(mod_name) - if loader is not None: - # Found a loader for our module - break - else: - # No path hook found, so accept the top level loader - loader = absolute_loader - return loader - - def _get_package(pkg_name): - """Retrieve a named package""" - pkg = __import__(pkg_name) - sub_pkg_names = pkg_name.split(".") - for sub_pkg in sub_pkg_names[1:]: - pkg = getattr(pkg, sub_pkg) - return pkg - - def _get_loader(mod_name, path=None): - """Retrieve a PEP 302 loader for the given module or package - - If the module or package is accessible via the normal import - mechanism, a wrapper around the relevant part of that machinery - is returned. - - Non PEP 302 mechanisms (e.g. the Windows registry) used by the - standard import machinery to find files in alternative locations - are partially supported, but are searched AFTER sys.path. Normally, - these locations are searched BEFORE sys.path, preventing sys.path - entries from shadowing them. - For this to cause a visible difference in behaviour, there must - be a module or package name that is accessible via both sys.path - and one of the non PEP 302 file system mechanisms. In this case, - the emulation will find the former version, while the builtin - import mechanism will find the latter. - Items of the following types can be affected by this discrepancy: - imp.C_EXTENSION - imp.PY_SOURCE - imp.PY_COMPILED - imp.PKG_DIRECTORY - """ - try: - loader = sys.modules[mod_name].__loader__ - except (KeyError, AttributeError): - loader = None - if loader is None: - imp.acquire_lock() - try: - # Module not in sys.modules, or uses an unhooked loader - parts = mod_name.rsplit(".", 1) - if len(parts) == 2: - # Sub package, so use parent package's path - pkg_name, sub_name = parts - if pkg_name and pkg_name[0] != '.': - if path is not None: - raise ImportError("Path argument must be None " - "for a dotted module name") - pkg = _get_package(pkg_name) - try: - path = pkg.__path__ - except AttributeError: - raise ImportError(pkg_name + - " is not a package") - else: - raise ImportError("Relative import syntax is not " - "supported by _get_loader()") - else: - # Top level module, so stick with default path - sub_name = mod_name - - for importer in sys.meta_path: - loader = importer.find_module(mod_name, path) - if loader is not None: - # Found a metahook to handle the module - break - else: - # Handling via the standard path mechanism - loader = _get_path_loader(mod_name, path) - finally: - imp.release_lock() - return loader - - -# This helper is needed due to a missing component in the PEP 302 -# loader protocol (specifically, "get_filename" is non-standard) -def _get_filename(loader, mod_name): - try: - get_filename = loader.get_filename - except AttributeError: - return None - else: - return get_filename(mod_name) - -# ------------------------------------------------------------ -# Done with the import machinery emulation, on with the code! def _run_code(code, run_globals, init_globals, mod_name, mod_fname, mod_loader): @@ -379,21 +45,17 @@ def _run_module_code(code, init_globals=None, restore_module = mod_name in sys.modules if restore_module: saved_module = sys.modules[mod_name] - imp.acquire_lock() + sys.argv[0] = mod_fname + sys.modules[mod_name] = temp_module try: - sys.argv[0] = mod_fname - sys.modules[mod_name] = temp_module - try: - _run_code(code, mod_globals, init_globals, - mod_name, mod_fname, mod_loader) - finally: - sys.argv[0] = saved_argv0 - if restore_module: - sys.modules[mod_name] = saved_module - else: - del sys.modules[mod_name] + _run_code(code, mod_globals, init_globals, + mod_name, mod_fname, mod_loader) finally: - imp.release_lock() + sys.argv[0] = saved_argv0 + if restore_module: + sys.modules[mod_name] = saved_module + else: + del sys.modules[mod_name] # Copy the globals of the temporary module, as they # may be cleared when the temporary module goes away return mod_globals.copy() @@ -403,13 +65,24 @@ def _run_module_code(code, init_globals=None, mod_name, mod_fname, mod_loader) +# This helper is needed due to a missing component in the PEP 302 +# loader protocol (specifically, "get_filename" is non-standard) +def _get_filename(loader, mod_name): + try: + get_filename = loader.get_filename + except AttributeError: + return None + else: + return get_filename(mod_name) + + def run_module(mod_name, init_globals=None, run_name=None, alter_sys=False): """Execute a module's code without importing it Returns the resulting top level namespace dictionary """ - loader = _get_loader(mod_name) + loader = get_loader(mod_name) if loader is None: raise ImportError("No module named " + mod_name) code = loader.get_code(mod_name) |