diff options
Diffstat (limited to 'coverage/execfile.py')
-rw-r--r-- | coverage/execfile.py | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/coverage/execfile.py b/coverage/execfile.py index 2d856897..3e20a527 100644 --- a/coverage/execfile.py +++ b/coverage/execfile.py @@ -1,3 +1,6 @@ +# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 +# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt + """Execute files of Python code.""" import marshal @@ -7,9 +10,12 @@ import types from coverage.backward import BUILTINS from coverage.backward import PYC_MAGIC_NUMBER, imp, importlib_util_find_spec -from coverage.misc import ExceptionDuringRun, NoCode, NoSource +from coverage.misc import ExceptionDuringRun, NoCode, NoSource, isolate_module +from coverage.phystokens import compile_unicode from coverage.python import get_python_source +os = isolate_module(os) + class DummyLoader(object): """A shim for the pep302 __loader__, emulating pkgutil.ImpLoader. @@ -35,7 +41,7 @@ if importlib_util_find_spec: raise NoSource("No module named %r" % (modulename,)) pathname = spec.origin packagename = spec.name - if pathname.endswith("__init__.py"): + if pathname.endswith("__init__.py") and not modulename.endswith("__init__"): mod_main = modulename + ".__main__" spec = importlib_util_find_spec(mod_main) if not spec: @@ -104,10 +110,10 @@ def run_python_module(modulename, args): pathname = os.path.abspath(pathname) args[0] = pathname - run_python_file(pathname, args, package=packagename, modulename=modulename) + run_python_file(pathname, args, package=packagename, modulename=modulename, path0="") -def run_python_file(filename, args, package=None, modulename=None): +def run_python_file(filename, args, package=None, modulename=None, path0=None): """Run a Python file as if it were the main program on the command line. `filename` is the path to the file to execute, it need not be a .py file. @@ -117,6 +123,9 @@ def run_python_file(filename, args, package=None, modulename=None): `modulename` is the name of the module the file was run as. + `path0` is the value to put into sys.path[0]. If it's None, then this + function will decide on a value. + """ if modulename is None and sys.version_info >= (3, 3): modulename = '__main__' @@ -137,6 +146,25 @@ def run_python_file(filename, args, package=None, modulename=None): old_argv = sys.argv sys.argv = args + if os.path.isdir(filename): + # Running a directory means running the __main__.py file in that + # directory. + my_path0 = filename + + for ext in [".py", ".pyc", ".pyo"]: + try_filename = os.path.join(filename, "__main__" + ext) + if os.path.exists(try_filename): + filename = try_filename + break + else: + raise NoSource("Can't find '__main__' module in '%s'" % filename) + else: + my_path0 = os.path.abspath(os.path.dirname(filename)) + + # Set sys.path correctly. + old_path0 = sys.path[0] + sys.path[0] = path0 if path0 is not None else my_path0 + try: # Make a code object somehow. if filename.endswith((".pyc", ".pyo")): @@ -167,11 +195,10 @@ def run_python_file(filename, args, package=None, modulename=None): raise ExceptionDuringRun(typ, err, tb.tb_next) finally: - # Restore the old __main__ + # Restore the old __main__, argv, and path. sys.modules['__main__'] = old_main_mod - - # Restore the old argv and path sys.argv = old_argv + sys.path[0] = old_path0 def make_code_from_py(filename): @@ -182,7 +209,7 @@ def make_code_from_py(filename): except (IOError, NoSource): raise NoSource("No file to run: '%s'" % filename) - code = compile(source, filename, "exec") + code = compile_unicode(source, filename, "exec") return code |