Merge lp:~edwin-grubbs/launchpad/bug-635302-dsp-filebug-oops into lp:launchpad
- bug-635302-dsp-filebug-oops
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Curtis Hovey |
Approved revision: | no longer in the source branch. |
Merged at revision: | 11688 |
Proposed branch: | lp:~edwin-grubbs/launchpad/bug-635302-dsp-filebug-oops |
Merge into: | lp:launchpad |
Diff against target: |
757 lines (+361/-73) 15 files modified
lib/lp/bugs/browser/bugtask.py (+15/-5) lib/lp/bugs/browser/tests/test_buglisting.py (+122/-0) lib/lp/bugs/stories/bugtask-searches/xx-advanced-people-filters.txt (+4/-0) lib/lp/bugs/stories/bugtask-searches/xx-advanced-upstream-pending-bugwatch.txt (+5/-0) lib/lp/bugs/stories/bugtask-searches/xx-distribution-statistics-portlet.txt (+34/-30) lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt (+6/-0) lib/lp/bugs/stories/bugtask-searches/xx-sort-orders.txt (+4/-0) lib/lp/bugs/templates/buglisting-default.pt (+26/-5) lib/lp/registry/browser/distributionsourcepackage.py (+18/-3) lib/lp/registry/browser/pillar.py (+19/-20) lib/lp/registry/browser/sourcepackage.py (+16/-1) lib/lp/registry/configure.zcml (+6/-8) lib/lp/registry/interfaces/projectgroup.py (+2/-1) lib/lp/registry/model/projectgroup.py (+51/-0) lib/lp/testing/service_usage_helpers.py (+33/-0) |
To merge this branch: | bzr merge lp:~edwin-grubbs/launchpad/bug-635302-dsp-filebug-oops |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Curtis Hovey (community) | code + ui | Approve | |
Review via email: mp+37679@code.launchpad.net |
Commit message
Description of the change
Summary
-------
The bugs.lp.
bugs and the "Report a bug" button despite the fact that the
distribution does not use Launchpad for tracking bugs.
Implementation details
-------
Added conditionals for hiding the bug listing and the "Report a bug"
button. It also sets robots=
help.lp.net/Bugs like bugtarget-bugs.pt does. However, I did not add a
link to configure the bugtracker, since buglisting-
so many different objects, and the code would have to determine if the
object is part of a distribution or a project, which actually can have
its bugtracker configured.
lib/
lib/
Adapt IDistributionSo
reduce the zcml for the IBreadcrumb adapter.
lib/
lib/
lib/
Since buglisting-
implement the IServiceUsage interface. This meant that the
browser.
lib/
lib/
lib/
Fix tests by setting bug_tracking_usage to LAUNCHPAD. I also corrected
the indent of the python code in xx-distribution
lib/
lib/
lib/
lib/
lib/
Tests
-----
./bin/test -vv -t 'xx-advanced-
Demo and Q/A
------------
* These pages should not show a list of bugs or the "Report a bug"
button, but they should show the "Getting started with bug tracking in
Launchpad" link.
* Open http://
* Open http://
* Open http://
* These pages should show the bug listing and the "Report a bug" button.
* Open http://
* Open http://
* Open http://
Edwin Grubbs (edwin-grubbs) wrote : | # |
Curtis Hovey (sinzui) wrote : | # |
Hi Edwin.
This is a very nice refactoring and improvement to the rules.
There is some scary things in xx-distribution
I believe you and Brad are solving the same PG issues. You may find you conflict with him. I like you refactoring and hope it is preserved.
I do not have any remarks about your code changes. You comments are clear. I do think something is missing though, and you should investigate why I get oopses when I merge your branch into a local branch:
https:/
* I see a sidebar with links to do bug searches. I do not think this is correct. The links will show bugs that were reported under the assumption that the project did you LP.
https:/
* OOPS
Line 74, Column 8
Expression: <PathExpr standard:
ForbiddenAttr
https:/
* OOPS (same as above)
Edwin Grubbs (edwin-grubbs) wrote : | # |
On Wed, Oct 6, 2010 at 4:35 PM, Curtis Hovey <email address hidden> wrote:
> Review: Needs Fixing code and ui
> Hi Edwin.
>
> This is a very nice refactoring and improvement to the rules.
>
> There is some scary things in xx-distribution
>
> I believe you and Brad are solving the same PG issues. You may find you conflict with him. I like you refactoring and hope it is preserved.
>
> I do not have any remarks about your code changes. You comments are clear. I do think something is missing though, and you should investigate why I get oopses when I merge your branch into a local branch:
>
> https:/
> * I see a sidebar with links to do bug searches. I do not think this is correct. The links will show bugs that were reported under the assumption that the project did you LP.
The portlet with bugfilter links is now hidden, and the bugtags
portlet is now also hidden.
> https:/
> * OOPS
> Line 74, Column 8
> Expression: <PathExpr standard:
> ForbiddenAttribute: ('official_malone', <ProjectGroup at 0xfd1b5ac>)<br />
>
>
> https:/
> * OOPS (same as above)
Both of these are now fixed.
Curtis Hovey (sinzui) wrote : | # |
Thanks for addressing my concerns. I think this branch is ready to land.
Preview Diff
1 | === modified file 'lib/lp/bugs/browser/bugtask.py' |
2 | --- lib/lp/bugs/browser/bugtask.py 2010-10-04 14:20:00 +0000 |
3 | +++ lib/lp/bugs/browser/bugtask.py 2010-10-07 13:33:43 +0000 |
4 | @@ -164,11 +164,6 @@ |
5 | from canonical.launchpad.webapp.interfaces import ILaunchBag |
6 | from canonical.launchpad.webapp.launchpadform import ReturnToReferrerMixin |
7 | from canonical.launchpad.webapp.menu import structured |
8 | -from lp.app.browser.tales import ( |
9 | - FormattersAPI, |
10 | - ObjectImageDisplayAPI, |
11 | - PersonFormatterAPI, |
12 | - ) |
13 | from canonical.lazr.interfaces import IObjectPrivacy |
14 | from canonical.lazr.utils import smartquote |
15 | from canonical.widgets.bug import BugTagsWidget |
16 | @@ -189,11 +184,17 @@ |
17 | ) |
18 | from canonical.widgets.project import ProjectScopeWidget |
19 | from lp.answers.interfaces.questiontarget import IQuestionTarget |
20 | +from lp.app.browser.tales import ( |
21 | + FormattersAPI, |
22 | + ObjectImageDisplayAPI, |
23 | + PersonFormatterAPI, |
24 | + ) |
25 | from lp.app.enums import ServiceUsage |
26 | from lp.app.errors import ( |
27 | NotFoundError, |
28 | UnexpectedFormData, |
29 | ) |
30 | +from lp.app.interfaces.launchpad import IServiceUsage |
31 | from lp.bugs.browser.bug import ( |
32 | BugContextMenu, |
33 | BugTextView, |
34 | @@ -2484,6 +2485,15 @@ |
35 | custom_widget('tags_combinator', RadioWidget) |
36 | custom_widget('component', LabeledMultiCheckBoxWidget) |
37 | |
38 | + @cachedproperty |
39 | + def bug_tracking_usage(self): |
40 | + """Whether the context tracks bugs in launchpad. |
41 | + |
42 | + :returns: ServiceUsage enum value |
43 | + """ |
44 | + service_usage = IServiceUsage(self.context) |
45 | + return service_usage.bug_tracking_usage |
46 | + |
47 | @property |
48 | def schema(self): |
49 | """Return the schema that defines the form.""" |
50 | |
51 | === added file 'lib/lp/bugs/browser/tests/test_buglisting.py' |
52 | --- lib/lp/bugs/browser/tests/test_buglisting.py 1970-01-01 00:00:00 +0000 |
53 | +++ lib/lp/bugs/browser/tests/test_buglisting.py 2010-10-07 13:33:43 +0000 |
54 | @@ -0,0 +1,122 @@ |
55 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
56 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
57 | + |
58 | +__metaclass__ = type |
59 | + |
60 | +from canonical.launchpad.testing.pages import ( |
61 | + extract_text, |
62 | + find_tag_by_id, |
63 | + find_tags_by_class, |
64 | + ) |
65 | +from canonical.launchpad.webapp import canonical_url |
66 | +from canonical.testing.layers import LaunchpadFunctionalLayer |
67 | +from lp.testing import BrowserTestCase |
68 | + |
69 | + |
70 | +class TestBugTaskSearchListingView(BrowserTestCase): |
71 | + |
72 | + layer = LaunchpadFunctionalLayer |
73 | + |
74 | + def _makeDistributionSourcePackage(self): |
75 | + distro = self.factory.makeDistribution('test-distro') |
76 | + return self.factory.makeDistributionSourcePackage('test-dsp', distro) |
77 | + |
78 | + def test_distributionsourcepackage_unknown_bugtracker_message(self): |
79 | + # A DistributionSourcePackage whose Distro does not use |
80 | + # Launchpad for bug tracking should explain that. |
81 | + dsp = self._makeDistributionSourcePackage() |
82 | + url = canonical_url(dsp, rootsite='bugs') |
83 | + browser = self.getUserBrowser(url) |
84 | + top_portlet = find_tags_by_class( |
85 | + browser.contents, 'top-portlet') |
86 | + self.assertTrue(len(top_portlet) > 0, |
87 | + "Tag with class=top-portlet not found") |
88 | + self.assertTextMatchesExpressionIgnoreWhitespace(""" |
89 | + test-dsp in test-distro does not use Launchpad for bug tracking. |
90 | + Getting started with bug tracking in Launchpad.""", |
91 | + extract_text(top_portlet[0])) |
92 | + |
93 | + def test_distributionsourcepackage_unknown_bugtracker_no_button(self): |
94 | + # A DistributionSourcePackage whose Distro does not use |
95 | + # Launchpad for bug tracking should not show the "Report a bug" |
96 | + # button. |
97 | + dsp = self._makeDistributionSourcePackage() |
98 | + url = canonical_url(dsp, rootsite='bugs') |
99 | + browser = self.getUserBrowser(url) |
100 | + self.assertIs(None, find_tag_by_id(browser.contents, 'involvement'), |
101 | + "Involvement portlet with Report-a-bug button should " |
102 | + "not be shown") |
103 | + |
104 | + def test_distributionsourcepackage_unknown_bugtracker_no_filters(self): |
105 | + # A DistributionSourcePackage whose Distro does not use |
106 | + # Launchpad for bug tracking should not show links to "New |
107 | + # bugs", "Open bugs", etc. |
108 | + dsp = self._makeDistributionSourcePackage() |
109 | + url = canonical_url(dsp, rootsite='bugs') |
110 | + browser = self.getUserBrowser(url) |
111 | + self.assertIs(None, |
112 | + find_tag_by_id(browser.contents, 'portlet-bugfilters'), |
113 | + "portlet-bugfilters should not be shown.") |
114 | + |
115 | + def test_distributionsourcepackage_unknown_bugtracker_no_tags(self): |
116 | + # A DistributionSourcePackage whose Distro does not use |
117 | + # Launchpad for bug tracking should not show links to search by |
118 | + # bug tags. |
119 | + dsp = self._makeDistributionSourcePackage() |
120 | + url = canonical_url(dsp, rootsite='bugs') |
121 | + browser = self.getUserBrowser(url) |
122 | + self.assertIs(None, find_tag_by_id(browser.contents, 'portlet-tags'), |
123 | + "portlet-tags should not be shown.") |
124 | + |
125 | + def _makeSourcePackage(self): |
126 | + distro = self.factory.makeDistribution('test-distro') |
127 | + series = self.factory.makeDistroRelease( |
128 | + distribution=distro, name='test-series') |
129 | + return self.factory.makeSourcePackage('test-sp', distro.currentseries) |
130 | + |
131 | + def test_sourcepackage_unknown_bugtracker_message(self): |
132 | + # A SourcePackage whose Distro does not use |
133 | + # Launchpad for bug tracking should explain that. |
134 | + sp = self._makeSourcePackage() |
135 | + url = canonical_url(sp, rootsite='bugs') |
136 | + browser = self.getUserBrowser(url) |
137 | + top_portlet = find_tags_by_class( |
138 | + browser.contents, 'top-portlet') |
139 | + self.assertTrue(len(top_portlet) > 0, |
140 | + "Tag with class=top-portlet not found") |
141 | + self.assertTextMatchesExpressionIgnoreWhitespace(""" |
142 | + test-sp in Test-distro Test-series does not |
143 | + use Launchpad for bug tracking. |
144 | + Getting started with bug tracking in Launchpad.""", |
145 | + extract_text(top_portlet[0])) |
146 | + |
147 | + def test_sourcepackage_unknown_bugtracker_no_button(self): |
148 | + # A SourcePackage whose Distro does not use Launchpad for bug |
149 | + # tracking should not show the "Report a bug" button. |
150 | + sp = self._makeSourcePackage() |
151 | + url = canonical_url(sp, rootsite='bugs') |
152 | + browser = self.getUserBrowser(url) |
153 | + self.assertIs(None, find_tag_by_id(browser.contents, 'involvement'), |
154 | + "Involvement portlet with Report-a-bug button should " |
155 | + "not be shown") |
156 | + |
157 | + def test_sourcepackage_unknown_bugtracker_no_filters(self): |
158 | + # A SourcePackage whose Distro does not use Launchpad for bug |
159 | + # tracking should not show links to "New bugs", "Open bugs", |
160 | + # etc. |
161 | + sp = self._makeSourcePackage() |
162 | + url = canonical_url(sp, rootsite='bugs') |
163 | + browser = self.getUserBrowser(url) |
164 | + self.assertIs(None, |
165 | + find_tag_by_id(browser.contents, 'portlet-bugfilters'), |
166 | + "portlet-bugfilters should not be shown.") |
167 | + |
168 | + def test_sourcepackage_unknown_bugtracker_no_tags(self): |
169 | + # A SourcePackage whose Distro does not use Launchpad for bug |
170 | + # tracking should not show links to search by bug tags. |
171 | + sp = self._makeSourcePackage() |
172 | + url = canonical_url(sp, rootsite='bugs') |
173 | + browser = self.getUserBrowser(url) |
174 | + self.assertIs(None, |
175 | + find_tag_by_id(browser.contents, 'portlet-tags'), |
176 | + "portlet-tags should not be shown.") |
177 | |
178 | === modified file 'lib/lp/bugs/stories/bugtask-searches/xx-advanced-people-filters.txt' |
179 | --- lib/lp/bugs/stories/bugtask-searches/xx-advanced-people-filters.txt 2010-06-12 05:14:55 +0000 |
180 | +++ lib/lp/bugs/stories/bugtask-searches/xx-advanced-people-filters.txt 2010-10-07 13:33:43 +0000 |
181 | @@ -28,6 +28,10 @@ |
182 | Let's test the advanced form for a distribution. We get the search |
183 | results when we use a valid assignee. |
184 | |
185 | + >>> # Debian must enable the Launchpad bug tracker to access bugs. |
186 | + >>> from lp.testing.service_usage_helpers import set_service_usage |
187 | + >>> set_service_usage('debian', bug_tracking_usage='LAUNCHPAD') |
188 | + |
189 | >>> anon_browser.open('http://bugs.launchpad.dev/debian/+bugs?advanced=1') |
190 | >>> anon_browser.getControl(name='field.assignee').value = 'name12' |
191 | >>> anon_browser.getControl('Search', index=0).click() |
192 | |
193 | === modified file 'lib/lp/bugs/stories/bugtask-searches/xx-advanced-upstream-pending-bugwatch.txt' |
194 | --- lib/lp/bugs/stories/bugtask-searches/xx-advanced-upstream-pending-bugwatch.txt 2010-06-12 14:30:43 +0000 |
195 | +++ lib/lp/bugs/stories/bugtask-searches/xx-advanced-upstream-pending-bugwatch.txt 2010-10-07 13:33:43 +0000 |
196 | @@ -37,6 +37,11 @@ |
197 | chooses to search for all bugs that need to be forwarded upstream. |
198 | He sees one match. |
199 | |
200 | + >>> # alsa-utils must use an external bugtracker to view bugs |
201 | + >>> # forwarded to an upstream. |
202 | + >>> from lp.testing.service_usage_helpers import set_service_usage |
203 | + >>> set_service_usage('alsa-utils', bug_tracking_usage='EXTERNAL') |
204 | + |
205 | >>> browser.open('http://bugs.launchpad.dev/alsa-utils/+bugs?advanced=1') |
206 | >>> pending_bugwatch_label = ( |
207 | ... 'Show bugs that need to be forwarded to an upstream ' |
208 | |
209 | === modified file 'lib/lp/bugs/stories/bugtask-searches/xx-distribution-statistics-portlet.txt' |
210 | --- lib/lp/bugs/stories/bugtask-searches/xx-distribution-statistics-portlet.txt 2009-06-12 16:36:02 +0000 |
211 | +++ lib/lp/bugs/stories/bugtask-searches/xx-distribution-statistics-portlet.txt 2010-10-07 13:33:43 +0000 |
212 | @@ -7,45 +7,49 @@ |
213 | |
214 | Viewing critical bugs as Sample Person: |
215 | |
216 | - >>> print http(r""" |
217 | - ... GET /debian/+bugs?field.status%3Alist=New&field.status%3Alist=Confirmed&field.importance%3Alist=Critical&search=Search HTTP/1.1 |
218 | - ... Authorization: Basic dGVzdEBjYW5vbmljYWwuY29tOnRlc3Q= |
219 | - ... """) |
220 | - HTTP/1.1 200 Ok |
221 | - ...No results for search... |
222 | + >>> # Debian must enable the Launchpad bug tracker to access bugs. |
223 | + >>> from lp.testing.service_usage_helpers import set_service_usage |
224 | + >>> set_service_usage('debian', bug_tracking_usage='LAUNCHPAD') |
225 | + |
226 | + >>> print http(r""" |
227 | + ... GET /debian/+bugs?field.status%3Alist=New&field.status%3Alist=Confirmed&field.importance%3Alist=Critical&search=Search HTTP/1.1 |
228 | + ... Authorization: Basic dGVzdEBjYW5vbmljYWwuY29tOnRlc3Q= |
229 | + ... """) |
230 | + HTTP/1.1 200 Ok |
231 | + ...No results for search... |
232 | |
233 | Viewing bugs "assigned to me", as Sample Person: |
234 | |
235 | - >>> print http(r""" |
236 | - ... GET /debian/+bugs?field.status%3Alist=New&field.status%3Alist=Confirmed&field.assignee=name12&search=Search HTTP/1.1 |
237 | - ... Authorization: Basic dGVzdEBjYW5vbmljYWwuY29tOnRlc3Q= |
238 | - ... """) |
239 | - HTTP/1.1 200 Ok |
240 | - ...1 result... |
241 | + >>> print http(r""" |
242 | + ... GET /debian/+bugs?field.status%3Alist=New&field.status%3Alist=Confirmed&field.assignee=name12&search=Search HTTP/1.1 |
243 | + ... Authorization: Basic dGVzdEBjYW5vbmljYWwuY29tOnRlc3Q= |
244 | + ... """) |
245 | + HTTP/1.1 200 Ok |
246 | + ...1 result... |
247 | |
248 | Viewing untriaged bugs as Sample Person: |
249 | |
250 | - >>> print http(r""" |
251 | - ... GET /debian/+bugs?field.status%3Alist=New&search=Search HTTP/1.1 |
252 | - ... Authorization: Basic dGVzdEBjYW5vbmljYWwuY29tOnRlc3Q= |
253 | - ... """) |
254 | - HTTP/1.1 200 Ok |
255 | - ...1 result... |
256 | + >>> print http(r""" |
257 | + ... GET /debian/+bugs?field.status%3Alist=New&search=Search HTTP/1.1 |
258 | + ... Authorization: Basic dGVzdEBjYW5vbmljYWwuY29tOnRlc3Q= |
259 | + ... """) |
260 | + HTTP/1.1 200 Ok |
261 | + ...1 result... |
262 | |
263 | Viewing unassigned bugs as Sample Person: |
264 | |
265 | - >>> print http(r""" |
266 | - ... GET /debian/+bugs?field.status%3Alist=New&field.status%3Alist=Confirmed&field.status-empty-marker=1&field.importance-empty-marker=1&field.assignee=&assignee_option=none&search=Search HTTP/1.1 |
267 | - ... Authorization: Basic dGVzdEBjYW5vbmljYWwuY29tOnRlc3Q= |
268 | - ... """) |
269 | - HTTP/1.1 200 Ok |
270 | - ...2 results... |
271 | + >>> print http(r""" |
272 | + ... GET /debian/+bugs?field.status%3Alist=New&field.status%3Alist=Confirmed&field.status-empty-marker=1&field.importance-empty-marker=1&field.assignee=&assignee_option=none&search=Search HTTP/1.1 |
273 | + ... Authorization: Basic dGVzdEBjYW5vbmljYWwuY29tOnRlc3Q= |
274 | + ... """) |
275 | + HTTP/1.1 200 Ok |
276 | + ...2 results... |
277 | |
278 | Viewing open reported bugs as Sample Person: |
279 | |
280 | - >>> print http(r""" |
281 | - ... GET /debian/+bugs?search=Search HTTP/1.1 |
282 | - ... Authorization: Basic dGVzdEBjYW5vbmljYWwuY29tOnRlc3Q= |
283 | - ... """) |
284 | - HTTP/1.1 200 Ok |
285 | - ...3 results... |
286 | + >>> print http(r""" |
287 | + ... GET /debian/+bugs?search=Search HTTP/1.1 |
288 | + ... Authorization: Basic dGVzdEBjYW5vbmljYWwuY29tOnRlc3Q= |
289 | + ... """) |
290 | + HTTP/1.1 200 Ok |
291 | + ...3 results... |
292 | |
293 | === modified file 'lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt' |
294 | --- lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt 2010-10-03 15:30:06 +0000 |
295 | +++ lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt 2010-10-07 13:33:43 +0000 |
296 | @@ -14,6 +14,10 @@ |
297 | |
298 | Bug listings default to open bugtasks: |
299 | |
300 | + >>> # Debian must enable the Launchpad bug tracker to access bugs. |
301 | + >>> from lp.testing.service_usage_helpers import set_service_usage |
302 | + >>> set_service_usage('debian', bug_tracking_usage='LAUNCHPAD') |
303 | + |
304 | >>> user_browser.open('http://launchpad.dev/debian/+bugs') |
305 | >>> print_bugtasks(user_browser.contents) |
306 | 3 Bug Title Test mozilla-firefox Unknown New |
307 | @@ -31,6 +35,7 @@ |
308 | |
309 | An anonymous user views the bug tasks in upstream Ubuntu. |
310 | |
311 | + >>> set_service_usage('tomcat', bug_tracking_usage='LAUNCHPAD') |
312 | >>> anon_browser.open("http://launchpad.dev/tomcat/+bugs") |
313 | >>> print_bugtasks(anon_browser.contents) |
314 | 2 Blackhole Trash folder Low New |
315 | @@ -179,6 +184,7 @@ |
316 | Similarly, if we don't do a search and there are no open bugs on that product, |
317 | it'll say so. |
318 | |
319 | + >>> set_service_usage('iso-codes', bug_tracking_usage='LAUNCHPAD') |
320 | >>> user_browser.open("http://launchpad.dev/iso-codes/+bugs") |
321 | >>> print user_browser.contents |
322 | <... |
323 | |
324 | === modified file 'lib/lp/bugs/stories/bugtask-searches/xx-sort-orders.txt' |
325 | --- lib/lp/bugs/stories/bugtask-searches/xx-sort-orders.txt 2009-06-12 16:36:02 +0000 |
326 | +++ lib/lp/bugs/stories/bugtask-searches/xx-sort-orders.txt 2010-10-07 13:33:43 +0000 |
327 | @@ -33,6 +33,10 @@ |
328 | |
329 | Default view: |
330 | |
331 | + >>> # Debian must enable the Launchpad bug tracker to access bugs. |
332 | + >>> from lp.testing.service_usage_helpers import set_service_usage |
333 | + >>> set_service_usage('debian', bug_tracking_usage='LAUNCHPAD') |
334 | + |
335 | >>> anon_browser.open("http://launchpad.dev/debian/+bugs") |
336 | >>> print_bugtasks(anon_browser.contents) |
337 | 3 Bug Title Test |
338 | |
339 | === modified file 'lib/lp/bugs/templates/buglisting-default.pt' |
340 | --- lib/lp/bugs/templates/buglisting-default.pt 2009-09-16 17:05:13 +0000 |
341 | +++ lib/lp/bugs/templates/buglisting-default.pt 2010-10-07 13:33:43 +0000 |
342 | @@ -8,8 +8,14 @@ |
343 | > |
344 | <body> |
345 | |
346 | + <metal:block fill-slot="head_epilogue"> |
347 | + <meta tal:condition="not: view/bug_tracking_usage/enumvalue:LAUNCHPAD" |
348 | + name="robots" content="noindex,nofollow" /> |
349 | + </metal:block> |
350 | + |
351 | <div metal:fill-slot="main"> |
352 | - <div class="top-portlet"> |
353 | + <div tal:condition="not: view/bug_tracking_usage/enumvalue:UNKNOWN" |
354 | + class="top-portlet"> |
355 | <tal:block condition="view/_projectContext"> |
356 | <tal:block condition="view/required:launchpad.Edit"> |
357 | <p tal:condition="not: context/products" class="warning message"> |
358 | @@ -31,7 +37,7 @@ |
359 | condition="not: view/shouldShowAdvancedForm"> |
360 | <div tal:define="batch_navigator view/search"> |
361 | |
362 | - <div metal:use-macro="context/@@+bugtarget-macros-search/simple-search-form" /> |
363 | + <div metal:use-macro="context/@@+bugtarget-macros-search/simple-search-form"></div> |
364 | <tal:buglisting content="structure batch_navigator/@@+table-view" /> |
365 | </div> |
366 | </tal:do_not_show_advanced_form> |
367 | @@ -41,9 +47,22 @@ |
368 | use-macro="context/@@+bugtask-macros-tableview/advanced_search_form" /> |
369 | </tal:show_advanced_form> |
370 | </div> |
371 | + <div tal:condition="view/bug_tracking_usage/enumvalue:UNKNOWN" |
372 | + class="top-portlet"> |
373 | + <p> |
374 | + <tal:displayname replace="context/displayname" /> |
375 | + does not use Launchpad for bug tracking. |
376 | + </p> |
377 | + <p> |
378 | + <a class="sprite maybe" |
379 | + href="https://help.launchpad.net/Bugs">Getting started |
380 | + with bug tracking in Launchpad</a>. |
381 | + </p> |
382 | + </div> |
383 | </div> |
384 | <tal:side metal:fill-slot="side"> |
385 | - <div id="involvement" class="portlet involvement"> |
386 | + <div id="involvement" class="portlet involvement" |
387 | + tal:condition="view/bug_tracking_usage/enumvalue:LAUNCHPAD"> |
388 | <ul> |
389 | <li style="border: 0"> |
390 | <a href="+filebug" class="menu-link-filebug sprite bugs"> |
391 | @@ -55,10 +74,12 @@ |
392 | <tal:menu replace="structure view/@@+related-pages" /> |
393 | <tal:do_not_show_portlets_advanced_form |
394 | condition="not: view/shouldShowAdvancedForm"> |
395 | - <tal:block content="structure context/@@+portlet-bugfilters" /> |
396 | + <tal:block content="structure context/@@+portlet-bugfilters" |
397 | + tal:condition="view/bug_tracking_usage/enumvalue:LAUNCHPAD"/> |
398 | <tal:block |
399 | content="structure context/@@+portlet-publishing-details | nothing"/> |
400 | - <tal:block content="structure context/@@+portlet-bugtags" /> |
401 | + <tal:block content="structure context/@@+portlet-bugtags" |
402 | + tal:condition="view/bug_tracking_usage/enumvalue:LAUNCHPAD"/> |
403 | <tal:releasecriticalbugs |
404 | tal:condition="view/shouldShowReleaseCriticalPortlet" |
405 | tal:content="structure context/@@+portlet-bugtasklist-seriesbugs" /> |
406 | |
407 | === modified file 'lib/lp/registry/browser/distributionsourcepackage.py' |
408 | --- lib/lp/registry/browser/distributionsourcepackage.py 2010-09-27 16:49:22 +0000 |
409 | +++ lib/lp/registry/browser/distributionsourcepackage.py 2010-10-07 13:33:43 +0000 |
410 | @@ -4,14 +4,15 @@ |
411 | __metaclass__ = type |
412 | |
413 | __all__ = [ |
414 | + 'distribution_from_distributionsourcepackage', |
415 | 'DistributionSourcePackageBreadcrumb', |
416 | + 'DistributionSourcePackageChangelogView', |
417 | 'DistributionSourcePackageEditView', |
418 | 'DistributionSourcePackageFacets', |
419 | 'DistributionSourcePackageNavigation', |
420 | 'DistributionSourcePackageOverviewMenu', |
421 | + 'DistributionSourcePackagePublishingHistoryView', |
422 | 'DistributionSourcePackageView', |
423 | - 'DistributionSourcePackageChangelogView', |
424 | - 'DistributionSourcePackagePublishingHistoryView', |
425 | ] |
426 | |
427 | from datetime import datetime |
428 | @@ -20,12 +21,17 @@ |
429 | |
430 | from lazr.delegates import delegates |
431 | import pytz |
432 | -from zope.component import getUtility |
433 | +from zope.component import ( |
434 | + adapter, |
435 | + getUtility, |
436 | + ) |
437 | from zope.interface import ( |
438 | + implementer, |
439 | implements, |
440 | Interface, |
441 | ) |
442 | |
443 | +from canonical.launchpad.webapp.interfaces import IBreadcrumb |
444 | from canonical.launchpad.helpers import shortlist |
445 | from canonical.launchpad.webapp import ( |
446 | action, |
447 | @@ -44,6 +50,7 @@ |
448 | NavigationMenu, |
449 | ) |
450 | from canonical.launchpad.webapp.sorting import sorted_dotted_numbers |
451 | +from lp.app.interfaces.launchpad import IServiceUsage |
452 | from lp.app.browser.tales import CustomizableFormatter |
453 | from canonical.lazr.utils import smartquote |
454 | from lp.answers.browser.questiontarget import ( |
455 | @@ -88,8 +95,10 @@ |
456 | return {'displayname': displayname} |
457 | |
458 | |
459 | +@adapter(IDistributionSourcePackage) |
460 | class DistributionSourcePackageBreadcrumb(Breadcrumb): |
461 | """Builds a breadcrumb for an `IDistributionSourcePackage`.""" |
462 | + implements(IBreadcrumb) |
463 | |
464 | @property |
465 | def text(self): |
466 | @@ -97,6 +106,12 @@ |
467 | self.context.sourcepackagename.name) |
468 | |
469 | |
470 | +@adapter(IDistributionSourcePackage) |
471 | +@implementer(IServiceUsage) |
472 | +def distribution_from_distributionsourcepackage(dsp): |
473 | + return dsp.distribution |
474 | + |
475 | + |
476 | class DistributionSourcePackageFacets(QuestionTargetFacetMixin, |
477 | StandardLaunchpadFacets): |
478 | |
479 | |
480 | === modified file 'lib/lp/registry/browser/pillar.py' |
481 | --- lib/lp/registry/browser/pillar.py 2010-10-06 19:44:28 +0000 |
482 | +++ lib/lp/registry/browser/pillar.py 2010-10-07 13:33:43 +0000 |
483 | @@ -31,8 +31,8 @@ |
484 | ) |
485 | from lp.app.browser.tales import MenuAPI |
486 | from lp.app.enums import ( |
487 | + service_uses_launchpad, |
488 | ServiceUsage, |
489 | - service_uses_launchpad, |
490 | ) |
491 | from lp.app.interfaces.launchpad import IServiceUsage |
492 | from lp.registry.browser.structuralsubscription import ( |
493 | @@ -113,34 +113,33 @@ |
494 | self.translations_usage = ServiceUsage.UNKNOWN |
495 | self.codehosting_usage = ServiceUsage.UNKNOWN |
496 | pillar = nearest(self.context, IPillar) |
497 | - if IProjectGroup.providedBy(pillar): |
498 | - for product in pillar.products: |
499 | - self._set_official_launchpad(product) |
500 | + |
501 | + self._set_official_launchpad(pillar) |
502 | + if IDistroSeries.providedBy(self.context): |
503 | + distribution = self.context.distribution |
504 | + self.codehosting_usage = distribution.codehosting_usage |
505 | + self.answers_usage = ServiceUsage.NOT_APPLICABLE |
506 | + elif IDistributionSourcePackage.providedBy(self.context): |
507 | + self.blueprints_usage = ServiceUsage.UNKNOWN |
508 | + self.translations_usage = ServiceUsage.UNKNOWN |
509 | + elif IProjectGroup.providedBy(pillar): |
510 | + # XXX: 2010-10-07 EdwinGrubbs bug=656292 |
511 | + # Fix _set_official_launchpad(). |
512 | + |
513 | # Project groups do not support submit code, override the |
514 | # default. |
515 | self.codehosting_usage = ServiceUsage.NOT_APPLICABLE |
516 | - # Product groups must have translatable products for |
517 | - # translations_usage to be ServiceUsage.LAUNCHPAD |
518 | - if not pillar.has_translatable(): |
519 | - self.translations_usage = ServiceUsage.UNKNOWN |
520 | else: |
521 | - self._set_official_launchpad(pillar) |
522 | - if IDistroSeries.providedBy(self.context): |
523 | - distribution = self.context.distribution |
524 | - self.codehosting_usage = distribution.codehosting_usage |
525 | - self.answers_usage = ServiceUsage.NOT_APPLICABLE |
526 | - elif IDistributionSourcePackage.providedBy(self.context): |
527 | - self.blueprints_usage = ServiceUsage.UNKNOWN |
528 | - self.translations_usage = ServiceUsage.UNKNOWN |
529 | - else: |
530 | - # The context is used by all apps. |
531 | - pass |
532 | + # The context is used by all apps. |
533 | + pass |
534 | |
535 | def _set_official_launchpad(self, pillar): |
536 | """Does the pillar officially use launchpad.""" |
537 | + # XXX: 2010-10-07 EdwinGrubbs bug=656292 |
538 | + # Fix _set_official_launchpad(). |
539 | # This if structure is required because it may be called many |
540 | # times to build the complete set of official applications. |
541 | - if pillar.official_malone: |
542 | + if service_uses_launchpad(IServiceUsage(pillar).bug_tracking_usage): |
543 | self.official_malone = True |
544 | if service_uses_launchpad(IServiceUsage(pillar).answers_usage): |
545 | self.answers_usage = ServiceUsage.LAUNCHPAD |
546 | |
547 | === modified file 'lib/lp/registry/browser/sourcepackage.py' |
548 | --- lib/lp/registry/browser/sourcepackage.py 2010-09-29 00:17:32 +0000 |
549 | +++ lib/lp/registry/browser/sourcepackage.py 2010-10-07 13:33:43 +0000 |
550 | @@ -27,11 +27,16 @@ |
551 | from zope.app.form.browser import DropdownWidget |
552 | from zope.app.form.interfaces import IInputWidget |
553 | from zope.component import ( |
554 | + adapter, |
555 | getMultiAdapter, |
556 | getUtility, |
557 | ) |
558 | from zope.formlib.form import Fields |
559 | -from zope.interface import Interface |
560 | +from zope.interface import ( |
561 | + implementer, |
562 | + implements, |
563 | + Interface, |
564 | + ) |
565 | from zope.schema import ( |
566 | Choice, |
567 | TextLine, |
568 | @@ -42,10 +47,12 @@ |
569 | SimpleVocabulary, |
570 | ) |
571 | |
572 | +from canonical.launchpad.webapp.interfaces import IBreadcrumb |
573 | from canonical.launchpad import ( |
574 | _, |
575 | helpers, |
576 | ) |
577 | +from lp.app.interfaces.launchpad import IServiceUsage |
578 | from lp.app.browser.tales import CustomizableFormatter |
579 | from canonical.launchpad.browser.multistep import ( |
580 | MultiStepView, |
581 | @@ -170,8 +177,16 @@ |
582 | return redirection(redirection_url) |
583 | |
584 | |
585 | +@adapter(ISourcePackage) |
586 | +@implementer(IServiceUsage) |
587 | +def distribution_from_sourcepackage(package): |
588 | + return package.distribution |
589 | + |
590 | + |
591 | +@adapter(ISourcePackage) |
592 | class SourcePackageBreadcrumb(Breadcrumb): |
593 | """Builds a breadcrumb for an `ISourcePackage`.""" |
594 | + implements(IBreadcrumb) |
595 | |
596 | @property |
597 | def text(self): |
598 | |
599 | === modified file 'lib/lp/registry/configure.zcml' |
600 | --- lib/lp/registry/configure.zcml 2010-10-04 20:46:55 +0000 |
601 | +++ lib/lp/registry/configure.zcml 2010-10-07 13:33:43 +0000 |
602 | @@ -498,10 +498,9 @@ |
603 | provides="canonical.launchpad.webapp.interfaces.ILaunchpadContainer" |
604 | factory="canonical.launchpad.components.launchpadcontainer.LaunchpadDistributionSourcePackageContainer"/> |
605 | <adapter |
606 | - provides="canonical.launchpad.webapp.interfaces.IBreadcrumb" |
607 | - for="lp.registry.interfaces.distributionsourcepackage.IDistributionSourcePackage" |
608 | - factory="lp.registry.browser.distributionsourcepackage.DistributionSourcePackageBreadcrumb" |
609 | - permission="zope.Public"/> |
610 | + factory="lp.registry.browser.distributionsourcepackage.distribution_from_distributionsourcepackage"/> |
611 | + <adapter |
612 | + factory="lp.registry.browser.distributionsourcepackage.DistributionSourcePackageBreadcrumb"/> |
613 | |
614 | <!-- CommercialSubscription --> |
615 | |
616 | @@ -1615,10 +1614,9 @@ |
617 | interface="lp.registry.interfaces.sourcepackage.ISourcePackageFactory"/> |
618 | </securedutility> |
619 | <adapter |
620 | - provides="canonical.launchpad.webapp.interfaces.IBreadcrumb" |
621 | - for="lp.registry.interfaces.sourcepackage.ISourcePackage" |
622 | - factory="lp.registry.browser.sourcepackage.SourcePackageBreadcrumb" |
623 | - permission="zope.Public"/> |
624 | + factory="lp.registry.browser.sourcepackage.SourcePackageBreadcrumb"/> |
625 | + <adapter |
626 | + factory="lp.registry.browser.sourcepackage.distribution_from_sourcepackage"/> |
627 | |
628 | <!-- This is class ProductReleaseSet --> |
629 | |
630 | |
631 | === modified file 'lib/lp/registry/interfaces/projectgroup.py' |
632 | --- lib/lp/registry/interfaces/projectgroup.py 2010-10-06 19:44:28 +0000 |
633 | +++ lib/lp/registry/interfaces/projectgroup.py 2010-10-07 13:33:43 +0000 |
634 | @@ -51,6 +51,7 @@ |
635 | ) |
636 | from canonical.launchpad.validators.name import name_validator |
637 | from lp.app.interfaces.headings import IRootContext |
638 | +from lp.app.interfaces.launchpad import IServiceUsage |
639 | from lp.blueprints.interfaces.specificationtarget import IHasSpecifications |
640 | from lp.blueprints.interfaces.sprint import IHasSprints |
641 | from lp.bugs.interfaces.bugtarget import ( |
642 | @@ -111,7 +112,7 @@ |
643 | IHasDrivers, IHasBranchVisibilityPolicy, IHasIcon, IHasLogo, |
644 | IHasMentoringOffers, IHasMergeProposals, IHasMilestones, IHasMugshot, |
645 | IHasOwner, IHasSpecifications, IHasSprints, IMakesAnnouncements, |
646 | - IKarmaContext, IRootContext, IHasOfficialBugTags): |
647 | + IKarmaContext, IRootContext, IHasOfficialBugTags, IServiceUsage): |
648 | """Public IProjectGroup properties.""" |
649 | |
650 | id = Int(title=_('ID'), readonly=True) |
651 | |
652 | === modified file 'lib/lp/registry/model/projectgroup.py' |
653 | --- lib/lp/registry/model/projectgroup.py 2010-10-06 19:44:28 +0000 |
654 | +++ lib/lp/registry/model/projectgroup.py 2010-10-07 13:33:43 +0000 |
655 | @@ -52,6 +52,7 @@ |
656 | FAQSearch, |
657 | ) |
658 | from lp.answers.model.question import QuestionTargetSearch |
659 | +from lp.app.enums import ServiceUsage |
660 | from lp.app.errors import NotFoundError |
661 | from lp.blueprints.interfaces.specification import ( |
662 | SpecificationFilter, |
663 | @@ -492,6 +493,56 @@ |
664 | |
665 | return ProjectGroupSeries(self, series_name) |
666 | |
667 | + def _get_usage(self, attr): |
668 | + """Determine ProjectGroup usage based on individual projects. |
669 | + |
670 | + By default, return ServiceUsage.UNKNOWN. |
671 | + If any project uses Launchpad, return ServiceUsage.LAUNCHPAD. |
672 | + Otherwise, return the ServiceUsage of the last project that was |
673 | + not ServiceUsage.UNKNOWN. |
674 | + """ |
675 | + result = ServiceUsage.UNKNOWN |
676 | + for product in self.products: |
677 | + product_usage = getattr(product, attr) |
678 | + if product_usage != ServiceUsage.UNKNOWN: |
679 | + result = product_usage |
680 | + if product_usage == ServiceUsage.LAUNCHPAD: |
681 | + break |
682 | + return result |
683 | + |
684 | + @property |
685 | + def answers_usage(self): |
686 | + return self._get_usage('answers_usage') |
687 | + |
688 | + @property |
689 | + def blueprints_usage(self): |
690 | + return self._get_usage('blueprints_usage') |
691 | + |
692 | + @property |
693 | + def translations_usage(self): |
694 | + if self.has_translatable(): |
695 | + return ServiceUsage.LAUNCHPAD |
696 | + return ServiceUsage.UNKNOWN |
697 | + |
698 | + @property |
699 | + def codehosting_usage(self): |
700 | + # Project groups do not support submitting code. |
701 | + return ServiceUsage.NOT_APPLICABLE |
702 | + |
703 | + @property |
704 | + def bug_tracking_usage(self): |
705 | + return self._get_usage('bug_tracking_usage') |
706 | + |
707 | + @property |
708 | + def uses_launchpad(self): |
709 | + if (self.answers_usage == ServiceUsage.LAUNCHPAD |
710 | + or self.blueprints_usage == ServiceUsage.LAUNCHPAD |
711 | + or self.translations_usage == ServiceUsage.LAUNCHPAD |
712 | + or self.codehosting_usage == ServiceUsage.LAUNCHPAD |
713 | + or self.bug_tracking_usage == ServiceUsage.LAUNCHPAD): |
714 | + return True |
715 | + return False |
716 | + |
717 | |
718 | class ProjectGroupSet: |
719 | implements(IProjectGroupSet) |
720 | |
721 | === added file 'lib/lp/testing/service_usage_helpers.py' |
722 | --- lib/lp/testing/service_usage_helpers.py 1970-01-01 00:00:00 +0000 |
723 | +++ lib/lp/testing/service_usage_helpers.py 2010-10-07 13:33:43 +0000 |
724 | @@ -0,0 +1,33 @@ |
725 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
726 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
727 | + |
728 | +"""Helper functions dealing with IServiceUsage.""" |
729 | +__metaclass__ = type |
730 | + |
731 | +import transaction |
732 | +from zope.component import getUtility |
733 | + |
734 | +from lp.app.enums import ServiceUsage |
735 | +from lp.registry.interfaces.pillar import IPillarNameSet |
736 | +from lp.testing import ( |
737 | + login, |
738 | + logout, |
739 | + ) |
740 | +from lp.testing.factory import LaunchpadObjectFactory |
741 | +from lp.testing.sampledata import ADMIN_EMAIL |
742 | + |
743 | + |
744 | +def set_service_usage(pillar_name, **kw): |
745 | + factory = LaunchpadObjectFactory() |
746 | + login(ADMIN_EMAIL) |
747 | + pillar = getUtility(IPillarNameSet)[pillar_name] |
748 | + for attr, service_usage_name in kw.items(): |
749 | + service_usage = getattr(ServiceUsage, service_usage_name) |
750 | + if attr == 'bug_tracking_usage': |
751 | + pillar.official_malone = (service_usage == ServiceUsage.LAUNCHPAD) |
752 | + if service_usage == ServiceUsage.EXTERNAL: |
753 | + pillar.bugtracker = factory.makeBugTracker() |
754 | + else: |
755 | + setattr(pillar, attr, service_usage) |
756 | + #transaction.commit() |
757 | + logout() |
Here is a diff of a couple of files that I forgot to commit before.
=== added file 'lib/lp/ bugs/browser/ tests/test_ buglisting. py' bugs/browser/ tests/test_ buglisting. py 1970-01-01 00:00:00 +0000 bugs/browser/ tests/test_ buglisting. py 2010-10-06 20:20:08 +0000 launchpad. testing. pages import ( launchpad. webapp import canonical_url testing. layers import LaunchpadFuncti onalLayer chListingView( BrowserTestCase ): onalLayer onSourcePackage (self): makeDistributio n('test- distro' ) makeDistributio nSourcePackage( 'test-dsp' , distro) onsourcepackage _unknown_ bugtracker_ message( self): ibutionSourcePa ckage() wser(url) (len(top_ portlet) > 0, MatchesExpressi onIgnoreWhitesp ace(""" text(top_ portlet[ 0])) onsourcepackage _unknown_ bugtracker_ no_button( self): ibutionSourcePa ckage() wser(url) by_id(browser. contents, 'involvement'), age(self) : makeDistributio n('test- distro' ) makeDistroRelea se( distro, name='test-series') makeSourcePacka ge('test- sp', distro. currentseries) age_unknown_ bugtracker_ message( self): ePackage( ) wser(url) (len(top_ portlet) > 0, MatchesExpressi onIgnoreWhitesp ace(""" text(top_ portlet[ 0])) age_unknown_ bugtracker_ no_button( self): ePackage( )
--- lib/lp/
+++ lib/lp/
@@ -0,0 +1,71 @@
+# Copyright 2010 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+__metaclass__ = type
+
+from canonical.
+ extract_text,
+ find_tag_by_id,
+ find_tags_by_class,
+ )
+from canonical.
+from canonical.
+from lp.testing import BrowserTestCase
+
+
+class TestBugTaskSear
+
+ layer = LaunchpadFuncti
+
+ def _makeDistributi
+ distro = self.factory.
+ return self.factory.
+
+ def test_distributi
+ dsp = self._makeDistr
+ url = canonical_url(dsp, rootsite='bugs')
+ browser = self.getUserBro
+ top_portlet = find_tags_by_class(
+ browser.contents, 'top-portlet')
+ self.assertTrue
+ "Tag with class=top-portlet not found")
+ self.assertText
+ test-dsp in test-distro does not use Launchpad for bug tracking.
+ Getting started with bug tracking in Launchpad.""",
+ extract_
+
+ def test_distributi
+ dsp = self._makeDistr
+ url = canonical_url(dsp, rootsite='bugs')
+ browser = self.getUserBro
+ self.assertIs(None, find_tag_
+ "Involvement portlet with Report-a-bug button should "
+ "not be shown")
+
+ def _makeSourcePack
+ distro = self.factory.
+ series = self.factory.
+ distribution=
+ return self.factory.
+
+ def test_sourcepack
+ sp = self._makeSourc
+ url = canonical_url(sp, rootsite='bugs')
+ browser = self.getUserBro
+ top_portlet = find_tags_by_class(
+ browser.contents, 'top-portlet')
+ self.assertTrue
+ "Tag with class=top-portlet not found")
+ self.assertText
+ test-sp in Test-distro Test-series does not
+ use Launchpad for bug tracking.
+ Getting started with bug tracking in Launchpad.""",
+ extract_
+
+ def test_sourcepack
+ sp = self._makeSourc
+ url...