diff options
author | Ned Batchelder <ned@nedbatchelder.com> | 2022-01-22 16:50:50 -0500 |
---|---|---|
committer | Ned Batchelder <ned@nedbatchelder.com> | 2022-01-22 17:37:50 -0500 |
commit | 2e8c1910cad1ba23726e62e03c4ae1608f3fb26e (patch) | |
tree | 39104fa106c947aefcd3d2c124dd584e800b1c1b /coverage | |
parent | 3f221e0339b74137bbf45289497955700dc49feb (diff) | |
download | python-coveragepy-git-2e8c1910cad1ba23726e62e03c4ae1608f3fb26e.tar.gz |
style: cleanups after lcov, though more than just lcov
Diffstat (limited to 'coverage')
-rw-r--r-- | coverage/cmdline.py | 49 | ||||
-rw-r--r-- | coverage/lcovreport.py | 46 |
2 files changed, 48 insertions, 47 deletions
diff --git a/coverage/cmdline.py b/coverage/cmdline.py index 9f5c9ea8..ad19ef29 100644 --- a/coverage/cmdline.py +++ b/coverage/cmdline.py @@ -123,15 +123,15 @@ class Opts: metavar="OUTFILE", help="Write the JSON report to this file. Defaults to 'coverage.json'", ) + output_lcov = optparse.make_option( + '-o', '', action='store', dest='outfile', + metavar="OUTFILE", + help="Write the LCOV report to this file. Defaults to 'coverage.lcov'", + ) json_pretty_print = optparse.make_option( '', '--pretty-print', action='store_true', help="Format the JSON for human readers.", ) - lcov = optparse.make_option( - '-o', '', action='store', dest='outfile', - metavar="OUTFILE", - help="Write the LCOV report to this file. Defaults to 'coverage.lcov'" - ) parallel_mode = optparse.make_option( '-p', '--parallel-mode', action='store_true', help=( @@ -423,7 +423,21 @@ CMDS = { Opts.show_contexts, ] + GLOBAL_ARGS, usage="[options] [modules]", - description="Generate a JSON report of coverage results." + description="Generate a JSON report of coverage results.", + ), + + 'lcov': CmdOptionParser( + "lcov", + [ + Opts.fail_under, + Opts.ignore_errors, + Opts.include, + Opts.output_lcov, + Opts.omit, + Opts.quiet, + ] + GLOBAL_ARGS, + usage="[options] [modules]", + description="Generate an LCOV report of coverage results.", ), 'report': CmdOptionParser( @@ -442,7 +456,7 @@ CMDS = { Opts.skip_empty, ] + GLOBAL_ARGS, usage="[options] [modules]", - description="Report coverage statistics on modules." + description="Report coverage statistics on modules.", ), 'run': CmdOptionParser( @@ -461,7 +475,7 @@ CMDS = { Opts.timid, ] + GLOBAL_ARGS, usage="[options] <pyfile> [program options]", - description="Run a Python program, measuring code execution." + description="Run a Python program, measuring code execution.", ), 'xml': CmdOptionParser( @@ -476,22 +490,8 @@ CMDS = { Opts.skip_empty, ] + GLOBAL_ARGS, usage="[options] [modules]", - description="Generate an XML report of coverage results." + description="Generate an XML report of coverage results.", ), - - 'lcov': CmdOptionParser( - "lcov", - [ - Opts.fail_under, - Opts.ignore_errors, - Opts.include, - Opts.lcov, - Opts.omit, - Opts.quiet, - ] + GLOBAL_ARGS, - usage="[options] [modules]", - description="Generate an LCOV report of coverage results." - ) } @@ -681,7 +681,6 @@ class CoverageScript: outfile=options.outfile, **report_args ) - else: # There are no other possible actions. raise AssertionError @@ -876,10 +875,10 @@ HELP_TOPICS = { help Get help on using coverage.py. html Create an HTML report. json Create a JSON report of coverage results. + lcov Create an LCOV report of coverage results. report Report coverage stats on modules. run Run a Python program and measure code execution. xml Create an XML report of coverage results. - lcov Create an LCOV report of coverage results. Use "{program_name} help <command>" for detailed help on any command. """, diff --git a/coverage/lcovreport.py b/coverage/lcovreport.py index 770f7a25..4dc73c29 100644 --- a/coverage/lcovreport.py +++ b/coverage/lcovreport.py @@ -20,7 +20,7 @@ class LcovReporter: self.config = self.coverage.config def report(self, morfs, outfile=None): - """Renders the full lcov report + """Renders the full lcov report. 'morfs' is a list of modules or filenames @@ -34,41 +34,42 @@ class LcovReporter: self.get_lcov(fr, analysis, outfile) def get_lcov(self, fr, analysis, outfile=None): - """Produces the lcov data for a single file + """Produces the lcov data for a single file. - get_lcov currently supports both line and branch coverage, + This currently supports both line and branch coverage, however function coverage is not supported. - """ - outfile.write("TN:\n") outfile.write(f"SF:{fr.relative_filename()}\n") source_lines = fr.source().splitlines() + for covered in sorted(analysis.executed): - # Note: Coveragepy currently only supports checking *if* a line has - # been executed, not how many times, so we set this to 1 for nice - # output even if it's technically incorrect - - # The lines below calculate a 64 bit encoded md5 hash of the line - # corresponding to the DA lines in the lcov file, - # for either case of the line being covered or missed in Coveragepy - # The final two characters of the encoding ("==") are removed from - # the hash to allow genhtml to run on the resulting lcov file + # Note: Coverage.py currently only supports checking *if* a line + # has been executed, not how many times, so we set this to 1 for + # nice output even if it's technically incorrect. + + # The lines below calculate a 64-bit encoded md5 hash of the line + # corresponding to the DA lines in the lcov file, for either case + # of the line being covered or missed in coverage.py. The final two + # characters of the encoding ("==") are removed from the hash to + # allow genhtml to run on the resulting lcov file. if source_lines: - line = source_lines[covered - 1].encode("utf-8") + line = source_lines[covered-1].encode("utf-8") else: line = b"" - hashed = str(base64.b64encode(md5(line).digest())[:-2], encoding="utf-8") + hashed = base64.b64encode(md5(line).digest()).decode().rstrip("=") outfile.write(f"DA:{covered},1,{hashed}\n") + for missed in sorted(analysis.missing): assert source_lines line = source_lines[missed-1].encode("utf-8") - hashed = str(base64.b64encode(md5(line).digest())[:-2], encoding="utf-8") + hashed = base64.b64encode(md5(line).digest()).decode().rstrip("=") outfile.write(f"DA:{missed},0,{hashed}\n") + outfile.write(f"LF:{len(analysis.statements)}\n") outfile.write(f"LH:{len(analysis.executed)}\n") - # More information dense branch coverage data + # More information dense branch coverage data. missing_arcs = analysis.missing_branch_arcs() executed_arcs = analysis.executed_branch_arcs() for block_number, block_line_number in enumerate( @@ -78,14 +79,15 @@ class LcovReporter: sorted(missing_arcs[block_line_number]) ): # The exit branches have a negative line number, - # this will not produce valid lcov, and so setting + # this will not produce valid lcov. Setting # the line number of the exit branch to 0 will allow - # for valid lcov, while preserving the data + # for valid lcov, while preserving the data. line_number = max(line_number, 0) outfile.write(f"BRDA:{line_number},{block_number},{branch_number},-\n") + # The start value below allows for the block number to be # preserved between these two for loops (stopping the loop from - # resetting the value of the block number to 0) + # resetting the value of the block number to 0). for branch_number, line_number in enumerate( sorted(executed_arcs[block_line_number]), start=len(missing_arcs[block_line_number]), @@ -93,7 +95,7 @@ class LcovReporter: line_number = max(line_number, 0) outfile.write(f"BRDA:{line_number},{block_number},{branch_number},1\n") - # Summary of the branch coverage + # Summary of the branch coverage. if analysis.has_arcs(): branch_stats = analysis.branch_stats() brf = sum(t for t, k in branch_stats.values()) |