diff options
-rw-r--r-- | CHANGES.txt | 3 | ||||
-rw-r--r-- | coverage/control.py | 4 | ||||
-rw-r--r-- | coverage/plugin.py | 12 | ||||
-rw-r--r-- | tests/test_plugins.py | 51 |
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.""" |