Allow maximum-issues to be set via command-line
This change allows the maximum issues to be passed in as an argument. If nothing is passed, then the existing build-in maximum is used. Retaining the existing built-in value makes sense for home users to keep track of their local build (otherwise they would have to remember the prior number of warnings and pass that value in for subsequent builds). Motivation: until now the built-in maximum covers the build permutation that happens to generate the most warnings versus other builds. In some cases new warnings may not be cause if they elicit a warning from the lesser-warning build(s) or compilers, but not in the maximum-warning build. This change lets us tighten-down the warning uniquely for each build, so we can be sure all new warnings are flagged to the developer.
This commit is contained in:
parent
e5d43e1b8f
commit
fd74aa0720
3 changed files with 109 additions and 40 deletions
3
.pylint
3
.pylint
|
@ -138,7 +138,8 @@ disable=print-statement,
|
|||
xreadlines-attribute,
|
||||
deprecated-sys-function,
|
||||
exception-escape,
|
||||
comprehension-escape
|
||||
comprehension-escape,
|
||||
duplicate-code
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
|
|
|
@ -3,11 +3,19 @@
|
|||
# Copyright (c) 2019 Patryk Obara <patryk.obara@gmail.com>
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# This script prints a summary snippet of information out of reports created
|
||||
# by scan-build or analyze-build for Clang's static code analysis.
|
||||
#
|
||||
# Usage: ./count-warnings.py path/to/report/index.html
|
||||
#
|
||||
"""
|
||||
This script prints a summary snippet of information out of reports
|
||||
created by scan-build or analyze-build for Clang's static code
|
||||
analysis.
|
||||
|
||||
It returns success to the shell if the number or bugs encountered
|
||||
is less than or equal to the desired maximum bugs. See --help
|
||||
for a description of how to set the maximum.
|
||||
|
||||
If the count exceeds the maximum then the script will return a
|
||||
status of 1 (failure), otherwise the script returns 0 (success).
|
||||
|
||||
"""
|
||||
# This script depends on BeautifulSoup module, if you're distribution is
|
||||
# missing it, you can use pipenv to install it for virtualenv spanning only
|
||||
# this repo: pipenv install beautifulsoup4 html5lib
|
||||
|
@ -15,16 +23,12 @@
|
|||
# pylint: disable=invalid-name
|
||||
# pylint: disable=missing-docstring
|
||||
|
||||
import os
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
# Maximum allowed number of issues; if report will include more bugs,
|
||||
# then script will return with status 1. Simply change this line if you
|
||||
# want to set a different limit.
|
||||
#
|
||||
MAX_ISSUES = 92
|
||||
|
||||
def summary_values(summary_table):
|
||||
if not summary_table:
|
||||
return
|
||||
|
@ -56,18 +60,52 @@ def print_summary(issues):
|
|||
text=warning, count=count, field_size=size))
|
||||
print()
|
||||
|
||||
def to_int(value):
|
||||
return int(value) if value is not None else None
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawTextHelpFormatter, description=__doc__)
|
||||
|
||||
parser.add_argument(
|
||||
'report',
|
||||
metavar='REPORT',
|
||||
help=("Path to the HTML report file"))
|
||||
|
||||
max_bugs = to_int(os.getenv('MAX_BUGS', None))
|
||||
parser.add_argument(
|
||||
'-m', '--max-bugs',
|
||||
type=int,
|
||||
required=not isinstance(max_bugs, int),
|
||||
default=max_bugs,
|
||||
help='Defines the maximum number of bugs permitted to exist\n'
|
||||
'in the report before returning a failure to the shell.\n'
|
||||
'If not provided, the script will attempt to read it from\n'
|
||||
'the MAX_BUGS environment variable, which is currently\n'
|
||||
'set to: {}. If a maximum of -1 is set then success is\n'
|
||||
'always returned to the shell.\n\n'.format(str(max_bugs)))
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
def main():
|
||||
bug_types = read_soup(sys.argv[1])
|
||||
rcode = 0
|
||||
args = parse_args()
|
||||
bug_types = read_soup(args.report)
|
||||
total = bug_types.pop('All Bugs')
|
||||
if bug_types:
|
||||
print("Bugs grouped by type:\n")
|
||||
print_summary(bug_types)
|
||||
print('Total: {} bugs (out of {} allowed)\n'.format(total, MAX_ISSUES))
|
||||
if total > MAX_ISSUES:
|
||||
print('Error: upper limit of allowed bugs is', MAX_ISSUES)
|
||||
sys.exit(1)
|
||||
|
||||
print('Total: {} bugs'.format(total), end='')
|
||||
if args.max_bugs >= 0:
|
||||
print(' (out of {} allowed)\n'.format(args.max_bugs))
|
||||
if total > args.max_bugs:
|
||||
print('Error: upper limit of allowed bugs is', args.max_bugs)
|
||||
rcode = 1
|
||||
else:
|
||||
print('\n')
|
||||
|
||||
return rcode
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
sys.exit(main())
|
||||
|
|
|
@ -2,29 +2,27 @@
|
|||
|
||||
# Copyright (c) 2019 Patryk Obara <patryk.obara@gmail.com>
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# This script counts all compiler warnings and prints a summary.
|
||||
#
|
||||
# Usage: ./count-warnings.py build.log
|
||||
# Usage: cat "*.log" | ./count-warnings.py -
|
||||
#
|
||||
# note: new compilers include additional flag -fdiagnostics-format=[text|json],
|
||||
# which could be used instead of parsing using regex, but we want to preserve
|
||||
# human-readable output in standard log.
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
# pylint: disable=missing-docstring
|
||||
|
||||
"""
|
||||
This script counts all compiler warnings and prints a summary.
|
||||
|
||||
It returns success to the shell if the number or warnings encountered
|
||||
is less than or equal to the desired maximum warnings. See --help
|
||||
for a description of how to set the maximum.
|
||||
|
||||
note: new compilers include additional flag -fdiagnostics-format=[text|json],
|
||||
which could be used instead of parsing using regex, but we want to preserve
|
||||
human-readable output in standard log.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
# Maximum allowed number of issues; if build will include more warnings,
|
||||
# then script will return with status 1. Simply change this line if you
|
||||
# want to set a different limit.
|
||||
#
|
||||
MAX_ISSUES = 384
|
||||
|
||||
# For recognizing warnings in GCC format in stderr:
|
||||
#
|
||||
WARNING_PATTERN = re.compile(r'([^:]+):(\d+):\d+: warning: .* \[-W(.+)\]')
|
||||
|
@ -76,20 +74,52 @@ def print_summary(issues):
|
|||
text=warning, count=count, field_size=size))
|
||||
print()
|
||||
|
||||
def to_int(value):
|
||||
return int(value) if value is not None else None
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawTextHelpFormatter, description=__doc__)
|
||||
|
||||
parser.add_argument(
|
||||
'logfile',
|
||||
metavar='LOGFILE',
|
||||
help=("Path to the logfile, or use - to read from stdin"))
|
||||
|
||||
max_warnings = to_int(os.getenv('MAX_WARNINGS', None))
|
||||
parser.add_argument(
|
||||
'-m', '--max-warnings',
|
||||
type=int,
|
||||
required=not isinstance(max_warnings, int),
|
||||
default=max_warnings,
|
||||
help='Defines the maximum number of warnings permitted to exist\n'
|
||||
'in the log file before returning a failure to the shell.\n'
|
||||
'If not provided, the script will attempt to read it from\n'
|
||||
'the MAX_WARNINGS environment variable, which is currently\n'
|
||||
'set to: {}. If a maximum of -1 is set then success is\n'
|
||||
'always returned to the shell.\n\n'.format(str(max_warnings)))
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
def main():
|
||||
rcode = 0
|
||||
total = 0
|
||||
warning_types = {}
|
||||
for line in get_input_lines(sys.argv[1]):
|
||||
args = parse_args()
|
||||
for line in get_input_lines(args.logfile):
|
||||
total += count_warning(line, warning_types)
|
||||
if warning_types:
|
||||
print("Warnings grouped by type:\n")
|
||||
print_summary(warning_types)
|
||||
print('Total: {} warnings (out of {} allowed)\n'.format(total, MAX_ISSUES))
|
||||
if total > MAX_ISSUES:
|
||||
print('Error: upper limit of allowed warnings is', MAX_ISSUES)
|
||||
sys.exit(1)
|
||||
|
||||
print('Total: {} warnings'.format(total), end='')
|
||||
if args.max_warnings >= 0:
|
||||
print(' (out of {} allowed)\n'.format(args.max_warnings))
|
||||
if total > args.max_warnings:
|
||||
print('Error: upper limit of allowed warnings is', args.max_warnings)
|
||||
rcode = 1
|
||||
else:
|
||||
print('\n')
|
||||
return rcode
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
sys.exit(main())
|
||||
|
|
Loading…
Add table
Reference in a new issue