diff options
author | Benjamin Peterson <benjamin@python.org> | 2012-10-12 12:04:32 -0400 |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2012-10-12 12:04:32 -0400 |
commit | 22bb42e43c74ca9f882d3ade8e5e47a884788e73 (patch) | |
tree | 4aa46f808b18a4ef41ec674982e8e44d36ceb508 /Lib/runpy.py | |
parent | 0cd22c598b57b4107e90a0b4cde98c21f6a803d9 (diff) | |
parent | d51b506754163bc7fbccb1c1f58d8dd849c18dad (diff) | |
download | cpython-22bb42e43c74ca9f882d3ade8e5e47a884788e73.tar.gz |
merge 3.2
Diffstat (limited to 'Lib/runpy.py')
-rw-r--r-- | Lib/runpy.py | 72 |
1 files changed, 22 insertions, 50 deletions
diff --git a/Lib/runpy.py b/Lib/runpy.py index 7cb4668a01..39c0e9f7dd 100644 --- a/Lib/runpy.py +++ b/Lib/runpy.py @@ -9,13 +9,12 @@ importers when locating support scripts as well as when importing modules. # Written by Nick Coghlan <ncoghlan at gmail.com> # to implement PEP 338 (Executing Modules as Scripts) + +import os import sys +import importlib.machinery # importlib first so we can test #15386 via -m import imp -from pkgutil import read_code -try: - from imp import get_loader -except ImportError: - from pkgutil import get_loader +from pkgutil import read_code, get_loader, get_importer __all__ = [ "run_module", "run_path", @@ -95,7 +94,7 @@ def _get_filename(loader, mod_name): for attr in ("get_filename", "_get_filename"): meth = getattr(loader, attr, None) if meth is not None: - return meth(mod_name) + return os.path.abspath(meth(mod_name)) return None # Helper to get the loader, code and filename for a module @@ -181,47 +180,23 @@ def run_module(mod_name, init_globals=None, def _get_main_module_details(): # Helper that gives a nicer error message when attempting to # execute a zipfile or directory by invoking __main__.py + # Also moves the standard __main__ out of the way so that the + # preexisting __loader__ entry doesn't cause issues main_name = "__main__" + saved_main = sys.modules[main_name] + del sys.modules[main_name] try: return _get_module_details(main_name) except ImportError as exc: if main_name in str(exc): raise ImportError("can't find %r module in %r" % - (main_name, sys.path[0])) + (main_name, sys.path[0])) from exc raise + finally: + sys.modules[main_name] = saved_main -# XXX (ncoghlan): Perhaps expose the C API function -# as imp.get_importer instead of reimplementing it in Python? -def _get_importer(path_name): - """Python version of PyImport_GetImporter C API function""" - cache = sys.path_importer_cache - try: - importer = cache[path_name] - except KeyError: - # Not yet cached. Flag as using the - # standard machinery until we finish - # checking the hooks - cache[path_name] = None - for hook in sys.path_hooks: - try: - importer = hook(path_name) - break - except ImportError: - pass - else: - # The following check looks a bit odd. The trick is that - # NullImporter throws ImportError if the supplied path is a - # *valid* directory entry (and hence able to be handled - # by the standard import machinery) - try: - importer = imp.NullImporter(path_name) - except ImportError: - return None - cache[path_name] = importer - return importer - -def _get_code_from_file(fname): +def _get_code_from_file(run_name, fname): # Check for a compiled file first with open(fname, "rb") as f: code = read_code(f) @@ -229,7 +204,10 @@ def _get_code_from_file(fname): # That didn't work, so try it as normal source code with open(fname, "rb") as f: code = compile(f.read(), fname, 'exec') - return code + loader = importlib.machinery.SourceFileLoader(run_name, fname) + else: + loader = importlib.machinery.SourcelessFileLoader(run_name, fname) + return code, loader def run_path(path_name, init_globals=None, run_name=None): """Execute code located at the specified filesystem location @@ -244,13 +222,13 @@ def run_path(path_name, init_globals=None, run_name=None): if run_name is None: run_name = "<run_path>" pkg_name = run_name.rpartition(".")[0] - importer = _get_importer(path_name) - if isinstance(importer, imp.NullImporter): + importer = get_importer(path_name) + if isinstance(importer, (type(None), imp.NullImporter)): # Not a valid sys.path entry, so run the code directly # execfile() doesn't help as we want to allow compiled files - code = _get_code_from_file(path_name) + code, mod_loader = _get_code_from_file(run_name, path_name) return _run_module_code(code, init_globals, run_name, path_name, - pkg_name=pkg_name) + mod_loader, pkg_name) else: # Importer is defined for path, so add it to # the start of sys.path @@ -262,13 +240,7 @@ def run_path(path_name, init_globals=None, run_name=None): # have no choice and we have to remove it even while we read the # code. If we don't do this, a __loader__ attribute in the # existing __main__ module may prevent location of the new module. - main_name = "__main__" - saved_main = sys.modules[main_name] - del sys.modules[main_name] - try: - mod_name, loader, code, fname = _get_main_module_details() - finally: - sys.modules[main_name] = saved_main + mod_name, loader, code, fname = _get_main_module_details() with _TempModule(run_name) as temp_module, \ _ModifiedArgv0(path_name): mod_globals = temp_module.module.__dict__ |