summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2019-06-16 17:00:16 -0400
committerNed Batchelder <ned@nedbatchelder.com>2019-06-16 17:00:16 -0400
commit237ac7a9518d6764a4af5a203d7e07caa7f5891a (patch)
treeb8b7eddd93241fcd11c6f72ae17838da61cdb6bd
parent3a04a88e88a92882ef92cf6778e42eaf3d4001f4 (diff)
downloadpython-coveragepy-git-237ac7a9518d6764a4af5a203d7e07caa7f5891a.tar.gz
Get rid of Reporter base class
-rw-r--r--coverage/annotate.py10
-rw-r--r--coverage/html.py12
-rw-r--r--coverage/report.py122
-rw-r--r--coverage/summary.py10
-rw-r--r--coverage/xmlreport.py10
5 files changed, 67 insertions, 97 deletions
diff --git a/coverage/annotate.py b/coverage/annotate.py
index 3380dccc..35b21360 100644
--- a/coverage/annotate.py
+++ b/coverage/annotate.py
@@ -9,12 +9,12 @@ import re
from coverage.files import flat_rootname
from coverage.misc import ensure_dir, isolate_module
-from coverage.report import Reporter
+from coverage.report import get_analysis_to_report
os = isolate_module(os)
-class AnnotateReporter(Reporter):
+class AnnotateReporter(object):
"""Generate annotated source files showing line coverage.
This reporter creates annotated copies of the measured source files. Each
@@ -37,7 +37,8 @@ class AnnotateReporter(Reporter):
"""
def __init__(self, coverage, config):
- super(AnnotateReporter, self).__init__(coverage, config)
+ self.coverage = coverage
+ self.config = config
self.directory = None
blank_re = re.compile(r"\s*(#|$)")
@@ -51,7 +52,8 @@ class AnnotateReporter(Reporter):
"""
self.directory = directory
self.coverage.get_data()
- self.report_files(self.annotate_file, morfs)
+ for fr, analysis in get_analysis_to_report(self.coverage, self.config, morfs):
+ self.annotate_file(fr, analysis)
def annotate_file(self, fr, analysis):
"""Annotate a single file.
diff --git a/coverage/html.py b/coverage/html.py
index 629f7d6a..627a19a0 100644
--- a/coverage/html.py
+++ b/coverage/html.py
@@ -16,7 +16,7 @@ from coverage.backward import iitems
from coverage.data import add_data_to_hash
from coverage.files import flat_rootname
from coverage.misc import CoverageException, ensure_dir, file_be_gone, Hasher, isolate_module
-from coverage.report import Reporter
+from coverage.report import get_analysis_to_report
from coverage.results import Numbers
from coverage.templite import Templite
@@ -74,7 +74,7 @@ def write_html(fname, html):
fout.write(html.encode('ascii', 'xmlcharrefreplace'))
-class HtmlReporter(Reporter):
+class HtmlReporter(object):
"""HTML reporting."""
# These files will be copied from the htmlfiles directory to the output
@@ -92,7 +92,8 @@ class HtmlReporter(Reporter):
]
def __init__(self, cov, config):
- super(HtmlReporter, self).__init__(cov, config)
+ self.coverage = cov
+ self.config = config
self.directory = None
title = self.config.html_title
if env.PY2:
@@ -108,7 +109,7 @@ class HtmlReporter(Reporter):
self.pyfile_html_source = read_data("pyfile.html")
self.source_tmpl = Templite(self.pyfile_html_source, self.template_globals)
- self.data = cov.get_data()
+ self.data = self.coverage.get_data()
self.files = []
self.all_files_nums = []
@@ -146,7 +147,8 @@ class HtmlReporter(Reporter):
# Process all the files.
self.coverage.get_data().set_query_contexts(self.config.query_contexts)
- self.report_files(self.html_file, morfs)
+ for fr, analysis in get_analysis_to_report(self.coverage, self.config, morfs):
+ self.html_file(fr, analysis)
if not self.all_files_nums:
raise CoverageException("No data to report.")
diff --git a/coverage/report.py b/coverage/report.py
index 2675cf0f..2c2e0198 100644
--- a/coverage/report.py
+++ b/coverage/report.py
@@ -3,85 +3,47 @@
"""Reporter foundation for coverage.py."""
-import os
-
from coverage.files import prep_patterns, FnmatchMatcher
-from coverage.misc import CoverageException, NoSource, NotPython, isolate_module
-
-os = isolate_module(os)
-
-
-class Reporter(object):
- """A base class for all reporters."""
-
- def __init__(self, coverage, config):
- """Create a reporter.
-
- `coverage` is the coverage instance. `config` is an instance of
- CoverageConfig, for controlling all sorts of behavior.
-
- """
- self.coverage = coverage
- self.config = config
-
- # Our method find_file_reporters used to set an attribute that other
- # code could read. That's been refactored away, but some third parties
- # were using that attribute. We'll continue to support it in a noisy
- # way for now.
- self._file_reporters = []
-
- def find_file_reporters(self, morfs):
- """Find the FileReporters we'll report on.
-
- `morfs` is a list of modules or file names.
-
- Returns a list of FileReporters.
-
- """
- reporters = self.coverage._get_file_reporters(morfs)
-
- if self.config.report_include:
- matcher = FnmatchMatcher(prep_patterns(self.config.report_include))
- reporters = [fr for fr in reporters if matcher.match(fr.filename)]
-
- if self.config.report_omit:
- matcher = FnmatchMatcher(prep_patterns(self.config.report_omit))
- reporters = [fr for fr in reporters if not matcher.match(fr.filename)]
-
- self._file_reporters = sorted(reporters)
- return self._file_reporters
-
- def report_files(self, report_fn, morfs):
- """Run a reporting function on a number of morfs.
-
- `report_fn` is called for each relative morf in `morfs`. It is called
- as::
-
- report_fn(file_reporter, analysis)
-
- where `file_reporter` is the `FileReporter` for the morf, and
- `analysis` is the `Analysis` for the morf.
-
- """
- file_reporters = self.find_file_reporters(morfs)
-
- if not file_reporters:
- raise CoverageException("No data to report.")
-
- for fr in file_reporters:
- try:
- report_fn(fr, self.coverage._analyze(fr))
- except NoSource:
- if not self.config.ignore_errors:
+from coverage.misc import CoverageException, NoSource, NotPython
+
+
+def get_analysis_to_report(coverage, config, morfs):
+ """Get the files to report on.
+
+ For each morf in `morfs`, if it should be reported on (based on the omit
+ and include configuration options), yield a pair, the `FileReporter` and
+ `Analysis` for the morf.
+
+ """
+ file_reporters = coverage._get_file_reporters(morfs)
+
+ if config.report_include:
+ matcher = FnmatchMatcher(prep_patterns(config.report_include))
+ file_reporters = [fr for fr in file_reporters if matcher.match(fr.filename)]
+
+ if config.report_omit:
+ matcher = FnmatchMatcher(prep_patterns(config.report_omit))
+ file_reporters = [fr for fr in file_reporters if not matcher.match(fr.filename)]
+
+ if not file_reporters:
+ raise CoverageException("No data to report.")
+
+ for fr in sorted(file_reporters):
+ try:
+ analysis = coverage._analyze(fr)
+ except NoSource:
+ if not config.ignore_errors:
+ raise
+ except NotPython:
+ # Only report errors for .py files, and only if we didn't
+ # explicitly suppress those errors.
+ # NotPython is only raised by PythonFileReporter, which has a
+ # should_be_python() method.
+ if fr.should_be_python():
+ if config.ignore_errors:
+ msg = "Could not parse Python file {0}".format(fr.filename)
+ coverage._warn(msg, slug="couldnt-parse")
+ else:
raise
- except NotPython:
- # Only report errors for .py files, and only if we didn't
- # explicitly suppress those errors.
- # NotPython is only raised by PythonFileReporter, which has a
- # should_be_python() method.
- if fr.should_be_python():
- if self.config.ignore_errors:
- msg = "Could not parse Python file {0}".format(fr.filename)
- self.coverage._warn(msg, slug="couldnt-parse")
- else:
- raise
+ else:
+ yield (fr, analysis)
diff --git a/coverage/summary.py b/coverage/summary.py
index 5b197f60..6e711089 100644
--- a/coverage/summary.py
+++ b/coverage/summary.py
@@ -6,16 +6,17 @@
import sys
from coverage import env
-from coverage.report import Reporter
+from coverage.report import get_analysis_to_report
from coverage.results import Numbers
from coverage.misc import NotPython, CoverageException, output_encoding
-class SummaryReporter(Reporter):
+class SummaryReporter(object):
"""A reporter for writing the summary report."""
def __init__(self, coverage, config):
- super(SummaryReporter, self).__init__(coverage, config)
+ self.coverage = coverage
+ self.config = config
self.branches = coverage.get_data().has_arcs()
self.outfile = None
self.fr_analysis = []
@@ -40,7 +41,8 @@ class SummaryReporter(Reporter):
self.outfile = outfile or sys.stdout
self.coverage.get_data().set_query_contexts(self.config.query_contexts)
- self.report_files(self.report_one_file, morfs)
+ for fr, analysis in get_analysis_to_report(self.coverage, self.config, morfs):
+ self.report_one_file(fr, analysis)
# Prepare the formatting strings, header, and column sorting.
max_name = max([len(fr.relative_filename()) for (fr, analysis) in self.fr_analysis] + [5])
diff --git a/coverage/xmlreport.py b/coverage/xmlreport.py
index 8ecdc24a..a414ed40 100644
--- a/coverage/xmlreport.py
+++ b/coverage/xmlreport.py
@@ -14,7 +14,7 @@ from coverage import env
from coverage import __url__, __version__, files
from coverage.backward import iitems
from coverage.misc import isolate_module
-from coverage.report import Reporter
+from coverage.report import get_analysis_to_report
os = isolate_module(os)
@@ -30,11 +30,12 @@ def rate(hit, num):
return "%.4g" % (float(hit) / num)
-class XmlReporter(Reporter):
+class XmlReporter(object):
"""A reporter for writing Cobertura-style XML coverage results."""
def __init__(self, coverage, config):
- super(XmlReporter, self).__init__(coverage, config)
+ self.coverage = coverage
+ self.config = config
self.source_paths = set()
if config.source:
@@ -71,7 +72,8 @@ class XmlReporter(Reporter):
xcoverage.appendChild(self.xml_out.createComment(" Based on %s " % DTD_URL))
# Call xml_file for each file in the data.
- self.report_files(self.xml_file, morfs)
+ for fr, analysis in get_analysis_to_report(self.coverage, self.config, morfs):
+ self.xml_file(fr, analysis)
xsources = self.xml_out.createElement("sources")
xcoverage.appendChild(xsources)