Merge lp:~stevenk/launchpad/say-no-bpns-alsoaffects into lp:launchpad

Proposed by Steve Kowalik
Status: Merged
Approved by: Steve Kowalik
Approved revision: no longer in the source branch.
Merged at revision: 13191
Proposed branch: lp:~stevenk/launchpad/say-no-bpns-alsoaffects
Merge into: lp:launchpad
Diff against target: 156 lines (+88/-34)
4 files modified
lib/lp/bugs/browser/bugalsoaffects.py (+11/-10)
lib/lp/bugs/browser/tests/test_bugalsoaffects.py (+76/-0)
lib/lp/bugs/stories/bug-also-affects/10-bug-requestdistrofix.txt (+0/-20)
lib/lp/registry/model/distribution.py (+1/-4)
To merge this branch: bzr merge lp:~stevenk/launchpad/say-no-bpns-alsoaffects
Reviewer Review Type Date Requested Status
Jeroen T. Vermeulen (community) Approve
Review via email: mp+63810@code.launchpad.net

Commit message

[r=jtv][bug=307620] Stop inviting users to file a bug on Launchpad if the picker for a distro task fails to find any results, and include whether or not Launchpad can search on binary package names as well.

Description of the change

Stop inviting users to file a bug on Launchpad if the picker for a distro task fails to find any results. Include text that suggest that Launchpad does not track binary package names for the distribution.

Drive-by a fix to IDistribution.has_published_binaries to make use of .is_empty().

To post a comment you must log in.
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :
Download full text (11.0 KiB)

Hi Steve,

My apologies for the delay in reviewing this. You can land this as-is if you really want, but there are a few tweaks I'd like you to consider (if not for now then for the future) and a few things that I do think need fixing.

1 === modified file 'lib/lp/bugs/browser/bugalsoaffects.py'
2 --- lib/lp/bugs/browser/bugalsoaffects.py 2011-05-27 21:12:25 +0000
3 +++ lib/lp/bugs/browser/bugalsoaffects.py 2011-06-08 04:03:29 +0000
4 @@ -418,16 +418,16 @@
5 self.widgets['sourcepackagename'].name)
6 if sourcepackagename is None and entered_package:
7 # The entered package doesn't exist.
8 - filebug_url = "%s/+filebug" % canonical_url(
9 - getUtility(ILaunchpadCelebrities).launchpad)
10 - self.setFieldError(
11 - 'sourcepackagename',
12 - structured(
13 - 'There is no package in %s named "%s". If it should'
14 - ' be here, <a href="%s">report this as a bug</a>.',
15 - distribution.displayname,
16 - entered_package,
17 - filebug_url))
18 + binary_tracking = ''
19 + if not distribution.has_published_binaries:
20 + binary_tracking = structured(
21 + ' Launchpad does not track binary package names '
22 + 'in %s.' % distribution.displayname)
23 + error = structured(
24 + 'There is no package in %s named "%s".%s',
25 + distribution.displayname, entered_package,
26 + binary_tracking)
27 + self.setFieldError('sourcepackagename', error)

You're running binary_tracking through structured twice here, and maybe compensating for that by not escaping distribution.displayname. To be honest it's not clear to me how this will work exactly: will the distro name in binary_tracking end up being escaped exactly once? Even if this is correct, please make it clearly correct as well. Otherwise an injection vulnerability could sneak in during future maintenance.

Also, it's traditionally been considered clearer in Launchpad to write alternative initializations of a variable in if/else form, rather than initializing it for both cases once and then conditionally overriding it:

18 + binary_tracking = ''
19 + if not distribution.has_published_binaries:
20 + binary_tracking = structured(
21 + ' Launchpad does not track binary package names '
22 + 'in %s.' % distribution.displayname)

…would be more obvious if written along the lines of…

    if distribution.has_published_binaries:
        binary_tracking = ""
    else:
        binary_tracking = "Whaaaa there's an error!"

Or you could use +=, or even (if you really want to be fancy about the whitespace) gather components of your message up in a list that you then " ".join().

In good news, structured supports keyword args. So you could do something like:

    error = structured(
        'There is no package in %(distro)s named "%(package)s". ' + binary_tracking,
        distro=distribution.displayname, package=entered_package)

N...

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/browser/bugalsoaffects.py'
2--- lib/lp/bugs/browser/bugalsoaffects.py 2011-05-27 21:12:25 +0000
3+++ lib/lp/bugs/browser/bugalsoaffects.py 2011-06-08 07:01:23 +0000
4@@ -418,16 +418,17 @@
5 self.widgets['sourcepackagename'].name)
6 if sourcepackagename is None and entered_package:
7 # The entered package doesn't exist.
8- filebug_url = "%s/+filebug" % canonical_url(
9- getUtility(ILaunchpadCelebrities).launchpad)
10- self.setFieldError(
11- 'sourcepackagename',
12- structured(
13- 'There is no package in %s named "%s". If it should'
14- ' be here, <a href="%s">report this as a bug</a>.',
15- distribution.displayname,
16- entered_package,
17- filebug_url))
18+ if distribution.has_published_binaries:
19+ binary_tracking = ''
20+ else:
21+ binary_tracking = structured(
22+ ' Launchpad does not track binary package names '
23+ 'in %s.', distribution.displayname)
24+ error = structured(
25+ 'There is no package in %s named "%s".%s',
26+ distribution.displayname, entered_package,
27+ binary_tracking)
28+ self.setFieldError('sourcepackagename', error)
29 else:
30 try:
31 validate_new_distrotask(
32
33=== added file 'lib/lp/bugs/browser/tests/test_bugalsoaffects.py'
34--- lib/lp/bugs/browser/tests/test_bugalsoaffects.py 1970-01-01 00:00:00 +0000
35+++ lib/lp/bugs/browser/tests/test_bugalsoaffects.py 2011-06-08 07:01:23 +0000
36@@ -0,0 +1,76 @@
37+# Copyright 2011 Canonical Ltd. This software is licensed under the
38+# GNU Affero General Public License version 3 (see the file LICENSE).
39+
40+__metaclass__ = type
41+
42+from zope.security.proxy import removeSecurityProxy
43+
44+from canonical.launchpad.testing.pages import get_feedback_messages
45+from canonical.launchpad.webapp import canonical_url
46+from canonical.testing.layers import DatabaseFunctionalLayer
47+from lp.soyuz.enums import PackagePublishingStatus
48+from lp.testing import (
49+ person_logged_in,
50+ TestCaseWithFactory,
51+ )
52+
53+
54+class TestBugAlsoAffectsDistribution(TestCaseWithFactory):
55+
56+ layer = DatabaseFunctionalLayer
57+
58+ def setUp(self):
59+ super(TestBugAlsoAffectsDistribution, self).setUp()
60+ self.distribution = self.factory.makeDistribution()
61+ removeSecurityProxy(self.distribution).official_malone = True
62+
63+ def test_bug_alsoaffects_spn_exists(self):
64+ # If the source package name exists, there is no error.
65+ bug = self.factory.makeBug()
66+ spn = self.factory.makeSourcePackageName()
67+ browser = self.getUserBrowser()
68+ browser.open(canonical_url(bug))
69+ browser.getLink(url='+distrotask').click()
70+ browser.getControl('Distribution').value = [self.distribution.name]
71+ browser.getControl('Source Package Name').value = spn.name
72+ browser.getControl('Continue').click()
73+ self.assertEqual([], get_feedback_messages(browser.contents))
74+
75+ def test_bug_alsoaffects_spn_not_exists_with_published_binaries(self):
76+ # When the distribution has published binaries, we search both
77+ # source and binary package names.
78+ bug = self.factory.makeBug()
79+ distroseries = self.factory.makeDistroSeries(
80+ distribution=self.distribution)
81+ das = self.factory.makeDistroArchSeries(distroseries=distroseries)
82+ bpph = self.factory.makeBinaryPackagePublishingHistory(
83+ distroarchseries=das, status=PackagePublishingStatus.PUBLISHED)
84+ self.assertTrue(self.distribution.has_published_binaries)
85+ browser = self.getUserBrowser()
86+ browser.open(canonical_url(bug))
87+ browser.getLink(url='+distrotask').click()
88+ browser.getControl('Distribution').value = [self.distribution.name]
89+ browser.getControl('Source Package Name').value = 'does-not-exist'
90+ browser.getControl('Continue').click()
91+ expected = [
92+ u'There is 1 error.',
93+ u'There is no package in %s named "does-not-exist".' % (
94+ self.distribution.displayname)]
95+ self.assertEqual(expected, get_feedback_messages(browser.contents))
96+
97+ def test_bug_alsoaffects_spn_not_exists_with_no_binaries(self):
98+ # When the distribution has no binary packages published, we can't.
99+ bug = self.factory.makeBug()
100+ browser = self.getUserBrowser()
101+ browser.open(canonical_url(bug))
102+ browser.getLink(url='+distrotask').click()
103+ browser.getControl('Distribution').value = [self.distribution.name]
104+ browser.getControl('Source Package Name').value = 'does-not-exist'
105+ browser.getControl('Continue').click()
106+ expected = [
107+ u'There is 1 error.',
108+ u'There is no package in %s named "does-not-exist". Launchpad '
109+ 'does not track binary package names in %s.' % (
110+ self.distribution.displayname,
111+ self.distribution.displayname)]
112+ self.assertEqual(expected, get_feedback_messages(browser.contents))
113
114=== modified file 'lib/lp/bugs/stories/bug-also-affects/10-bug-requestdistrofix.txt'
115--- lib/lp/bugs/stories/bug-also-affects/10-bug-requestdistrofix.txt 2009-09-18 15:24:30 +0000
116+++ lib/lp/bugs/stories/bug-also-affects/10-bug-requestdistrofix.txt 2011-06-08 07:01:23 +0000
117@@ -177,23 +177,3 @@
118 <...
119 ...>pmount (Debian)</a>...
120 ...
121-
122-If we enter a source package which doesn't exist, we get an error
123-message saying so.
124-
125- >>> browser.getLink(url='+distrotask').click()
126- >>> browser.getControl('Distribution').value = ['ubuntu']
127- >>> browser.getControl('Source Package Name').value = 'no-such-package'
128- >>> browser.getControl('Continue').click()
129- >>> browser.url
130- 'http://bugs.launchpad.dev/debian/+source/pmount/+bug/1/+distrotask'
131- >>> print get_feedback_messages(browser.contents)
132- [u'There is 1 error.',
133- u'There is no package in Ubuntu named "no-such-package". If it should
134- be here, report this as a bug.']
135-
136-The link in the error page links to the Launchpad filebug page.
137-
138- >>> browser.getLink('report this as a bug').click()
139- >>> print browser.title
140- Report a bug about Launchpad...
141
142=== modified file 'lib/lp/registry/model/distribution.py'
143--- lib/lp/registry/model/distribution.py 2011-06-07 03:30:25 +0000
144+++ lib/lp/registry/model/distribution.py 2011-06-08 07:01:23 +0000
145@@ -1835,10 +1835,7 @@
146 BinaryPackagePublishingHistory.status ==
147 PackagePublishingStatus.PUBLISHED).config(limit=1)
148
149- # XXX 2009-02-19 Julian
150- # Storm is not very useful for bool checking on the results,
151- # see: https://bugs.launchpad.net/soyuz/+bug/246200
152- return results.any() != None
153+ return not results.is_empty()
154
155 def sharesTranslationsWithOtherSide(self, person, language,
156 sourcepackage=None,