Merge lp:~sinzui/launchpad/obsolete-series-0 into lp:launchpad

Proposed by Curtis Hovey
Status: Merged
Approved by: Brad Crittenden
Approved revision: no longer in the source branch.
Merged at revision: 11002
Proposed branch: lp:~sinzui/launchpad/obsolete-series-0
Merge into: lp:launchpad
Diff against target: 271 lines (+90/-19)
10 files modified
lib/lp/registry/browser/__init__.py (+3/-0)
lib/lp/registry/browser/product.py (+1/-1)
lib/lp/registry/browser/tests/product-files-views.txt (+20/-0)
lib/lp/registry/browser/tests/productseries-views.txt (+8/-0)
lib/lp/registry/interfaces/productseries.py (+5/-2)
lib/lp/registry/scripts/productreleasefinder/finder.py (+3/-1)
lib/lp/registry/stories/team/xx-team-membership.txt (+8/-0)
lib/lp/registry/stories/webservice/xx-project-registry.txt (+1/-0)
lib/lp/registry/templates/person-participation.pt (+17/-13)
lib/lp/registry/tests/test_prf_finder.py (+24/-2)
To merge this branch: bzr merge lp:~sinzui/launchpad/obsolete-series-0
Reviewer Review Type Date Requested Status
Brad Crittenden (community) code Approve
Review via email: mp+27319@code.launchpad.net

Description of the change

This is my branch to prevent timeout caused by the product-release-finder.

    lp:~sinzui/launchpad/obsolete-series-0
    Diff size:
    Launchpad bug:5
          https://bugs.launchpad.net/bugs/590806
          https://bugs.launchpad.net/bugs/490945
    Test command: ./bin/test -vv \
          -t productseries-views -t GetFiltersTestCase -t xx-project-registry
    Pre-implementation: no one.
    Target release: 10.06

prevent timeout caused by the product-release-finder
----------------------------------------------------

A review of the PRF revealed that it was downloading files and creating
released for series that belong to obsolete junk. These series are obsolete so
the PRF must ignore them. The releases were deleted when the series was moved
to obsolete junk. There are timeouts on obsolete-junks pages because there
PRF recreated information that users wanted gone.

ADDENDUM Bug #490945 [obsolete series takes precedence over stable]
    If I move milestone 1.5, for instance, to obsolete instead of stable, the
    main download page ( https://launchpad.net/kabikaboo/ ) changes the
    primary download to the newest obsolete download

Rules
-----

    * Ensure the file release glob is set to Null during series delete
    * Ensure that the series status is set to Obsolete
    * Ensure that the PRF ignores Obsolete series
    * Export releasefileglob to API so that problem series can be fixed
      before 10.06 is released.

ADDENDUM Bug #490945 [obsolete series takes precedence over stable]
    * latest_release_with_download_files() should use
      sorted_active_series_list() to filter out obsolete series.

QA
--

    * Verify that a deletes series is marked obsolete and that the
      filereleaseglob is set to None
    * Verify that the release_file_glob is visible:
        from lpscripts import lp_factory
        from launchpadlib.launchpad import (
            Launchpad, EDGE_SERVICE_ROOT, STAGING_SERVICE_ROOT)
        lp = lp_factory('edge', app_name='testing')
        project = lp.projects['gedit']
        series = project.getSeries(name='master')
        print series.name
        print series.release_file_glob

ADDENDUM Bug #490945 [obsolete series takes precedence over stable]
    * Visit a project with a release shown of the front page.
    * Mark the series obsolete
    * Verify the release changes on the front page.

Lint
----

Linting changed files:
  lib/lp/registry/browser/__init__.py
  lib/lp/registry/browser/product.py
  lib/lp/registry/browser/tests/product-files-views.txt
  lib/lp/registry/browser/tests/productseries-views.txt
  lib/lp/registry/interfaces/productseries.py
  lib/lp/registry/scripts/productreleasefinder/finder.py
  lib/lp/registry/stories/webservice/xx-project-registry.txt
  lib/lp/registry/tests/test_prf_finder.py

Test
----
    * lib/lp/registry/browser/tests/product-files-views.txt
      * Verify that obsolete releases are not shown on the project's index
        page.
    * lib/lp/registry/browser/tests/productseries-views.txt
      * Verify that the "deleted" series was marked obsolete and the
        relasefileglob was set to None.
    * lib/lp/registry/stories/webservice/xx-project-registry.txt
      * Verify that release_file_glob is exported.
    * lib/lp/registry/tests/test_prf_finder.py
      * Verify that obsolete series are not included in the finder filters.

Implementation
--------------

    * lib/lp/registry/browser/__init__.py
      * Marked the series as obsolete and clear the releasefileglob when
        the user deletes (moves) the series.
    * lib/lp/registry/browser/product.py
      * Use sorted_active_series_list in latest_release_with_download_files().
    * lib/lp/registry/interfaces/productseries.py
      * Export release_file_glob so that I can see and fix the damage.
    * lib/lp/registry/scripts/productreleasefinder/finder.py
      * Skip obsolete series.

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

Hi Curtis, thanks for this branch.

On IRC we discussed the following:

* Test update to lib/lp/registry/browser/tests/product-files-views.txt to properly show the latest release with downloads. (http://pastebin.ubuntu.com/448271/)

Also,

* I hate 'releasefileglob' but it is too ingrained to change.

* What would you think about adding a launchpadlib test to exercise the newly exported release_file_glob? On the one hand it would be a dumb test showing just that one field out of a zillion. On the other, we've got to start somewhere.

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/__init__.py'
2--- lib/lp/registry/browser/__init__.py 2010-05-14 14:55:26 +0000
3+++ lib/lp/registry/browser/__init__.py 2010-06-12 04:32:28 +0000
4@@ -22,6 +22,7 @@
5
6 from lp.bugs.interfaces.bugtask import BugTaskSearchParams, IBugTaskSet
7 from lp.registry.interfaces.productseries import IProductSeries
8+from lp.registry.interfaces.series import SeriesStatus
9 from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
10 from canonical.launchpad.webapp.launchpadform import (
11 action, LaunchpadEditFormView)
12@@ -207,6 +208,8 @@
13 date_time = series.datecreated.strftime('%Y%m%d-%H%M%S')
14 series.name = '%s-%s-%s' % (
15 series.product.name, series.name, date_time)
16+ series.status = SeriesStatus.OBSOLETE
17+ series.releasefileglob = None
18 series.product = getUtility(ILaunchpadCelebrities).obsolete_junk
19
20 def _deleteMilestone(self, milestone):
21
22=== modified file 'lib/lp/registry/browser/product.py'
23--- lib/lp/registry/browser/product.py 2010-06-04 15:07:42 +0000
24+++ lib/lp/registry/browser/product.py 2010-06-12 04:32:28 +0000
25@@ -859,7 +859,7 @@
26 @cachedproperty
27 def latest_release_with_download_files(self):
28 """Return the latest release with download files."""
29- for series in self.sorted_series_list:
30+ for series in self.sorted_active_series_list:
31 for release in series.releases:
32 if len(list(release.files)) > 0:
33 return release
34
35=== modified file 'lib/lp/registry/browser/tests/product-files-views.txt'
36--- lib/lp/registry/browser/tests/product-files-views.txt 2010-01-15 20:41:29 +0000
37+++ lib/lp/registry/browser/tests/product-files-views.txt 2010-06-12 04:32:28 +0000
38@@ -68,3 +68,23 @@
39 Add download file to the s3 series for release: 3.3, 3.2, 3.1
40 Add download file to the s2 series for release: 2.3, 2.2, 2.1
41 Add download file to the s1 series for release: 1.3, 1.2, 1.1
42+
43+
44+Product index
45+-------------
46+
47+The product index view shows the latest release for the project.
48+
49+ >>> view = create_initialized_view(product, name='+index')
50+ >>> print view.latest_release_with_download_files.version
51+ 4.3
52+
53+Obsolete series are ignored.
54+
55+ >>> from lp.registry.interfaces.series import SeriesStatus
56+
57+ >>> obsolete_series = product.getSeries('s4')
58+ >>> obsolete_series.status = SeriesStatus.OBSOLETE
59+ >>> view = create_initialized_view(product, name='+index')
60+ >>> print view.latest_release_with_download_files.version
61+ 3.3
62
63=== modified file 'lib/lp/registry/browser/tests/productseries-views.txt'
64--- lib/lp/registry/browser/tests/productseries-views.txt 2010-05-06 18:13:55 +0000
65+++ lib/lp/registry/browser/tests/productseries-views.txt 2010-06-12 04:32:28 +0000
66@@ -259,6 +259,7 @@
67 >>> product = factory.makeProduct(name="field", displayname='Field')
68 >>> productseries = factory.makeProductSeries(
69 ... product=product, name='rabbit')
70+ >>> productseries.filereleaseglob = 'http://eg.dom/rabbit/*'
71
72 # Hack the creation date for testing purposes.
73 >>> test_date = datetime(2009, 05, 01, 19, 34, 24, tzinfo=UTC)
74@@ -467,6 +468,13 @@
75 >>> print productseries.name
76 field-rabbit-20090501-193424
77
78+The series status is set to obsolete and the filereleaseglob was set to None.
79+
80+ >>> print productseries.status
81+ Obsolete
82+ >>> print productseries.filereleaseglob
83+ None
84+
85 A series cannot be deleted if it is has translation templates.
86
87 >>> translated_series = factory.makeProductSeries(product=product)
88
89=== modified file 'lib/lp/registry/interfaces/productseries.py'
90--- lib/lp/registry/interfaces/productseries.py 2010-05-17 09:35:18 +0000
91+++ lib/lp/registry/interfaces/productseries.py 2010-06-12 04:32:28 +0000
92@@ -260,12 +260,15 @@
93 """Return the POTemplate with this name for the series."""
94
95 # where are the tarballs released from this branch placed?
96- releasefileglob = TextLine(title=_("Release URL pattern"),
97+ releasefileglob = exported(
98+ TextLine(title=_("Release URL pattern"),
99 required=False, constraint=validate_release_glob,
100 description=_('A URL pattern that matches releases that are part '
101 'of this series. Launchpad automatically scans this '
102 'site to import new releases. Example: '
103- 'http://ftp.gnu.org/gnu/emacs/emacs-21.*.tar.gz'))
104+ 'http://ftp.gnu.org/gnu/emacs/emacs-21.*.tar.gz')),
105+ exported_as='release_finder_url_pattern')
106+
107 releaseverstyle = Attribute("The version numbering style for this "
108 "series of releases.")
109
110
111=== modified file 'lib/lp/registry/scripts/productreleasefinder/finder.py'
112--- lib/lp/registry/scripts/productreleasefinder/finder.py 2009-12-09 11:47:58 +0000
113+++ lib/lp/registry/scripts/productreleasefinder/finder.py 2010-06-12 04:32:28 +0000
114@@ -22,6 +22,7 @@
115 from canonical.launchpad.validators.name import invalid_name_pattern
116 from canonical.launchpad.validators.version import sane_version
117
118+from lp.registry.interfaces.series import SeriesStatus
119 from lp.registry.interfaces.product import IProductSet
120 from lp.registry.interfaces.productrelease import UpstreamFileType
121 from lp.registry.scripts.productreleasefinder.hose import Hose
122@@ -105,7 +106,8 @@
123 filters = []
124
125 for series in product.series:
126- if not series.releasefileglob:
127+ if (series.status == SeriesStatus.OBSOLETE
128+ or not series.releasefileglob):
129 continue
130
131 filters.append(FilterPattern(series.name,
132
133=== modified file 'lib/lp/registry/stories/team/xx-team-membership.txt'
134--- lib/lp/registry/stories/team/xx-team-membership.txt 2010-06-08 12:54:44 +0000
135+++ lib/lp/registry/stories/team/xx-team-membership.txt 2010-06-12 04:32:28 +0000
136@@ -249,3 +249,11 @@
137 >>> user_browser.getLink('Change mailing list subscriptions')
138 <Link ... url='http://.../~no-priv/+editemails'>
139
140+Teams also have a participation page, but it does not include a mailing
141+list column.
142+
143+ >>> admin_browser.open('http://launchpad.dev/~admins/+participation')
144+ >>> print extract_text(
145+ ... find_tag_by_id(admin_browser.contents, 'participation'))
146+ Team Joined Role Via
147+ Mailing List Experts 2007-10-04 Owner &mdash;
148
149=== modified file 'lib/lp/registry/stories/webservice/xx-project-registry.txt'
150--- lib/lp/registry/stories/webservice/xx-project-registry.txt 2010-06-09 08:26:26 +0000
151+++ lib/lp/registry/stories/webservice/xx-project-registry.txt 2010-06-12 04:32:28 +0000
152@@ -876,6 +876,7 @@
153 official_bug_tags: []
154 owner_link: u'http://.../~babadoo-owner'
155 project_link: u'http://.../babadoo'
156+ release_finder_url_pattern: None
157 releases_collection_link: u'http://.../babadoo/foobadoo/releases'
158 resource_type_link: u'...'
159 self_link: u'http://.../babadoo/foobadoo'
160
161=== modified file 'lib/lp/registry/templates/person-participation.pt'
162--- lib/lp/registry/templates/person-participation.pt 2010-06-07 23:12:44 +0000
163+++ lib/lp/registry/templates/person-participation.pt 2010-06-12 04:32:28 +0000
164@@ -28,7 +28,8 @@
165 <th>Joined</th>
166 <th>Role</th>
167 <th>Via</th>
168- <th>Mailing List</th>
169+ <th
170+ tal:condition="not: context/teamowner">Mailing List</th>
171 </tr>
172 </thead>
173 <tbody>
174@@ -57,7 +58,8 @@
175 &mdash;
176 </tal:direct>
177 </td>
178- <td>
179+ <td
180+ tal:condition="not: context/teamowner">
181 <tal:subscribed condition="participation/team/mailing_list"
182 replace="participation/subscribed">
183 yes
184@@ -70,17 +72,19 @@
185 </tbody>
186 </table>
187
188- <ul id="participation-actions" class="horizontal"
189- tal:condition="context/required:launchpad.Edit">
190- <li>
191- <a class="sprite add" href="/people/+newteam">Register a team</a>
192- </li>
193- <li>
194- <a class="sprite edit"
195- tal:attributes="href context/menu:overview/editemailaddresses/fmt:url"
196- >Change mailing list subscriptions</a>
197- </li>
198- </ul>
199+ <tal:user condition="not: context/teamowner">
200+ <ul id="participation-actions" class="horizontal"
201+ tal:condition="context/required:launchpad.Edit">
202+ <li>
203+ <a class="sprite add" href="/people/+newteam">Register a team</a>
204+ </li>
205+ <li>
206+ <a class="sprite edit"
207+ tal:attributes="href context/menu:overview/editemailaddresses/fmt:url"
208+ >Change mailing list subscriptions</a>
209+ </li>
210+ </ul>
211+ </tal:user>
212 </div>
213 </body>
214 </html>
215
216=== modified file 'lib/lp/registry/tests/test_prf_finder.py'
217--- lib/lp/registry/tests/test_prf_finder.py 2009-11-02 19:43:37 +0000
218+++ lib/lp/registry/tests/test_prf_finder.py 2010-06-12 04:32:28 +0000
219@@ -15,6 +15,7 @@
220 from canonical.config import config
221 from canonical.testing import LaunchpadZopelessLayer, reset_logging
222
223+from lp.registry.interfaces.series import SeriesStatus
224 from lp.registry.interfaces.product import IProductSet
225 from lp.registry.interfaces.productrelease import (
226 IProductReleaseFile, UpstreamFileType)
227@@ -22,7 +23,7 @@
228 FilterPattern)
229 from lp.registry.scripts.productreleasefinder.finder import (
230 extract_version, ProductReleaseFinder)
231-
232+from lp.testing import TestCaseWithFactory
233
234 class FindReleasesTestCase(unittest.TestCase):
235
236@@ -51,7 +52,7 @@
237 ('product2', ['filter3', 'filter4']))
238
239
240-class GetFiltersTestCase(unittest.TestCase):
241+class GetFiltersTestCase(TestCaseWithFactory):
242
243 layer = LaunchpadZopelessLayer
244
245@@ -87,6 +88,27 @@
246 'http://ftp.gnome.org/pub/GNOME/sources/evolution/2.7/'
247 'evolution-2.7.1.tar.gz'))
248
249+ def test_getFilters_ignore_obsolete(self):
250+ # Verify that obsolete series are ignnored.
251+ ztm = self.layer.txn
252+ ztm.begin()
253+ product = self.factory.makeProduct(name="bunny")
254+ active_series = product.getSeries('trunk')
255+ active_series.releasefileglob = 'http://eg.dom/bunny/trunk/*'
256+ obsolete_series = self.factory.makeProductSeries(
257+ product=product, name='rabbit')
258+ obsolete_series.releasefileglob = 'http://eg.dom/bunny/rabbit/*'
259+ obsolete_series.status = SeriesStatus.OBSOLETE
260+ ztm.commit()
261+ logging.basicConfig(level=logging.CRITICAL)
262+ prf = ProductReleaseFinder(ztm, logging.getLogger())
263+ product_filters = prf.getFilters()
264+ self.assertEqual(1, len(product_filters))
265+ found_product, filters = product_filters[0]
266+ self.assertEqual('bunny', found_product)
267+ self.assertEqual(1, len(filters))
268+ self.assertEqual(filters[0].key, 'trunk')
269+
270
271 class HandleProductTestCase(unittest.TestCase):
272