12293.1.11
by Curtis Hovey
Updated copyright. |
1 |
# Copyright 2010-2011 Canonical Ltd. This software is licensed under the
|
8687.15.15
by Karl Fogel
Add the copyright header block to files under lib/lp/bugs/. |
2 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
2764.2.1
by Brad Bollenbach
apply my +filebug patch on a fresh new bzr branch |
3 |
|
4 |
"""IBugTarget-related browser views."""
|
|
5 |
||
6 |
__metaclass__ = type |
|
7 |
||
3539.1.2
by Brad Bollenbach
fix failing tests |
8 |
__all__ = [ |
9565.2.1
by Gary Poster
fix vhost breadcrumbs so that we do not duplicate information |
9 |
"BugsVHostBreadcrumb", |
10137.7.43
by Karl Fogel
Incorporate some more review feedback from beuno and intellectronic: |
10 |
"BugsPatchesView", |
3539.1.2
by Brad Bollenbach
fix failing tests |
11 |
"BugTargetBugListingView", |
9360.1.1
by Gavin Panella
Remove bugtarget-filebug-advanced.pt, and clean up the view module. |
12 |
"BugTargetBugTagsView", |
3789.2.7
by Bjorn Tillenius
add a pie chart to the distributin Bugs page. |
13 |
"BugTargetBugsView", |
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
14 |
"FileBugAdvancedView", |
3691.249.20
by Brad Bollenbach
Get the +package filebug workflow working again, using the same form and views as the other filebug workflows |
15 |
"FileBugGuidedView", |
9360.1.1
by Gavin Panella
Remove bugtarget-filebug-advanced.pt, and clean up the view module. |
16 |
"FileBugViewBase", |
10898.5.2
by Curtis Hovey
Include the bug supervisor and security contact in the +configure-bugtraker. |
17 |
"IProductBugConfiguration", |
7968.4.1
by Abel Deuring
non-js version of editing official bug tags |
18 |
"OfficialBugTagsManageView", |
10898.5.2
by Curtis Hovey
Include the bug supervisor and security contact in the +configure-bugtraker. |
19 |
"ProductConfigureBugTrackerView", |
3764.1.2
by Bjorn Tillenius
make it possible to file a bug from the project page. |
20 |
"ProjectFileBugGuidedView", |
10898.5.2
by Curtis Hovey
Include the bug supervisor and security contact in the +configure-bugtraker. |
21 |
"product_to_productbugconfiguration", |
3539.1.2
by Brad Bollenbach
fix failing tests |
22 |
]
|
2764.2.1
by Brad Bollenbach
apply my +filebug patch on a fresh new bzr branch |
23 |
|
3691.320.9
by Bjorn Tillenius
display feedback of what was added to the bug report. |
24 |
import cgi |
3691.320.5
by Bjorn Tillenius
support adding attachments to the bug report. |
25 |
from cStringIO import StringIO |
10137.7.9
by Karl Fogel
With Abel, use the view instead of the model to prepare data for display. |
26 |
from datetime import datetime |
12584.1.2
by Gary Poster
clean lint |
27 |
from operator import itemgetter |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
28 |
import urllib |
29 |
||
30 |
from lazr.restful.interface import copy_field |
|
10137.7.9
by Karl Fogel
With Abel, use the view instead of the model to prepare data for display. |
31 |
from pytz import timezone |
7968.6.1
by Abel Deuring
parital JS code for the Official Bug Tags management page |
32 |
from simplejson import dumps |
7675.547.2
by Graham Binns
FileBugViewBase now has working extra_data_processing_job and extra_data_processed properties. |
33 |
from sqlobject import SQLObjectNotFound |
8426.8.14
by Graham Binns
Merged devel. |
34 |
from z3c.ptcompat import ViewPageTemplateFile |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
35 |
from zope import formlib |
4338.3.11
by Gavin Panella
Remove superfluous bug_already_reported field and widget. |
36 |
from zope.app.form.browser import TextWidget |
3938.1.1
by kiko
Implement first cut at a better +filebug page for non-Malone-using contexts. Factor out doesn't-use-Malone code to a macro. Infrastructure: provide a fmt:link for HasGotchiAndEmblemFormatterAPI, add a helpwanted CSS message class, add a distrosourcepackages to Product, and prejoin the packaging query. |
37 |
from zope.app.form.interfaces import InputErrors |
10898.5.4
by Curtis Hovey
Added bug supervisor and security contact to +configure-bugtracker. |
38 |
from zope.component import getUtility |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
39 |
from zope.interface import ( |
40 |
alsoProvides, |
|
41 |
implements, |
|
42 |
Interface, |
|
43 |
)
|
|
3691.320.10
by Bjorn Tillenius
make publishTraverse work properly when it can't find the tokens. |
44 |
from zope.publisher.interfaces import NotFound |
3691.320.2
by Bjorn Tillenius
support adding extra description to the filed bug. |
45 |
from zope.publisher.interfaces.browser import IBrowserPublisher |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
46 |
from zope.schema import ( |
47 |
Bool, |
|
48 |
Choice, |
|
49 |
)
|
|
12337.3.11
by Curtis Hovey
Replaced doctest with unittest. Updated the validation method to use the errors |
50 |
from zope.schema.interfaces import TooLong |
10017.3.8
by Graham Binns
De-lint. |
51 |
from zope.schema.vocabulary import SimpleVocabulary |
10898.5.9
by Curtis Hovey
Add IProductBugConfiguration to the instance, not the implemented interface. |
52 |
from zope.security.proxy import removeSecurityProxy |
2764.2.1
by Brad Bollenbach
apply my +filebug patch on a fresh new bzr branch |
53 |
|
9366.2.1
by Tom Berger
make it possible to disable th web interface filebug for ubuntu |
54 |
from canonical.config import config |
10699.1.2
by Tom Berger
Additional adjustments to make the security field writable in forms and correct some tests. |
55 |
from canonical.launchpad import _ |
5429.1.2
by Edwin Grubbs
Changed templates and HasAnnouncementsView to use the FeedsMixin |
56 |
from canonical.launchpad.browser.feeds import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
57 |
BugFeedLink, |
58 |
BugTargetLatestBugsFeedLink, |
|
59 |
FeedsMixin, |
|
60 |
)
|
|
11235.8.5
by Abel Deuring
change the bug attachment download URL shown in bug-portlet-attachments.py; fix failures in test_bugchanges.txt |
61 |
from canonical.launchpad.browser.librarian import ProxiedLibraryFileAlias |
12164.2.6
by Gavin Panella
Move canonical.widgets.bug to lp.bugs.browser.widgets.bug. |
62 |
from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities |
10230.1.1
by Deryck Hodge
Bring back the move from hot_bugtasks to hot_bugs, |
63 |
from canonical.launchpad.searchbuilder import any |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
64 |
from canonical.launchpad.webapp import ( |
65 |
canonical_url, |
|
66 |
LaunchpadView, |
|
67 |
urlappend, |
|
68 |
)
|
|
69 |
from canonical.launchpad.webapp.authorization import check_permission |
|
70 |
from canonical.launchpad.webapp.batching import BatchNavigator |
|
9209.4.5
by Guilherme Salgado
Update all existing breadcrumb adapters to use Breadcrumb rather than BreadcrumbBuilder. Also rename them all |
71 |
from canonical.launchpad.webapp.breadcrumb import Breadcrumb |
11270.1.3
by Tim Penhey
Changed NotFoundError imports - gee there were a lot of them. |
72 |
from canonical.launchpad.webapp.interfaces import ILaunchBag |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
73 |
from canonical.launchpad.webapp.menu import structured |
12811.2.16
by Ian Booth
Test fixes |
74 |
from canonical.launchpad.webapp.publisher import HTTP_MOVED_PERMANENTLY |
11929.9.1
by Tim Penhey
Move launchpadform into lp.app.browser. |
75 |
from lp.app.browser.launchpadform import ( |
76 |
action, |
|
77 |
custom_widget, |
|
78 |
LaunchpadEditFormView, |
|
79 |
LaunchpadFormView, |
|
80 |
safe_action, |
|
81 |
)
|
|
12289.7.1
by William Grant
Run text_to_html over the bug acknowledgement message before displaying it. |
82 |
from lp.app.browser.stringformatter import FormattersAPI |
7675.916.58
by Jeroen Vermeulen
Merged db-stable. |
83 |
from lp.app.browser.tales import BugTrackerFormatterAPI |
11411.8.1
by j.c.sackett
Changes from review. |
84 |
from lp.app.enums import ServiceUsage |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
85 |
from lp.app.errors import ( |
86 |
NotFoundError, |
|
87 |
UnexpectedFormData, |
|
88 |
)
|
|
11411.7.7
by j.c.sackett
Added adapter for distroseries to serviceusage and updated bugtarget.py to make use of it. |
89 |
from lp.app.interfaces.launchpad import ( |
90 |
ILaunchpadUsage, |
|
91 |
IServiceUsage, |
|
92 |
)
|
|
12442.2.9
by j.c.sackett
Ran import reformatter per review. |
93 |
from lp.app.validators.name import valid_name_pattern |
12293.1.10
by Curtis Hovey
Formatted imports. |
94 |
from lp.app.widgets.product import ( |
95 |
GhostCheckBoxWidget, |
|
96 |
GhostWidget, |
|
97 |
ProductBugTrackerWidget, |
|
98 |
)
|
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
99 |
from lp.bugs.browser.bugrole import BugRoleMixin |
100 |
from lp.bugs.browser.bugtask import BugTaskSearchListingView |
|
12393.10.2
by Gary Poster
fix some broken code, and eliminate some redendant code. JS is still broken. |
101 |
from lp.bugs.browser.structuralsubscription import ( |
12393.30.1
by Brad Crittenden
Add structural subscription link to all IStructuralSubscriptionTargets |
102 |
expose_structural_subscription_data_to_js, |
12393.10.2
by Gary Poster
fix some broken code, and eliminate some redendant code. JS is still broken. |
103 |
)
|
12164.2.6
by Gavin Panella
Move canonical.widgets.bug to lp.bugs.browser.widgets.bug. |
104 |
from lp.bugs.browser.widgets.bug import ( |
105 |
BugTagsWidget, |
|
106 |
LargeBugTagsWidget, |
|
107 |
)
|
|
12164.3.5
by Gavin Panella
Move lib/canonical/widgets/bugtask.py to lib/lp/bugs/browser/widgets/bugtask.py and adjust all imports, fix lint, etc. |
108 |
from lp.bugs.browser.widgets.bugtask import NewLineToSpacesWidget |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
109 |
from lp.bugs.interfaces.apportjob import IProcessApportBlobJobSource |
8523.3.1
by Gavin Panella
Bugs tree reorg after automated migration. |
110 |
from lp.bugs.interfaces.bug import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
111 |
CreateBugParams, |
12811.2.2
by Ian Booth
Refactor bug submission form |
112 |
IBug, |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
113 |
IBugAddForm, |
114 |
IBugSet, |
|
115 |
IProjectGroupBugAddForm, |
|
116 |
)
|
|
117 |
from lp.bugs.interfaces.bugsupervisor import IHasBugSupervisor |
|
118 |
from lp.bugs.interfaces.bugtarget import ( |
|
119 |
IBugTarget, |
|
120 |
IOfficialBugTagTargetPublic, |
|
121 |
IOfficialBugTagTargetRestricted, |
|
122 |
)
|
|
123 |
from lp.bugs.interfaces.bugtask import ( |
|
124 |
BugTaskSearchParams, |
|
125 |
BugTaskStatus, |
|
126 |
IBugTaskSet, |
|
127 |
UNRESOLVED_BUGTASK_STATUSES, |
|
128 |
)
|
|
129 |
from lp.bugs.interfaces.bugtracker import IBugTracker |
|
8523.3.1
by Gavin Panella
Bugs tree reorg after automated migration. |
130 |
from lp.bugs.interfaces.malone import IMaloneApplication |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
131 |
from lp.bugs.interfaces.securitycontact import IHasSecurityContact |
12392.4.4
by Robert Collins
Use aggregation rather that looping in python to determine series bug counts in bug searches. |
132 |
from lp.bugs.model.bugtask import BugTask |
12584.1.1
by Gary Poster
add a simple page to start building JS on |
133 |
from lp.bugs.model.structuralsubscription import ( |
12393.10.2
by Gary Poster
fix some broken code, and eliminate some redendant code. JS is still broken. |
134 |
get_structural_subscriptions_for_target, |
12584.1.1
by Gary Poster
add a simple page to start building JS on |
135 |
)
|
7675.547.10
by Graham Binns
Removed lint. |
136 |
from lp.bugs.utilities.filebugdataparser import FileBugData |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
137 |
from lp.hardwaredb.interfaces.hwdb import IHWSubmissionSet |
138 |
from lp.registry.browser.product import ProductConfigureBase |
|
10100.1.24
by Jonathan Lange
Catch a few more not exercised by an empty test run. |
139 |
from lp.registry.interfaces.distribution import IDistribution |
8523.3.23
by Gavin Panella
Merge devel. |
140 |
from lp.registry.interfaces.distributionsourcepackage import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
141 |
IDistributionSourcePackage, |
142 |
)
|
|
8523.3.1
by Gavin Panella
Bugs tree reorg after automated migration. |
143 |
from lp.registry.interfaces.distroseries import IDistroSeries |
10137.10.2
by Gavin Panella
When the context is an IPerson, fix the silly title wording and show the package in the results table. |
144 |
from lp.registry.interfaces.person import IPerson |
10100.1.25
by Jonathan Lange
Fix the last of them |
145 |
from lp.registry.interfaces.product import IProduct |
8523.3.1
by Gavin Panella
Bugs tree reorg after automated migration. |
146 |
from lp.registry.interfaces.productseries import IProductSeries |
10326.1.2
by Henning Eggers
Renamed project interfaces module to projectgroup. |
147 |
from lp.registry.interfaces.projectgroup import IProjectGroup |
7675.338.3
by Deryck Hodge
Get the fix right so that we do allow Ubuntu's bug |
148 |
from lp.registry.interfaces.sourcepackage import ISourcePackage |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
149 |
from lp.registry.vocabularies import ValidPersonOrTeamVocabulary |
7675.547.2
by Graham Binns
FileBugViewBase now has working extra_data_processing_job and extra_data_processed properties. |
150 |
from lp.services.job.interfaces.job import JobStatus |
11382.6.34
by Gavin Panella
Reformat imports in all files touched so far. |
151 |
from lp.services.propertycache import cachedproperty |
3691.249.3
by Brad Bollenbach
make the dupes search form work with new formlib goo |
152 |
|
8426.8.1
by Graham Binns
Added the duplicate finder overlay. Woot, etc. |
153 |
# A simple vocabulary for the subscribe_to_existing_bug form field.
|
154 |
SUBSCRIBE_TO_BUG_VOCABULARY = SimpleVocabulary.fromItems( |
|
155 |
[('yes', True), ('no', False)]) |
|
156 |
||
157 |
||
10898.5.2
by Curtis Hovey
Include the bug supervisor and security contact in the +configure-bugtraker. |
158 |
class IProductBugConfiguration(Interface): |
159 |
"""A composite schema for editing bug app configuration."""
|
|
160 |
||
161 |
bug_supervisor = copy_field( |
|
162 |
IHasBugSupervisor['bug_supervisor'], readonly=False) |
|
163 |
security_contact = copy_field(IHasSecurityContact['security_contact']) |
|
164 |
official_malone = copy_field(ILaunchpadUsage['official_malone']) |
|
165 |
enable_bug_expiration = copy_field( |
|
166 |
ILaunchpadUsage['enable_bug_expiration']) |
|
167 |
bugtracker = copy_field(IProduct['bugtracker']) |
|
168 |
remote_product = copy_field(IProduct['remote_product']) |
|
169 |
bug_reporting_guidelines = copy_field( |
|
170 |
IBugTarget['bug_reporting_guidelines']) |
|
10977.7.2
by Abel Deuring
the relevant edit forms for ProjectGroup, Product, Distribution, DistributionSourcePackage now have fields to edit the bug report acknowledgement message |
171 |
bug_reported_acknowledgement = copy_field( |
172 |
IBugTarget['bug_reported_acknowledgement']) |
|
7675.993.1
by Abel Deuring
The forms to configure the bugtracker for products and for DSPs now contains a field enable_bugfiling_duplicate_search; bug filing pages show immediately the complete form if enable_bugfiling_duplicate_search is turned off. |
173 |
enable_bugfiling_duplicate_search = copy_field( |
174 |
IBugTarget['enable_bugfiling_duplicate_search']) |
|
10898.5.2
by Curtis Hovey
Include the bug supervisor and security contact in the +configure-bugtraker. |
175 |
|
176 |
||
177 |
def product_to_productbugconfiguration(product): |
|
178 |
"""Adapts an `IProduct` into an `IProductBugConfiguration`."""
|
|
10898.5.9
by Curtis Hovey
Add IProductBugConfiguration to the instance, not the implemented interface. |
179 |
alsoProvides( |
180 |
removeSecurityProxy(product), IProductBugConfiguration) |
|
10898.5.2
by Curtis Hovey
Include the bug supervisor and security contact in the +configure-bugtraker. |
181 |
return product |
182 |
||
183 |
||
10898.5.4
by Curtis Hovey
Added bug supervisor and security contact to +configure-bugtracker. |
184 |
class ProductConfigureBugTrackerView(BugRoleMixin, ProductConfigureBase): |
10876.5.2
by Curtis Hovey
Remove configure-bugtracker and remove_product tests. |
185 |
"""View class to configure the bug tracker for a project."""
|
186 |
||
187 |
label = "Configure bug tracker" |
|
10898.5.2
by Curtis Hovey
Include the bug supervisor and security contact in the +configure-bugtraker. |
188 |
schema = IProductBugConfiguration |
10995.1.3
by Curtis Hovey
Render the enable_bug_expiration and remote_product field as subordinate fields |
189 |
# This ProductBugTrackerWidget renders enable_bug_expiration and
|
10995.1.16
by Curtis Hovey
Fixed grammar. |
190 |
# remote_product as subordinate fields, so this view suppresses them.
|
10876.5.2
by Curtis Hovey
Remove configure-bugtracker and remove_product tests. |
191 |
custom_widget('bugtracker', ProductBugTrackerWidget) |
10995.1.11
by Curtis Hovey
Pushed the bugtracker vocab rules to the base vocab. Reimplemented GhostWidget as a mixin to cover bool fields. |
192 |
custom_widget('enable_bug_expiration', GhostCheckBoxWidget) |
10995.1.3
by Curtis Hovey
Render the enable_bug_expiration and remote_product field as subordinate fields |
193 |
custom_widget('remote_product', GhostWidget) |
10876.5.2
by Curtis Hovey
Remove configure-bugtracker and remove_product tests. |
194 |
|
11587.3.7
by Brian Murray
allow bug supervisor to view some +configure-bugtracker fields |
195 |
@property
|
196 |
def field_names(self): |
|
197 |
"""Return the list of field names to display."""
|
|
198 |
field_names = [ |
|
7675.993.1
by Abel Deuring
The forms to configure the bugtracker for products and for DSPs now contains a field enable_bugfiling_duplicate_search; bug filing pages show immediately the complete form if enable_bugfiling_duplicate_search is turned off. |
199 |
"bugtracker", |
200 |
"enable_bug_expiration", |
|
201 |
"remote_product", |
|
202 |
"bug_reporting_guidelines", |
|
203 |
"bug_reported_acknowledgement", |
|
204 |
"enable_bugfiling_duplicate_search", |
|
205 |
]
|
|
11587.3.7
by Brian Murray
allow bug supervisor to view some +configure-bugtracker fields |
206 |
if check_permission("launchpad.Edit", self.context): |
207 |
field_names.extend(["bug_supervisor", "security_contact"]) |
|
208 |
||
209 |
return field_names |
|
210 |
||
10876.5.2
by Curtis Hovey
Remove configure-bugtracker and remove_product tests. |
211 |
def validate(self, data): |
212 |
"""Constrain bug expiration to Launchpad Bugs tracker."""
|
|
11823.1.1
by Brian Murray
allow bug supervisor to commit changes on the +configure-bugtracker page |
213 |
if check_permission("launchpad.Edit", self.context): |
214 |
self.validateBugSupervisor(data) |
|
215 |
self.validateSecurityContact(data) |
|
10876.5.2
by Curtis Hovey
Remove configure-bugtracker and remove_product tests. |
216 |
# enable_bug_expiration is disabled by JavaScript when bugtracker
|
217 |
# is not 'In Launchpad'. The constraint is enforced here in case the
|
|
218 |
# JavaScript fails to activate or run. Note that the bugtracker
|
|
219 |
# name : values are {'In Launchpad' : object, 'Somewhere else' : None
|
|
220 |
# 'In a registered bug tracker' : IBugTracker}.
|
|
221 |
bugtracker = data.get('bugtracker', None) |
|
222 |
if bugtracker is None or IBugTracker.providedBy(bugtracker): |
|
223 |
data['enable_bug_expiration'] = False |
|
224 |
||
10898.5.4
by Curtis Hovey
Added bug supervisor and security contact to +configure-bugtracker. |
225 |
@action("Change", name='change') |
226 |
def change_action(self, action, data): |
|
11134.5.1
by Curtis Hovey
Allow owners to change bug configuration fields they have permission to change. |
227 |
# bug_supervisor and security_contactrequires a transition method,
|
228 |
# so it must be handled separately and removed for the
|
|
229 |
# updateContextFromData to work as expected.
|
|
11823.1.1
by Brian Murray
allow bug supervisor to commit changes on the +configure-bugtracker page |
230 |
if check_permission("launchpad.Edit", self.context): |
231 |
self.changeBugSupervisor(data['bug_supervisor']) |
|
232 |
del data['bug_supervisor'] |
|
233 |
self.changeSecurityContact(data['security_contact']) |
|
234 |
del data['security_contact'] |
|
10898.5.4
by Curtis Hovey
Added bug supervisor and security contact to +configure-bugtracker. |
235 |
self.updateContextFromData(data) |
236 |
||
10876.5.2
by Curtis Hovey
Remove configure-bugtracker and remove_product tests. |
237 |
|
12811.2.11
by Ian Booth
Code review fixes and ensure changing products hides/shows the relevant bug detail fields |
238 |
class FileBugReportingGuidelines(LaunchpadFormView): |
12811.2.2
by Ian Booth
Refactor bug submission form |
239 |
"""Provides access to common bug reporting attributes.
|
240 |
||
241 |
Attributes provided are: security_related and bug_reporting_guidelines.
|
|
242 |
||
243 |
This view is a superclass of `FileBugViewBase` so that non-ajax browsers
|
|
244 |
can load the file bug form, and it is also invoked directly via an XHR
|
|
245 |
request to provide an HTML snippet for Javascript enabled browsers.
|
|
246 |
"""
|
|
247 |
||
248 |
schema = IBug |
|
12811.2.8
by Ian Booth
Lint fixes |
249 |
|
12811.2.2
by Ian Booth
Refactor bug submission form |
250 |
@property
|
251 |
def field_names(self): |
|
252 |
"""Return the list of field names to display."""
|
|
253 |
return ['security_related'] |
|
254 |
||
255 |
def setUpFields(self): |
|
256 |
"""Set up the form fields. See `LaunchpadFormView`."""
|
|
12811.2.11
by Ian Booth
Code review fixes and ensure changing products hides/shows the relevant bug detail fields |
257 |
super(FileBugReportingGuidelines, self).setUpFields() |
12811.2.2
by Ian Booth
Refactor bug submission form |
258 |
|
259 |
security_related_field = Bool( |
|
260 |
__name__='security_related', |
|
261 |
title=_("This bug is a security vulnerability"), |
|
262 |
required=False, default=False) |
|
263 |
||
264 |
self.form_fields = self.form_fields.omit('security_related') |
|
265 |
self.form_fields += formlib.form.Fields(security_related_field) |
|
266 |
||
267 |
@property
|
|
268 |
def bug_reporting_guidelines(self): |
|
269 |
"""Guidelines for filing bugs in the current context.
|
|
270 |
||
271 |
Returns a list of dicts, with each dict containing values for
|
|
272 |
"preamble" and "content".
|
|
273 |
"""
|
|
274 |
||
275 |
def target_name(target): |
|
276 |
# IProjectGroup can be considered the target of a bug during
|
|
277 |
# the bug filing process, but does not extend IBugTarget
|
|
278 |
# and ultimately cannot actually be the target of a
|
|
279 |
# bug. Hence this function to determine a suitable
|
|
280 |
# name/title to display. Hurrumph.
|
|
281 |
if IBugTarget.providedBy(target): |
|
282 |
return target.bugtargetdisplayname |
|
283 |
else: |
|
12811.2.11
by Ian Booth
Code review fixes and ensure changing products hides/shows the relevant bug detail fields |
284 |
return target.displayname |
12811.2.2
by Ian Booth
Refactor bug submission form |
285 |
|
286 |
guidelines = [] |
|
287 |
bugtarget = self.context |
|
288 |
if bugtarget is not None: |
|
289 |
content = bugtarget.bug_reporting_guidelines |
|
290 |
if content is not None and len(content) > 0: |
|
291 |
guidelines.append({ |
|
292 |
"source": target_name(bugtarget), |
|
293 |
"content": content, |
|
294 |
})
|
|
295 |
# Distribution source packages are shown with both their
|
|
296 |
# own reporting guidelines and those of their
|
|
297 |
# distribution.
|
|
298 |
if IDistributionSourcePackage.providedBy(bugtarget): |
|
299 |
distribution = bugtarget.distribution |
|
300 |
content = distribution.bug_reporting_guidelines |
|
301 |
if content is not None and len(content) > 0: |
|
302 |
guidelines.append({ |
|
303 |
"source": target_name(distribution), |
|
304 |
"content": content, |
|
305 |
})
|
|
306 |
return guidelines |
|
307 |
||
308 |
def getMainContext(self): |
|
309 |
if IDistributionSourcePackage.providedBy(self.context): |
|
310 |
return self.context.distribution |
|
311 |
else: |
|
312 |
return self.context |
|
313 |
||
314 |
||
12811.2.11
by Ian Booth
Code review fixes and ensure changing products hides/shows the relevant bug detail fields |
315 |
class FileBugViewBase(FileBugReportingGuidelines, LaunchpadFormView): |
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
316 |
"""Base class for views related to filing a bug."""
|
3691.249.29
by Brad Bollenbach
add a basic filebug steps macro, for mpt to tweak |
317 |
|
3691.320.2
by Bjorn Tillenius
support adding extra description to the filed bug. |
318 |
implements(IBrowserPublisher) |
319 |
||
3691.342.1
by Bjorn Tillenius
make it possible to specify the default bug summary in the +filebug blob. |
320 |
extra_data_token = None |
3691.415.2
by Bjorn Tillenius
add a Tags: field to the advanced filebug page. |
321 |
advanced_form = False |
4486.4.24
by Graham Binns
UI and pagetest tweaks |
322 |
frontpage_form = False |
7143.4.20
by Bjorn Tillenius
make sure temporary files are removed. |
323 |
data_parser = None |
3691.342.1
by Bjorn Tillenius
make it possible to specify the default bug summary in the +filebug blob. |
324 |
|
325 |
def __init__(self, context, request): |
|
326 |
LaunchpadFormView.__init__(self, context, request) |
|
327 |
self.extra_data = FileBugData() |
|
3691.320.2
by Bjorn Tillenius
support adding extra description to the filed bug. |
328 |
|
10054.11.3
by Graham Binns
Refactored the FileBug views to ensure that the extra data code doesn't get moved unnecessarily. |
329 |
def initialize(self): |
330 |
LaunchpadFormView.initialize(self) |
|
331 |
if (not self.redirect_ubuntu_filebug and |
|
7675.547.8
by Graham Binns
Hurrah, the +filebug form now works with processed apport blob jobs. |
332 |
self.extra_data_token is not None and |
333 |
not self.extra_data_to_process): |
|
10054.11.3
by Graham Binns
Refactored the FileBug views to ensure that the extra data code doesn't get moved unnecessarily. |
334 |
# self.extra_data has been initialized in publishTraverse().
|
335 |
if self.extra_data.initial_summary: |
|
336 |
self.widgets['title'].setRenderedValue( |
|
337 |
self.extra_data.initial_summary) |
|
338 |
if self.extra_data.initial_tags: |
|
339 |
self.widgets['tags'].setRenderedValue( |
|
340 |
self.extra_data.initial_tags) |
|
341 |
# XXX: Bjorn Tillenius 2006-01-15:
|
|
342 |
# We should include more details of what will be added
|
|
343 |
# to the bug report.
|
|
344 |
self.request.response.addNotification( |
|
345 |
'Extra debug information will be added to the bug report'
|
|
346 |
' automatically.') |
|
347 |
||
348 |
@cachedproperty
|
|
349 |
def redirect_ubuntu_filebug(self): |
|
350 |
if IDistribution.providedBy(self.context): |
|
351 |
bug_supervisor = self.context.bug_supervisor |
|
352 |
elif (IDistributionSourcePackage.providedBy(self.context) or |
|
353 |
ISourcePackage.providedBy(self.context)): |
|
354 |
bug_supervisor = self.context.distribution.bug_supervisor |
|
10054.11.4
by Graham Binns
Fixed a test error with bug supervisors not being set in redirect_ubuntu_filebug. |
355 |
else: |
356 |
bug_supervisor = None |
|
10054.11.3
by Graham Binns
Refactored the FileBug views to ensure that the extra data code doesn't get moved unnecessarily. |
357 |
|
358 |
# Work out whether the redirect should be overidden.
|
|
359 |
do_not_redirect = ( |
|
360 |
self.request.form.get('no-redirect') is not None or |
|
361 |
[key for key in self.request.form.keys() |
|
362 |
if 'field.actions' in key] != [] or |
|
363 |
self.user.inTeam(bug_supervisor)) |
|
364 |
||
365 |
return ( |
|
366 |
config.malone.ubuntu_disable_filebug and |
|
367 |
self.targetIsUbuntu() and |
|
368 |
self.extra_data_token is None and |
|
369 |
not do_not_redirect) |
|
3691.320.12
by Bjorn Tillenius
display a notification that extra information will be added to the bug. |
370 |
|
3691.249.23
by Brad Bollenbach
fix test failures |
371 |
@property
|
3995.4.1
by Bjorn Tillenius
move field_names generation into FileBugViewBase. |
372 |
def field_names(self): |
373 |
"""Return the list of field names to display."""
|
|
374 |
context = self.context |
|
4338.3.4
by Gavin Panella
Add bug_already_reported and bug_already_reported_as. |
375 |
field_names = ['title', 'comment', 'tags', 'security_related', |
5491.1.6
by Graham Binns
Added fields to bugtarget.FileBugViewBase. |
376 |
'bug_already_reported_as', 'filecontent', 'patch', |
8426.8.1
by Graham Binns
Added the duplicate finder overlay. Woot, etc. |
377 |
'attachment_description', 'subscribe_to_existing_bug'] |
3995.4.1
by Bjorn Tillenius
move field_names generation into FileBugViewBase. |
378 |
if (IDistribution.providedBy(context) or |
379 |
IDistributionSourcePackage.providedBy(context)): |
|
380 |
field_names.append('packagename') |
|
381 |
elif IMaloneApplication.providedBy(context): |
|
382 |
field_names.append('bugtarget') |
|
10326.1.1
by Henning Eggers
Mechanically renamed IProject* to IProjectGroup*. |
383 |
elif IProjectGroup.providedBy(context): |
3995.4.1
by Bjorn Tillenius
move field_names generation into FileBugViewBase. |
384 |
field_names.append('product') |
385 |
elif not IProduct.providedBy(context): |
|
386 |
raise AssertionError('Unknown context: %r' % context) |
|
387 |
||
12811.2.12
by Ian Booth
Fix rendering of assignee/importance etc fields for project groups, fix test |
388 |
# If the context is a project group we want to render the optional
|
389 |
# fields since they will initially be hidden and later exposed if the
|
|
390 |
# selected project supports them.
|
|
391 |
include_extra_fields = IProjectGroup.providedBy(context) |
|
392 |
if not include_extra_fields and IHasBugSupervisor.providedBy(context): |
|
393 |
include_extra_fields = self.user.inTeam(context.bug_supervisor) |
|
394 |
||
395 |
if include_extra_fields: |
|
396 |
field_names.extend( |
|
397 |
['assignee', 'importance', 'milestone', 'status']) |
|
8137.17.24
by Barry Warsaw
thread merge |
398 |
|
3995.4.3
by Bjorn Tillenius
add a security checkbox on +filebug. |
399 |
return field_names |
3995.4.1
by Bjorn Tillenius
move field_names generation into FileBugViewBase. |
400 |
|
401 |
@property
|
|
3691.249.23
by Brad Bollenbach
fix test failures |
402 |
def initial_values(self): |
403 |
"""Give packagename a default value, if applicable."""
|
|
404 |
if not IDistributionSourcePackage.providedBy(self.context): |
|
405 |
return {} |
|
406 |
||
407 |
return {'packagename': self.context.name} |
|
3691.249.29
by Brad Bollenbach
add a basic filebug steps macro, for mpt to tweak |
408 |
|
4640.3.15
by Matthew Paul Thomas
Fixes from Tim's first review. |
409 |
def isPrivate(self): |
4640.3.9
by Matthew Paul Thomas
Gives bug-reporting pages the private appearance if you're reporting a bug on a project that has private bugs by default. |
410 |
"""Whether bug reports on this target are private by default."""
|
411 |
return IProduct.providedBy(self.context) and self.context.private_bugs |
|
412 |
||
3938.1.1
by kiko
Implement first cut at a better +filebug page for non-Malone-using contexts. Factor out doesn't-use-Malone code to a macro. Infrastructure: provide a fmt:link for HasGotchiAndEmblemFormatterAPI, add a helpwanted CSS message class, add a distrosourcepackages to Product, and prejoin the packaging query. |
413 |
def contextIsProduct(self): |
414 |
return IProduct.providedBy(self.context) |
|
415 |
||
4508.3.32
by Graham Binns
Added a list of products that don't use Malone to the bug target not_uses_malone macro |
416 |
def contextIsProject(self): |
10326.1.1
by Henning Eggers
Mechanically renamed IProject* to IProjectGroup*. |
417 |
return IProjectGroup.providedBy(self.context) |
4508.3.32
by Graham Binns
Added a list of products that don't use Malone to the bug target not_uses_malone macro |
418 |
|
9366.2.1
by Tom Berger
make it possible to disable th web interface filebug for ubuntu |
419 |
def targetIsUbuntu(self): |
420 |
ubuntu = getUtility(ILaunchpadCelebrities).ubuntu |
|
421 |
return (self.context == ubuntu or |
|
422 |
(IMaloneApplication.providedBy(self.context) and |
|
423 |
self.request.form.get('field.bugtarget.distribution') == |
|
9731.1.1
by Tom Berger
disable +filebug redirection for ubuntu packages |
424 |
ubuntu.name)) |
9366.2.1
by Tom Berger
make it possible to disable th web interface filebug for ubuntu |
425 |
|
3691.249.23
by Brad Bollenbach
fix test failures |
426 |
def getPackageNameFieldCSSClass(self): |
427 |
"""Return the CSS class for the packagename field."""
|
|
428 |
if self.widget_errors.get("packagename"): |
|
429 |
return 'error' |
|
430 |
else: |
|
431 |
return '' |
|
432 |
||
433 |
def validate(self, data): |
|
434 |
"""Make sure the package name, if provided, exists in the distro."""
|
|
4338.3.10
by Gavin Panella
Vastly improved bug form behaviour. |
435 |
# The comment field is only required if filing a new bug.
|
436 |
if self.submit_bug_action.submitted(): |
|
5243.3.7
by Jonathan Knowles
Removing prototype length validator function. |
437 |
comment = data.get('comment') |
12337.3.11
by Curtis Hovey
Replaced doctest with unittest. Updated the validation method to use the errors |
438 |
# The widget only exposes the error message. The private
|
439 |
# attr contains the real error.
|
|
440 |
widget_error = self.widgets.get('comment')._error |
|
441 |
if widget_error and isinstance(widget_error.errors, TooLong): |
|
442 |
self.setFieldError('comment', |
|
443 |
'The description is too long. If you have lots '
|
|
444 |
'text to add, attach a file to the bug instead.') |
|
445 |
elif not comment or widget_error is not None: |
|
12337.3.1
by Curtis Hovey
Used NoneableDescription to ensure empty or whitespace-only bug comments are |
446 |
self.setFieldError( |
447 |
'comment', "Provide details about the issue.") |
|
4338.3.10
by Gavin Panella
Vastly improved bug form behaviour. |
448 |
# Check a bug has been selected when the user wants to
|
449 |
# subscribe to an existing bug.
|
|
450 |
elif self.this_is_my_bug_action.submitted(): |
|
451 |
if not data.get('bug_already_reported_as'): |
|
5309.1.3
by Edwin Grubbs
The <link> tag for referencing atom feeds in other web pages is now |
452 |
self.setFieldError('bug_already_reported_as', |
453 |
"Please choose a bug.") |
|
4338.3.10
by Gavin Panella
Vastly improved bug form behaviour. |
454 |
else: |
4338.3.23
by Gavin Panella
Changes suggested by Tim Penhey in review. |
455 |
# We only care about those two actions.
|
4338.3.10
by Gavin Panella
Vastly improved bug form behaviour. |
456 |
pass
|
4338.3.5
by Gavin Panella
Add handling for the Yes/No radio buttons. |
457 |
|
3691.249.23
by Brad Bollenbach
fix test failures |
458 |
# We have to poke at the packagename value directly in the
|
459 |
# request, because if validation failed while getting the
|
|
460 |
# widget's data, it won't appear in the data dict.
|
|
461 |
form = self.request.form |
|
462 |
if form.get("packagename_option") == "choose": |
|
463 |
packagename = form.get("field.packagename") |
|
464 |
if packagename: |
|
465 |
if IDistribution.providedBy(self.context): |
|
466 |
distribution = self.context |
|
3691.249.33
by Bjorn Tillenius
fix test failures, unbreak the +package page |
467 |
elif 'distribution' in data: |
468 |
distribution = data['distribution'] |
|
3691.249.23
by Brad Bollenbach
fix test failures |
469 |
else: |
470 |
assert IDistributionSourcePackage.providedBy(self.context) |
|
471 |
distribution = self.context.distribution |
|
472 |
||
473 |
try: |
|
474 |
distribution.guessPackageNames(packagename) |
|
475 |
except NotFoundError: |
|
9760.8.1
by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase. |
476 |
if distribution.series: |
477 |
# If a distribution doesn't have any series,
|
|
3691.249.33
by Bjorn Tillenius
fix test failures, unbreak the +package page |
478 |
# it won't have any source packages published at
|
479 |
# all, so we set the error only if there are
|
|
9760.8.1
by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase. |
480 |
# series.
|
3691.249.33
by Bjorn Tillenius
fix test failures, unbreak the +package page |
481 |
packagename_error = ( |
482 |
'"%s" does not exist in %s. Please choose a ' |
|
3691.249.34
by Bjorn Tillenius
make the guided filebug ui more like the support tracker's. |
483 |
"different package. If you're unsure, please "
|
3691.249.33
by Bjorn Tillenius
fix test failures, unbreak the +package page |
484 |
'select "I don\'t know"' % ( |
485 |
packagename, distribution.displayname)) |
|
486 |
self.setFieldError("packagename", packagename_error) |
|
3691.249.23
by Brad Bollenbach
fix test failures |
487 |
else: |
9565.2.1
by Gary Poster
fix vhost breadcrumbs so that we do not duplicate information |
488 |
self.setFieldError("packagename", |
5309.1.3
by Edwin Grubbs
The <link> tag for referencing atom feeds in other web pages is now |
489 |
"Please enter a package name") |
3553.3.11
by Brad Bollenbach
checkpoint |
490 |
|
4486.4.15
by Graham Binns
Review-suggested changes |
491 |
# If we've been called from the frontpage filebug forms we must check
|
492 |
# that whatever product or distro is having a bug filed against it
|
|
4486.4.25
by Graham Binns
Fixed a typo |
493 |
# actually uses Malone for its bug tracking.
|
4486.4.15
by Graham Binns
Review-suggested changes |
494 |
product_or_distro = self.getProductOrDistroFromContext() |
495 |
if (product_or_distro is not None and |
|
11411.7.1
by j.c.sackett
Fixed majority of official_malone calls in code-space. Still need to fix templates. |
496 |
product_or_distro.bug_tracking_usage != ServiceUsage.LAUNCHPAD): |
5309.1.3
by Edwin Grubbs
The <link> tag for referencing atom feeds in other web pages is now |
497 |
self.setFieldError( |
498 |
'bugtarget', |
|
499 |
"%s does not use Launchpad as its bug tracker " % |
|
500 |
product_or_distro.displayname) |
|
4486.4.15
by Graham Binns
Review-suggested changes |
501 |
|
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
502 |
def setUpWidgets(self): |
4338.3.25
by Gavin Panella
Revert to using showOptionalMarker after discussion with BjornT. |
503 |
"""Customize the onKeyPress event of the package name chooser."""
|
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
504 |
LaunchpadFormView.setUpWidgets(self) |
505 |
||
506 |
if "packagename" in self.field_names: |
|
507 |
self.widgets["packagename"].onKeyPress = ( |
|
508 |
"selectWidget('choose', event)") |
|
509 |
||
8426.8.1
by Graham Binns
Added the duplicate finder overlay. Woot, etc. |
510 |
def setUpFields(self): |
511 |
"""Set up the form fields. See `LaunchpadFormView`."""
|
|
512 |
super(FileBugViewBase, self).setUpFields() |
|
513 |
||
514 |
# Override the vocabulary for the subscribe_to_existing_bug
|
|
515 |
# field.
|
|
516 |
subscribe_field = Choice( |
|
517 |
__name__='subscribe_to_existing_bug', |
|
8426.8.8
by Graham Binns
Fixed a a silly pagetest error. |
518 |
title=u'Subscribe to this bug', |
8426.8.1
by Graham Binns
Added the duplicate finder overlay. Woot, etc. |
519 |
vocabulary=SUBSCRIBE_TO_BUG_VOCABULARY, |
520 |
required=True, default=False) |
|
521 |
||
522 |
self.form_fields = self.form_fields.omit('subscribe_to_existing_bug') |
|
8426.8.5
by Graham Binns
Fixed some lint. |
523 |
self.form_fields += formlib.form.Fields(subscribe_field) |
8426.8.1
by Graham Binns
Added the duplicate finder overlay. Woot, etc. |
524 |
|
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
525 |
def contextUsesMalone(self): |
526 |
"""Does the context use Malone as its official bugtracker?"""
|
|
10326.1.1
by Henning Eggers
Mechanically renamed IProject* to IProjectGroup*. |
527 |
if IProjectGroup.providedBy(self.context): |
3764.1.4
by Bjorn Tillenius
refactor the filebug views to reduce code duplication. |
528 |
products_using_malone = [ |
529 |
product for product in self.context.products |
|
11411.7.1
by j.c.sackett
Fixed majority of official_malone calls in code-space. Still need to fix templates. |
530 |
if product.bug_tracking_usage == ServiceUsage.LAUNCHPAD] |
3764.1.4
by Bjorn Tillenius
refactor the filebug views to reduce code duplication. |
531 |
return len(products_using_malone) > 0 |
532 |
else: |
|
11411.7.27
by j.c.sackett
Lint fixes. |
533 |
bug_tracking_usage = self.getMainContext().bug_tracking_usage |
534 |
return bug_tracking_usage == ServiceUsage.LAUNCHPAD |
|
3764.1.4
by Bjorn Tillenius
refactor the filebug views to reduce code duplication. |
535 |
|
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
536 |
def shouldSelectPackageName(self): |
3691.249.23
by Brad Bollenbach
fix test failures |
537 |
"""Should the radio button to select a package be selected?"""
|
538 |
return ( |
|
539 |
self.request.form.get("field.packagename") or |
|
540 |
self.initial_values.get("packagename")) |
|
541 |
||
542 |
def handleSubmitBugFailure(self, action, data, errors): |
|
543 |
return self.showFileBugForm() |
|
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
544 |
|
545 |
@action("Submit Bug Report", name="submit_bug", |
|
3691.249.23
by Brad Bollenbach
fix test failures |
546 |
failure=handleSubmitBugFailure) |
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
547 |
def submit_bug_action(self, action, data): |
2764.2.1
by Brad Bollenbach
apply my +filebug patch on a fresh new bzr branch |
548 |
"""Add a bug to this IBugTarget."""
|
3691.320.2
by Bjorn Tillenius
support adding extra description to the filed bug. |
549 |
title = data["title"] |
3691.320.9
by Bjorn Tillenius
display feedback of what was added to the bug report. |
550 |
comment = data["comment"].rstrip() |
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
551 |
packagename = data.get("packagename") |
3691.249.20
by Brad Bollenbach
Get the +package filebug workflow working again, using the same form and views as the other filebug workflows |
552 |
security_related = data.get("security_related", False) |
553 |
distribution = data.get( |
|
554 |
"distribution", getUtility(ILaunchBag).distribution) |
|
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
555 |
|
2846.1.36
by Brad Bollenbach
more small fixes |
556 |
context = self.context |
557 |
if distribution is not None: |
|
3691.249.20
by Brad Bollenbach
Get the +package filebug workflow working again, using the same form and views as the other filebug workflows |
558 |
# We're being called from the generic bug filing form, so
|
559 |
# manually set the chosen distribution as the context.
|
|
2846.1.36
by Brad Bollenbach
more small fixes |
560 |
context = distribution |
12811.2.5
by Ian Booth
Fix tests |
561 |
elif IProjectGroup.providedBy(context): |
562 |
context = data['product'] |
|
3778.2.3
by Bjorn Tillenius
make the general +filebug page work. |
563 |
elif IMaloneApplication.providedBy(context): |
3778.2.11
by Bjorn Tillenius
clean-up. |
564 |
context = data['bugtarget'] |
2764.2.1
by Brad Bollenbach
apply my +filebug patch on a fresh new bzr branch |
565 |
|
3327.1.7
by Brad Bollenbach
checkpoint |
566 |
# Ensure that no package information is used, if the user
|
567 |
# enters a package name but then selects "I don't know".
|
|
568 |
if self.request.form.get("packagename_option") == "none": |
|
569 |
packagename = None |
|
570 |
||
3553.3.17
by Brad Bollenbach
revert the createBug API change that collapsed security_related and private into just security_related |
571 |
# Security bugs are always private when filed, but can be disclosed
|
572 |
# after they've been reported.
|
|
573 |
if security_related: |
|
574 |
private = True |
|
575 |
else: |
|
576 |
private = False |
|
577 |
||
12289.7.1
by William Grant
Run text_to_html over the bug acknowledgement message before displaying it. |
578 |
linkified_ack = structured(FormattersAPI( |
12289.7.3
by William Grant
Remove the margin from the bottom paragraph of the bug acknowledgement notification, since the notification div has its own padding. |
579 |
self.getAcknowledgementMessage(self.context)).text_to_html( |
580 |
last_paragraph_class="last")) |
|
12289.7.1
by William Grant
Run text_to_html over the bug acknowledgement message before displaying it. |
581 |
notifications = [linkified_ack] |
3691.415.1
by Bjorn Tillenius
factor out the creation of CreateBugParams in FileBugBaseView. |
582 |
params = CreateBugParams( |
583 |
title=title, comment=comment, owner=self.user, |
|
3691.415.2
by Bjorn Tillenius
add a Tags: field to the advanced filebug page. |
584 |
security_related=security_related, private=private, |
585 |
tags=data.get('tags')) |
|
2846.1.36
by Brad Bollenbach
more small fixes |
586 |
if IDistribution.providedBy(context) and packagename: |
2846.1.32
by Brad Bollenbach
simplify and fix package name guessing |
587 |
# We don't know if the package name we got was a source or binary
|
588 |
# package name, so let the Soyuz API figure it out for us.
|
|
3691.315.12
by kiko
The BinaryAndSourcePackageNameVocabulary no longer uses name as its object, so account for that in browser code |
589 |
packagename = str(packagename.name) |
1716.3.41
by kiko
Fix for bug 31367: Specifying a non-published binary package when filing a bug causes an oops. Change the add bug process to ignore the package if it was never published in the distribution, and test it using Gentoo (which now uses Malone officially, yay. Or at least in sampledata). This fixes a topcrasher, so hooray for us. |
590 |
try: |
591 |
sourcepackagename, binarypackagename = ( |
|
3504.1.58
by kiko
Hack Distribution.getPackageNames around a bit: rename it to guessPackageNames to make clear it is a best-effort and might not give the right answer; test the fact that it restricts publication to a single distribution, and ensure that the code does that; revamp comments. |
592 |
context.guessPackageNames(packagename)) |
1716.3.41
by kiko
Fix for bug 31367: Specifying a non-published binary package when filing a bug causes an oops. Change the add bug process to ignore the package if it was never published in the distribution, and test it using Gentoo (which now uses Malone officially, yay. Or at least in sampledata). This fixes a topcrasher, so hooray for us. |
593 |
except NotFoundError: |
3504.1.58
by kiko
Hack Distribution.getPackageNames around a bit: rename it to guessPackageNames to make clear it is a best-effort and might not give the right answer; test the fact that it restricts publication to a single distribution, and ensure that the code does that; revamp comments. |
594 |
# guessPackageNames may raise NotFoundError. It would be
|
1716.3.41
by kiko
Fix for bug 31367: Specifying a non-published binary package when filing a bug causes an oops. Change the add bug process to ignore the package if it was never published in the distribution, and test it using Gentoo (which now uses Malone officially, yay. Or at least in sampledata). This fixes a topcrasher, so hooray for us. |
595 |
# nicer to allow people to indicate a package even if
|
596 |
# never published, but the quick fix for now is to note
|
|
597 |
# the issue and move on.
|
|
3691.320.16
by Bjorn Tillenius
fix test failure. |
598 |
notifications.append( |
3691.320.9
by Bjorn Tillenius
display feedback of what was added to the bug report. |
599 |
"The package %s is not published in %s; the " |
3553.3.17
by Brad Bollenbach
revert the createBug API change that collapsed security_related and private into just security_related |
600 |
"bug was targeted only to the distribution."
|
601 |
% (packagename, context.displayname)) |
|
3691.415.1
by Bjorn Tillenius
factor out the creation of CreateBugParams in FileBugBaseView. |
602 |
params.comment += ( |
603 |
"\r\n\r\nNote: the original reporter indicated " |
|
604 |
"the bug was in package %r; however, that package " |
|
605 |
"was not published in %s." % ( |
|
606 |
packagename, context.displayname)) |
|
1716.3.41
by kiko
Fix for bug 31367: Specifying a non-published binary package when filing a bug causes an oops. Change the add bug process to ignore the package if it was never published in the distribution, and test it using Gentoo (which now uses Malone officially, yay. Or at least in sampledata). This fixes a topcrasher, so hooray for us. |
607 |
else: |
3598.1.31
by Brad Bollenbach
response to code review |
608 |
context = context.getSourcePackage(sourcepackagename.name) |
3691.415.1
by Bjorn Tillenius
factor out the creation of CreateBugParams in FileBugBaseView. |
609 |
params.binarypackagename = binarypackagename |
2764.2.1
by Brad Bollenbach
apply my +filebug patch on a fresh new bzr branch |
610 |
|
3691.342.1
by Bjorn Tillenius
make it possible to specify the default bug summary in the +filebug blob. |
611 |
extra_data = self.extra_data |
3691.320.9
by Bjorn Tillenius
display feedback of what was added to the bug report. |
612 |
if extra_data.extra_description: |
613 |
params.comment = "%s\n\n%s" % ( |
|
614 |
params.comment, extra_data.extra_description) |
|
615 |
notifications.append( |
|
616 |
'Additional information was added to the bug description.') |
|
617 |
||
4374.1.2
by David Murphy
Incorporated review feedback from BjornT. Improved doctest, and switched change to modifiy params instead of bug. |
618 |
if extra_data.private: |
619 |
params.private = extra_data.private |
|
620 |
||
3691.320.1
by Bjorn Tillenius
add a test for FileBugBaseView. |
621 |
self.added_bug = bug = context.createBug(params) |
8137.17.24
by Barry Warsaw
thread merge |
622 |
|
623 |
# Apply any extra options given by a bug supervisor.
|
|
624 |
bugtask = self.added_bug.default_bugtask |
|
12811.2.11
by Ian Booth
Code review fixes and ensure changing products hides/shows the relevant bug detail fields |
625 |
if IHasBugSupervisor.providedBy(context): |
626 |
if self.user.inTeam(context.bug_supervisor): |
|
627 |
if 'assignee' in data: |
|
628 |
bugtask.transitionToAssignee(data['assignee']) |
|
629 |
if 'status' in data: |
|
630 |
bugtask.transitionToStatus(data['status'], self.user) |
|
631 |
if 'importance' in data: |
|
632 |
bugtask.transitionToImportance( |
|
633 |
data['importance'], self.user) |
|
634 |
if 'milestone' in data: |
|
635 |
bugtask.milestone = data['milestone'] |
|
8137.17.24
by Barry Warsaw
thread merge |
636 |
|
3691.320.3
by Bjorn Tillenius
support more than one inline part, which will be added as comments. |
637 |
for comment in extra_data.comments: |
638 |
bug.newMessage(self.user, bug.followup_subject(), comment) |
|
3691.320.9
by Bjorn Tillenius
display feedback of what was added to the bug report. |
639 |
notifications.append( |
640 |
'A comment with additional information was added to the'
|
|
641 |
' bug report.') |
|
3691.320.3
by Bjorn Tillenius
support more than one inline part, which will be added as comments. |
642 |
|
5491.1.14
by Graham Binns
Review changes. |
643 |
# XXX 2007-01-19 gmb:
|
644 |
# We need to have a proper FileUpload widget rather than
|
|
645 |
# this rather hackish solution.
|
|
5491.1.10
by Graham Binns
Put attachment handling with existing attachment handling code. |
646 |
attachment = self.request.form.get(self.widgets['filecontent'].name) |
5491.1.20
by Graham Binns
Fixed bug 186564. |
647 |
if attachment or extra_data.attachments: |
3691.365.1
by Bjorn Tillenius
collapse the attachments uploaded on +storeblob into one comment. |
648 |
# Attach all the comments to a single empty comment.
|
649 |
attachment_comment = bug.newMessage( |
|
650 |
owner=self.user, subject=bug.followup_subject(), content=None) |
|
5491.1.10
by Graham Binns
Put attachment handling with existing attachment handling code. |
651 |
|
652 |
# Deal with attachments added in the filebug form.
|
|
5491.1.20
by Graham Binns
Fixed bug 186564. |
653 |
if attachment: |
5491.1.10
by Graham Binns
Put attachment handling with existing attachment handling code. |
654 |
# We convert slashes in filenames to hyphens to avoid
|
655 |
# problems.
|
|
656 |
filename = attachment.filename.replace('/', '-') |
|
657 |
||
658 |
# If the user hasn't entered a description for the
|
|
659 |
# attachment we use its name.
|
|
660 |
file_description = None |
|
661 |
if 'attachment_description' in data: |
|
662 |
file_description = data['attachment_description'] |
|
5491.1.13
by Graham Binns
Review changes for sinzui. |
663 |
if file_description is None: |
5491.1.10
by Graham Binns
Put attachment handling with existing attachment handling code. |
664 |
file_description = filename |
665 |
||
666 |
bug.addAttachment( |
|
6655.4.5
by Gavin Panella
Test fixes for addAttachment signature change. |
667 |
owner=self.user, data=StringIO(data['filecontent']), |
5491.1.10
by Graham Binns
Put attachment handling with existing attachment handling code. |
668 |
filename=filename, description=file_description, |
669 |
comment=attachment_comment, is_patch=data['patch']) |
|
670 |
||
671 |
notifications.append( |
|
672 |
'The file "%s" was attached to the bug report.' % |
|
673 |
cgi.escape(filename)) |
|
674 |
||
5491.1.16
by Graham Binns
Fixed some spurious test failures. |
675 |
for attachment in extra_data.attachments: |
7675.547.8
by Graham Binns
Hurrah, the +filebug form now works with processed apport blob jobs. |
676 |
bug.linkAttachment( |
677 |
owner=self.user, file_alias=attachment['file_alias'], |
|
5491.1.16
by Graham Binns
Fixed some spurious test failures. |
678 |
description=attachment['description'], |
11634.2.9
by Robert Collins
Another missed fixture stateless-use. |
679 |
comment=attachment_comment, |
680 |
send_notifications=False) |
|
5491.1.16
by Graham Binns
Fixed some spurious test failures. |
681 |
notifications.append( |
682 |
'The file "%s" was attached to the bug report.' % |
|
7675.547.8
by Graham Binns
Hurrah, the +filebug form now works with processed apport blob jobs. |
683 |
cgi.escape(attachment['file_alias'].filename)) |
5491.1.16
by Graham Binns
Fixed some spurious test failures. |
684 |
|
4375.1.1
by David Murphy
Added the ability to subscribe people via the extra data file (used by Apport). |
685 |
if extra_data.subscribers: |
686 |
# Subscribe additional subscribers to this bug
|
|
687 |
for subscriber in extra_data.subscribers: |
|
688 |
valid_person_vocabulary = ValidPersonOrTeamVocabulary() |
|
689 |
try: |
|
690 |
person = valid_person_vocabulary.getTermByToken( |
|
691 |
subscriber).value |
|
4375.1.4
by David Murphy
Changed field name to Subscribers (was Subscribe). |
692 |
except LookupError: |
693 |
# We cannot currently pass this error up to the user, so
|
|
694 |
# we'll just ignore it.
|
|
695 |
pass
|
|
696 |
else: |
|
5454.1.5
by Tom Berger
record who created each bug subscription, and display the result in the title of the subscriber link |
697 |
bug.subscribe(person, self.user) |
4375.1.1
by David Murphy
Added the ability to subscribe people via the extra data file (used by Apport). |
698 |
notifications.append( |
699 |
'%s has been subscribed to this bug.' % |
|
700 |
person.displayname) |
|
701 |
||
9360.3.1
by Abel Deuring
create links between a bug and a HWSubmission if bug data provided by apport contains the header HWDB-Submission |
702 |
submission_set = getUtility(IHWSubmissionSet) |
703 |
for submission_key in extra_data.hwdb_submission_keys: |
|
704 |
submission = submission_set.getBySubmissionKey( |
|
705 |
submission_key, self.user) |
|
706 |
if submission is not None: |
|
707 |
bug.linkHWSubmission(submission) |
|
708 |
||
2828.1.1
by Brad Bollenbach
add a feedback message for a successfully opened bug |
709 |
# Give the user some feedback on the bug just opened.
|
3691.320.9
by Bjorn Tillenius
display feedback of what was added to the bug report. |
710 |
for notification in notifications: |
711 |
self.request.response.addNotification(notification) |
|
4374.1.1
by David Murphy
Added support for a Private field in the extra data file. This sets the bugs private flag accordingly. |
712 |
if bug.security_related: |
5594.1.11
by Maris Fogels
Beautified the addNotification(structured(...)) construct. |
713 |
self.request.response.addNotification( |
714 |
structured( |
|
5512.1.5
by Matthew Paul Thomas
Fixes a typo (ironic, that). |
715 |
'Security-related bugs are by default private '
|
5512.1.1
by Matthew Paul Thomas
Fixes bug 174086 ('Publicly' misspelled as 'publically' after reporting security bug). |
716 |
'(visible only to their direct subscribers). '
|
717 |
'You may choose to <a href="+secrecy">publicly '
|
|
5594.1.7
by Maris Fogels
Fixed all of the calls to addNotification() that contain HTML so that they use the structured() class. |
718 |
'disclose</a> this bug.')) |
4374.1.1
by David Murphy
Added support for a Private field in the extra data file. This sets the bugs private flag accordingly. |
719 |
if bug.private and not bug.security_related: |
5594.1.11
by Maris Fogels
Beautified the addNotification(structured(...)) construct. |
720 |
self.request.response.addNotification( |
721 |
structured( |
|
5512.1.1
by Matthew Paul Thomas
Fixes bug 174086 ('Publicly' misspelled as 'publically' after reporting security bug). |
722 |
'This bug report has been marked private '
|
723 |
'(visible only to its direct subscribers). '
|
|
5594.1.28
by Maris Fogels
Merge from RF; resolved one conflict. |
724 |
'You may choose to <a href="+secrecy">change this</a>.')) |
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
725 |
|
726 |
self.request.response.redirect(canonical_url(bug.bugtasks[0])) |
|
3691.249.29
by Brad Bollenbach
add a basic filebug steps macro, for mpt to tweak |
727 |
|
8401.1.1
by Graham Binns
The default action when the user clicks "this is my bug" on the guided |
728 |
@action("Yes, this is the bug I'm trying to report", |
729 |
name="this_is_my_bug", failure=handleSubmitBugFailure) |
|
4338.3.2
by Gavin Panella
Improve duplicate list: |
730 |
def this_is_my_bug_action(self, action, data): |
4338.3.23
by Gavin Panella
Changes suggested by Tim Penhey in review. |
731 |
"""Subscribe to the bug suggested."""
|
4338.3.12
by Gavin Panella
Subscribe to selected bug and notify user. |
732 |
bug = data.get('bug_already_reported_as') |
8426.8.1
by Graham Binns
Added the duplicate finder overlay. Woot, etc. |
733 |
subscribe = data.get('subscribe_to_existing_bug') |
4338.3.12
by Gavin Panella
Subscribe to selected bug and notify user. |
734 |
|
8401.1.1
by Graham Binns
The default action when the user clicks "this is my bug" on the guided |
735 |
if bug.isUserAffected(self.user): |
4338.3.12
by Gavin Panella
Subscribe to selected bug and notify user. |
736 |
self.request.response.addNotification( |
8401.1.1
by Graham Binns
The default action when the user clicks "this is my bug" on the guided |
737 |
"This bug is already marked as affecting you.") |
4338.3.12
by Gavin Panella
Subscribe to selected bug and notify user. |
738 |
else: |
8401.1.1
by Graham Binns
The default action when the user clicks "this is my bug" on the guided |
739 |
bug.markUserAffected(self.user) |
4338.3.12
by Gavin Panella
Subscribe to selected bug and notify user. |
740 |
self.request.response.addNotification( |
8401.1.1
by Graham Binns
The default action when the user clicks "this is my bug" on the guided |
741 |
"This bug has been marked as affecting you.") |
4338.3.12
by Gavin Panella
Subscribe to selected bug and notify user. |
742 |
|
8426.8.1
by Graham Binns
Added the duplicate finder overlay. Woot, etc. |
743 |
# If the user wants to be subscribed, subscribe them, unless
|
744 |
# they're already subscribed.
|
|
745 |
if subscribe: |
|
746 |
if bug.isSubscribed(self.user): |
|
747 |
self.request.response.addNotification( |
|
748 |
"You are already subscribed to this bug.") |
|
749 |
else: |
|
750 |
bug.subscribe(self.user, self.user) |
|
751 |
self.request.response.addNotification( |
|
752 |
"You have been subscribed to this bug.") |
|
753 |
||
4338.3.23
by Gavin Panella
Changes suggested by Tim Penhey in review. |
754 |
self.next_url = canonical_url(bug.bugtasks[0]) |
4338.3.2
by Gavin Panella
Improve duplicate list: |
755 |
|
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
756 |
def showFileBugForm(self): |
757 |
"""Override this method in base classes to show the filebug form."""
|
|
758 |
raise NotImplementedError |
|
759 |
||
9947.2.8
by Graham Binns
Merged old dupefinder work. |
760 |
@property
|
10017.3.4
by Graham Binns
De-hackified the loading of the +filebug form and resetting of the dupe search URL. |
761 |
def inline_filebug_base_url(self): |
762 |
"""Return the base URL for the current request.
|
|
763 |
||
764 |
This allows us to build URLs in Javascript without guessing at
|
|
765 |
domains.
|
|
766 |
"""
|
|
767 |
return self.request.getRootURL(None) |
|
768 |
||
769 |
@property
|
|
9947.2.8
by Graham Binns
Merged old dupefinder work. |
770 |
def inline_filebug_form_url(self): |
10017.3.4
by Graham Binns
De-hackified the loading of the +filebug form and resetting of the dupe search URL. |
771 |
"""Return the URL to the inline filebug form.
|
9947.2.8
by Graham Binns
Merged old dupefinder work. |
772 |
|
773 |
If a token was passed to this view, it will be be passed through
|
|
774 |
to the inline bug filing form via the returned URL.
|
|
775 |
"""
|
|
9947.2.21
by Graham Binns
Review changes for Gavin. |
776 |
url = canonical_url(self.context, view_name='+filebug-inline-form') |
9947.2.8
by Graham Binns
Merged old dupefinder work. |
777 |
if self.extra_data_token is not None: |
778 |
url = urlappend(url, self.extra_data_token) |
|
779 |
return url |
|
780 |
||
781 |
@property
|
|
782 |
def duplicate_search_url(self): |
|
10017.3.4
by Graham Binns
De-hackified the loading of the +filebug form and resetting of the dupe search URL. |
783 |
"""Return the URL to the inline duplicate search view."""
|
9947.2.21
by Graham Binns
Review changes for Gavin. |
784 |
url = canonical_url(self.context, view_name='+filebug-show-similar') |
9947.2.8
by Graham Binns
Merged old dupefinder work. |
785 |
if self.extra_data_token is not None: |
786 |
url = urlappend(url, self.extra_data_token) |
|
787 |
return url |
|
788 |
||
3691.320.2
by Bjorn Tillenius
support adding extra description to the filed bug. |
789 |
def publishTraverse(self, request, name): |
790 |
"""See IBrowserPublisher."""
|
|
3691.342.1
by Bjorn Tillenius
make it possible to specify the default bug summary in the +filebug blob. |
791 |
if self.extra_data_token is not None: |
3691.342.2
by Bjorn Tillenius
make it possible to specify the default bug summary in the +filebug blob. |
792 |
# publishTraverse() has already been called once before,
|
793 |
# which means that he URL contains more path components than
|
|
794 |
# expected.
|
|
3691.320.10
by Bjorn Tillenius
make publishTraverse work properly when it can't find the tokens. |
795 |
raise NotFound(self, name, request=request) |
796 |
||
7675.547.6
by Graham Binns
FileBugData parsed from a blob by a ProcessApportBlobJob is now used during the filebug process, rather than parsing the blob in the request. |
797 |
self.extra_data_token = name |
798 |
if self.extra_data_processing_job is None: |
|
3691.320.10
by Bjorn Tillenius
make publishTraverse work properly when it can't find the tokens. |
799 |
# The URL might be mistyped, or the blob has expired.
|
4664.1.1
by Curtis Hovey
Normalized comments for bug 3732. |
800 |
# XXX: Bjorn Tillenius 2006-01-15:
|
801 |
# We should handle this case better, since a user might
|
|
3691.320.11
by Bjorn Tillenius
raise NotFound if the token can't be found. |
802 |
# come to this page when finishing his account
|
803 |
# registration. In that case we should inform the user
|
|
804 |
# that the blob has expired.
|
|
805 |
raise NotFound(self, name, request=request) |
|
7675.547.6
by Graham Binns
FileBugData parsed from a blob by a ProcessApportBlobJob is now used during the filebug process, rather than parsing the blob in the request. |
806 |
else: |
807 |
self.extra_data = self.extra_data_processing_job.getFileBugData() |
|
808 |
||
3691.320.2
by Bjorn Tillenius
support adding extra description to the filed bug. |
809 |
return self |
810 |
||
811 |
def browserDefault(self, request): |
|
812 |
"""See IBrowserPublisher."""
|
|
813 |
return self, () |
|
814 |
||
3938.1.1
by kiko
Implement first cut at a better +filebug page for non-Malone-using contexts. Factor out doesn't-use-Malone code to a macro. Infrastructure: provide a fmt:link for HasGotchiAndEmblemFormatterAPI, add a helpwanted CSS message class, add a distrosourcepackages to Product, and prejoin the packaging query. |
815 |
def getProductOrDistroFromContext(self): |
816 |
"""Return the product or distribution relative to the context.
|
|
3938.1.5
by kiko
Fix up comment |
817 |
|
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
818 |
For instance, if the context is an IDistroSeries, return the
|
3938.1.5
by kiko
Fix up comment |
819 |
distribution related to it. Will return None if the context is
|
820 |
not related to a product or a distro.
|
|
821 |
"""
|
|
3938.1.10
by kiko
Fix wrapping even betterly |
822 |
context = self.context |
823 |
if IProduct.providedBy(context) or IDistribution.providedBy(context): |
|
824 |
return context |
|
825 |
elif IProductSeries.providedBy(context): |
|
826 |
return context.product |
|
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
827 |
elif (IDistroSeries.providedBy(context) or |
3938.1.10
by kiko
Fix wrapping even betterly |
828 |
IDistributionSourcePackage.providedBy(context)): |
829 |
return context.distribution |
|
3938.1.1
by kiko
Implement first cut at a better +filebug page for non-Malone-using contexts. Factor out doesn't-use-Malone code to a macro. Infrastructure: provide a fmt:link for HasGotchiAndEmblemFormatterAPI, add a helpwanted CSS message class, add a distrosourcepackages to Product, and prejoin the packaging query. |
830 |
else: |
831 |
return None |
|
832 |
||
4338.3.25
by Gavin Panella
Revert to using showOptionalMarker after discussion with BjornT. |
833 |
def showOptionalMarker(self, field_name): |
4338.4.6
by Gavin Panella
Add docstrings and other small changes. |
834 |
"""See `LaunchpadFormView`."""
|
4338.3.25
by Gavin Panella
Revert to using showOptionalMarker after discussion with BjornT. |
835 |
# The comment field _is_ required, but only when filing the
|
836 |
# bug. Since the same form is also used for subscribing to a
|
|
837 |
# bug, the comment field in the schema cannot be marked
|
|
838 |
# required=True. Instead it's validated in
|
|
839 |
# FileBugViewBase.validate. So... we need to suppress the
|
|
840 |
# "(Optional)" marker.
|
|
841 |
if field_name == 'comment': |
|
842 |
return False |
|
843 |
else: |
|
844 |
return LaunchpadFormView.showOptionalMarker(self, field_name) |
|
845 |
||
4338.4.4
by Gavin Panella
More logic to get a relevant bugtask for display, and how to cope if one cannot be found. |
846 |
def getRelevantBugTask(self, bug): |
5723.4.5
by Gavin Panella
Use BjornT's suggested implementation; remove XXX comment. |
847 |
"""Return the first bugtask from this bug that's relevant in the
|
848 |
current context.
|
|
4338.4.9
by Gavin Panella
Address review comments from spiv. |
849 |
|
5723.4.5
by Gavin Panella
Use BjornT's suggested implementation; remove XXX comment. |
850 |
This is a pragmatic function, not general purpose. It tries to
|
851 |
find a bugtask that can be used to pretty-up the page, making
|
|
852 |
it more user-friendly and informative. It's not concerned by
|
|
853 |
total accuracy, and will return the first 'relevant' bugtask
|
|
854 |
it finds even if there are other candidates. Be warned!
|
|
4338.4.6
by Gavin Panella
Add docstrings and other small changes. |
855 |
"""
|
4338.4.4
by Gavin Panella
More logic to get a relevant bugtask for display, and how to cope if one cannot be found. |
856 |
context = self.context |
857 |
||
10326.1.1
by Henning Eggers
Mechanically renamed IProject* to IProjectGroup*. |
858 |
if IProjectGroup.providedBy(context): |
5723.4.5
by Gavin Panella
Use BjornT's suggested implementation; remove XXX comment. |
859 |
contexts = set(context.products) |
4338.4.4
by Gavin Panella
More logic to get a relevant bugtask for display, and how to cope if one cannot be found. |
860 |
else: |
5723.4.5
by Gavin Panella
Use BjornT's suggested implementation; remove XXX comment. |
861 |
contexts = [context] |
4338.4.4
by Gavin Panella
More logic to get a relevant bugtask for display, and how to cope if one cannot be found. |
862 |
|
5723.4.5
by Gavin Panella
Use BjornT's suggested implementation; remove XXX comment. |
863 |
for bugtask in bug.bugtasks: |
864 |
if bugtask.target in contexts or bugtask.pillar in contexts: |
|
4338.4.6
by Gavin Panella
Add docstrings and other small changes. |
865 |
return bugtask |
5723.4.5
by Gavin Panella
Use BjornT's suggested implementation; remove XXX comment. |
866 |
return None |
4338.4.4
by Gavin Panella
More logic to get a relevant bugtask for display, and how to cope if one cannot be found. |
867 |
|
7251.2.11
by Gavin Panella
Move the 'append the distro guidelines to the distro source package guidelines' logic into the view. |
868 |
@property
|
7251.2.12
by Gavin Panella
Display bug reporting guidelines when bugs are reported via the bugs front page. |
869 |
def bugtarget(self): |
870 |
"""The bugtarget we're currently assuming.
|
|
871 |
||
872 |
The same as the context.
|
|
873 |
"""
|
|
874 |
return self.context |
|
875 |
||
10977.7.1
by Abel Deuring
show customized bug report acknowledgement message in notifications |
876 |
default_bug_reported_acknowledgement = "Thank you for your bug report." |
877 |
||
878 |
def getAcknowledgementMessage(self, context): |
|
879 |
"""An acknowlegement message displayed to the user."""
|
|
10977.7.4
by Abel Deuring
fixed grammar bug in doc string |
880 |
# If a given context doesnot have a custom message, we go up in the
|
10977.7.1
by Abel Deuring
show customized bug report acknowledgement message in notifications |
881 |
# "object hierachy" until we find one. If no cusotmized messages
|
882 |
# exist for any conext, a default message is returned.
|
|
883 |
#
|
|
884 |
# bug_reported_acknowledgement is defined as a "real" property
|
|
885 |
# for IDistribution, IDistributionSourcePackage, IProduct and
|
|
886 |
# IProjectGroup. Other IBugTarget implementations inherit this
|
|
887 |
# property from their parents. For these classes, we can directly
|
|
888 |
# try to find a custom message farther up in the hierarchy.
|
|
889 |
message = context.bug_reported_acknowledgement |
|
890 |
if message is not None and len(message.strip()) > 0: |
|
891 |
return message |
|
892 |
next_context = None |
|
893 |
if IProductSeries.providedBy(context): |
|
894 |
# we don't need to look at
|
|
895 |
# context.product.bug_reported_acknowledgement because a
|
|
896 |
# product series inherits this property from the product.
|
|
897 |
next_context = context.product.project |
|
898 |
elif IProduct.providedBy(context): |
|
899 |
next_context = context.project |
|
900 |
elif IDistributionSourcePackage.providedBy(context): |
|
901 |
next_context = context.distribution |
|
902 |
# IDistroseries and ISourcePackage inherit
|
|
903 |
# bug_reported_acknowledgement from their IDistribution, so we
|
|
904 |
# don't need to look up this property in IDistribution.
|
|
905 |
# IDistribution and IProjectGroup don't have any parents.
|
|
906 |
elif (IDistribution.providedBy(context) or |
|
907 |
IProjectGroup.providedBy(context) or |
|
908 |
IDistroSeries.providedBy(context) or |
|
909 |
ISourcePackage.providedBy(context)): |
|
910 |
pass
|
|
911 |
else: |
|
912 |
raise TypeError("Unexpected bug target: %r" % context) |
|
913 |
if next_context is not None: |
|
914 |
return self.getAcknowledgementMessage(next_context) |
|
915 |
return self.default_bug_reported_acknowledgement |
|
916 |
||
7675.547.6
by Graham Binns
FileBugData parsed from a blob by a ProcessApportBlobJob is now used during the filebug process, rather than parsing the blob in the request. |
917 |
@cachedproperty
|
7675.547.2
by Graham Binns
FileBugViewBase now has working extra_data_processing_job and extra_data_processed properties. |
918 |
def extra_data_processing_job(self): |
7675.547.1
by Graham Binns
Added a _getApportBlobJobForToken() method to FileBugViewBase. |
919 |
"""Return the ProcessApportBlobJob for a given BLOB token."""
|
7675.547.2
by Graham Binns
FileBugViewBase now has working extra_data_processing_job and extra_data_processed properties. |
920 |
if self.extra_data_token is None: |
921 |
# If there's no extra data token, don't bother looking for a
|
|
922 |
# ProcessApportBlobJob.
|
|
923 |
return None |
|
924 |
||
925 |
try: |
|
926 |
return getUtility(IProcessApportBlobJobSource).getByBlobUUID( |
|
927 |
self.extra_data_token) |
|
928 |
except SQLObjectNotFound: |
|
929 |
return None |
|
930 |
||
931 |
@property
|
|
7675.547.3
by Graham Binns
Renamed extra_data_processed -> extra_data_to_process so that it made more sense in the context of using it in templates. |
932 |
def extra_data_to_process(self): |
933 |
"""Return True if there is extra data to process."""
|
|
7675.547.2
by Graham Binns
FileBugViewBase now has working extra_data_processing_job and extra_data_processed properties. |
934 |
apport_processing_job = self.extra_data_processing_job |
7675.547.3
by Graham Binns
Renamed extra_data_processed -> extra_data_to_process so that it made more sense in the context of using it in templates. |
935 |
if apport_processing_job is None: |
936 |
return False |
|
937 |
elif apport_processing_job.job.status == JobStatus.COMPLETED: |
|
938 |
return False |
|
939 |
else: |
|
7675.547.2
by Graham Binns
FileBugViewBase now has working extra_data_processing_job and extra_data_processed properties. |
940 |
return True |
7675.547.1
by Graham Binns
Added a _getApportBlobJobForToken() method to FileBugViewBase. |
941 |
|
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
942 |
|
9947.2.8
by Graham Binns
Merged old dupefinder work. |
943 |
class FileBugInlineFormView(FileBugViewBase): |
944 |
"""A browser view for displaying the inline filebug form."""
|
|
945 |
schema = IBugAddForm |
|
946 |
||
947 |
||
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
948 |
class FileBugAdvancedView(FileBugViewBase): |
949 |
"""Browser view for filing a bug.
|
|
950 |
||
8971.19.14
by Graham Binns
Removed any unnecessary references to +filebug-advanced. |
951 |
This view exists only to redirect from +filebug-advanced to +filebug.
|
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
952 |
"""
|
10234.3.5
by Curtis Hovey
Quiet lint. |
953 |
|
8971.19.1
by Graham Binns
Added a redirect from +filebug-advanced to +filebug. |
954 |
def initialize(self): |
8971.19.15
by Graham Binns
Made 301 a constant. |
955 |
filebug_url = canonical_url( |
956 |
self.context, rootsite='bugs', view_name='+filebug') |
|
9360.1.1
by Gavin Panella
Remove bugtarget-filebug-advanced.pt, and clean up the view module. |
957 |
self.request.response.redirect( |
958 |
filebug_url, status=HTTP_MOVED_PERMANENTLY) |
|
8971.19.1
by Graham Binns
Added a redirect from +filebug-advanced to +filebug. |
959 |
|
3691.249.19
by Brad Bollenbach
get +filebug-advanced working |
960 |
|
8137.17.24
by Barry Warsaw
thread merge |
961 |
class FilebugShowSimilarBugsView(FileBugViewBase): |
962 |
"""A view for showing possible dupes for a bug.
|
|
963 |
||
964 |
This view will only be used to populate asynchronously-driven parts
|
|
965 |
of a page.
|
|
966 |
"""
|
|
8223.5.7
by Graham Binns
Removed the useless mixing and merged it with FileBugShowSimilarBugsView, which FileBugGuidedView now extends. |
967 |
schema = IBugAddForm |
968 |
||
9947.2.8
by Graham Binns
Merged old dupefinder work. |
969 |
# XXX: Brad Bollenbach 2006-10-04: This assignment to actions is a
|
970 |
# hack to make the action decorator Just Work across inheritance.
|
|
971 |
actions = FileBugViewBase.actions |
|
972 |
custom_widget('title', TextWidget, displayWidth=40) |
|
973 |
custom_widget('tags', BugTagsWidget) |
|
974 |
||
3691.249.5
by Brad Bollenbach
checkpoint |
975 |
_MATCHING_BUGS_LIMIT = 10 |
9947.2.9
by Graham Binns
The title for the async results set is now more meaningful. |
976 |
show_summary_in_results = False |
8137.17.24
by Barry Warsaw
thread merge |
977 |
|
978 |
@property
|
|
10224.5.1
by Deryck Hodge
Force the +filbug-inline-form to use +filebug |
979 |
def action_url(self): |
980 |
"""Return the +filebug page as the action URL.
|
|
981 |
||
982 |
This enables better validation error handling,
|
|
983 |
since the form is always used inline on the +filebug page.
|
|
984 |
"""
|
|
10224.5.2
by Deryck Hodge
Ensure the data blob is added back. |
985 |
url = '%s/+filebug' % canonical_url(self.context) |
986 |
if self.extra_data_token is not None: |
|
987 |
url = urlappend(url, self.extra_data_token) |
|
988 |
return url |
|
10224.5.1
by Deryck Hodge
Force the +filbug-inline-form to use +filebug |
989 |
|
990 |
@property
|
|
8137.17.24
by Barry Warsaw
thread merge |
991 |
def search_context(self): |
3778.2.11
by Bjorn Tillenius
clean-up. |
992 |
"""Return the context used to search for similar bugs."""
|
8137.17.24
by Barry Warsaw
thread merge |
993 |
return self.context |
994 |
||
995 |
@property
|
|
996 |
def search_text(self): |
|
997 |
"""Return the search string entered by the user."""
|
|
998 |
return self.request.get('title') |
|
8223.5.5
by Graham Binns
Added tests to cover FileBugShowSimilarBugsView. |
999 |
|
3691.249.34
by Bjorn Tillenius
make the guided filebug ui more like the support tracker's. |
1000 |
@cachedproperty
|
1001 |
def similar_bugs(self): |
|
3691.249.13
by Brad Bollenbach
move the workflow steps code into the view code |
1002 |
"""Return the similar bugs based on the user search."""
|
8137.17.24
by Barry Warsaw
thread merge |
1003 |
title = self.search_text |
3691.251.2
by Bjorn Tillenius
make sure that input errors are handled correctly. includes converting the template to use the standard form macros. |
1004 |
if not title: |
1005 |
return [] |
|
8137.17.24
by Barry Warsaw
thread merge |
1006 |
search_context = self.search_context |
4097.1.1
by Gavin Panella
Test and initial implementation for bug-103364 |
1007 |
if search_context is None: |
1008 |
return [] |
|
1009 |
elif IProduct.providedBy(search_context): |
|
3691.249.43
by Bjorn Tillenius
use IBugTaskSet.findSimilar when searching for existings bugs on +filebug |
1010 |
context_params = {'product': search_context} |
3778.2.3
by Bjorn Tillenius
make the general +filebug page work. |
1011 |
elif IDistribution.providedBy(search_context): |
3691.249.43
by Bjorn Tillenius
use IBugTaskSet.findSimilar when searching for existings bugs on +filebug |
1012 |
context_params = {'distribution': search_context} |
3778.2.3
by Bjorn Tillenius
make the general +filebug page work. |
1013 |
else: |
1014 |
assert IDistributionSourcePackage.providedBy(search_context), ( |
|
1015 |
'Unknown search context: %r' % search_context) |
|
1016 |
context_params = { |
|
1017 |
'distribution': search_context.distribution, |
|
1018 |
'sourcepackagename': search_context.sourcepackagename} |
|
1019 |
||
3691.249.43
by Bjorn Tillenius
use IBugTaskSet.findSimilar when searching for existings bugs on +filebug |
1020 |
matching_bugtasks = getUtility(IBugTaskSet).findSimilar( |
1021 |
self.user, title, **context_params) |
|
8486.16.9
by Graham Binns
Extracted common portion of BugTask.findSimilar() and FilebugShowSimilarBugsView.similar_bugs into IBugSet.getDistinctBugsForBugTasks(). |
1022 |
matching_bugs = getUtility(IBugSet).getDistinctBugsForBugTasks( |
1023 |
matching_bugtasks, self.user, self._MATCHING_BUGS_LIMIT) |
|
3691.249.13
by Brad Bollenbach
move the workflow steps code into the view code |
1024 |
return matching_bugs |
1025 |
||
9947.2.8
by Graham Binns
Merged old dupefinder work. |
1026 |
@property
|
1027 |
def show_duplicate_list(self): |
|
1028 |
"""Return whether or not to show the duplicate list.
|
|
1029 |
||
1030 |
We only show the dupes if:
|
|
1031 |
- The context uses Malone AND
|
|
1032 |
- There are dupes to show AND
|
|
1033 |
- There are no widget errors.
|
|
1034 |
"""
|
|
1035 |
return ( |
|
1036 |
self.contextUsesMalone and |
|
1037 |
len(self.similar_bugs) > 0 and |
|
1038 |
len(self.widget_errors) == 0) |
|
1039 |
||
8137.17.24
by Barry Warsaw
thread merge |
1040 |
|
1041 |
class FileBugGuidedView(FilebugShowSimilarBugsView): |
|
1042 |
||
1043 |
_SEARCH_FOR_DUPES = ViewPageTemplateFile( |
|
1044 |
"../templates/bugtarget-filebug-search.pt") |
|
12811.2.13
by Ian Booth
Rework product group bug filing so that it works |
1045 |
_PROJECTGROUP_SEARCH_FOR_DUPES = ViewPageTemplateFile( |
1046 |
"../templates/projectgroup-filebug-search.pt") |
|
8137.17.24
by Barry Warsaw
thread merge |
1047 |
_FILEBUG_FORM = ViewPageTemplateFile( |
1048 |
"../templates/bugtarget-filebug-submit-bug.pt") |
|
1049 |
||
9947.2.8
by Graham Binns
Merged old dupefinder work. |
1050 |
# XXX 2009-07-17 Graham Binns
|
1051 |
# As above, this assignment to actions is to make sure that the
|
|
1052 |
# actions from the ancestor views are preserved, otherwise they
|
|
1053 |
# get nuked.
|
|
1054 |
actions = FilebugShowSimilarBugsView.actions |
|
8137.17.24
by Barry Warsaw
thread merge |
1055 |
template = _SEARCH_FOR_DUPES |
1056 |
||
1057 |
focused_element_id = 'field.title' |
|
9947.2.9
by Graham Binns
The title for the async results set is now more meaningful. |
1058 |
show_summary_in_results = True |
8137.17.24
by Barry Warsaw
thread merge |
1059 |
|
10054.11.2
by Graham Binns
Moved no_ubuntu_redirect into FileBugGuidedView, since that's the place where it actually has an effect. |
1060 |
def initialize(self): |
10054.11.3
by Graham Binns
Refactored the FileBug views to ensure that the extra data code doesn't get moved unnecessarily. |
1061 |
FilebugShowSimilarBugsView.initialize(self) |
1062 |
if self.redirect_ubuntu_filebug: |
|
10054.11.2
by Graham Binns
Moved no_ubuntu_redirect into FileBugGuidedView, since that's the place where it actually has an effect. |
1063 |
# The user is trying to file a new Ubuntu bug via the web
|
1064 |
# interface and without using apport. Redirect to a page
|
|
1065 |
# explaining the preferred bug-filing procedure.
|
|
1066 |
self.request.response.redirect( |
|
1067 |
config.malone.ubuntu_bug_filing_url) |
|
1068 |
||
8137.17.24
by Barry Warsaw
thread merge |
1069 |
@safe_action
|
12811.2.17
by Ian Booth
Fix tests |
1070 |
@action("Continue", name="projectgroupsearch", validator="validate_search") |
12811.2.13
by Ian Booth
Rework product group bug filing so that it works |
1071 |
def projectgroup_search_action(self, action, data): |
1072 |
"""Search for similar bug reports."""
|
|
1073 |
# Don't give focus to any widget, to ensure that the browser
|
|
1074 |
# won't scroll past the "possible duplicates" list.
|
|
1075 |
self.initial_focus_widget = None |
|
1076 |
return self._PROJECTGROUP_SEARCH_FOR_DUPES() |
|
1077 |
||
1078 |
@safe_action
|
|
8137.17.24
by Barry Warsaw
thread merge |
1079 |
@action("Continue", name="search", validator="validate_search") |
1080 |
def search_action(self, action, data): |
|
1081 |
"""Search for similar bug reports."""
|
|
1082 |
# Don't give focus to any widget, to ensure that the browser
|
|
1083 |
# won't scroll past the "possible duplicates" list.
|
|
1084 |
self.initial_focus_widget = None |
|
1085 |
return self.showFileBugForm() |
|
1086 |
||
1087 |
@property
|
|
1088 |
def search_context(self): |
|
1089 |
"""Return the context used to search for similar bugs."""
|
|
1090 |
if IDistributionSourcePackage.providedBy(self.context): |
|
1091 |
return self.context |
|
1092 |
||
1093 |
search_context = self.getMainContext() |
|
10326.1.1
by Henning Eggers
Mechanically renamed IProject* to IProjectGroup*. |
1094 |
if IProjectGroup.providedBy(search_context): |
8137.17.24
by Barry Warsaw
thread merge |
1095 |
assert self.widgets['product'].hasValidInput(), ( |
1096 |
"This method should be called only when we know which"
|
|
1097 |
" product the user selected.") |
|
1098 |
search_context = self.widgets['product'].getInputValue() |
|
1099 |
elif IMaloneApplication.providedBy(search_context): |
|
1100 |
if self.widgets['bugtarget'].hasValidInput(): |
|
1101 |
search_context = self.widgets['bugtarget'].getInputValue() |
|
1102 |
else: |
|
1103 |
search_context = None |
|
1104 |
||
1105 |
return search_context |
|
1106 |
||
1107 |
@property
|
|
1108 |
def search_text(self): |
|
3691.249.13
by Brad Bollenbach
move the workflow steps code into the view code |
1109 |
"""Return the search string entered by the user."""
|
3691.251.2
by Bjorn Tillenius
make sure that input errors are handled correctly. includes converting the template to use the standard form macros. |
1110 |
try: |
1111 |
return self.widgets['title'].getInputValue() |
|
1112 |
except InputErrors: |
|
1113 |
return None |
|
3691.249.13
by Brad Bollenbach
move the workflow steps code into the view code |
1114 |
|
3691.249.3
by Brad Bollenbach
make the dupes search form work with new formlib goo |
1115 |
def validate_search(self, action, data): |
1116 |
"""Make sure some keywords are provided."""
|
|
1117 |
try: |
|
1118 |
data['title'] = self.widgets['title'].getInputValue() |
|
1119 |
except InputErrors, error: |
|
1120 |
self.setFieldError("title", "A summary is required.") |
|
1121 |
return [error] |
|
1122 |
||
1123 |
# Return an empty list of errors to satisfy the validation API,
|
|
1124 |
# and say "we've handled the validation and found no errors."
|
|
3778.2.3
by Bjorn Tillenius
make the general +filebug page work. |
1125 |
return [] |
3691.249.29
by Brad Bollenbach
add a basic filebug steps macro, for mpt to tweak |
1126 |
|
3691.249.25
by Brad Bollenbach
add tests for the guided bug workflow |
1127 |
def validate_no_dupe_found(self, action, data): |
1128 |
return () |
|
3691.249.11
by Brad Bollenbach
fix some crasher issues with distro guided filebug workflow |
1129 |
|
3691.249.25
by Brad Bollenbach
add tests for the guided bug workflow |
1130 |
@action("Continue", name="continue", |
1131 |
validator="validate_no_dupe_found") |
|
1132 |
def continue_action(self, action, data): |
|
1133 |
"""The same action as no-dupe-found, with a different label."""
|
|
1134 |
return self.showFileBugForm() |
|
3691.249.13
by Brad Bollenbach
move the workflow steps code into the view code |
1135 |
|
1136 |
def showFileBugForm(self): |
|
3691.249.11
by Brad Bollenbach
fix some crasher issues with distro guided filebug workflow |
1137 |
return self._FILEBUG_FORM() |
1138 |
||
4338.3.20
by Gavin Panella
Prevent the (Optional) marker from appearing on the comment field. |
1139 |
|
3764.1.2
by Bjorn Tillenius
make it possible to file a bug from the project page. |
1140 |
class ProjectFileBugGuidedView(FileBugGuidedView): |
10326.1.1
by Henning Eggers
Mechanically renamed IProject* to IProjectGroup*. |
1141 |
"""Guided filebug pages for IProjectGroup."""
|
3764.1.2
by Bjorn Tillenius
make it possible to file a bug from the project page. |
1142 |
|
3764.1.6
by Bjorn Tillenius
final tweaks before review. |
1143 |
# Make inheriting the base class' actions work.
|
3764.1.2
by Bjorn Tillenius
make it possible to file a bug from the project page. |
1144 |
actions = FileBugGuidedView.actions |
10326.1.1
by Henning Eggers
Mechanically renamed IProject* to IProjectGroup*. |
1145 |
schema = IProjectGroupBugAddForm |
3764.1.2
by Bjorn Tillenius
make it possible to file a bug from the project page. |
1146 |
|
10017.3.1
by Graham Binns
ProjectFileBugGuidedView is now ajax-enabled. |
1147 |
@cachedproperty
|
1148 |
def products_using_malone(self): |
|
1149 |
return [ |
|
1150 |
product for product in self.context.products |
|
11411.7.1
by j.c.sackett
Fixed majority of official_malone calls in code-space. Still need to fix templates. |
1151 |
if product.bug_tracking_usage == ServiceUsage.LAUNCHPAD] |
10017.3.1
by Graham Binns
ProjectFileBugGuidedView is now ajax-enabled. |
1152 |
|
1153 |
@property
|
|
1154 |
def default_product(self): |
|
1155 |
if len(self.products_using_malone) > 0: |
|
1156 |
return self.products_using_malone[0] |
|
1157 |
else: |
|
1158 |
return None |
|
1159 |
||
1160 |
@property
|
|
1161 |
def inline_filebug_form_url(self): |
|
10017.3.5
by Graham Binns
Added tests for the additional FileBug view links. |
1162 |
"""Return the URL to the inline filebug form.
|
10017.3.1
by Graham Binns
ProjectFileBugGuidedView is now ajax-enabled. |
1163 |
|
1164 |
If a token was passed to this view, it will be be passed through
|
|
1165 |
to the inline bug filing form via the returned URL.
|
|
1166 |
||
1167 |
The URL returned will be the URL of the first of the current
|
|
10724.1.1
by Henning Eggers
First batch of Project -> ProjectGrpoup renamings. |
1168 |
ProjectGroup's products, since that's the product that will be
|
10017.3.1
by Graham Binns
ProjectFileBugGuidedView is now ajax-enabled. |
1169 |
selected by default when the view is rendered.
|
1170 |
"""
|
|
1171 |
url = canonical_url( |
|
1172 |
self.default_product, view_name='+filebug-inline-form') |
|
1173 |
if self.extra_data_token is not None: |
|
1174 |
url = urlappend(url, self.extra_data_token) |
|
1175 |
return url |
|
1176 |
||
1177 |
@property
|
|
1178 |
def duplicate_search_url(self): |
|
10017.3.5
by Graham Binns
Added tests for the additional FileBug view links. |
1179 |
"""Return the URL to the inline duplicate search view.
|
10017.3.1
by Graham Binns
ProjectFileBugGuidedView is now ajax-enabled. |
1180 |
|
1181 |
The URL returned will be the URL of the first of the current
|
|
10724.1.1
by Henning Eggers
First batch of Project -> ProjectGrpoup renamings. |
1182 |
ProjectGroup's products, since that's the product that will be
|
10017.3.1
by Graham Binns
ProjectFileBugGuidedView is now ajax-enabled. |
1183 |
selected by default when the view is rendered.
|
1184 |
"""
|
|
1185 |
url = canonical_url( |
|
1186 |
self.default_product, view_name='+filebug-show-similar') |
|
1187 |
if self.extra_data_token is not None: |
|
1188 |
url = urlappend(url, self.extra_data_token) |
|
1189 |
return url |
|
1190 |
||
3764.1.3
by Bjorn Tillenius
make the +filebug-advanced page work for IProject. |
1191 |
|
3539.1.2
by Brad Bollenbach
fix failing tests |
1192 |
class BugTargetBugListingView: |
1193 |
"""Helper methods for rendering bug listings."""
|
|
1194 |
||
1195 |
@property
|
|
9448.1.1
by Deryck Hodge
Add a portlet for links to milestone-targeted bugs. |
1196 |
def series_list(self): |
4285.2.5
by Mark Shuttleworth
Test fixes for renamed series |
1197 |
if IDistribution(self.context, None): |
9760.8.1
by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase. |
1198 |
series = self.context.series |
4285.2.5
by Mark Shuttleworth
Test fixes for renamed series |
1199 |
elif IProduct(self.context, None): |
9760.8.1
by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase. |
1200 |
series = self.context.series |
4285.2.5
by Mark Shuttleworth
Test fixes for renamed series |
1201 |
elif IDistroSeries(self.context, None): |
9760.8.1
by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase. |
1202 |
series = self.context.distribution.series |
4285.2.5
by Mark Shuttleworth
Test fixes for renamed series |
1203 |
elif IProductSeries(self.context, None): |
9760.8.1
by Brad Crittenden
Change the non-English 'serieses' to 'series' throughout our codebase. |
1204 |
series = self.context.product.series |
3539.1.2
by Brad Bollenbach
fix failing tests |
1205 |
else: |
9448.1.5
by Deryck Hodge
Stylistic updates after review. |
1206 |
raise AssertionError("series_list called with illegal context") |
12392.4.4
by Robert Collins
Use aggregation rather that looping in python to determine series bug counts in bug searches. |
1207 |
return list(series) |
9448.1.1
by Deryck Hodge
Add a portlet for links to milestone-targeted bugs. |
1208 |
|
1209 |
@property
|
|
12415.6.1
by Robert Collins
refactor out the milestones list. |
1210 |
def milestones_list(self): |
12415.6.2
by Robert Collins
Avoid late evaluation of milestones per series - instead use the same context the series are coming from to generate one set of milestones. |
1211 |
if IDistribution(self.context, None): |
1212 |
milestone_resultset = self.context.milestones |
|
1213 |
elif IProduct(self.context, None): |
|
1214 |
milestone_resultset = self.context.milestones |
|
1215 |
elif IDistroSeries(self.context, None): |
|
1216 |
milestone_resultset = self.context.distribution.milestones |
|
1217 |
elif IProductSeries(self.context, None): |
|
1218 |
milestone_resultset = self.context.product.milestones |
|
1219 |
else: |
|
1220 |
raise AssertionError("series_list called with illegal context") |
|
1221 |
return list(milestone_resultset) |
|
12415.6.1
by Robert Collins
refactor out the milestones list. |
1222 |
|
1223 |
@property
|
|
9448.1.1
by Deryck Hodge
Add a portlet for links to milestone-targeted bugs. |
1224 |
def series_buglistings(self): |
1225 |
"""Return a buglisting for each series.
|
|
1226 |
||
1227 |
The list is sorted newest series to oldest.
|
|
1228 |
||
1229 |
The count only considers bugs that the user would actually be
|
|
1230 |
able to see in a listing.
|
|
1231 |
"""
|
|
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
1232 |
series_buglistings = [] |
12392.4.4
by Robert Collins
Use aggregation rather that looping in python to determine series bug counts in bug searches. |
1233 |
bug_task_set = getUtility(IBugTaskSet) |
12415.4.2
by Robert Collins
Fix defect where we did searches that could not match anything and tripped a setTarget assertion. |
1234 |
series_list = self.series_list |
1235 |
if not series_list: |
|
1236 |
return series_buglistings |
|
12392.4.4
by Robert Collins
Use aggregation rather that looping in python to determine series bug counts in bug searches. |
1237 |
open_bugs = bug_task_set.open_bugtask_search |
12415.4.2
by Robert Collins
Fix defect where we did searches that could not match anything and tripped a setTarget assertion. |
1238 |
open_bugs.setTarget(any(*series_list)) |
12392.4.4
by Robert Collins
Use aggregation rather that looping in python to determine series bug counts in bug searches. |
1239 |
# This would be better as delegation not a case statement.
|
1240 |
if IDistribution(self.context, None): |
|
1241 |
backlink = BugTask.distroseriesID |
|
1242 |
elif IProduct(self.context, None): |
|
1243 |
backlink = BugTask.productseriesID |
|
1244 |
elif IDistroSeries(self.context, None): |
|
1245 |
backlink = BugTask.distroseriesID |
|
1246 |
elif IProductSeries(self.context, None): |
|
1247 |
backlink = BugTask.productseriesID |
|
1248 |
else: |
|
1249 |
raise AssertionError("illegal context %r" % self.context) |
|
1250 |
counts = bug_task_set.countBugs(open_bugs, (backlink,)) |
|
12415.4.2
by Robert Collins
Fix defect where we did searches that could not match anything and tripped a setTarget assertion. |
1251 |
for series in series_list: |
12392.4.4
by Robert Collins
Use aggregation rather that looping in python to determine series bug counts in bug searches. |
1252 |
series_bug_count = counts.get((series.id,), 0) |
9122.3.1
by Deryck Hodge
Don't show links to series bugs on the project bugs home if the |
1253 |
if series_bug_count > 0: |
1254 |
series_buglistings.append( |
|
1255 |
dict( |
|
1256 |
title=series.name, |
|
1257 |
url=canonical_url(series) + "/+bugs", |
|
9448.1.5
by Deryck Hodge
Stylistic updates after review. |
1258 |
count=series_bug_count, |
1259 |
))
|
|
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
1260 |
return series_buglistings |
3691.40.12
by Bjorn Tillenius
add a tags portlet to buglistings. |
1261 |
|
9448.1.1
by Deryck Hodge
Add a portlet for links to milestone-targeted bugs. |
1262 |
@property
|
1263 |
def milestone_buglistings(self): |
|
1264 |
"""Return a buglisting for each milestone."""
|
|
1265 |
milestone_buglistings = [] |
|
12415.4.1
by Robert Collins
Also do milestone bug listings with one pass over the bugtasks table. Drive by to handle conjoined bugtasks properly if someone needs that in countBugs. |
1266 |
bug_task_set = getUtility(IBugTaskSet) |
12415.6.1
by Robert Collins
refactor out the milestones list. |
1267 |
milestones = self.milestones_list |
12415.4.2
by Robert Collins
Fix defect where we did searches that could not match anything and tripped a setTarget assertion. |
1268 |
if not milestones: |
1269 |
return milestone_buglistings |
|
12415.4.1
by Robert Collins
Also do milestone bug listings with one pass over the bugtasks table. Drive by to handle conjoined bugtasks properly if someone needs that in countBugs. |
1270 |
open_bugs = bug_task_set.open_bugtask_search |
1271 |
open_bugs.setTarget(any(*milestones)) |
|
1272 |
counts = bug_task_set.countBugs(open_bugs, (BugTask.milestoneID,)) |
|
1273 |
for milestone in milestones: |
|
1274 |
milestone_bug_count = counts.get((milestone.id,), 0) |
|
1275 |
if milestone_bug_count > 0: |
|
1276 |
milestone_buglistings.append( |
|
1277 |
dict( |
|
1278 |
title=milestone.name, |
|
1279 |
url=canonical_url(milestone), |
|
1280 |
count=milestone_bug_count, |
|
1281 |
))
|
|
9448.1.1
by Deryck Hodge
Add a portlet for links to milestone-targeted bugs. |
1282 |
return milestone_buglistings |
1283 |
||
3691.40.12
by Bjorn Tillenius
add a tags portlet to buglistings. |
1284 |
|
3789.2.7
by Bjorn Tillenius
add a pie chart to the distributin Bugs page. |
1285 |
class BugCountDataItem: |
3789.2.12
by Bjorn Tillenius
clean-up |
1286 |
"""Data about bug count for a status."""
|
3789.2.7
by Bjorn Tillenius
add a pie chart to the distributin Bugs page. |
1287 |
|
1288 |
def __init__(self, label, count, color): |
|
1289 |
self.label = label |
|
1290 |
self.count = count |
|
1291 |
if color.startswith('#'): |
|
1292 |
self.color = 'MochiKit.Color.Color.fromHexString("%s")' % color |
|
1293 |
else: |
|
1294 |
self.color = 'MochiKit.Color.Color["%sColor"]()' % color |
|
1295 |
||
3789.2.8
by Bjorn Tillenius
add a pie chart to the distrorelease Bugs page. |
1296 |
|
5309.1.2
by Edwin Grubbs
Created mixin to include feeds link |
1297 |
class BugTargetBugsView(BugTaskSearchListingView, FeedsMixin): |
3789.2.12
by Bjorn Tillenius
clean-up |
1298 |
"""View for the Bugs front page."""
|
3789.2.7
by Bjorn Tillenius
add a pie chart to the distributin Bugs page. |
1299 |
|
8919.4.1
by Graham Binns
Expanded and centred the search box on the BugTargetBugsView. |
1300 |
# We have a custom searchtext widget here so that we can set the
|
1301 |
# width of the search box properly.
|
|
1302 |
custom_widget('searchtext', NewLineToSpacesWidget, displayWidth=36) |
|
1303 |
||
5429.1.2
by Edwin Grubbs
Changed templates and HasAnnouncementsView to use the FeedsMixin |
1304 |
# Only include <link> tags for bug feeds when using this view.
|
1305 |
feed_types = ( |
|
1306 |
BugFeedLink, |
|
1307 |
BugTargetLatestBugsFeedLink, |
|
1308 |
)
|
|
1309 |
||
4664.1.1
by Curtis Hovey
Normalized comments for bug 3732. |
1310 |
# XXX: Bjorn Tillenius 2007-02-13:
|
1311 |
# These colors should be changed. It's the same colors that are used
|
|
3789.2.12
by Bjorn Tillenius
clean-up |
1312 |
# to color statuses in buglistings using CSS, but there should be one
|
1313 |
# unique color for each status in the pie chart
|
|
3789.2.7
by Bjorn Tillenius
add a pie chart to the distributin Bugs page. |
1314 |
status_color = { |
4318.3.3
by Gavin Panella
First round of status renames throughout the tree. |
1315 |
BugTaskStatus.NEW: '#993300', |
1316 |
BugTaskStatus.INCOMPLETE: 'red', |
|
3789.2.14
by Bjorn Tillenius
choose some better colors. |
1317 |
BugTaskStatus.CONFIRMED: 'orange', |
4450.2.1
by Bjorn Tillenius
include Triaged in the pie chart. |
1318 |
BugTaskStatus.TRIAGED: 'black', |
3789.2.14
by Bjorn Tillenius
choose some better colors. |
1319 |
BugTaskStatus.INPROGRESS: 'blue', |
1320 |
BugTaskStatus.FIXCOMMITTED: 'green', |
|
1321 |
BugTaskStatus.FIXRELEASED: 'magenta', |
|
4318.3.3
by Gavin Panella
First round of status renames throughout the tree. |
1322 |
BugTaskStatus.INVALID: 'yellow', |
3789.2.14
by Bjorn Tillenius
choose some better colors. |
1323 |
BugTaskStatus.UNKNOWN: 'purple', |
3789.2.7
by Bjorn Tillenius
add a pie chart to the distributin Bugs page. |
1324 |
}
|
1325 |
||
9389.10.15
by Tom Berger
override the title |
1326 |
override_title_breadcrumbs = True |
1327 |
||
9389.10.11
by Tom Berger
correct placement of breadcrumbs and title |
1328 |
@property
|
1329 |
def label(self): |
|
1330 |
"""The display label for the view."""
|
|
1331 |
return 'Bugs in %s' % self.context.title |
|
1332 |
||
3789.2.7
by Bjorn Tillenius
add a pie chart to the distributin Bugs page. |
1333 |
def initialize(self): |
12393.30.17
by Brad Crittenden
Merge from yellow + use expose_structural_subscription_data_to_js instead of new JSMixin |
1334 |
super(BugTargetBugsView, self).initialize() |
4450.2.1
by Bjorn Tillenius
include Triaged in the pie chart. |
1335 |
bug_statuses_to_show = list(UNRESOLVED_BUGTASK_STATUSES) |
4285.2.1
by Mark Shuttleworth
Massive renaming of distrorelease to distroseries |
1336 |
if IDistroSeries.providedBy(self.context): |
3789.2.12
by Bjorn Tillenius
clean-up |
1337 |
bug_statuses_to_show.append(BugTaskStatus.FIXRELEASED) |
12393.30.1
by Brad Crittenden
Add structural subscription link to all IStructuralSubscriptionTargets |
1338 |
expose_structural_subscription_data_to_js( |
1339 |
self.context, self.request, self.user) |
|
3789.2.7
by Bjorn Tillenius
add a pie chart to the distributin Bugs page. |
1340 |
|
11462.2.3
by Edwin Grubbs
Fixed some tests. |
1341 |
@property
|
11462.2.12
by Edwin Grubbs
Made changes for UI reviews. |
1342 |
def can_have_external_bugtracker(self): |
1343 |
return (IProduct.providedBy(self.context) |
|
1344 |
or IProductSeries.providedBy(self.context)) |
|
1345 |
||
1346 |
@property
|
|
11462.2.3
by Edwin Grubbs
Fixed some tests. |
1347 |
def bug_tracking_usage(self): |
1348 |
"""Whether the context tracks bugs in launchpad.
|
|
1349 |
||
1350 |
:returns: ServiceUsage enum value
|
|
1351 |
"""
|
|
1352 |
service_usage = IServiceUsage(self.context) |
|
1353 |
return service_usage.bug_tracking_usage |
|
1354 |
||
1355 |
@property
|
|
6649.1.7
by Edwin Grubbs
Implemented reviewers suggestions |
1356 |
def bugtracker(self): |
1357 |
"""Description of the context's bugtracker.
|
|
1358 |
||
1359 |
:returns: str which may contain HTML.
|
|
1360 |
"""
|
|
11462.2.3
by Edwin Grubbs
Fixed some tests. |
1361 |
if self.bug_tracking_usage == ServiceUsage.LAUNCHPAD: |
6649.1.7
by Edwin Grubbs
Implemented reviewers suggestions |
1362 |
return 'Launchpad' |
1363 |
elif self.external_bugtracker: |
|
7119.1.5
by Guilherme Salgado
Fix a couple tests |
1364 |
return BugTrackerFormatterAPI(self.external_bugtracker).link(None) |
6649.1.7
by Edwin Grubbs
Implemented reviewers suggestions |
1365 |
else: |
1366 |
return 'None specified' |
|
1367 |
||
10230.1.13
by Deryck Hodge
Updates after review, to make the code a bit more |
1368 |
@cachedproperty
|
1369 |
def hot_bugs_info(self): |
|
10230.1.12
by Deryck Hodge
Add a better doc string. |
1370 |
"""Return a dict of the 10 hottest tasks and a has_more_bugs flag."""
|
10230.1.5
by Deryck Hodge
Add a link to all hot bugs from the bugs home. |
1371 |
has_more_bugs = False |
10230.1.1
by Deryck Hodge
Bring back the move from hot_bugtasks to hot_bugs, |
1372 |
params = BugTaskSearchParams( |
7675.1086.2
by Robert Collins
Change hottest bugs query to trigger the use of the new bugtask indices. |
1373 |
orderby=['-heat', 'task'], omit_dupes=True, |
10230.1.1
by Deryck Hodge
Bring back the move from hot_bugtasks to hot_bugs, |
1374 |
user=self.user, status=any(*UNRESOLVED_BUGTASK_STATUSES)) |
1375 |
# Use 4x as many tasks as bugs that are needed to improve performance.
|
|
1376 |
bugtasks = self.context.searchTasks(params)[:40] |
|
10230.1.13
by Deryck Hodge
Updates after review, to make the code a bit more |
1377 |
hot_bugtasks = [] |
10230.1.1
by Deryck Hodge
Bring back the move from hot_bugtasks to hot_bugs, |
1378 |
hot_bugs = [] |
1379 |
for task in bugtasks: |
|
10230.1.13
by Deryck Hodge
Updates after review, to make the code a bit more |
1380 |
# Use hot_bugs list to ensure a bug is only listed once.
|
1381 |
if task.bug not in hot_bugs: |
|
1382 |
if len(hot_bugtasks) < 10: |
|
1383 |
hot_bugtasks.append(task) |
|
1384 |
hot_bugs.append(task.bug) |
|
10230.1.1
by Deryck Hodge
Bring back the move from hot_bugtasks to hot_bugs, |
1385 |
else: |
10230.1.5
by Deryck Hodge
Add a link to all hot bugs from the bugs home. |
1386 |
has_more_bugs = True |
10230.1.1
by Deryck Hodge
Bring back the move from hot_bugtasks to hot_bugs, |
1387 |
break
|
10230.1.13
by Deryck Hodge
Updates after review, to make the code a bit more |
1388 |
return {'has_more_bugs': has_more_bugs, 'bugtasks': hot_bugtasks} |
10230.1.1
by Deryck Hodge
Bring back the move from hot_bugtasks to hot_bugs, |
1389 |
|
3789.2.7
by Bjorn Tillenius
add a pie chart to the distributin Bugs page. |
1390 |
|
3691.40.12
by Bjorn Tillenius
add a tags portlet to buglistings. |
1391 |
class BugTargetBugTagsView(LaunchpadView): |
1392 |
"""Helper methods for rendering the bug tags portlet."""
|
|
1393 |
||
1394 |
def _getSearchURL(self, tag): |
|
1395 |
"""Return the search URL for the tag."""
|
|
3973.1.96
by Steve Alexander
make bug and bugtask canonical URLs be on the bugs site. change fmt:url to use links relative to the current site where possible. make links to bug tag search pages not include the host, all in the name of saving a lot of rendered characters on large search results pages. |
1396 |
# Use path_only here to reduce the size of the rendered page.
|
4758.1.1
by Bjorn Tillenius
make the bug tags portlet work on the Bugs page for a product. |
1397 |
return "+bugs?field.tag=%s" % urllib.quote(tag) |
3691.40.12
by Bjorn Tillenius
add a tags portlet to buglistings. |
1398 |
|
12775.3.10
by William Grant
Extract factor calculation, turn for loop into list comprehension. |
1399 |
def _calculateFactor(self, tag, count, max_count, official_tags): |
1400 |
bonus = 1.5 if tag in official_tags else 1 |
|
1401 |
return (count / max_count) + bonus |
|
1402 |
||
7968.4.2
by Abel Deuring
provide a link for editing official bug tags |
1403 |
@property
|
9389.10.3
by Tom Berger
interim commit |
1404 |
def tags_cloud_data(self): |
1405 |
"""The data for rendering a tags cloud"""
|
|
12775.3.8
by William Grant
Fix comment typo. |
1406 |
official_tags = self.context.official_bug_tags |
1407 |
||
1408 |
# Construct a dict of official and top 10 tags.
|
|
1409 |
# getUsedBugTagsWithOpenCounts is expensive, so do the union in
|
|
1410 |
# SQL. Also preseed with 0 for all the official tags, as gUBTWOC
|
|
1411 |
# won't return unused ones.
|
|
1412 |
top_ten = removeSecurityProxy( |
|
1413 |
self.context.getUsedBugTagsWithOpenCounts(self.user)[:10]) |
|
1414 |
official = removeSecurityProxy( |
|
1415 |
self.context.getUsedBugTagsWithOpenCounts( |
|
1416 |
self.user, official_tags)) |
|
12775.3.11
by William Grant
Remove tags local, rename raw_tags to tags. |
1417 |
tags = dict((tag, 0) for tag in official_tags) |
1418 |
tags.update(dict(top_ten.union(official))) |
|
1419 |
||
1420 |
max_count = float(max([1] + tags.values())) |
|
1421 |
||
1422 |
return sorted( |
|
1423 |
[dict( |
|
12775.3.10
by William Grant
Extract factor calculation, turn for loop into list comprehension. |
1424 |
tag=tag, |
1425 |
factor=self._calculateFactor( |
|
1426 |
tag, count, max_count, official_tags), |
|
1427 |
url=self._getSearchURL(tag), |
|
1428 |
)
|
|
12775.3.11
by William Grant
Remove tags local, rename raw_tags to tags. |
1429 |
for (tag, count) in tags.iteritems()], |
1430 |
key=itemgetter('tag')) |
|
9389.10.3
by Tom Berger
interim commit |
1431 |
|
1432 |
@property
|
|
7968.4.2
by Abel Deuring
provide a link for editing official bug tags |
1433 |
def show_manage_tags_link(self): |
7968.4.3
by Abel Deuring
test for LargeBugTagsWidget added |
1434 |
"""Should a link to a "manage official tags" page be shown?"""
|
7968.4.2
by Abel Deuring
provide a link for editing official bug tags |
1435 |
return (IOfficialBugTagTargetRestricted.providedBy(self.context) and |
11587.4.3
by Brian Murray
allow BugSupervisor to actually set the official_bug_tags |
1436 |
check_permission('launchpad.BugSupervisor', self.context)) |
7968.4.2
by Abel Deuring
provide a link for editing official bug tags |
1437 |
|
7968.4.1
by Abel Deuring
non-js version of editing official bug tags |
1438 |
|
1439 |
class OfficialBugTagsManageView(LaunchpadEditFormView): |
|
1440 |
"""View class for management of official bug tags."""
|
|
1441 |
||
1442 |
schema = IOfficialBugTagTargetPublic |
|
1443 |
custom_widget('official_bug_tags', LargeBugTagsWidget) |
|
1444 |
||
9332.2.1
by Deryck Hodge
Update the page for managing tags for 3.0 UI. |
1445 |
@property
|
1446 |
def label(self): |
|
1447 |
"""The form label."""
|
|
1448 |
return 'Manage official bug tags for %s' % self.context.title |
|
1449 |
||
1450 |
@property
|
|
1451 |
def page_title(self): |
|
1452 |
"""The page title."""
|
|
1453 |
return self.label |
|
1454 |
||
7968.4.1
by Abel Deuring
non-js version of editing official bug tags |
1455 |
@action('Save', name='save') |
1456 |
def save_action(self, action, data): |
|
1457 |
"""Action for saving new official bug tags."""
|
|
1458 |
self.context.official_bug_tags = data['official_bug_tags'] |
|
1459 |
self.next_url = canonical_url(self.context) |
|
7968.6.1
by Abel Deuring
parital JS code for the Official Bug Tags management page |
1460 |
|
1461 |
@property
|
|
1462 |
def tags_js_data(self): |
|
1463 |
"""Return the JSON representation of the bug tags."""
|
|
7968.6.11
by Tom Berger
enable/disbale buttons and other ui improvements |
1464 |
used_tags = dict(self.context.getUsedBugTagsWithOpenCounts(self.user)) |
1465 |
official_tags = list(self.context.official_bug_tags) |
|
7968.6.1
by Abel Deuring
parital JS code for the Official Bug Tags management page |
1466 |
return """<script type="text/javascript"> |
1467 |
var used_bug_tags = %s; |
|
1468 |
var official_bug_tags = %s; |
|
7968.6.7
by Tom Berger
it works |
1469 |
var valid_name_pattern = %s; |
7968.6.1
by Abel Deuring
parital JS code for the Official Bug Tags management page |
1470 |
</script>
|
7968.6.7
by Tom Berger
it works |
1471 |
""" % ( |
7968.6.11
by Tom Berger
enable/disbale buttons and other ui improvements |
1472 |
dumps(used_tags), |
1473 |
dumps(official_tags), |
|
7968.6.14
by Tom Berger
change the background colour of selected items |
1474 |
dumps(valid_name_pattern.pattern)) |
7968.6.10
by Tom Berger
merge changes from rocketfuel and resolve conflicts |
1475 |
|
7968.6.11
by Tom Berger
enable/disbale buttons and other ui improvements |
1476 |
@property
|
7968.4.6
by Abel Deuring
fixed some UI issues |
1477 |
def cancel_url(self): |
1478 |
"""The URL the user is sent to when clicking the "cancel" link."""
|
|
1479 |
return canonical_url(self.context) |
|
7968.6.10
by Tom Berger
merge changes from rocketfuel and resolve conflicts |
1480 |
|
9087.4.9
by Guilherme Salgado
Fix a couple existing tests and tweak my implementation to not break others |
1481 |
|
9565.2.1
by Gary Poster
fix vhost breadcrumbs so that we do not duplicate information |
1482 |
class BugsVHostBreadcrumb(Breadcrumb): |
9087.4.9
by Guilherme Salgado
Fix a couple existing tests and tweak my implementation to not break others |
1483 |
rootsite = 'bugs' |
9565.2.1
by Gary Poster
fix vhost breadcrumbs so that we do not duplicate information |
1484 |
text = 'Bugs' |
10137.7.1
by Karl Fogel
Start on bug #506018 ("implement +patches view"). |
1485 |
|
1486 |
||
1487 |
class BugsPatchesView(LaunchpadView): |
|
1488 |
"""View list of patch attachments associated with bugs."""
|
|
1489 |
||
1490 |
@property
|
|
1491 |
def label(self): |
|
1492 |
"""The display label for the view."""
|
|
10137.10.2
by Gavin Panella
When the context is an IPerson, fix the silly title wording and show the package in the results table. |
1493 |
if IPerson.providedBy(self.context): |
1494 |
return 'Patch attachments for %s' % self.context.displayname |
|
1495 |
else: |
|
1496 |
return 'Patch attachments in %s' % self.context.displayname |
|
10137.7.9
by Karl Fogel
With Abel, use the view instead of the model to prepare data for display. |
1497 |
|
7675.549.1
by Karl Fogel
Start on bug #515584 (use Zope form for patches view task orderings). |
1498 |
@property
|
7675.549.4
by Karl Fogel
Fixes in response to intellectronica's review. |
1499 |
def patch_task_orderings(self): |
7675.549.1
by Karl Fogel
Start on bug #515584 (use Zope form for patches view task orderings). |
1500 |
"""The list of possible sort orderings for the patches view.
|
1501 |
||
1502 |
The orderings are a list of tuples of the form:
|
|
1503 |
[(DisplayName, InternalOrderingName), ...]
|
|
1504 |
For example:
|
|
1505 |
[("Patch age", "-latest_patch_uploaded"),
|
|
1506 |
("Importance", "-importance"),
|
|
1507 |
...]
|
|
1508 |
"""
|
|
7675.549.4
by Karl Fogel
Fixes in response to intellectronica's review. |
1509 |
orderings = [("patch age", "-latest_patch_uploaded"), |
1510 |
("importance", "-importance"), |
|
1511 |
("status", "status"), |
|
1512 |
("oldest first", "datecreated"), |
|
1513 |
("newest first", "-datecreated")] |
|
7675.549.7
by Karl Fogel
Fix a regression from the previous change. |
1514 |
targetname = self.targetName() |
1515 |
if targetname is not None: |
|
1516 |
# Lower case for consistency with the other orderings.
|
|
1517 |
orderings.append((targetname.lower(), "targetname")) |
|
7675.549.1
by Karl Fogel
Start on bug #515584 (use Zope form for patches view task orderings). |
1518 |
return orderings |
1519 |
||
10137.7.11
by Karl Fogel
With Abel, implement pagination on the result set. |
1520 |
def batchedPatchTasks(self): |
1521 |
"""Return a BatchNavigator for bug tasks with patch attachments."""
|
|
7675.513.1
by Tom Berger
Make it possible to sort by patch age. Also fix validation and test it. |
1522 |
orderby = self.request.get("orderby", "-latest_patch_uploaded") |
7675.549.4
by Karl Fogel
Fixes in response to intellectronica's review. |
1523 |
if orderby not in [x[1] for x in self.patch_task_orderings]: |
10137.7.53
by Karl Fogel
Various small fixups, after suggestions by Michael Hudson. |
1524 |
raise UnexpectedFormData( |
1525 |
"Unexpected value for field 'orderby': '%s'" % orderby) |
|
10137.7.11
by Karl Fogel
With Abel, implement pagination on the result set. |
1526 |
return BatchNavigator( |
10137.7.43
by Karl Fogel
Incorporate some more review feedback from beuno and intellectronic: |
1527 |
self.context.searchTasks( |
1528 |
None, user=self.user, order_by=orderby, |
|
10480.1.1
by Karl Fogel
Fix bug #532022 ("don't show Fix Released bugs in patches view"): |
1529 |
status=UNRESOLVED_BUGTASK_STATUSES, |
10137.7.43
by Karl Fogel
Incorporate some more review feedback from beuno and intellectronic: |
1530 |
omit_duplicates=True, has_patch=True), |
10137.7.11
by Karl Fogel
With Abel, implement pagination on the result set. |
1531 |
self.request) |
10137.10.2
by Gavin Panella
When the context is an IPerson, fix the silly title wording and show the package in the results table. |
1532 |
|
10137.7.55
by Karl Fogel
In patches view, make a column name dynamic on package vs project. |
1533 |
def targetName(self): |
1534 |
"""Return the name of the current context's target type, or None.
|
|
1535 |
||
1536 |
The name is something like "Package" or "Project" (meaning
|
|
1537 |
Product); it is intended to be appropriate to use as a column
|
|
1538 |
name in a web page, for example. If no target type is
|
|
1539 |
appropriate for the current context, then return None.
|
|
1540 |
"""
|
|
1541 |
if (IDistribution.providedBy(self.context) or |
|
1542 |
IDistroSeries.providedBy(self.context)): |
|
1543 |
return "Package" |
|
7675.537.1
by Henning Eggers
Found one last IProject. |
1544 |
elif (IProjectGroup.providedBy(self.context) or |
7675.512.9
by Karl Fogel
Merge from lp:~allenap/launchpad/patch-report-for-people-and-teams-bug-506018 |
1545 |
IPerson.providedBy(self.context)): |
1546 |
# In the case of an IPerson, the target column can vary
|
|
1547 |
# row-by-row, showing both packages and products. We
|
|
1548 |
# decided to go with the table header "Project" for both,
|
|
1549 |
# as its meaning is broad and could conceivably cover
|
|
1550 |
# packages too. We also considered "Target", but rejected
|
|
1551 |
# it because it's used as a verb elsewhere in Launchpad's
|
|
1552 |
# UI, with a totally different meaning. If anyone can
|
|
1553 |
# think of a better term than "Project", please JFDI here.
|
|
1554 |
return "Project" # "Project" meaning Product, of course |
|
10137.7.55
by Karl Fogel
In patches view, make a column name dynamic on package vs project. |
1555 |
else: |
1556 |
return None |
|
10137.7.9
by Karl Fogel
With Abel, use the view instead of the model to prepare data for display. |
1557 |
|
10137.7.43
by Karl Fogel
Incorporate some more review feedback from beuno and intellectronic: |
1558 |
def patchAge(self, patch): |
10137.7.9
by Karl Fogel
With Abel, use the view instead of the model to prepare data for display. |
1559 |
"""Return a timedelta object for the age of a patch attachment."""
|
1560 |
now = datetime.now(timezone('UTC')) |
|
1561 |
return now - patch.message.datecreated |
|
11235.8.5
by Abel Deuring
change the bug attachment download URL shown in bug-portlet-attachments.py; fix failures in test_bugchanges.txt |
1562 |
|
1563 |
def proxiedUrlForLibraryFile(self, patch): |
|
1564 |
"""Return the proxied download URL for a Librarian file."""
|
|
1565 |
return ProxiedLibraryFileAlias(patch.libraryfile, patch).http_url |
|
12584.1.1
by Gary Poster
add a simple page to start building JS on |
1566 |
|
1567 |
||
1568 |
class TargetSubscriptionView(LaunchpadView): |
|
1569 |
"""A view to show all a person's structural subscriptions to a target."""
|
|
1570 |
||
12636.1.2
by Gary Poster
add missing test file from ~yellow branch; tweak views to use initialize |
1571 |
def initialize(self): |
1572 |
super(TargetSubscriptionView, self).initialize() |
|
12393.30.17
by Brad Crittenden
Merge from yellow + use expose_structural_subscription_data_to_js instead of new JSMixin |
1573 |
expose_structural_subscription_data_to_js( |
1574 |
self.context, self.request, self.user, self.subscriptions) |
|
1575 |
||
12636.1.8
by Gary Poster
respond to review |
1576 |
@property
|
1577 |
def subscriptions(self): |
|
1578 |
return get_structural_subscriptions_for_target( |
|
12393.10.2
by Gary Poster
fix some broken code, and eliminate some redendant code. JS is still broken. |
1579 |
self.context, self.user) |
1580 |
||
12584.1.1
by Gary Poster
add a simple page to start building JS on |
1581 |
@property
|
1582 |
def label(self): |
|
1583 |
return "Your subscriptions to %s" % (self.context.displayname,) |
|
1584 |
||
1585 |
page_title = label |