~launchpad-pqm/launchpad/devel

14557.1.20 by Curtis Hovey
Updated copyright.
1
# Copyright 2009-2011 Canonical Ltd.  This software is licensed under the
8687.15.18 by Karl Fogel
Add the copyright header block to files under lib/canonical/.
2
# GNU Affero General Public License version 3 (see the file LICENSE).
4675.3.1 by Abel Deuring
HWDB data upload form added
3
4
__metaclass__ = type
5
6
__all__ = [
7353.2.1 by Abel Deuring
Webservice API for IHWDevice
7
    'HWDBApplicationNavigation',
4675.3.2 by Abel Deuring
added views for hwdb submissiions from a person and submissions for a fingerprint
8
    'HWDBFingerprintSetView',
7353.2.1 by Abel Deuring
Webservice API for IHWDevice
9
    'HWDBPersonSubmissionsView',
4912.1.1 by Christian Reis
Merge Abel's work, add a test for textual HWDB output, and make sure submission IDs are valid_names too.
10
    'HWDBSubmissionTextView',
7353.2.1 by Abel Deuring
Webservice API for IHWDevice
11
    'HWDBUploadView',
12
    ]
4675.3.1 by Abel Deuring
HWDB data upload form added
13
4912.1.3 by Christian Reis
Implement the plain-text view for HWDB submissions, check that submission IDs are really valid_names, rename submission_id to submission_key consistently, rename distro*release to distro*series consistently. What else..
14
from textwrap import dedent
15
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
16
from z3c.ptcompat import ViewPageTemplateFile
8971.12.2 by Abel Deuring
implemented reviewr's comments
17
from zope.component import getUtility
4675.3.2 by Abel Deuring
added views for hwdb submissiions from a person and submissions for a fingerprint
18
from zope.interface import implements
19
from zope.publisher.interfaces.browser import IBrowserPublisher
7849.16.64 by Sidnei da Silva
- Fix a couple problems found by Francis during review
20
14600.2.2 by Curtis Hovey
Moved webapp to lp.services.
21
from lp.services.webapp import (
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
22
    LaunchpadView,
23
    Navigation,
24
    stepthrough,
25
    )
14600.2.2 by Curtis Hovey
Moved webapp to lp.services.
26
from lp.services.webapp.interfaces import ILaunchBag
27
from lp.services.webapp.batching import BatchNavigator
11929.9.1 by Tim Penhey
Move launchpadform into lp.app.browser.
28
from lp.app.browser.launchpadform import (
29
    action,
30
    LaunchpadFormView,
31
    )
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
32
from lp.app.errors import NotFoundError
33
from lp.hardwaredb.interfaces.hwdb import (
34
    IHWDBApplication,
35
    IHWDeviceClassSet,
36
    IHWDeviceSet,
37
    IHWDriverSet,
38
    IHWSubmissionDeviceSet,
39
    IHWSubmissionForm,
40
    IHWSubmissionSet,
41
    IHWSystemFingerprintSet,
42
    IHWVendorIDSet,
43
    )
44
from lp.registry.interfaces.distribution import IDistributionSet
4675.3.1 by Abel Deuring
HWDB data upload form added
45
46
47
class HWDBUploadView(LaunchpadFormView):
48
    """View class for hardware database submissions."""
49
4675.4.1 by Christian Reis
Fix some broken merges, update test to properly use sampledata, rename HWDBSubmission* to HWSubmission.
50
    schema = IHWSubmissionForm
9521.2.1 by Gary Poster
handle the majority of the remaining launchpad templates for 3.0: remove 6 and change 6. Also remove another template bigjools requested removal for.
51
    label = 'Hardware Database Submission'
52
    page_title = 'Submit New Data to the Launchpad Hardware Database'
4675.3.1 by Abel Deuring
HWDB data upload form added
53
54
    @action(u'Upload', name='upload')
55
    def upload_action(self, action, data):
4675.4.1 by Christian Reis
Fix some broken merges, update test to properly use sampledata, rename HWDBSubmission* to HWSubmission.
56
        """Create a record in the HWSubmission table."""
8971.12.1 by Abel Deuring
fix for bug 357316: hwdb +submit failing with KeyError OOPS
57
        # We expect that the data submitted by the client contains
58
        # data for all fields defined in the form. The main client
59
        # which POSTs data to this URL, checkbox, sometimes omits
60
        # some fields (see bug 357316). The absence of required
61
        # fields is not caught by Zope's form validation -- it only
62
        # checks if required fields are not empty, and does this only
63
        # if these fields are present in the form data. Absent fields
64
        # are not detected, so let's do that here.
65
        expected_fields = set(self.schema.names())
8971.12.2 by Abel Deuring
implemented reviewr's comments
66
        submitted_fields = set(data)
8971.12.1 by Abel Deuring
fix for bug 357316: hwdb +submit failing with KeyError OOPS
67
        missing_fields = expected_fields.difference(submitted_fields)
68
        if len(missing_fields) > 0:
69
            missing_fields = ', '.join(sorted(missing_fields))
70
            self.addCustomHeader(
8971.12.2 by Abel Deuring
implemented reviewr's comments
71
                'Error: Required fields not contained in POST data: '
8971.12.1 by Abel Deuring
fix for bug 357316: hwdb +submit failing with KeyError OOPS
72
                + missing_fields)
73
            return
74
4675.3.1 by Abel Deuring
HWDB data upload form added
75
        distributionset = getUtility(IDistributionSet)
4912.1.5 by Christian Reis
Make the hwdb/+fingerprint hierarchy work, add canonical_url to systems and fingerprints, and link them in the web pages' tables.
76
        distribution = distributionset.getByName(data['distribution'].lower())
4675.3.1 by Abel Deuring
HWDB data upload form added
77
        if distribution is not None:
4912.1.3 by Christian Reis
Implement the plain-text view for HWDB submissions, check that submission IDs are really valid_names, rename submission_id to submission_key consistently, rename distro*release to distro*series consistently. What else..
78
            release = data['distroseries']
4675.3.1 by Abel Deuring
HWDB data upload form added
79
            architecture = data['architecture']
80
            try:
81
                distroseries = distribution.getSeries(release)
4912.1.3 by Christian Reis
Implement the plain-text view for HWDB submissions, check that submission IDs are really valid_names, rename submission_id to submission_key consistently, rename distro*release to distro*series consistently. What else..
82
            except NotFoundError:
83
                self.addErrorHeader("distroseries",
84
                    "%s isn't a valid distribution series"
85
                     % data['distroseries'])
86
                return
87
88
            try:
4675.3.1 by Abel Deuring
HWDB data upload form added
89
                distroarchseries = distroseries[architecture]
90
            except NotFoundError:
4912.1.3 by Christian Reis
Implement the plain-text view for HWDB submissions, check that submission IDs are really valid_names, rename submission_id to submission_key consistently, rename distro*release to distro*series consistently. What else..
91
                self.addErrorHeader("distroarchseries",
92
                    "%s isn't a valid distribution architecture"
93
                     % data['architecture'])
94
                return
4675.3.1 by Abel Deuring
HWDB data upload form added
95
        else:
96
            distroarchseries = None
97
4675.4.1 by Christian Reis
Fix some broken merges, update test to properly use sampledata, rename HWDBSubmission* to HWSubmission.
98
        fingerprintset = getUtility(IHWSystemFingerprintSet)
4675.3.1 by Abel Deuring
HWDB data upload form added
99
        fingerprint = fingerprintset.getByName(data['system'])
100
        if fingerprint is None:
101
            fingerprint = fingerprintset.createFingerprint(data['system'])
102
103
        filesize = len(data['submission_data'])
4675.2.3 by Abel Deuring
implemented reviewr's comments
104
        submission_file = self.request.form[
105
            self.widgets['submission_data'].name]
106
        submission_file.seek(0)
107
        # convert a filename with "path elements" to a regular filename
108
        filename = submission_file.filename.replace('/', '-')
4675.3.1 by Abel Deuring
HWDB data upload form added
109
4675.4.1 by Christian Reis
Fix some broken merges, update test to properly use sampledata, rename HWDBSubmission* to HWSubmission.
110
        hw_submissionset = getUtility(IHWSubmissionSet)
4974.3.2 by Abel Deuring
No automatic creation of Person records for HWDB from unknown email addresses
111
        hw_submissionset.createSubmission(
112
            date_created=data['date_created'],
113
            format=data['format'],
114
            private=data['private'],
115
            contactable=data['contactable'],
116
            submission_key=data['submission_key'],
117
            emailaddress=data['emailaddress'],
118
            distroarchseries=distroarchseries,
119
            raw_submission=submission_file,
120
            filename=filename,
121
            filesize=filesize,
122
            system_fingerprint=data['system'])
4675.2.3 by Abel Deuring
implemented reviewr's comments
123
4912.1.2 by Christian Reis
Change the way headers are used to communicate problems.
124
        self.addCustomHeader('OK data stored')
4675.3.1 by Abel Deuring
HWDB data upload form added
125
        self.request.response.addNotification(
126
            "Thank you for your submission.")
127
128
    def render(self):
4675.2.3 by Abel Deuring
implemented reviewr's comments
129
        """See ILaunchpadFormView."""
130
        if self.errors:
131
            self.setHeadersForHWDBClient()
132
        return LaunchpadFormView.render(self)
133
134
    def setHeadersForHWDBClient(self):
4675.3.1 by Abel Deuring
HWDB data upload form added
135
        """Add headers that help the HWDB client detect a successful upload.
136
137
        An upload is normally not made by a regular web browser, but by the
138
        HWDB client. In order to allow the client to easily detect a
139
        successful as well as an failed request, add some HTTP headers
140
        to the response.
141
        """
4675.2.3 by Abel Deuring
implemented reviewr's comments
142
        for field in self.form_fields:
143
            field_name = field.__name__
5243.1.1 by Jonathan Knowles
Renaming method getWidgetError (in LaunchpadFormView) to getFieldError.
144
            error = self.getFieldError(field_name)
4675.2.3 by Abel Deuring
implemented reviewr's comments
145
            if error:
4912.1.2 by Christian Reis
Change the way headers are used to communicate problems.
146
                self.addErrorHeader(field_name, error)
147
148
    def addErrorHeader(self, field_name, error):
149
        """Adds a header informing an error to automated clients."""
5311.1.1 by David Murphy
Reformatted HWDB upload error messages to be less ambiguous.
150
        return self.addCustomHeader(u"Error in field '%s' - %s" %
151
                                    (field_name, error))
4912.1.2 by Christian Reis
Change the way headers are used to communicate problems.
152
153
    def addCustomHeader(self, value):
154
        """Adds a custom header to HWDB clients."""
155
        self.request.response.setHeader(
156
            u'X-Launchpad-HWDB-Submission', value)
157
4675.3.1 by Abel Deuring
HWDB data upload form added
158
159
class HWDBPersonSubmissionsView(LaunchpadView):
160
    """View class for preseting HWDB submissions by a person."""
161
9521.2.1 by Gary Poster
handle the majority of the remaining launchpad templates for 3.0: remove 6 and change 6. Also remove another template bigjools requested removal for.
162
    @property
163
    def label(self):
164
        return 'Hardware submissions for %s' % (self.context.title,)
165
166
    @property
167
    def page_title(self):
168
        return "Hardware Database submissions by %s" % (self.context.title,)
169
4675.3.2 by Abel Deuring
added views for hwdb submissiions from a person and submissions for a fingerprint
170
    def getAllBatched(self):
171
        """Return the list of HWDB submissions made by this person."""
4675.4.1 by Christian Reis
Fix some broken merges, update test to properly use sampledata, rename HWDBSubmission* to HWSubmission.
172
        hw_submissionset = getUtility(IHWSubmissionSet)
173
        submissions = hw_submissionset.getByOwner(self.context, self.user)
4675.3.2 by Abel Deuring
added views for hwdb submissiions from a person and submissions for a fingerprint
174
        return BatchNavigator(submissions, self.request)
4675.3.1 by Abel Deuring
HWDB data upload form added
175
176
    def userIsOwner(self):
177
        """Return true, if self.context == self.user"""
178
        return self.context == self.user
4675.3.2 by Abel Deuring
added views for hwdb submissiions from a person and submissions for a fingerprint
179
180
4912.1.1 by Christian Reis
Merge Abel's work, add a test for textual HWDB output, and make sure submission IDs are valid_names too.
181
class HWDBSubmissionTextView(LaunchpadView):
182
    """Renders a HWDBSubmission in parseable text."""
183
    def render(self):
4912.1.3 by Christian Reis
Implement the plain-text view for HWDB submissions, check that submission IDs are really valid_names, rename submission_id to submission_key consistently, rename distro*release to distro*series consistently. What else..
184
        data = {}
185
        data["date_created"] = self.context.date_created
186
        data["date_submitted"] = self.context.date_submitted
187
        data["format"] = self.context.format.name
188
189
        dar = self.context.distroarchseries
190
        if dar:
191
            data["distribution"] = dar.distroseries.distribution.name
192
            data["distribution_series"] = dar.distroseries.version
193
            data["architecture"] = dar.architecturetag
194
        else:
195
            data["distribution"] = "(unknown)"
196
            data["distribution_series"] = "(unknown)"
197
            data["architecture"] = "(unknown)"
198
7353.2.1 by Abel Deuring
Webservice API for IHWDevice
199
        data["system_fingerprint"] = (
200
            self.context.system_fingerprint.fingerprint)
4912.1.3 by Christian Reis
Implement the plain-text view for HWDB submissions, check that submission IDs are really valid_names, rename submission_id to submission_key consistently, rename distro*release to distro*series consistently. What else..
201
        data["url"] = self.context.raw_submission.http_url
202
203
        return dedent("""
204
            Date-Created: %(date_created)s
205
            Date-Submitted: %(date_submitted)s
206
            Format: %(format)s
207
            Distribution: %(distribution)s
208
            Distribution-Series: %(distribution_series)s
209
            Architecture: %(architecture)s
210
            System: %(system_fingerprint)s
211
            Submission URL: %(url)s""" % data)
4912.1.1 by Christian Reis
Merge Abel's work, add a test for textual HWDB output, and make sure submission IDs are valid_names too.
212
213
7353.2.1 by Abel Deuring
Webservice API for IHWDevice
214
class HWDBApplicationNavigation(Navigation):
4675.3.2 by Abel Deuring
added views for hwdb submissiions from a person and submissions for a fingerprint
215
    """Navigation class for HWDBSubmissionSet."""
216
217
    usedfor = IHWDBApplication
218
4912.1.3 by Christian Reis
Implement the plain-text view for HWDB submissions, check that submission IDs are really valid_names, rename submission_id to submission_key consistently, rename distro*release to distro*series consistently. What else..
219
    @stepthrough('+submission')
220
    def traverse_submission(self, name):
221
        user = getUtility(ILaunchBag).user
222
        submission = getUtility(IHWSubmissionSet).getBySubmissionKey(
223
            name, user=user)
224
        return submission
225
4912.1.5 by Christian Reis
Make the hwdb/+fingerprint hierarchy work, add canonical_url to systems and fingerprints, and link them in the web pages' tables.
226
    @stepthrough('+fingerprint')
4675.3.2 by Abel Deuring
added views for hwdb submissiions from a person and submissions for a fingerprint
227
    def traverse_hwdb_fingerprint(self, name):
228
        return HWDBFingerprintSetView(self.context, self.request, name)
229
7353.2.1 by Abel Deuring
Webservice API for IHWDevice
230
    @stepthrough('+device')
231
    def traverse_device(self, id):
232
        try:
233
            id = int(id)
234
        except ValueError:
235
            raise NotFoundError('invalid value for ID: %r' % id)
236
        return getUtility(IHWDeviceSet).getByID(id)
237
9094.2.2 by Abel Deuring
implemented reviewer's comments
238
    @stepthrough('+deviceclass')
239
    def traverse_device_class(self, id):
240
        try:
241
            id = int(id)
242
        except ValueError:
243
            raise NotFoundError('invalid value for ID: %r' % id)
244
        return getUtility(IHWDeviceClassSet).get(id)
245
7353.2.6 by Abel Deuring
added missing implementation to access a single HWDriver instance via the webservice API
246
    @stepthrough('+driver')
247
    def traverse_driver(self, id):
248
        try:
249
            id = int(id)
250
        except ValueError:
251
            raise NotFoundError('invalid value for ID: %r' % id)
252
        return getUtility(IHWDriverSet).getByID(id)
253
7525.3.1 by Abel Deuring
Webservice API for IHWSubmissionDevice
254
    @stepthrough('+submissiondevice')
255
    def traverse_submissiondevice(self, id):
256
        try:
257
            id = int(id)
258
        except ValueError:
259
            raise NotFoundError('invalid value for ID: %r' % id)
7525.3.2 by Abel Deuring
implemented reviewer's comments
260
        return getUtility(IHWSubmissionDeviceSet).get(id)
7525.3.1 by Abel Deuring
Webservice API for IHWSubmissionDevice
261
7553.1.1 by Abel Deuring
webservice API for IHWVendorID
262
    @stepthrough('+hwvendorid')
263
    def traverse_hw_vendor_id(self, id):
264
        try:
265
            id = int(id)
266
        except ValueError:
267
            raise NotFoundError('invalid value for ID: %r' % id)
268
        return getUtility(IHWVendorIDSet).get(id)
269
4675.3.2 by Abel Deuring
added views for hwdb submissiions from a person and submissions for a fingerprint
270
271
class HWDBFingerprintSetView(LaunchpadView):
272
    """View class for lists of HWDB submissions for a system fingerprint."""
273
274
    implements(IBrowserPublisher)
9521.2.1 by Gary Poster
handle the majority of the remaining launchpad templates for 3.0: remove 6 and change 6. Also remove another template bigjools requested removal for.
275
    label = page_title = "Hardware Database submissions for a fingerprint"
4675.3.2 by Abel Deuring
added views for hwdb submissiions from a person and submissions for a fingerprint
276
277
    template = ViewPageTemplateFile(
4675.2.3 by Abel Deuring
implemented reviewr's comments
278
        '../templates/hwdb-fingerprint-submissions.pt')
4912.1.3 by Christian Reis
Implement the plain-text view for HWDB submissions, check that submission IDs are really valid_names, rename submission_id to submission_key consistently, rename distro*release to distro*series consistently. What else..
279
4675.3.2 by Abel Deuring
added views for hwdb submissiions from a person and submissions for a fingerprint
280
    def __init__(self, context,  request, system_name):
281
        LaunchpadView.__init__(self, context, request)
282
        self.system_name = system_name
283
284
    def getAllBatched(self):
285
        """A BatchNavigator instance with the submissions."""
4675.4.1 by Christian Reis
Fix some broken merges, update test to properly use sampledata, rename HWDBSubmission* to HWSubmission.
286
        submissions = getUtility(IHWSubmissionSet).getByFingerprintName(
4675.3.2 by Abel Deuring
added views for hwdb submissiions from a person and submissions for a fingerprint
287
            self.system_name, self.user)
288
        return BatchNavigator(submissions, self.request)
289
290
    def browserDefault(self, request):
291
        """See `IBrowserPublisher`."""
292
        return self, ()
293
294
    def showOwner(self, submission):
295
        """Check if the owner can be shown in the list.
296
        """
297
        return (submission.owner is not None
298
                and (submission.contactable
299
                     or (submission.owner == self.user)))