ANN: firehose-0.3 released
Alec Leamas
leamas.alec at gmail.com
Thu Oct 10 12:50:10 UTC 2013
On 2013-10-08 18:46, David Malcolm wrote:
> "firehose" is a Python package intended for managing the results from
> code analysis tools (e.g. compiler warnings, static analysis, linters,
> etc).
>
> It currently provides parsers for the output of gcc, clang-analyzer,
> cppcheck, and findbugs. These parsers convert the results into a common
> data model of Python objects, with methods for lossless roundtrips
> through a provided XML format. There is also a JSON equivalent.
Don't really know what to do with this, but I enclose a simple rpmlint
to firehose converter. Perhaps it has a better home in "your" project.
It's a simple script, but it has been tested on the complete Fedora
distribution so it should at least not crash that often. If you like it,
just add it to the firehose repo.
--alec
-------------- next part --------------
#!/usr/bin/env python
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
'''
Convert rpmlint output to firehose-compatible XML.
Synopsis:
rpmlint2xml <specfile> <resultsfile>
specfile:
The file being checked by rpmlint.
resultfile:
The rpmlint results file.
Writes resulting xml on stdout.
See: https://github.com/fedora-static-analysis/firehose
'''
# pylint: disable=W0621,C0103
import re
import subprocess
import sys
import xml.etree.ElementTree as ET
import xml.dom.minidom
import rpm
def get_specfile(path):
' Return a (specfile, sha224sum) tuple. '
path = path.strip()
cs = subprocess.check_output(['sha224sum', path]).split()[0]
if '/' in path:
path = path.rsplit('/', 1)[1]
return path, cs
def get_version():
''' rpmlint version. '''
raw = subprocess.check_output(['rpmlint', '--version'])
return re.search('[0-9]+[.][0-9]+', raw).group()
def parse_spec_nvr(specpath):
''' return name-version-release dict for spec. '''
try:
spec = rpm.TransactionSet().parseSpec(specpath)
except Exception as ex: # pylint: disable=W0703
print "Can't parse specfile: " + ex.__str__()
sys.exit(2)
header = spec.sourceHeader
return {'name': header[rpm.RPMTAG_NAME],
'version': header[rpm.RPMTAG_VERSION],
'release': header[rpm.RPMTAG_RELEASE]}
def create_xmltree(path, nvr, cs, lintversion):
''' Create the basic xml report complete with <metadata>. '''
root = ET.Element('analysis')
metadata = ET.SubElement(root, 'metadata')
ET.SubElement(metadata, 'generator', {'name': 'rpmlint',
'version': lintversion})
file_ = ET.SubElement(metadata, 'file', {'given-path': path})
ET.SubElement(file_, 'hash', {'alg': 'sha224', 'hexdigest': cs})
sut = ET.SubElement(metadata, 'sut')
ET.SubElement(sut, 'source-rpm', nvr)
ET.SubElement(root, 'results')
return root
def add_xml_result(root, result, descriptions):
''' Add a rpmlint warning/error to the results. '''
path = root.find('metadata/file').attrib['given-path']
results = root.find('results')
if not result['name'] in descriptions:
d = subprocess.check_output(['rpmlint', '-I', result['name']])
descriptions[result['name']] = d
issue = ET.SubElement(results,
'issue',
{'test-id': result['name'],
'severity': result['severity']})
message = ET.SubElement(issue, 'message')
message.text = descriptions[result['name']]
location = ET.SubElement(issue, 'location')
ET.SubElement(location, 'file', {'given-path': path})
if 'line' in result:
ET.SubElement(location, 'point', {'line': result['line']})
ET.SubElement(issue, 'notes').text = result['text']
def parse_issues(resultpath):
''' Convert rpmlint results to a list of issues. '''
with open(resultpath) as f:
lines = f.readlines()
issues = []
for line in [l for l in lines if ':' in l]:
issue = {}
issue['path'], line = line.split(':', 1)
nr_or_severity, line = line.split(':', 1)
if re.search('[0-9]+', nr_or_severity):
issue['line'] = nr_or_severity
else:
issue['severity'] = nr_or_severity
if not 'severity' in issue:
issue['severity'], line = line.split(':', 1)
line = line.strip()
if ' ' in line:
issue['name'], issue['text'] = line.split(' ', 1)
else:
issue['name'], issue['text'] = line, ''
for key in issue.iterkeys():
issue[key] = issue[key].strip()
issues.append(dict(issue))
return issues
if __name__ == "__main__":
if len(sys.argv) == 2 and sys.argv[1] == '-h' or sys.argv[1] == '--help':
print sys.modules[__name__].__doc__
sys.exit(0)
elif len(sys.argv) != 3:
print sys.modules[__name__].__doc__
sys.exit(1)
specpath = sys.argv[1]
resultpath = sys.argv[2]
lintversion = get_version()
nvr = parse_spec_nvr(specpath)
specpath, cs = get_specfile(specpath)
issues = parse_issues(resultpath)
descriptions = {}
root = create_xmltree(specpath, nvr, cs, lintversion)
for issue in issues:
add_xml_result(root, issue, descriptions)
dom = xml.dom.minidom.parseString(ET.tostring(root))
sys.stdout.write(dom.toprettyxml(indent=' '))
# vim: set expandtab ts=4 sw=4:
More information about the firehose-devel
mailing list