Commit ae10b0f2 authored by Clément Schreiner's avatar Clément Schreiner
Browse files

Update lintian plugin to new API. Abstract severity lookup with a dictionary.

parent 95483768
......@@ -6,6 +6,7 @@
#
# Copyright © 2008 Jonny Lamb <jonny@debian.org>
# Copyright © 2012 Nicolas Dandrimont <Nicolas.Dandrimont@crans.org>
# Copyright © 2012 Clément Schreiner <clement@mux.me>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
......@@ -36,20 +37,88 @@ __author__ = 'Jonny Lamb'
__copyright__ = ', '.join([
'Copyright © 2008 Jonny Lamb',
'Copyright © 2012 Nicolas Dandrimont',
'Copyright © 2012 Clément Schreiner',
])
__license__ = 'MIT'
from collections import defaultdict
import subprocess
import logging
from collections import defaultdict, namedtuple
from debexpo.lib import constants
from debexpo.plugins import BasePlugin
from debexpo.plugins.api import *
from debexpo.model import meta
log = logging.getLogger(__name__)
class LintianPlugin(BasePlugin):
LintianSeverity = namedtuple('SeverityTuple',
['str', 'int', 'plugin_severity'])
severities = {
'E': LintianSeverity('Package has lintian errors', 5,
constants.PLUGIN_SEVERITY_ERROR),
'W': LintianSeverity('Package has lintian warnings', 4,
constants.PLUGIN_SEVERITY_WARNING),
'I': LintianSeverity('Package has lintian informational warnings', 3,
constants.PLUGIN_SEVERITY_INFO),
'O': LintianSeverity('Package has overridden lintian tags', 2,
constants.PLUGIN_SEVERITY_INFO),
'P': LintianSeverity('Package has lintian pedantic tags', 1,
constants.PLUGIN_SEVERITY_INFO),
'X': LintianSeverity('Package has lintian experimental tags', 0,
constants.PLUGIN_SEVERITY_INFO),
}
@test_result
class LintianTest(PluginResult):
""" Summary of the lintian results """
max_lintian_severity = string_field('max_lintian_severity')
severity = int_field('severity')
def get_tags(self):
"""
Returns the LintianTag objects for this package, as a
dictionary.
"""
# Yes, three levels of defaultdict and one of list...
# FIXME: how exactly is this new API better? :/
def defaultdict_defaultdict_list():
def defaultdict_list():
return defaultdict(list)
return defaultdict(defaultdict_list)
lintian_warnings = defaultdict(defaultdict_defaultdict_list)
q = meta.session.query(LintianWarning)
q = q.filter_by(package_version_id=self.package_version.id)
for w in q.all():
lintian_warnings[w.package][w.severity][w.tag].append(w.data)
return lintian_warnings
def __str__(self):
return severities[self.max_lintian_severity].str
class LintianWarning(PluginResult):
""" A lintian warning found for the package """
package = string_field('package')
severity = string_field('severity')
tag = string_field('tag')
data = string_field('data')
def __str__(self):
return 'Lintian warning ({severity}): [{tag}] {data}'.format(
severity=self.severity,
tag=self.tag,
data=self.data)
class LintianPlugin(QAPlugin):
""" Runs lintian tests on the package's binaries """
@importercmd
def test_lintian(self):
"""
Method to run lintian on the package.
......@@ -61,18 +130,11 @@ class LintianPlugin(BasePlugin):
"-I",
"--pedantic",
"--show-overrides",
self.changes_file], stdout=subprocess.PIPE).communicate()[0]
self.changes_file],
stdout=subprocess.PIPE).communicate()[0]
items = output.split('\n')
# Yes, three levels of defaultdict and one of list...
def defaultdict_defaultdict_list():
def defaultdict_list():
return defaultdict(list)
return defaultdict(defaultdict_list)
lintian_warnings = defaultdict(defaultdict_defaultdict_list)
lintian_severities = set()
override_comments = []
......@@ -81,7 +143,9 @@ class LintianPlugin(BasePlugin):
if not item:
continue
# lintian output is of the form """SEVERITY: package: lintian_tag [lintian tag arguments]""" or """N: Override comment"""
# lintian output is of the form:
# " SEVERITY: package: lintian_tag [lintian tag arguments] "
# or " N: Override comment "
if item.startswith("N: "):
override_comments.append(item[3:].strip())
continue
......@@ -91,26 +155,22 @@ class LintianPlugin(BasePlugin):
lintian_tag = lintian_tag_data[0]
lintian_data = lintian_tag_data[1:]
if override_comments:
lintian_data.append("(override comment: " + " ".join(override_comments) + ")")
lintian_data.append("(override comment: "
+ " ".join(override_comments) + ")")
override_comments = []
lintian_warnings[package][severity][lintian_tag].append(lintian_data)
severity = constants.PLUGIN_SEVERITY_INFO
if 'E' in lintian_severities:
severity = constants.PLUGIN_SEVERITY_ERROR
outcome = 'Package has lintian errors'
elif 'W' in lintian_severities:
severity = constants.PLUGIN_SEVERITY_WARNING
outcome = 'Package has lintian warnings'
elif 'I' in lintian_severities:
outcome = 'Package has lintian informational warnings'
elif 'O' in lintian_severities:
outcome = 'Package has overridden lintian tags'
elif 'P' in lintian_severities or 'X' in lintian_severities:
outcome = 'Package has lintian pedantic/experimental warnings'
else:
outcome = 'Package is lintian clean'
self.failed(outcome, lintian_warnings, severity)
for line in lintian_data:
self.new_result(LintianWarning, package=package, severity=severity,
tag=lintian_tag, data=line)
max_lintian_severity = max(lintian_severities,
key=lambda s: severities[s].int)
severity = severities[max_lintian_severity].plugin_severity
self.new_test_result(severity=severity,
max_lintian_severity=max_lintian_severity)
plugin = LintianPlugin
models = [
LintianTest,
LintianWarning,
]
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment