Merge lp:~edwin-grubbs/launchpad/bug-526001-edit-packaging-oops into lp:launchpad

Proposed by Edwin Grubbs
Status: Merged
Approved by: Brad Crittenden
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~edwin-grubbs/launchpad/bug-526001-edit-packaging-oops
Merge into: lp:launchpad
Diff against target: 134 lines (+91/-9)
2 files modified
lib/lp/registry/browser/sourcepackage.py (+16/-9)
lib/lp/registry/tests/test_sourcepackage.py (+75/-0)
To merge this branch: bzr merge lp:~edwin-grubbs/launchpad/bug-526001-edit-packaging-oops
Reviewer Review Type Date Requested Status
Brad Crittenden (community) code Approve
Review via email: mp+19997@code.launchpad.net

Commit message

Fix oops when changing the sourcepackage's productseries if the current series is obsolete.

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

Summary
-------

Fix bug where an exception is raised if you try to change the
productseries for a sourcepackage, when the current productseries
is obsolete.

Implementation details
----------------------

If the current context.productseries is not in the series_list variable,
add it. The code that converts the series_list into SimpleTerm objects
was moved below that if-statement.

Tests
-----

./bin/test -vv -t 'xx-distribution-packages.txt|xx-also-affects-upstream-default-values.txt|sourcepackage-views.txt|xx-sourcepackage-packaging.txt'

Demo and Q/A
------------

* Open https://launchpad.dev/ubuntu/warty/+source/mozilla-firefox/+edit-packaging
    * Set the product series.
* Open the productseries page that you used.
    * Change the status to OBSOLETE.
* Open https://launchpad.dev/ubuntu/warty/+source/mozilla-firefox/+edit-packaging
    * The current project should already be entered, so just click "Continue".
        * The obsolete series should show up as a radio button option
          instead of raising an exception.

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

Edwin as we discussed on IRC I think we need a test showing the successful working when the productseries is obsolete. Otherwise it looks good.

review: Needs Fixing (code)
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :
Download full text (4.0 KiB)

Hi Brad,

Thanks for the review. Here are the added tests.

=== modified file 'lib/lp/registry/tests/test_sourcepackage.py'
--- lib/lp/registry/tests/test_sourcepackage.py 2009-12-13 11:55:40 +0000
+++ lib/lp/registry/tests/test_sourcepackage.py 2010-02-24 03:06:12 +0000
@@ -22,6 +22,7 @@
 from lp.code.interfaces.seriessourcepackagebranch import (
     IMakeOfficialBranchLinks)
 from lp.testing import TestCaseWithFactory
+from lp.testing.views import create_initialized_view
 from canonical.testing.layers import DatabaseFunctionalLayer

@@ -238,5 +239,79 @@
             Unauthorized, sourcepackage.setBranch, pocket, branch, registrant)

+class TestSourcePackageViews(TestCaseWithFactory):
+ """Tests for source package view classes."""
+
+ layer = DatabaseFunctionalLayer
+
+ def setUp(self):
+ TestCaseWithFactory.setUp(self)
+ self.owner = self.factory.makePerson()
+ self.product = self.factory.makeProduct(
+ name='bonkers', displayname='Bonkers', owner=self.owner)
+
+ self.obsolete_productseries = self.factory.makeProductSeries(
+ name='obsolete', product=self.product)
+ self.obsolete_productseries.status = SeriesStatus.OBSOLETE
+
+ self.dev_productseries = self.factory.makeProductSeries(
+ name='current', product=self.product)
+ self.dev_productseries.status = SeriesStatus.DEVELOPMENT
+
+ self.distribution = self.factory.makeDistribution(
+ name='youbuntu', displayname='Youbuntu', owner=self.owner)
+ self.distroseries = self.factory.makeDistroRelease(name='busy',
+ distribution=self.distribution)
+ self.sourcepackagename = self.factory.makeSourcePackageName(
+ name='bonkers')
+ self.package = self.factory.makeSourcePackage(
+ sourcepackagename=self.sourcepackagename,
+ distroseries=self.distroseries)
+
+ def test_editpackaging_obsolete_series_in_vocabulary(self):
+ # The sourcepackage's current product series is included in
+ # the vocabulary even if it is obsolete.
+ self.package.setPackaging(self.obsolete_productseries, self.owner)
+ form = {
+ 'field.product': 'bonkers',
+ 'field.actions.continue': 'Continue',
+ 'field.__visited_steps__': 'sourcepackage_change_upstream_step1',
+ }
+ view = create_initialized_view(
+ self.package, name='+edit-packaging', form=form,
+ principal=self.owner)
+ self.assertEqual([], view.view.errors)
+ self.assertEqual(
+ self.obsolete_productseries,
+ view.view.form_fields['productseries'].field.default,
+ "The form's default productseries must be the current one.")
+ options = [term.token
+ for term in view.view.widgets['productseries'].vocabulary]
+ self.assertEqual(
+ ['trunk', 'current', 'obsolete'], options,
+ "The obsolete series must be in the vocabulary.")
+
+ def test_editpackaging_obsolete_series_not_in_vocabulary(self):
+ # Obsolete productseries are normally not in the vocabulary.
+ form = {
+ ...

Read more...

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

Thanks for adding the test.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/registry/browser/sourcepackage.py'
2--- lib/lp/registry/browser/sourcepackage.py 2010-02-18 20:39:01 +0000
3+++ lib/lp/registry/browser/sourcepackage.py 2010-02-24 17:24:21 +0000
4@@ -212,6 +212,22 @@
5 series for series in self.product.series
6 if series.status != SeriesStatus.OBSOLETE
7 ]
8+
9+ # If the product is not being changed, then the current
10+ # productseries can be the default choice. Otherwise,
11+ # it will not exist in the vocabulary.
12+ if (self.context.productseries is not None
13+ and self.context.productseries.product == self.product):
14+ series_default = self.context.productseries
15+ # This only happens for obsolete series, since they aren't
16+ # added to the vocabulary normally.
17+ if series_default not in series_list:
18+ series_list.append(series_default)
19+ else:
20+ series_default = None
21+
22+ # Put the development focus at the top of the list and create
23+ # the vocabulary.
24 dev_focus = self.product.development_focus
25 if dev_focus in series_list:
26 series_list.remove(dev_focus)
27@@ -223,15 +239,6 @@
28 dev_focus, dev_focus.name, "%s (Recommended)" % dev_focus.name)
29 vocab_terms.insert(0, dev_focus_term)
30
31- # If the product is not being changed, then the current
32- # productseries can be the default choice. Otherwise,
33- # it will not exist in the vocabulary.
34- if (self.context.productseries is not None
35- and self.context.productseries.product == self.product):
36- series_default = self.context.productseries
37- else:
38- series_default = None
39-
40 productseries_choice = Choice(
41 __name__='productseries',
42 title=_("Series"),
43
44=== modified file 'lib/lp/registry/tests/test_sourcepackage.py'
45--- lib/lp/registry/tests/test_sourcepackage.py 2009-12-13 11:55:40 +0000
46+++ lib/lp/registry/tests/test_sourcepackage.py 2010-02-24 17:24:21 +0000
47@@ -22,6 +22,7 @@
48 from lp.code.interfaces.seriessourcepackagebranch import (
49 IMakeOfficialBranchLinks)
50 from lp.testing import TestCaseWithFactory
51+from lp.testing.views import create_initialized_view
52 from canonical.testing.layers import DatabaseFunctionalLayer
53
54
55@@ -238,5 +239,79 @@
56 Unauthorized, sourcepackage.setBranch, pocket, branch, registrant)
57
58
59+class TestSourcePackageViews(TestCaseWithFactory):
60+ """Tests for source package view classes."""
61+
62+ layer = DatabaseFunctionalLayer
63+
64+ def setUp(self):
65+ TestCaseWithFactory.setUp(self)
66+ self.owner = self.factory.makePerson()
67+ self.product = self.factory.makeProduct(
68+ name='bonkers', displayname='Bonkers', owner=self.owner)
69+
70+ self.obsolete_productseries = self.factory.makeProductSeries(
71+ name='obsolete', product=self.product)
72+ self.obsolete_productseries.status = SeriesStatus.OBSOLETE
73+
74+ self.dev_productseries = self.factory.makeProductSeries(
75+ name='current', product=self.product)
76+ self.dev_productseries.status = SeriesStatus.DEVELOPMENT
77+
78+ self.distribution = self.factory.makeDistribution(
79+ name='youbuntu', displayname='Youbuntu', owner=self.owner)
80+ self.distroseries = self.factory.makeDistroRelease(name='busy',
81+ distribution=self.distribution)
82+ self.sourcepackagename = self.factory.makeSourcePackageName(
83+ name='bonkers')
84+ self.package = self.factory.makeSourcePackage(
85+ sourcepackagename=self.sourcepackagename,
86+ distroseries=self.distroseries)
87+
88+ def test_editpackaging_obsolete_series_in_vocabulary(self):
89+ # The sourcepackage's current product series is included in
90+ # the vocabulary even if it is obsolete.
91+ self.package.setPackaging(self.obsolete_productseries, self.owner)
92+ form = {
93+ 'field.product': 'bonkers',
94+ 'field.actions.continue': 'Continue',
95+ 'field.__visited_steps__': 'sourcepackage_change_upstream_step1',
96+ }
97+ view = create_initialized_view(
98+ self.package, name='+edit-packaging', form=form,
99+ principal=self.owner)
100+ self.assertEqual([], view.view.errors)
101+ self.assertEqual(
102+ self.obsolete_productseries,
103+ view.view.form_fields['productseries'].field.default,
104+ "The form's default productseries must be the current one.")
105+ options = [term.token
106+ for term in view.view.widgets['productseries'].vocabulary]
107+ self.assertEqual(
108+ ['trunk', 'current', 'obsolete'], options,
109+ "The obsolete series must be in the vocabulary.")
110+
111+ def test_editpackaging_obsolete_series_not_in_vocabulary(self):
112+ # Obsolete productseries are normally not in the vocabulary.
113+ form = {
114+ 'field.product': 'bonkers',
115+ 'field.actions.continue': 'Continue',
116+ 'field.__visited_steps__': 'sourcepackage_change_upstream_step1',
117+ }
118+ view = create_initialized_view(
119+ self.package, name='+edit-packaging', form=form,
120+ principal=self.owner)
121+ self.assertEqual([], view.view.errors)
122+ self.assertEqual(
123+ None,
124+ view.view.form_fields['productseries'].field.default,
125+ "The form's default productseries must be None.")
126+ options = [term.token
127+ for term in view.view.widgets['productseries'].vocabulary]
128+ self.assertEqual(
129+ ['trunk', 'current'], options,
130+ "The obsolete series must NOT be in the vocabulary.")
131+
132+
133 def test_suite():
134 return unittest.TestLoader().loadTestsFromName(__name__)