summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt10
-rw-r--r--coverage/cmdline.py13
-rw-r--r--coverage/control.py6
-rw-r--r--coverage/execfile.py9
-rw-r--r--tests/test_api.py12
-rw-r--r--tests/test_process.py43
6 files changed, 68 insertions, 25 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 82b1b84f..48876c18 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -7,12 +7,22 @@ Change history for Coverage.py
- Improved the branch coverage mechanism, fixing `issue 175`_.
+- Running code with ``coverage run -m`` now behaves more like Python does,
+ setting sys.path properly, which fixes `issue 207`_ and `issue 242`_.
+
+- Omitting files within a tree specified with the ``source`` option would
+ cause them to be incorrectly marked as unexecuted, as described in
+ `issue 218`_. This is now fixed.
+
- When running a threaded program under the Python tracer, coverage would issue
a spurious warning about the trace function changing: "Trace function
changed, measurement is likely wrong: None." This is now fixed.
.. _issue 164: https://bitbucket.org/ned/coveragepy/issue/164/trace-function-changed-warning-when-using
.. _issue 175: https://bitbucket.org/ned/coveragepy/issue/175/branch-coverage-gets-confused-in-certain
+.. _issue 207: https://bitbucket.org/ned/coveragepy/issue/207/run-m-cannot-find-module-or-package-in
+.. _issue 242: https://bitbucket.org/ned/coveragepy/issue/242/running-a-two-level-package-doesnt-work
+.. _issue 218: https://bitbucket.org/ned/coveragepy/issue/218/run-command-does-not-respect-the-omit-flag
Version 3.6 --- 5 January 2013
diff --git a/coverage/cmdline.py b/coverage/cmdline.py
index cb1d7a3e..ac803109 100644
--- a/coverage/cmdline.py
+++ b/coverage/cmdline.py
@@ -1,6 +1,6 @@
"""Command-line support for Coverage."""
-import optparse, sys, traceback
+import optparse, os, sys, traceback
from coverage.backward import sorted # pylint: disable=W0622
from coverage.execfile import run_python_file, run_python_module
@@ -549,15 +549,21 @@ class CoverageScript(object):
def do_execute(self, options, args):
"""Implementation of 'coverage run'."""
+ # Set the first path element properly.
+ old_path0 = sys.path[0]
+
# Run the script.
self.coverage.start()
code_ran = True
try:
try:
if options.module:
+ sys.path[0] = ''
self.run_python_module(args[0], args)
else:
- self.run_python_file(args[0], args)
+ filename = args[0]
+ sys.path[0] = os.path.abspath(os.path.dirname(filename))
+ self.run_python_file(filename, args)
except NoSource:
code_ran = False
raise
@@ -566,6 +572,9 @@ class CoverageScript(object):
if code_ran:
self.coverage.save()
+ # Restore the old path
+ sys.path[0] = old_path0
+
def do_debug(self, args):
"""Implementation of 'coverage debug'."""
diff --git a/coverage/control.py b/coverage/control.py
index afb61370..09bd75fc 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -499,6 +499,12 @@ class coverage(object):
for src in self.source:
for py_file in find_python_files(src):
py_file = self.file_locator.canonical_filename(py_file)
+
+ if self.omit_match and self.omit_match.match(py_file):
+ # Turns out this file was omitted, so don't pull it
+ # back in as unexecuted.
+ continue
+
self.data.touch_file(py_file)
self._measured = False
diff --git a/coverage/execfile.py b/coverage/execfile.py
index 587c2d3c..fbb49b2a 100644
--- a/coverage/execfile.py
+++ b/coverage/execfile.py
@@ -65,6 +65,7 @@ def run_python_module(modulename, args):
openfile.close()
# Finally, hand the file off to run_python_file for execution.
+ pathname = os.path.abspath(pathname)
args[0] = pathname
run_python_file(pathname, args, package=packagename)
@@ -87,14 +88,9 @@ def run_python_file(filename, args, package=None):
main_mod.__package__ = package
main_mod.__builtins__ = BUILTINS
- # Set sys.argv and the first path element properly.
+ # Set sys.argv properly.
old_argv = sys.argv
- old_path0 = sys.path[0]
sys.argv = args
- if package:
- sys.path[0] = ''
- else:
- sys.path[0] = os.path.abspath(os.path.dirname(filename))
try:
# Open the source file.
@@ -135,4 +131,3 @@ def run_python_file(filename, args, package=None):
# Restore the old argv and path
sys.argv = old_argv
- sys.path[0] = old_path0
diff --git a/tests/test_api.py b/tests/test_api.py
index 300a2374..097947d2 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -430,7 +430,7 @@ class OmitIncludeTestsMixin(UsingModulesMixin):
self.filenames_not_in(result, "p1a p1c p2a othera osa")
def test_omit_and_include(self):
- result = self.coverage_usepkgs( include=["*/p1*"], omit=["*/p1a.py"])
+ result = self.coverage_usepkgs(include=["*/p1*"], omit=["*/p1a.py"])
self.filenames_in(result, "p1b")
self.filenames_not_in(result, "p1a p1c p2a p2b")
@@ -467,6 +467,16 @@ class SourceOmitIncludeTest(OmitIncludeTestsMixin, CoverageTest):
self.filenames_in(lines, "p1b")
self.filenames_not_in(lines, "p1a p1c p2a p2b othera otherb osa osb")
+ def test_source_package_part_omitted(self):
+ # https://bitbucket.org/ned/coveragepy/issue/218
+ # Used to be if you omitted something executed and inside the source,
+ # then after it was executed but not recorded, it would be found in
+ # the search for unexecuted files, and given a score of 0%.
+ lines = self.coverage_usepkgs(source=["pkg1"], omit=["pkg1/p1b.py"])
+ self.filenames_in(lines, "p1a")
+ self.filenames_not_in(lines, "p1b")
+ self.assertEqual(lines['p1c'], 0)
+
class ReportIncludeOmitTest(OmitIncludeTestsMixin, CoverageTest):
"""Tests of the report include/omit functionality."""
diff --git a/tests/test_process.py b/tests/test_process.py
index 8e31bd18..8554eb54 100644
--- a/tests/test_process.py
+++ b/tests/test_process.py
@@ -320,25 +320,38 @@ class ProcessTest(CoverageTest):
def test_coverage_run_is_like_python(self):
tryfile = os.path.join(here, "try_execfile.py")
self.make_file("run_me.py", open(tryfile).read())
- out = self.run_command("coverage run run_me.py")
- out2 = self.run_command("python run_me.py")
- self.assertMultiLineEqual(out, out2)
+ out_cov = self.run_command("coverage run run_me.py")
+ out_py = self.run_command("python run_me.py")
+ self.assertMultiLineEqual(out_cov, out_py)
- if sys.version_info >= (2, 6): # Doesn't work in 2.5, and I don't care!
+ if sys.version_info >= (2, 6):
+ # Doesn't work in 2.5, and I don't care! For some reason, python -m
+ # in 2.5 has __builtins__ as a dictionary instead of a module?
def test_coverage_run_dashm_is_like_python_dashm(self):
# These -m commands assume the coverage tree is on the path.
- out = self.run_command("coverage run -m tests.try_execfile")
- out2 = self.run_command("python -m tests.try_execfile")
- self.assertMultiLineEqual(out, out2)
-
- if 0: # Expected failure
- # For https://bitbucket.org/ned/coveragepy/issue/207
+ out_cov = self.run_command("coverage run -m tests.try_execfile")
+ out_py = self.run_command("python -m tests.try_execfile")
+ self.assertMultiLineEqual(out_cov, out_py)
+
+ def test_coverage_run_dashm_is_like_python_dashm_off_path(self):
+ # https://bitbucket.org/ned/coveragepy/issue/242
+ tryfile = os.path.join(here, "try_execfile.py")
+ self.make_file("sub/__init__.py", "")
+ self.make_file("sub/run_me.py", open(tryfile).read())
+ out_cov = self.run_command("coverage run -m sub.run_me")
+ out_py = self.run_command("python -m sub.run_me")
+ self.assertMultiLineEqual(out_cov, out_py)
+
+ if sys.version_info >= (2, 7):
+ # Coverage isn't bug-for-bug compatible in the behavior of -m for
+ # Pythons < 2.7
def test_coverage_run_dashm_is_like_python_dashm_with__main__207(self):
- self.make_file("package/__init__.py") # empty
- self.make_file("package/__main__.py", "#\n") # empty
- out = self.run_command("coverage run -m package")
- out2 = self.run_command("python -m package")
- self.assertMultiLineEqual(out, out2)
+ # https://bitbucket.org/ned/coveragepy/issue/207
+ self.make_file("package/__init__.py", "print('init')")
+ self.make_file("package/__main__.py", "print('main')")
+ out_cov = self.run_command("coverage run -m package")
+ out_py = self.run_command("python -m package")
+ self.assertMultiLineEqual(out_cov, out_py)
if hasattr(os, 'fork'):
def test_fork(self):