debianqa.py 6.05 KB
Newer Older
Jonny Lamb's avatar
Jonny Lamb committed
1
2
3
4
# -*- coding: utf-8 -*-
#
#   debian.py — debian plugin
#
Arno Töll's avatar
Arno Töll committed
5
#   This file is part of debexpo - https://alioth.debian.org/projects/debexpo/
Jonny Lamb's avatar
Jonny Lamb committed
6
#
Jonny Lamb's avatar
Jonny Lamb committed
7
#   Copyright © 2008 Jonny Lamb <jonny@debian.org>
8
#   Copyright © 2012 Nicolas Dandrimont <Nicolas.Dandrimont@crans.org>
Jonny Lamb's avatar
Jonny Lamb committed
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#
#   Permission is hereby granted, free of charge, to any person
#   obtaining a copy of this software and associated documentation
#   files (the "Software"), to deal in the Software without
#   restriction, including without limitation the rights to use,
#   copy, modify, merge, publish, distribute, sublicense, and/or sell
#   copies of the Software, and to permit persons to whom the
#   Software is furnished to do so, subject to the following
#   conditions:
#
#   The above copyright notice and this permission notice shall be
#   included in all copies or substantial portions of the Software.
#
#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
#   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
#   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
#   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
#   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
#   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
#   OTHER DEALINGS IN THE SOFTWARE.

"""
Holds the debian plugin.
"""

__author__ = 'Jonny Lamb'
36
37
38
39
__copyright__ = ', '.join([
        'Copyright © 2008 Jonny Lamb',
        'Copyright © 2012 Nicolas Dandrimont',
        ])
Jonny Lamb's avatar
Jonny Lamb committed
40
41
42
__license__ = 'MIT'

import logging
43
44
45
46
47
import lxml.etree
import urllib2

from debexpo.model import meta
from debexpo.model.users import User
Jonny Lamb's avatar
Jonny Lamb committed
48

49
from debexpo.plugins.api import *
Jonny Lamb's avatar
Jonny Lamb committed
50
51
52

log = logging.getLogger(__name__)

53
54
55
56
57
58
59
60
61
62
63
@test_result
class DebianqaTest(PluginResult):

    in_debian = bool_field('in_debian')
    is_nmu = bool_field('is_nmu')
    is_debian_maintainer = bool_field('is_debian_maintainer')

    def __str__(self):
        # FIXME: this variable name sucks.
        s = 'already' if self.in_debian else 'not'
        return 'Package is %s in debian' % s
64

65
66
67

class DebianQAPlugin(QAPlugin):
    """ Plugin for Debian QA tests """
Jonny Lamb's avatar
Jonny Lamb committed
68

69
    @property
Jonny Lamb's avatar
Jonny Lamb committed
70
    def _in_debian(self):
71
        try:
72
73
            self.qa_page = urllib2.urlopen('http://packages.qa.debian.org/%s'
                                           % self.changes['Source'])
74
        except urllib2.HTTPError:
75
           return False
76
        else:
77
            self.parsed_qa = lxml.etree.fromstring(self.qa_page.read())
78
            return True
Jonny Lamb's avatar
Jonny Lamb committed
79

80
81
82
83
84
85
86
87
88
89
    def _qa_xpath(self, query, item = None):
        """Perform the xpath query on the given item"""
        if item is None:
            item = self.parsed_qa
        return item.xpath(
            query,
            namespaces={'xhtml': 'http://www.w3.org/1999/xhtml'}
            )

    def _test_package_in_debian(self):
Jonny Lamb's avatar
Jonny Lamb committed
90
91
92
93
        """
        Finds whether the package is in Debian.
        """
        log.debug('Testing whether the package is in Debian already')
94
        self.test_result.in_debian=self._in_debian
95
96

    def _test_last_upload(self):
Jonny Lamb's avatar
Jonny Lamb committed
97
98
99
100
101
        """
        Finds the date of the last upload of the package.
        """
        log.debug('Finding when the last upload of the package was')

102
103
104
105
        news = self._qa_xpath('//xhtml:ul[@id="news-list"]')[0]
        for item in news.getchildren():
            if 'Accepted' in self._qa_xpath('xhtml:a/child::text()', item):
                last_change = item.text[1:11]
106
                log.debug('Last upload on %s' % last_change)
107
                self.test_result["latest_upload"] = last_change
Jonny Lamb's avatar
Jonny Lamb committed
108
109
110
111
                return

        log.warning('Couldn\'t find last upload date')

112
    def _test_is_nmu(self):
Jonny Lamb's avatar
Jonny Lamb committed
113
114
115
        """
        Finds out whether the package is an NMU.
        """
116
        log.debug('Finding out whether the package is a NMU')
Jonny Lamb's avatar
Jonny Lamb committed
117

118
119
120
121
122
        import string

        delete_chars = string.maketrans(
            string.ascii_lowercase + "\n", " " * (len(string.ascii_lowercase) + 1)
            )
Jonny Lamb's avatar
Jonny Lamb committed
123

124
125
        changes = str(self.changes["Changes"]).lower().translate(None, delete_chars).splitlines()

126
        self.test_result.is_nmu = (
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
            any(change.startswith('nonmaintainerupload') for change in changes) or
            any(change.startswith('nmu') for change in changes) or
            'nmu' in self.changes["Version"]
            )

    def _get_debian_maintainer_data(self):

        self.debian_maintainers = sorted(
            self._qa_xpath('//xhtml:span[@title="maintainer"]/child::text()') +
            self._qa_xpath('//xhtml:span[@title="uploader"]/child::text()')
            )

        self.user_name = ""
        self.user_email = ""

142
143
144
        user_id = self.kw.get('user_id', None)
        if user_id is not None:
            user = meta.session.query(User).get(user_id)
145
146
147
148
149
150

            if user is not None:
                self.user_name = user.name
                self.user_email = user.email

    def _test_is_debian_maintainer(self):
Jonny Lamb's avatar
Jonny Lamb committed
151
152
153
154
155
156
        """
        Tests whether the package Maintainer is the Debian Maintainer.
        """

        log.debug('Finding out whether the package Maintainer is the Debian Maintainer')

157
        self.test_result.is_debian_maintainer = self.user_name in self.debian_maintainers
Jonny Lamb's avatar
Jonny Lamb committed
158

159
160

    def _test_has_new_maintainer(self):
Jonny Lamb's avatar
Jonny Lamb committed
161
162
163
164
165
166
167
        """
        Tests whether this package version introduces a new Maintainer.
        """
        log.debug('Finding out whether this package version introduces a new Maintainer')

        # TODO

168
    def _test_previous_sponsors(self):
Jonny Lamb's avatar
Jonny Lamb committed
169
        """
170
        Finds previous sponsors.
Jonny Lamb's avatar
Jonny Lamb committed
171
        """
172
        log.debug('Finding previous sponsors of the package')
Jonny Lamb's avatar
Jonny Lamb committed
173
174
175

        # TODO

176
    @importercmd
177
178
    def test_qa(self):
        """Run the Debian QA tests"""
Jonny Lamb's avatar
Jonny Lamb committed
179

180
        self.test_result = self.new_test_result()
Jonny Lamb's avatar
Jonny Lamb committed
181

182
        self._test_package_in_debian()
183
        if self._in_debian:
184
185
186
187
188
189
190
            self._test_last_upload()
            self._test_is_nmu()
            self._get_debian_maintainer_data()
            self._test_is_debian_maintainer()
            self._test_has_new_maintainer()
            self._test_previous_sponsors()

Jonny Lamb's avatar
Jonny Lamb committed
191
192


193
194
195
196
197
plugin = DebianQAPlugin
models = [
    DebianqaTest,
    ]
template = 'debianqa'