123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
- # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
- """Reporter foundation for coverage.py."""
- import os
- import warnings
- 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
- # The directory into which to place the report, used by some derived
- # classes.
- self.directory = None
- # 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 = []
- @property
- def file_reporters(self):
- """Keep .file_reporters working for private-grabbing tools."""
- warnings.warn(
- "Report.file_reporters will no longer be available in Coverage.py 4.2",
- DeprecationWarning,
- )
- return 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.include:
- matcher = FnmatchMatcher(prep_patterns(self.config.include))
- reporters = [fr for fr in reporters if matcher.match(fr.filename)]
- if self.config.omit:
- matcher = FnmatchMatcher(prep_patterns(self.config.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, directory=None):
- """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.")
- self.directory = directory
- if self.directory and not os.path.exists(self.directory):
- os.makedirs(self.directory)
- for fr in file_reporters:
- try:
- report_fn(fr, self.coverage._analyze(fr))
- except NoSource:
- if not self.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 self.config.ignore_errors:
- self.coverage._warn("Could not parse Python file {0}".format(fr.filename))
- else:
- raise
|