1 """Reporter foundation for Coverage."""
4 from coverage
.codeunit
import code_unit_factory
5 from coverage
.files
import prep_patterns
6 from coverage
.misc
import CoverageException
, NoSource
, NotPython
8 class Reporter(object):
9 """A base class for all reporters."""
11 def __init__(self
, coverage
, config
):
14 `coverage` is the coverage instance. `config` is an instance of
15 CoverageConfig, for controlling all sorts of behavior.
18 self
.coverage
= coverage
21 # The code units to report on. Set by find_code_units.
24 # The directory into which to place the report, used by some derived
28 def find_code_units(self
, morfs
):
29 """Find the code units we'll report on.
31 `morfs` is a list of modules or filenames.
34 morfs
= morfs
or self
.coverage
.data
.measured_files()
35 file_locator
= self
.coverage
.file_locator
36 self
.code_units
= code_unit_factory(morfs
, file_locator
)
38 if self
.config
.include
:
39 patterns
= prep_patterns(self
.config
.include
)
41 for cu
in self
.code_units
:
42 for pattern
in patterns
:
43 if fnmatch
.fnmatch(cu
.filename
, pattern
):
46 self
.code_units
= filtered
49 patterns
= prep_patterns(self
.config
.omit
)
51 for cu
in self
.code_units
:
52 for pattern
in patterns
:
53 if fnmatch
.fnmatch(cu
.filename
, pattern
):
57 self
.code_units
= filtered
59 self
.code_units
.sort()
61 def report_files(self
, report_fn
, morfs
, directory
=None):
62 """Run a reporting function on a number of morfs.
64 `report_fn` is called for each relative morf in `morfs`. It is called
67 report_fn(code_unit, analysis)
69 where `code_unit` is the `CodeUnit` for the morf, and `analysis` is
70 the `Analysis` for the morf.
73 self
.find_code_units(morfs
)
75 if not self
.code_units
:
76 raise CoverageException("No data to report.")
78 self
.directory
= directory
79 if self
.directory
and not os
.path
.exists(self
.directory
):
80 os
.makedirs(self
.directory
)
82 for cu
in self
.code_units
:
84 report_fn(cu
, self
.coverage
._analyze
(cu
))
86 if not self
.config
.ignore_errors
:
89 # Only report errors for .py files, and only if we didn't
90 # explicitly suppress those errors.
91 if cu
.should_be_python() and not self
.config
.ignore_errors
: