summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.txt3
-rw-r--r--coverage/control.py4
-rw-r--r--coverage/plugin.py12
-rw-r--r--tests/test_plugins.py51
4 files changed, 63 insertions, 7 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 0883caa5..492e831c 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -38,6 +38,9 @@ Latest
- Plugins are now initialized differently. Instead of looking for a class
called ``Plugin``, coverage.py looks for a function called ``coverage_init``.
+- A file-tracing plugin can now ask to have built-in Python reporting by
+ returning `"python"` from its `file_reporter()` method.
+
- Code that was executed with `exec` would be mis-attributed to the file that
called it. This is now fixed, closing `issue 380`_.
diff --git a/coverage/control.py b/coverage/control.py
index 4396374e..4837356d 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -844,6 +844,7 @@ class Coverage(object):
def _get_file_reporter(self, morf):
"""Get a FileReporter for a module or filename."""
plugin = None
+ file_reporter = "python"
if isinstance(morf, string_class):
abs_morf = abs_file(morf)
@@ -859,7 +860,8 @@ class Coverage(object):
plugin._coverage_plugin_name, morf
)
)
- else:
+
+ if file_reporter == "python":
file_reporter = PythonFileReporter(morf, self)
return file_reporter
diff --git a/coverage/plugin.py b/coverage/plugin.py
index 62cc6dce..5b0479c3 100644
--- a/coverage/plugin.py
+++ b/coverage/plugin.py
@@ -157,18 +157,18 @@ class FileReporter(object):
# Annoying comparison operators. Py3k wants __lt__ etc, and Py2k needs all
# of them defined.
+ def __eq__(self, other):
+ return isinstance(other, FileReporter) and self.filename == other.filename
+
+ def __ne__(self, other):
+ return not (self == other)
+
def __lt__(self, other):
return self.filename < other.filename
def __le__(self, other):
return self.filename <= other.filename
- def __eq__(self, other):
- return self.filename == other.filename
-
- def __ne__(self, other):
- return self.filename != other.filename
-
def __gt__(self, other):
return self.filename > other.filename
diff --git a/tests/test_plugins.py b/tests/test_plugins.py
index 18b662f7..558c0436 100644
--- a/tests/test_plugins.py
+++ b/tests/test_plugins.py
@@ -462,6 +462,57 @@ class GoodPluginTest(FileTracerTest):
]:
self.assertIn(snip, xml)
+ def test_defer_to_python(self):
+ # A plugin that measures, but then wants built-in python reporting.
+ self.make_file("fairly_odd_plugin.py", """\
+ # A plugin that claims all the odd lines are executed, and none of
+ # the even lines, and then punts reporting off to the built-in
+ # Python reporting.
+ import coverage.plugin
+ class Plugin(coverage.CoveragePlugin):
+ def file_tracer(self, filename):
+ return OddTracer(filename)
+ def file_reporter(self, filename):
+ return "python"
+
+ class OddTracer(coverage.plugin.FileTracer):
+ def __init__(self, filename):
+ self.filename = filename
+ def source_filename(self):
+ return self.filename
+ def line_number_range(self, frame):
+ lineno = frame.f_lineno
+ if lineno % 2:
+ return (lineno, lineno)
+ else:
+ return (-1, -1)
+
+ def coverage_init(reg, options):
+ reg.add_file_tracer(Plugin())
+ """)
+ self.make_file("unsuspecting.py", """\
+ a = 1
+ b = 2
+ c = 3
+ d = 4
+ e = 5
+ f = 6
+ """)
+ cov = coverage.Coverage(include=["unsuspecting.py"])
+ cov.config["run:plugins"] = ["fairly_odd_plugin"]
+ self.start_import_stop(cov, "unsuspecting")
+
+ repout = StringIO()
+ total = cov.report(file=repout)
+ report = repout.getvalue().splitlines()
+ expected = [
+ 'Name Stmts Miss Cover Missing',
+ '-----------------------------------------------',
+ 'unsuspecting.py 6 3 50% 2, 4, 6',
+ ]
+ self.assertEqual(report, expected)
+ self.assertEqual(total, 50)
+
class BadPluginTest(FileTracerTest):
"""Test error handling around plugins."""