summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2016-12-17 16:14:58 -0500
committerNed Batchelder <ned@nedbatchelder.com>2016-12-17 16:14:58 -0500
commit3f320139291a93beccea0089c5a843c1e38bd356 (patch)
treef096c09fcd54ccf8e475cb967b08a2b3d23d2465
parent51ee731f82f2e562741d91e930bb59358bc64805 (diff)
downloadpython-coveragepy-git-3f320139291a93beccea0089c5a843c1e38bd356.tar.gz
Provide a more useful error message if failing to run a non-Python file. #514
-rw-r--r--CHANGES.rst4
-rw-r--r--CONTRIBUTORS.txt1
-rw-r--r--coverage/execfile.py18
-rw-r--r--tests/test_execfile.py19
4 files changed, 36 insertions, 6 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 1c40c2e2..4c6ba6d8 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -55,6 +55,9 @@ Unreleased
- Fixed an unusual bug involving multiple coding declarations affecting code
containing code in multi-line strings: `issue 529`_.
+- If you try to run a non-Python file with coverage.py, you will now get a more
+ useful error message. `Issue 514`_.
+
- The default pragma regex changed slightly, but this will only matter to you
if you are deranged and use mixed-case pragmas.
@@ -80,6 +83,7 @@ Unreleased
.. _issue 265: https://bitbucket.org/ned/coveragepy/issues/265/when-using-source-include-is-silently
.. _issue 412: https://bitbucket.org/ned/coveragepy/issues/412/coverage-combine-should-error-if-no
.. _issue 505: https://bitbucket.org/ned/coveragepy/issues/505/use-canonical-filename-for-debounce
+.. _issue 514: https://bitbucket.org/ned/coveragepy/issues/514/path-to-problem-file-not-reported-when
.. _issue 510: https://bitbucket.org/ned/coveragepy/issues/510/erase-still-needed-in-42
.. _issue 511: https://bitbucket.org/ned/coveragepy/issues/511/version-42-coverage-combine-empties
.. _issue 516: https://bitbucket.org/ned/coveragepy/issues/516/running-coverage-combine-twice-deletes-all
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index 36db14bb..60d43ef3 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -17,6 +17,7 @@ Calen Pennington
Carl Gieringer
Catherine Proulx
Chris Adams
+Chris Jerdonek
Chris Rose
Christian Heimes
Christine Lytwynec
diff --git a/coverage/execfile.py b/coverage/execfile.py
index 3e20a527..58b05402 100644
--- a/coverage/execfile.py
+++ b/coverage/execfile.py
@@ -10,7 +10,7 @@ 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, isolate_module
+from coverage.misc import CoverageException, ExceptionDuringRun, NoCode, NoSource, isolate_module
from coverage.phystokens import compile_unicode
from coverage.python import get_python_source
@@ -166,11 +166,17 @@ def run_python_file(filename, args, package=None, modulename=None, path0=None):
sys.path[0] = path0 if path0 is not None else my_path0
try:
- # Make a code object somehow.
- if filename.endswith((".pyc", ".pyo")):
- code = make_code_from_pyc(filename)
- else:
- code = make_code_from_py(filename)
+ try:
+ # Make a code object somehow.
+ if filename.endswith((".pyc", ".pyo")):
+ code = make_code_from_pyc(filename)
+ else:
+ code = make_code_from_py(filename)
+ except CoverageException:
+ raise
+ except Exception as exc:
+ msg = "Couldn't run {filename!r} as Python code: {exc.__class__.__name__}: {exc}"
+ raise CoverageException(msg.format(filename=filename, exc=exc))
# Execute the code object.
try:
diff --git a/tests/test_execfile.py b/tests/test_execfile.py
index 889d6cfd..8585b16d 100644
--- a/tests/test_execfile.py
+++ b/tests/test_execfile.py
@@ -145,6 +145,25 @@ class RunPycFileTest(CoverageTest):
with self.assertRaisesRegex(NoCode, "No file to run: 'xyzzy.pyc'"):
run_python_file("xyzzy.pyc", [])
+ def test_running_py_from_binary(self):
+ # Use make_file to get the bookkeeping. Ideally, it would
+ # be able to write binary files.
+ bf = self.make_file("binary")
+ with open(bf, "wb") as f:
+ f.write(b'\x7fELF\x02\x01\x01\x00\x00\x00')
+
+ msg = (
+ r"Couldn't run 'binary' as Python code: "
+ r"(TypeError|ValueError): "
+ r"("
+ r"compile\(\) expected string without null bytes" # for py2
+ r"|"
+ r"source code string cannot contain null bytes" # for py3
+ r")"
+ )
+ with self.assertRaisesRegex(Exception, msg):
+ run_python_file(bf, [bf])
+
class RunModuleTest(CoverageTest):
"""Test run_python_module."""