1"""Summary reporting"""
2
3import sys
4
5from coverage.report import Reporter
6from coverage.results import Numbers
7
8
9class SummaryReporter(Reporter):
10    """A reporter for writing the summary report."""
11
12    def __init__(self, coverage, show_missing=True, ignore_errors=False):
13        super(SummaryReporter, self).__init__(coverage, ignore_errors)
14        self.show_missing = show_missing
15        self.branches = coverage.data.has_arcs()
16
17    def report(self, morfs, outfile=None, config=None):
18        """Writes a report summarizing coverage statistics per module.
19
20        `outfile` is a file object to write the summary to.  `config` is a
21        CoverageConfig instance.
22
23        """
24        self.find_code_units(morfs, config)
25
26        # Prepare the formatting strings
27        max_name = max([len(cu.name) for cu in self.code_units] + [5])
28        fmt_name = "%%- %ds  " % max_name
29        fmt_err = "%s   %s: %s\n"
30        header = (fmt_name % "Name") + " Stmts   Miss"
31        fmt_coverage = fmt_name + "%6d %6d"
32        if self.branches:
33            header += " Branch BrPart"
34            fmt_coverage += " %6d %6d"
35        width100 = Numbers.pc_str_width()
36        header += "%*s" % (width100+4, "Cover")
37        fmt_coverage += "%%%ds%%%%" % (width100+3,)
38        if self.show_missing:
39            header += "   Missing"
40            fmt_coverage += "   %s"
41        rule = "-" * len(header) + "\n"
42        header += "\n"
43        fmt_coverage += "\n"
44
45        if not outfile:
46            outfile = sys.stdout
47
48        # Write the header
49        outfile.write(header)
50        outfile.write(rule)
51
52        total = Numbers()
53
54        for cu in self.code_units:
55            try:
56                analysis = self.coverage._analyze(cu)
57                nums = analysis.numbers
58                args = (cu.name, nums.n_statements, nums.n_missing)
59                if self.branches:
60                    args += (nums.n_branches, nums.n_missing_branches)
61                args += (nums.pc_covered_str,)
62                if self.show_missing:
63                    args += (analysis.missing_formatted(),)
64                outfile.write(fmt_coverage % args)
65                total += nums
66            except KeyboardInterrupt:                       # pragma: no cover
67                raise
68            except:
69                if not self.ignore_errors:
70                    typ, msg = sys.exc_info()[:2]
71                    outfile.write(fmt_err % (cu.name, typ.__name__, msg))
72
73        if total.n_files > 1:
74            outfile.write(rule)
75            args = ("TOTAL", total.n_statements, total.n_missing)
76            if self.branches:
77                args += (total.n_branches, total.n_missing_branches)
78            args += (total.pc_covered_str,)
79            if self.show_missing:
80                args += ("",)
81            outfile.write(fmt_coverage % args)
82