summaryrefslogtreecommitdiff
path: root/coverage/execfile.py
diff options
context:
space:
mode:
Diffstat (limited to 'coverage/execfile.py')
-rw-r--r--coverage/execfile.py43
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