Merge lp:~bac/launchpad/bug-512408 into lp:launchpad

Proposed by Brad Crittenden
Status: Merged
Approved by: Aaron Bentley
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~bac/launchpad/bug-512408
Merge into: lp:launchpad
Diff against target: 655 lines (+429/-47)
11 files modified
lib/canonical/launchpad/testing/pages.py (+1/-12)
lib/canonical/launchpad/testing/systemdocs.py (+13/-0)
lib/lp/registry/browser/configure.zcml (+7/-4)
lib/lp/registry/browser/product.py (+55/-0)
lib/lp/registry/browser/tests/product-portlet-packages-view.txt (+174/-0)
lib/lp/registry/browser/tests/product-views.txt (+75/-0)
lib/lp/registry/model/distributionsourcepackage.py (+2/-1)
lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt (+3/-3)
lib/lp/registry/stories/product/xx-product-index.txt (+33/-0)
lib/lp/registry/templates/product-portlet-packages.pt (+65/-26)
lib/lp/registry/tests/test_doc_product.py (+1/-1)
To merge this branch: bzr merge lp:~bac/launchpad/bug-512408
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code + ui Approve
Aaron Bentley (community) Approve
Review via email: mp+20379@code.launchpad.net

Commit message

Project index page packaging portlet suggests which Ubuntu package it may be associated.

To post a comment you must log in.
Revision history for this message
Brad Crittenden (bac) wrote :

= Summary =

Change the packaging portlet on the product index page to suggest Ubuntu packages
that may be potential matches if the product is not currently linked.

== Proposed fix ==

Create a new view to query ubuntu.searchSourcePackages and show the results in the
portlet.

== Pre-implementation notes ==

Chats with Curtis.

== Implementation details ==

As above.

== Tests ==

bin/test -vvm lp.registry -t product-portlet-packages-view.txt \
   -t xx-product-index.txt

== Demo and Q/A ==

In launchpad.dev create a product called pmount. Visit https://launchpad.dev/pmount
and see that the pmount package in the sample data is suggested. Make the link and
then marvel that it is shown on the product's index page.

= Launchpad lint =

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/lp/registry/browser/configure.zcml
  lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt
  lib/lp/registry/browser/product.py
  lib/lp/registry/browser/tests/product-views.txt
  lib/lp/registry/browser/tests/product-portlet-packages-view.txt
  lib/lp/registry/templates/product-portlet-packages.pt
  lib/lp/registry/tests/test_doc_product.py
  lib/lp/registry/stories/product/xx-product-index.txt

== Pylint notices ==

lib/lp/registry/browser/product.py
    59: [F0401] Unable to import 'lazr.delegates' (No module named delegates)

Revision history for this message
Aaron Bentley (abentley) :
review: Approve
Revision history for this message
Curtis Hovey (sinzui) wrote :

Hi Brad.

The UI looks and behaves well and I think it is good to land, but there is an implementation issue.

As we saw on IRC, The UI prompts me to create duplicate packaging links. The list of candiates is not filtering the packages that have packaging links. My test case was to create a link to lucid pmount from applets. When I registered pmount, I was prompted to link it to lucid pmount--which leads to a db constraint violation in db-devel and a NotOneError in devel when I vistit lucid pmount.

review: Approve (ui)
Revision history for this message
Brad Crittenden (bac) wrote :

Curtis I made the change you requested.

In the process of writing the tests I needed to use Barry's 'stop()' command but it was only available to page tests, not doc tests, so I did a quick drive-by to move it over.

Diff @ http://pastebin.ubuntu.com/386572/

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

All this is lovely, unlike merge reviews which just ate my UI approve because I wanted to give you my code approve.

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/canonical/launchpad/testing/pages.py'
2--- lib/canonical/launchpad/testing/pages.py 2010-02-24 23:18:40 +0000
3+++ lib/canonical/launchpad/testing/pages.py 2010-03-06 12:18:33 +0000
4@@ -14,7 +14,6 @@
5 import pprint
6 import re
7 import transaction
8-import sys
9 import unittest
10
11 from BeautifulSoup import (
12@@ -34,7 +33,7 @@
13 IOAuthConsumerSet, OAUTH_REALM, ILaunchpadCelebrities,
14 TeamMembershipStatus)
15 from canonical.launchpad.testing.systemdocs import (
16- LayeredDocFileSuite, SpecialOutputChecker, strip_prefix)
17+ LayeredDocFileSuite, SpecialOutputChecker, stop, strip_prefix)
18 from canonical.launchpad.webapp import canonical_url
19 from canonical.launchpad.webapp.interfaces import OAuthPermission
20 from canonical.launchpad.webapp.url import urlsplit
21@@ -715,16 +714,6 @@
22 return setupBrowser(auth='Basic re@ex.com:test')
23
24
25-def stop():
26- # Temporarily restore the real stdout.
27- old_stdout = sys.stdout
28- sys.stdout = sys.__stdout__
29- try:
30- pdb.set_trace()
31- finally:
32- sys.stdout = old_stdout
33-
34-
35 def setUpGlobs(test):
36 test.globs['transaction'] = transaction
37 test.globs['http'] = UnstickyCookieHTTPCaller()
38
39=== modified file 'lib/canonical/launchpad/testing/systemdocs.py'
40--- lib/canonical/launchpad/testing/systemdocs.py 2009-10-15 11:47:32 +0000
41+++ lib/canonical/launchpad/testing/systemdocs.py 2010-03-06 12:18:33 +0000
42@@ -10,12 +10,14 @@
43 'SpecialOutputChecker',
44 'setUp',
45 'setGlobs',
46+ 'stop',
47 'strip_prefix',
48 'tearDown',
49 ]
50
51 import logging
52 import os
53+import pdb
54 import pprint
55 import sys
56
57@@ -170,6 +172,16 @@
58 "%r: %r" % (key, value) for key, value in sorted(dict.items()))
59
60
61+def stop():
62+ # Temporarily restore the real stdout.
63+ old_stdout = sys.stdout
64+ sys.stdout = sys.__stdout__
65+ try:
66+ pdb.set_trace()
67+ finally:
68+ sys.stdout = old_stdout
69+
70+
71 def setGlobs(test):
72 """Add the common globals for testing system documentation."""
73 test.globs['ANONYMOUS'] = ANONYMOUS
74@@ -186,6 +198,7 @@
75 test.globs['ordered_dict_as_string'] = ordered_dict_as_string
76 test.globs['verifyObject'] = verifyObject
77 test.globs['pretty'] = pprint.PrettyPrinter(width=1).pformat
78+ test.globs['stop'] = stop
79
80
81 def setUp(test):
82
83=== modified file 'lib/lp/registry/browser/configure.zcml'
84--- lib/lp/registry/browser/configure.zcml 2010-03-05 14:18:18 +0000
85+++ lib/lp/registry/browser/configure.zcml 2010-03-06 12:18:33 +0000
86@@ -1412,15 +1412,18 @@
87 facet="overview"
88 template="../templates/product-portlet-license-missing.pt"/>
89 <browser:page
90- name="+portlet-packages"
91- facet="overview"
92- template="../templates/product-portlet-packages.pt"/>
93- <browser:page
94 name="+purchase-subscription"
95 template="../templates/product-purchase-subscription.pt"/>
96 </browser:pages>
97 <browser:page
98 for="lp.registry.interfaces.product.IProduct"
99+ permission="zope.Public"
100+ name="+portlet-packages"
101+ facet="overview"
102+ class="lp.registry.browser.product.ProductPackagesPortletView"
103+ template="../templates/product-portlet-packages.pt"/>
104+ <browser:page
105+ for="lp.registry.interfaces.product.IProduct"
106 class="lp.registry.browser.product.ProductSeriesView"
107 name="+series"
108 facet="overview"
109
110=== modified file 'lib/lp/registry/browser/product.py'
111--- lib/lp/registry/browser/product.py 2010-02-16 21:21:14 +0000
112+++ lib/lp/registry/browser/product.py 2010-03-06 12:18:33 +0000
113@@ -21,6 +21,7 @@
114 'ProductNavigationMenu',
115 'ProductOverviewMenu',
116 'ProductPackagesView',
117+ 'ProductPackagesPortletView',
118 'ProductRdfView',
119 'ProductReviewLicenseView',
120 'ProductSeriesView',
121@@ -37,6 +38,7 @@
122 ]
123
124
125+from cgi import escape
126 from operator import attrgetter
127
128 from zope.component import getUtility
129@@ -45,6 +47,9 @@
130 from zope.lifecycleevent import ObjectCreatedEvent
131 from zope.interface import implements, Interface
132 from zope.formlib import form
133+from zope.schema import Choice
134+from zope.schema.vocabulary import (
135+ SimpleVocabulary, SimpleTerm)
136
137 from z3c.ptcompat import ViewPageTemplateFile
138
139@@ -981,6 +986,56 @@
140 return results
141
142
143+class ProductPackagesPortletView(LaunchpadFormView):
144+ """View class for product packaging portlet."""
145+
146+ schema = Interface
147+ custom_widget(
148+ 'distributionsourcepackage', LaunchpadRadioWidget,
149+ orientation='vertical')
150+ suggestions = None
151+
152+ def setUpFields(self):
153+ """See `LaunchpadFormView`."""
154+ super(ProductPackagesPortletView, self).setUpFields()
155+ ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
156+ source_packages = ubuntu.searchSourcePackages(self.context.name)
157+ # Based upon the matches, create a new vocabulary with
158+ # term descriptions that include a link to the source package.
159+ self.suggestions = []
160+ vocab_terms = []
161+ for package in source_packages:
162+ if package.upstream_product is not None:
163+ continue
164+ self.suggestions.append(package)
165+ item_url = canonical_url(package)
166+ description = """<a href="%s">%s</a>""" % (
167+ item_url, escape(package.name))
168+ vocab_terms.append(SimpleTerm(package, package.name, description))
169+ vocabulary = SimpleVocabulary(vocab_terms)
170+ self.form_fields = form.Fields(
171+ Choice(__name__='distributionsourcepackage',
172+ title=_('Ubuntu packages'),
173+ default=None,
174+ vocabulary=vocabulary,
175+ required=True))
176+
177+ @action(_('Link to this Ubuntu Package'), name='link')
178+ def link(self, action, data):
179+ product = self.context
180+ dsp = data.get('distributionsourcepackage')
181+ assert dsp is not None, "distributionsourcepackage was not specified"
182+ product_series = product.development_focus
183+ ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
184+ product_series.setPackaging(ubuntu.currentseries,
185+ dsp.sourcepackagename,
186+ self.user)
187+ self.request.response.addInfoNotification(
188+ 'This project was linked to the source package "%s"' %
189+ dsp.displayname)
190+ self.next_url = self.request.getURL()
191+
192+
193 class SeriesReleasePair:
194 """Class for holding a series and release.
195
196
197=== added file 'lib/lp/registry/browser/tests/product-portlet-packages-view.txt'
198--- lib/lp/registry/browser/tests/product-portlet-packages-view.txt 1970-01-01 00:00:00 +0000
199+++ lib/lp/registry/browser/tests/product-portlet-packages-view.txt 2010-03-06 12:18:33 +0000
200@@ -0,0 +1,174 @@
201++portlet-packages
202+-----------------
203+
204+When the product is not linked to a source package in Ubuntu the
205++portlet-packages will show suggestions on potential matches and ask
206+the user to make the connection.
207+
208+Create a helper to update the distribution source package cache, which
209+does not happen automatically.
210+
211+ >>> from canonical.launchpad.testing.pages import find_tag_by_id
212+ >>> from canonical.launchpad.testing.pages import extract_text
213+ >>> from canonical.launchpad.interfaces.launchpad import (
214+ ... ILaunchpadCelebrities)
215+ >>> from lp.registry.interfaces.product import IProductSet
216+ >>> from lp.registry.interfaces.sourcepackagename import (
217+ ... ISourcePackageNameSet)
218+
219+ >>> import transaction
220+ >>> from canonical.launchpad.scripts import QuietFakeLogger
221+ >>> logger = QuietFakeLogger()
222+ >>> from canonical.testing.layers import reconnect_stores
223+ >>> from canonical.config import config
224+ >>> def updateCache():
225+ ... # Switch to the statistician user who is the only user with
226+ ... # write permission to the source package cache tables.
227+ ... transaction.commit()
228+ ... reconnect_stores(config.statistician.dbuser)
229+ ... ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
230+ ... updated = ubuntu.updateCompleteSourcePackageCache(
231+ ... archive=ubuntu.main_archive, log=logger, ztm=transaction)
232+ ... transaction.commit()
233+ ... reconnect_stores('launchpad')
234+ ... # Get ubuntu, our product, and the sourcepackage name again
235+ ... # since the transaction changed.
236+ ... ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
237+ ... product = getUtility(IProductSet)['bingo']
238+ ... spn = getUtility(ISourcePackageNameSet)['bingo']
239+ ... login(ANONYMOUS)
240+ ... return (ubuntu, product, spn)
241+
242+
243+Let's create a test project.
244+
245+ >>> product = factory.makeProduct(name="bingo")
246+ >>> login_person(product.owner)
247+ >>> view = create_initialized_view(
248+ ... product, name="+portlet-packages",
249+ ... principal=product.owner)
250+ >>> print view.suggestions
251+ []
252+
253+No distribution source packages match so the user is shown an
254+appropriate message asking to suggest a match.
255+
256+ >>> content = find_tag_by_id(view.render(), 'portlet-packages')
257+ >>> print extract_text(content)
258+ All packages
259+ Packages in Ubuntu
260+ Launchpad doesn't know which Ubuntu packages this project
261+ provides. Links from distribution packages to upstream projects
262+ let distribution and upstream maintainers share bugs, patches, and
263+ translations efficiently.
264+ There are no unlinked source packages that are a good match. Can you suggest one?
265+ Link to Ubuntu package
266+
267+
268+A distribution source package in a distribution other than ubuntu will
269+not be suggested.
270+
271+ >>> spn = factory.makeSourcePackageName(name="bingo")
272+ >>> distro_package = factory.makeDistributionSourcePackage(
273+ ... sourcepackagename=spn)
274+ >>> spph = factory.makeSourcePackagePublishingHistory(
275+ ... sourcepackagename=spn)
276+ >>> (ubuntu, product, spn) = updateCache()
277+ >>> view = create_initialized_view(
278+ ... product, name="+portlet-packages",
279+ ... principal=product.owner)
280+ >>> print view.suggestions
281+ []
282+
283+An Ubuntu distribution package that is not in the current series
284+will be suggested.
285+
286+ >>> distro_package = factory.makeDistributionSourcePackage(
287+ ... sourcepackagename=spn, distribution=ubuntu)
288+ >>> warty = ubuntu.getSeries('warty')
289+ >>> warty == ubuntu.currentseries
290+ False
291+ >>> spph = factory.makeSourcePackagePublishingHistory(
292+ ... sourcepackagename=spn, distroseries=warty)
293+ >>> (ubuntu, product, spn) = updateCache()
294+ >>> view = create_initialized_view(
295+ ... product, name="+portlet-packages",
296+ ... principal=product.owner)
297+ >>> for dsp in view.suggestions:
298+ ... print dsp.name
299+ bingo
300+
301+And the user is presented with a form to select the distribution
302+source package.
303+
304+ >>> content = find_tag_by_id(view.render(), 'portlet-packages')
305+
306+ >>> print extract_text(content)
307+ All packages
308+ Packages in Ubuntu
309+ Launchpad doesn't know which Ubuntu packages this project
310+ provides. Links from distribution packages to upstream projects
311+ let distribution and upstream maintainers share bugs, patches, and
312+ translations efficiently.
313+ Ubuntu packages:
314+ bingo...
315+
316+A distribution series with a matching name in the Ubuntu current
317+series will be suggested.
318+
319+ >>> distro_package = factory.makeDistributionSourcePackage(
320+ ... sourcepackagename=spn, distribution=ubuntu)
321+ >>> spph = factory.makeSourcePackagePublishingHistory(
322+ ... sourcepackagename=spn, distroseries=ubuntu.currentseries)
323+ >>> (ubuntu, product, spn) = updateCache()
324+ >>> view = create_initialized_view(
325+ ... product, name="+portlet-packages",
326+ ... principal=product.owner)
327+ >>> for dsp in view.suggestions:
328+ ... print dsp.name
329+ bingo
330+
331+If multiple source packages match they will all be displayed.
332+
333+ >>> spn = factory.makeSourcePackageName(name="ba-bingo")
334+ >>> distro_package = factory.makeDistributionSourcePackage(
335+ ... sourcepackagename=spn, distribution=ubuntu)
336+ >>> spph = factory.makeSourcePackagePublishingHistory(
337+ ... sourcepackagename=spn, distroseries=ubuntu.currentseries)
338+ >>> (ubuntu, product, spn) = updateCache()
339+ >>> view = create_initialized_view(
340+ ... product, name="+portlet-packages",
341+ ... principal=product.owner)
342+ >>> for dsp in view.suggestions:
343+ ... print dsp.name
344+ bingo
345+ ba-bingo
346+
347+ >>> content = find_tag_by_id(view.render(), 'portlet-packages')
348+ >>> print extract_text(content)
349+ All packages
350+ Packages in Ubuntu
351+ Launchpad doesn't know which Ubuntu packages this project
352+ provides. Links from distribution packages to upstream projects
353+ let distribution and upstream maintainers share bugs, patches, and
354+ translations efficiently.
355+ Ubuntu packages:
356+ bingo
357+ ba-bingo...
358+
359+If a package matches by name but is already linked to an Ubuntu
360+package then it will not be shown as one of the suggestions.
361+
362+ >>> new_product = factory.makeProduct(name="not-bingo")
363+ >>> product_series = new_product.development_focus
364+ >>> babingo_spn = getUtility(ISourcePackageNameSet)['ba-bingo']
365+ >>> pkg = product_series.setPackaging(
366+ ... ubuntu.currentseries,
367+ ... babingo_spn, product.owner)
368+ >>> (ubuntu, product, spn) = updateCache()
369+ >>> view = create_initialized_view(
370+ ... product, name="+portlet-packages",
371+ ... principal=product.owner)
372+ >>> for dsp in view.suggestions:
373+ ... print dsp.name
374+ bingo
375
376=== modified file 'lib/lp/registry/browser/tests/product-views.txt'
377--- lib/lp/registry/browser/tests/product-views.txt 2010-02-17 11:19:42 +0000
378+++ lib/lp/registry/browser/tests/product-views.txt 2010-03-06 12:18:33 +0000
379@@ -478,3 +478,78 @@
380 portlet-latest-bugs
381 >>> print find_tag_by_id(content, 'portlet-blueprints')['id']
382 portlet-blueprints
383+
384+
385++portlet-packages
386+-----------------
387+
388+When the product is not linked to a source package in Ubuntu the
389++portlet-packages will show suggestions on potential matches and ask
390+the user to make the connection.
391+
392+ >>> product = factory.makeProduct(name="bingo")
393+ >>> login_person(product.owner)
394+ >>> view = create_initialized_view(
395+ ... product, name="+portlet-packages",
396+ ... principal=product.owner)
397+ >>> print view.suggestions
398+ []
399+
400+ >>> content = find_tag_by_id(view.render(), 'portlet-packages')
401+ >>> print extract_text(content)
402+ All packages
403+ Packages in Ubuntu
404+ Launchpad doesn't know which Ubuntu packages this project
405+ provides. Links from distribution packages to upstream projects
406+ let distribution and upstream maintainers share bugs, patches, and
407+ translations efficiently.
408+ There are no unlinked source packages that are a good match.
409+ Can you suggest one?
410+ Link to Ubuntu package
411+
412+ >>> spn = factory.makeSourcePackageName(name="bingo")
413+ >>> from canonical.launchpad.interfaces.launchpad import (
414+ ... ILaunchpadCelebrities)
415+ >>> ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
416+ >>> distro_package = factory.makeDistributionSourcePackage(
417+ ... sourcepackagename=spn, distribution=ubuntu)
418+ >>> spph = factory.makeSourcePackagePublishingHistory(
419+ ... sourcepackagename=spn, distroseries=ubuntu.currentseries)
420+
421+ >>> view = create_initialized_view(
422+ ... product, name="+portlet-packages",
423+ ... principal=product.owner)
424+ >>> print view.suggestions
425+ []
426+
427+ >>> distro_package = factory.makeDistributionSourcePackage(
428+ ... sourcepackagename=spn, distribution=ubuntu)
429+
430+ >>> view = create_initialized_view(
431+ ... product, name="+portlet-packages",
432+ ... principal=product.owner)
433+ >>> print view.suggestions
434+ []
435+
436+ >>> import transaction
437+ >>> #transaction.commit()
438+ >>> from canonical.launchpad.scripts import QuietFakeLogger
439+ >>> logger = QuietFakeLogger()
440+ >>> from canonical.testing.layers import reconnect_stores
441+ >>> from canonical.config import config
442+ >>> # Switch to the statistician user who is the only user with
443+ >>> # write permission to the source package cache tables.
444+ >>> reconnect_stores(config.statistician.dbuser)
445+ >>> # LaunchpadZopelessLayer.switchDbUser(config.statistician.dbuser)
446+ >>> ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
447+ >>> updated = ubuntu.updateCompleteSourcePackageCache(
448+ ... archive=ubuntu.main_archive, log=logger, ztm=transaction)
449+ >>> transaction.commit()
450+ >>> reconnect_stores('launchpad')
451+ >>> login(ANONYMOUS)
452+ >>> product = getUtility(IProductSet)['bingo']
453+ >>> view = create_initialized_view(
454+ ... product, name="+portlet-packages",
455+ ... principal=product.owner)
456+ >>> print view.suggestions
457+ []
458
459=== modified file 'lib/lp/registry/model/distributionsourcepackage.py'
460--- lib/lp/registry/model/distributionsourcepackage.py 2010-02-27 20:20:03 +0000
461+++ lib/lp/registry/model/distributionsourcepackage.py 2010-03-06 12:18:33 +0000
462@@ -187,7 +187,7 @@
463 PackagePublishingStatus.PUBLISHED,
464 PackagePublishingStatus.OBSOLETE),
465 clauseTables=["SourcePackagePublishingHistory",
466- "SourcePackageRelease",
467+ "SourcePackageRelease",
468 "DistroSeries"],
469 orderBy=["status",
470 SQLConstant(
471@@ -319,6 +319,7 @@
472 self.sourcepackagename)
473 if source_package.direct_packaging is not None:
474 return source_package.direct_packaging.productseries.product
475+ return None
476
477 # XXX kiko 2006-08-16: Bad method name, no need to be a property.
478 @property
479
480=== modified file 'lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt'
481--- lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt 2010-02-18 20:41:01 +0000
482+++ lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt 2010-03-06 12:18:33 +0000
483@@ -1,13 +1,13 @@
484 = Packaging =
485
486-No Privileges Person visit the distroseries upstream linkes page for Hoary
487+No Privileges Person visit the distroseries upstream links page for Hoary
488 and sees that pmount is not linked.
489
490 >>> user_browser.open(
491 ... 'http://launchpad.dev/ubuntu/hoary/+needs-packaging')
492 >>> print extract_text(find_tag_by_id(user_browser.contents, 'packages'))
493- Source Package Bugs Translations
494- pmount No bugs 64 strings ...
495+ Source Package Bugs Translations
496+ pmount No bugs 64 strings ...
497
498 He looks at the pmount source package page in Hoary and reads that the
499 upstream project is not set.
500
501=== modified file 'lib/lp/registry/stories/product/xx-product-index.txt'
502--- lib/lp/registry/stories/product/xx-product-index.txt 2009-10-30 15:40:55 +0000
503+++ lib/lp/registry/stories/product/xx-product-index.txt 2010-03-06 12:18:33 +0000
504@@ -348,3 +348,36 @@
505 >>> anon_browser.open('http://launchpad.dev/firefox')
506 >>> print extract_text(find_tag_by_id(anon_browser.contents, 'aliases'))
507 Also known as: iceweasel, snowchicken
508+
509+
510+Ubuntu packaging
511+----------------
512+
513+If a product is packaged in Ubuntu the links are shown.
514+
515+ >>> user_browser.open('http://launchpad.dev/firefox')
516+ >>> print extract_text(
517+ ... find_tag_by_id(user_browser.contents, 'portlet-packages'))
518+ All packages
519+ Packages in distributions
520+ “mozilla-firefox” source package in Hoary
521+ “mozilla-firefox” source package in Warty Version 0.9 uploaded on...
522+
523+A product that has linked packages now displays suggestions and asks
524+the user to select the package.
525+
526+ >>> login(ANONYMOUS)
527+ >>> product = factory.makeProduct(name='pmount')
528+ >>> logout()
529+ >>> user_browser.open('http://launchpad.dev/pmount')
530+ >>> print extract_text(
531+ ... find_tag_by_id(user_browser.contents, 'portlet-packages'))
532+ All packages...
533+ Packages in Ubuntu...
534+ Ubuntu packages:
535+ pmount...
536+
537+ >>> user_browser.getControl(name='field.distributionsourcepackage').value = ['pmount']
538+ >>> user_browser.getControl('Link to this Ubuntu Package').click()
539+ >>> print_feedback_messages(user_browser.contents)
540+ This project was linked to the source package "pmount in ubuntu"
541
542=== modified file 'lib/lp/registry/templates/product-portlet-packages.pt'
543--- lib/lp/registry/templates/product-portlet-packages.pt 2009-09-05 03:17:24 +0000
544+++ lib/lp/registry/templates/product-portlet-packages.pt 2010-03-06 12:18:33 +0000
545@@ -3,32 +3,71 @@
546 xmlns:metal="http://xml.zope.org/namespaces/metal"
547 xmlns:i18n="http://xml.zope.org/namespaces/i18n"
548 omit-tag=""
549- define="packages context/sourcepackages"
550- condition="packages">
551+ define="packages context/sourcepackages">
552+
553 <div class="portlet" id="portlet-packages">
554- <h2>
555- <span class="see-all"><a
556- tal:attributes="href context/menu:overview/packages/fmt:url">All
557- packages</a></span>
558- Packages in distributions
559- </h2>
560-
561- <ul>
562- <tal:pair tal:repeat="package packages">
563- <li>
564- <a class="sprite package-source"
565- tal:attributes="href package/fmt:url"
566- tal:content="package/title">apache in ubuntu hoary</a>
567- <br />
568- <span class="registered"
569- tal:define="release package/currentrelease"
570- tal:condition="release">
571- <strong>Version
572- <tal:version content="release/version">2.3</tal:version></strong>
573- uploaded <tal:date replace="release/dateuploaded/fmt:displaydate" />
574- </span>
575- </li>
576- </tal:pair>
577- </ul>
578+
579+ <tal:has_packages condition="packages">
580+ <h2>
581+ <span class="see-all"><a
582+ tal:attributes="href context/menu:overview/packages/fmt:url">All
583+ packages</a></span>
584+ Packages in distributions
585+ </h2>
586+
587+ <ul>
588+ <tal:pair tal:repeat="package packages">
589+ <li>
590+ <a class="sprite package-source"
591+ tal:attributes="href package/fmt:url"
592+ tal:content="package/title">apache in ubuntu hoary</a>
593+ <br />
594+ <span class="registered"
595+ tal:define="release package/currentrelease"
596+ tal:condition="release">
597+ <strong>Version
598+ <tal:version content="release/version">2.3</tal:version></strong>
599+ uploaded <tal:date replace="release/dateuploaded/fmt:displaydate" />
600+ </span>
601+ </li>
602+ </tal:pair>
603+ </ul>
604+ </tal:has_packages>
605+
606+ <tal:has_no_packages condition="not:packages">
607+ <h2>
608+ <span class="see-all"><a
609+ tal:attributes="href context/menu:overview/packages/fmt:url">All
610+ packages</a></span>
611+ Packages in Ubuntu
612+ </h2>
613+
614+ <p>
615+ Launchpad doesn't know which Ubuntu packages this project
616+ provides. Links from distribution packages to upstream projects
617+ let distribution and upstream maintainers share bugs, patches, and
618+ translations efficiently.
619+ </p>
620+ <div id="suggestions" tal:condition="view/suggestions">
621+ <div metal:use-macro="context/@@launchpad_form/form">
622+ <div class="actions" metal:fill-slot="buttons">
623+ <input tal:replace="structure view/link/render"/>
624+ &nbsp;or&nbsp;
625+ <a tal:replace="structure
626+ context/development_focus/menu:overview/ubuntupkg/fmt:link" />
627+ </div>
628+ </div>
629+ </div>
630+
631+ <div id="suggestions" tal:condition="not:view/suggestions">
632+ <p>
633+ There are no unlinked source packages that are a good match.
634+ Can you suggest one?
635+ </p>
636+ <a tal:replace="structure
637+ context/development_focus/menu:overview/ubuntupkg/fmt:link" />
638+ </div>
639+
640+ </tal:has_no_packages>
641 </div>
642 </tal:root>
643
644=== modified file 'lib/lp/registry/tests/test_doc_product.py'
645--- lib/lp/registry/tests/test_doc_product.py 2009-06-30 16:56:07 +0000
646+++ lib/lp/registry/tests/test_doc_product.py 2010-03-06 12:18:33 +0000
647@@ -3,7 +3,7 @@
648
649 """Test the doctests in the product module."""
650
651-# XXX sinzui 2009-04-03 bug=354881: This test harness shold be removed
652+# XXX sinzui 2009-04-03 bug=354881: This test harness should be removed
653 # and the inline tests moved to docs/
654
655 __metaclass__ = type