Merge lp:~edwin-grubbs/launchpad/bug-635302-dsp-filebug-oops into lp:launchpad

Proposed by Edwin Grubbs
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
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code + ui Approve
Review via email: mp+37679@code.launchpad.net

Description of the change

Summary
-------

The bugs.lp.net/fedora/+source/$distributionsourcepackage page would display a list of
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=noindex,nofollow and displays a link to
help.lp.net/Bugs like bugtarget-bugs.pt does. However, I did not add a
link to configure the bugtracker, since buglisting-default.pt is used on
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/lp/bugs/templates/buglisting-default.pt
    lib/lp/bugs/browser/bugtask.py

Adapt IDistributionSourcePackage/ISourcePackage to IServiceUsage and
reduce the zcml for the IBreadcrumb adapter.
    lib/lp/registry/browser/distributionsourcepackage.py
    lib/lp/registry/browser/sourcepackage.py
    lib/lp/registry/configure.zcml

Since buglisting-default.pt is also used by ProjectGroups, I made it
implement the IServiceUsage interface. This meant that the
browser.pillar.InvolvedMenu code could be simplified.
    lib/lp/registry/browser/pillar.py
    lib/lp/registry/interfaces/projectgroup.py
    lib/lp/registry/model/projectgroup.py

Fix tests by setting bug_tracking_usage to LAUNCHPAD. I also corrected
the indent of the python code in xx-distribution-statistics-portlet.txt.
    lib/lp/bugs/stories/bugtask-searches/xx-advanced-people-filters.txt
    lib/lp/bugs/stories/bugtask-searches/xx-advanced-upstream-pending-bugwatch.txt
    lib/lp/bugs/stories/bugtask-searches/xx-distribution-statistics-portlet.txt
    lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt
    lib/lp/bugs/stories/bugtask-searches/xx-sort-orders.txt

Tests
-----

./bin/test -vv -t 'xx-advanced-people-filters.txt|xx-advanced-upstream-pending-bugwatch.txt|xx-distribution-statistics-portlet.txt|xx-listing-basics.txt|xx-sort-orders.txt'

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://launchpad.dev/debian/+source/mozilla-firefox
    * Open http://launchpad.dev/debian/sarge/+source/mozilla-firefox
    * Open http://launchpad.dev/apache
* These pages should show the bug listing and the "Report a bug" button.
    * Open http://launchpad.dev/ubuntu/+source/mozilla-firefox
    * Open http://launchpad.dev/ubuntu/warty/+source/mozilla-firefox
    * Open http://launchpad.dev/gnome

To post a comment you must log in.
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :
Download full text (4.7 KiB)

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'
--- lib/lp/bugs/browser/tests/test_buglisting.py 1970-01-01 00:00:00 +0000
+++ lib/lp/bugs/browser/tests/test_buglisting.py 2010-10-06 20:20:08 +0000
@@ -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.launchpad.testing.pages import (
+ extract_text,
+ find_tag_by_id,
+ find_tags_by_class,
+ )
+from canonical.launchpad.webapp import canonical_url
+from canonical.testing.layers import LaunchpadFunctionalLayer
+from lp.testing import BrowserTestCase
+
+
+class TestBugTaskSearchListingView(BrowserTestCase):
+
+ layer = LaunchpadFunctionalLayer
+
+ def _makeDistributionSourcePackage(self):
+ distro = self.factory.makeDistribution('test-distro')
+ return self.factory.makeDistributionSourcePackage('test-dsp', distro)
+
+ def test_distributionsourcepackage_unknown_bugtracker_message(self):
+ dsp = self._makeDistributionSourcePackage()
+ url = canonical_url(dsp, rootsite='bugs')
+ browser = self.getUserBrowser(url)
+ top_portlet = find_tags_by_class(
+ browser.contents, 'top-portlet')
+ self.assertTrue(len(top_portlet) > 0,
+ "Tag with class=top-portlet not found")
+ self.assertTextMatchesExpressionIgnoreWhitespace("""
+ test-dsp in test-distro does not use Launchpad for bug tracking.
+ Getting started with bug tracking in Launchpad.""",
+ extract_text(top_portlet[0]))
+
+ def test_distributionsourcepackage_unknown_bugtracker_no_button(self):
+ dsp = self._makeDistributionSourcePackage()
+ url = canonical_url(dsp, rootsite='bugs')
+ browser = self.getUserBrowser(url)
+ self.assertIs(None, find_tag_by_id(browser.contents, 'involvement'),
+ "Involvement portlet with Report-a-bug button should "
+ "not be shown")
+
+ def _makeSourcePackage(self):
+ distro = self.factory.makeDistribution('test-distro')
+ series = self.factory.makeDistroRelease(
+ distribution=distro, name='test-series')
+ return self.factory.makeSourcePackage('test-sp', distro.currentseries)
+
+ def test_sourcepackage_unknown_bugtracker_message(self):
+ sp = self._makeSourcePackage()
+ url = canonical_url(sp, rootsite='bugs')
+ browser = self.getUserBrowser(url)
+ top_portlet = find_tags_by_class(
+ browser.contents, 'top-portlet')
+ self.assertTrue(len(top_portlet) > 0,
+ "Tag with class=top-portlet not found")
+ self.assertTextMatchesExpressionIgnoreWhitespace("""
+ test-sp in Test-distro Test-series does not
+ use Launchpad for bug tracking.
+ Getting started with bug tracking in Launchpad.""",
+ extract_text(top_portlet[0]))
+
+ def test_sourcepackage_unknown_bugtracker_no_button(self):
+ sp = self._makeSourcePackage()
+ url...

Read more...

Revision history for this message
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-statistics-portlet.txt, but I will ignore them since you it is unclear what the test is really doing. I think the bugs team should consider deleting it.

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://bugs.launchpad.dev/debian/+source/mozilla-firefox
* 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://launchpad.dev/apache
* OOPS
  Line 74, Column 8
  Expression: <PathExpr standard:u'context/@@+get-involved/answers_usage/enumvalue:LAUNCHPAD'>
  ForbiddenAttribute: ('official_malone', <ProjectGroup at 0xfd1b5ac>)<br />

https://launchpad.dev/gnome
* OOPS (same as above)

review: Needs Fixing (code and ui)
Revision history for this message
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-statistics-portlet.txt, but I will ignore them since you it is unclear what the test is really doing. I think the bugs team should consider deleting it.
>
> 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://bugs.launchpad.dev/debian/+source/mozilla-firefox
> * 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://launchpad.dev/apache
> * OOPS
>  Line 74, Column 8
>  Expression: <PathExpr standard:u'context/@@+get-involved/answers_usage/enumvalue:LAUNCHPAD'>
>  ForbiddenAttribute: ('official_malone', <ProjectGroup at 0xfd1b5ac>)<br />
>
>
> https://launchpad.dev/gnome
> * OOPS (same as above)

Both of these are now fixed.

Revision history for this message
Curtis Hovey (sinzui) wrote :

Thanks for addressing my concerns. I think this branch is ready to land.

review: Approve (code + ui)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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()