Merge lp:~edwin-grubbs/launchpad/bug-663857-product-packages-timeout into lp:launchpad

Proposed by Edwin Grubbs
Status: Merged
Approved by: Curtis Hovey
Approved revision: no longer in the source branch.
Merged at revision: 12236
Proposed branch: lp:~edwin-grubbs/launchpad/bug-663857-product-packages-timeout
Merge into: lp:launchpad
Diff against target: 308 lines (+86/-59)
5 files modified
lib/lp/registry/browser/product.py (+4/-19)
lib/lp/registry/browser/tests/packaging-views.txt (+19/-20)
lib/lp/registry/interfaces/product.py (+3/-0)
lib/lp/registry/model/product.py (+27/-7)
lib/lp/registry/templates/product-packages.pt (+33/-13)
To merge this branch: bzr merge lp:~edwin-grubbs/launchpad/bug-663857-product-packages-timeout
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code ui Approve
Review via email: mp+46222@code.launchpad.net

Commit message

[r=sinzui][ui=sinzui][bug=663857] Fixed timeout on $project/+packages page.

Description of the change

Summary
-------

This branch fixes the timeout on the $project/+packages page. It
restricts the results to series that are active or have packages. It
also batches the results.

I cleaned up the formatting, since a list of tables is fairly
confusing. I also sorted the results descending. If the series are named
by version number, the latest versions will appear at the top.

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

    lib/lp/registry/browser/product.py
lib/lp/registry/browser/tests/packaging-views.txt
lib/lp/registry/interfaces/product.py
lib/lp/registry/model/product.py
lib/lp/registry/templates/product-packages.pt

Tests
-----

./bin/test -vv -t 'packaging-views.txt|xx-product-package-pages.txt'

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

* Open https://code.edge.launchpad.net/obsolete-junk/+packages
  * The page should not timeout.

Lint
----

The one remaining lint item shouldn't be fixed.

Linting changed files:
  lib/lp/registry/browser/product.py
  lib/lp/registry/browser/tests/packaging-views.txt
  lib/lp/registry/interfaces/product.py
  lib/lp/registry/model/product.py
  lib/lp/registry/templates/product-packages.pt

./lib/lp/registry/interfaces/product.py
     981: E301 expected 1 blank line, found 2

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Hi Edwin.

Thank you for improving the layout while address the timeout. This makes the page much easier to read.

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/registry/browser/product.py'
2--- lib/lp/registry/browser/product.py 2010-12-30 16:22:22 +0000
3+++ lib/lp/registry/browser/product.py 2011-01-19 15:36:00 +0000
4@@ -1117,25 +1117,10 @@
5 page_title = label
6
7 @cachedproperty
8- def series_packages(self):
9- """A hierarchy of product series, packaging and field data.
10-
11- A dict of series and packagings. Each packaging is a dict of the
12- packaging and a hidden HTML field for forms:
13- [{series: <hoary>,
14- packagings: {
15- packaging: <packaging>,
16- field: '<input type=''hidden' ...>},
17- }]
18- """
19- packaged_series = []
20- for series in self.context.series:
21- packagings = []
22- for packaging in series.packagings:
23- packagings.append(packaging)
24- packaged_series.append(dict(
25- series=series, packagings=packagings))
26- return packaged_series
27+ def series_batch(self):
28+ """A batch of series that are active or have packages."""
29+ return BatchNavigator(
30+ self.context.active_or_packaged_series, self.request)
31
32 @property
33 def distro_packaging(self):
34
35=== modified file 'lib/lp/registry/browser/tests/packaging-views.txt'
36--- lib/lp/registry/browser/tests/packaging-views.txt 2010-05-27 04:22:46 +0000
37+++ lib/lp/registry/browser/tests/packaging-views.txt 2011-01-19 15:36:00 +0000
38@@ -224,20 +224,19 @@
39 >>> print view.label
40 Linked packages
41
42-The view provides the series_packages property that returns a list of
43-dicts. Each dict as a series and a list of packages.
44+The view provides the series_batch property.
45
46 >>> def print_packages(view):
47- ... for series_dict in view.series_packages:
48- ... print series_dict['series'].name
49- ... for package in series_dict['packagings']:
50- ... print package.distroseries.name
51+ ... for series in view.series_batch.batch:
52+ ... print series.name
53+ ... for package in series.packagings:
54+ ... print ' Package:', package.distroseries.name
55 >>> print_packages(view)
56+ trunk
57+ hotter
58+ Package: grumpy
59+ Package: hoary
60 cold
61- hotter
62- grumpy
63- hoary
64- trunk
65
66 The view provides the distro_packaging property that is a list of
67 dictionaries for the distributions and their packaging. The list is
68@@ -255,11 +254,11 @@
69 >>> view = create_initialized_view(
70 ... product, name='+packages', principal=a_user)
71 >>> print_packages(view)
72+ trunk
73+ hotter
74+ Package: grumpy
75+ Package: hoary
76 cold
77- hotter
78- grumpy
79- hoary
80- trunk
81
82 # There are links to the +remove-packaging page.
83 >>> table = find_tag_by_id(view.render(), 'packages-hotter')
84@@ -270,8 +269,8 @@
85 http://launchpad.dev/ubuntu/hoary/+source/thunderbird/+remove-packaging
86
87 >>> [hoary_package] = [
88- ... package for series_dict in view.series_packages
89- ... for package in series_dict['packagings']
90+ ... package for series in view.series_batch.batch
91+ ... for package in series.packagings
92 ... if package.distroseries.name == 'hoary']
93 >>> form = {'field.actions.unlink': 'Unlink'}
94 >>> unlink_view = create_initialized_view(
95@@ -279,13 +278,13 @@
96 >>> unlink_view.errors
97 []
98
99- # The view has to be reloaded since view.series_packages is cached.
100+ # The view has to be reloaded since view.series_batch is cached.
101 >>> view = create_initialized_view(product, name='+packages')
102 >>> print_packages(view)
103+ trunk
104+ hotter
105+ Package: grumpy
106 cold
107- hotter
108- grumpy
109- trunk
110
111
112 Distro series +packaging view
113
114=== modified file 'lib/lp/registry/interfaces/product.py'
115--- lib/lp/registry/interfaces/product.py 2010-12-31 03:39:53 +0000
116+++ lib/lp/registry/interfaces/product.py 2011-01-19 15:36:00 +0000
117@@ -732,6 +732,9 @@
118 "Some bug trackers host multiple projects at the same URL "
119 "and require an identifier for the specific project.")))
120
121+ active_or_packaged_series = Attribute(
122+ _("Series that are active and/or have been packaged."))
123+
124 def getVersionSortedSeries(statuses=None, filter_statuses=None):
125 """Return all the series sorted by the name field as a version.
126
127
128=== modified file 'lib/lp/registry/model/product.py'
129--- lib/lp/registry/model/product.py 2010-12-02 16:13:51 +0000
130+++ lib/lp/registry/model/product.py 2011-01-19 15:36:00 +0000
131@@ -28,13 +28,17 @@
132 SQLObjectNotFound,
133 StringCol,
134 )
135-from storm.expr import NamedFunc
136+from storm.expr import (
137+ LeftJoin,
138+ NamedFunc,
139+ )
140 from storm.locals import (
141 And,
142 Desc,
143 Int,
144 Join,
145 Not,
146+ Or,
147 Select,
148 SQL,
149 Store,
150@@ -48,9 +52,6 @@
151 )
152 from zope.security.proxy import removeSecurityProxy
153
154-from canonical.launchpad.components.decoratedresultset import (
155- DecoratedResultSet,
156- )
157 from canonical.database.constants import UTC_NOW
158 from canonical.database.datetimecol import UtcDateTimeCol
159 from canonical.database.enumcol import EnumCol
160@@ -59,6 +60,9 @@
161 SQLBase,
162 sqlvalues,
163 )
164+from canonical.launchpad.components.decoratedresultset import (
165+ DecoratedResultSet,
166+ )
167 from canonical.launchpad.interfaces.launchpad import (
168 IHasIcon,
169 IHasLogo,
170@@ -74,7 +78,6 @@
171 IStoreSelector,
172 MAIN_STORE,
173 )
174-from lp.registry.model.series import ACTIVE_STATUSES
175 from lp.answers.interfaces.faqtarget import IFAQTarget
176 from lp.answers.interfaces.questioncollection import (
177 QUESTION_STATUS_DEFAULT_SEARCH,
178@@ -145,6 +148,7 @@
179 from lp.registry.model.commercialsubscription import CommercialSubscription
180 from lp.registry.model.distribution import Distribution
181 from lp.registry.model.distroseries import DistroSeries
182+from lp.registry.model.hasdrivers import HasDriversMixin
183 from lp.registry.model.karma import KarmaContextMixin
184 from lp.registry.model.milestone import (
185 HasMilestonesMixin,
186@@ -156,7 +160,7 @@
187 from lp.registry.model.productlicense import ProductLicense
188 from lp.registry.model.productrelease import ProductRelease
189 from lp.registry.model.productseries import ProductSeries
190-from lp.registry.model.hasdrivers import HasDriversMixin
191+from lp.registry.model.series import ACTIVE_STATUSES
192 from lp.registry.model.sourcepackagename import SourcePackageName
193 from lp.registry.model.structuralsubscription import (
194 StructuralSubscriptionTargetMixin,
195@@ -801,6 +805,22 @@
196 orderBy='name')
197
198 @property
199+ def active_or_packaged_series(self):
200+ store = Store.of(self)
201+ tables = [
202+ ProductSeries,
203+ LeftJoin(Packaging, Packaging.productseries == ProductSeries.id),
204+ ]
205+ result = store.using(*tables).find(
206+ ProductSeries,
207+ ProductSeries.product == self,
208+ Or(ProductSeries.status.is_in(ACTIVE_STATUSES),
209+ Packaging.id != None))
210+ result = result.order_by(Desc(ProductSeries.name))
211+ result.config(distinct=True)
212+ return result
213+
214+ @property
215 def name_with_project(self):
216 """See lib.canonical.launchpad.interfaces.IProduct"""
217 if self.project and self.project.name != self.name:
218@@ -1572,7 +1592,7 @@
219
220 def getTranslatables(self):
221 """See `IProductSet`"""
222- # XXX j.c.sackett 2010-11-19 bug=677532 It's less than ideal that
223+ # XXX j.c.sackett 2010-11-19 bug=677532 It's less than ideal that
224 # this query is using _translations_usage, but there's no cleaner
225 # way to deal with it. Once the bug above is resolved, this should
226 # should be fixed to use translations_usage.
227
228=== modified file 'lib/lp/registry/templates/product-packages.pt'
229--- lib/lp/registry/templates/product-packages.pt 2010-03-03 18:35:08 +0000
230+++ lib/lp/registry/templates/product-packages.pt 2011-01-19 15:36:00 +0000
231@@ -10,28 +10,44 @@
232 <body>
233
234 <div metal:fill-slot="main">
235- <div class="top-portlet">
236+ <div class="top-portlet"
237+ tal:define="batch_nav view/series_batch">
238 <h2>Packages by project series</h2>
239
240- <tal:series_dict repeat="series_dict view/series_packages">
241- <tal:series_packagings
242- define="series series_dict/series;
243- packagings series_dict/packagings">
244+ <tal:multipage tal:condition="batch_nav/has_multiple_pages">
245+ <tal:navigation
246+ replace="structure batch_nav/@@+navigation-links-upper"/>
247+ </tal:multipage>
248+ <table class="listing">
249+ <tr tal:repeat="series batch_nav/batch">
250+ <td tal:define="packagings series/packagings">
251+ <table style="width: 100%; margin: 0.5em 0 0 0">
252+ <tr>
253+ <td style="width: 33%">
254 <h3>
255 <a tal:attributes="href series/name">
256 <span tal:replace="series/name">main</span> series
257 </a>
258 </h3>
259+ </td>
260
261- <p tal:condition="not: packagings">
262+ <tal:no-packages condition="not: packagings">
263+ <td style="width: 33%; text-align: center">
264 No packages linked to this series.
265- </p>
266+ </td>
267+ <td style="width: 33%; padding: 0 1.5em 0 0; text-align: right">
268+ <a tal:condition="series/menu:overview/ubuntupkg/linked"
269+ tal:replace="structure series/menu:overview/ubuntupkg/fmt:link" />
270+ </td>
271+ </tal:no-packages>
272+ </tr>
273+ </table>
274
275 <tal:comment condition="nothing">
276 This DIV is necessary for the table-actions:nth-child stylesheet.
277 </tal:comment>
278 <div>
279- <table class="listing"
280+ <table class="listing" style="border: 0"
281 tal:condition="packagings"
282 tal:attributes="id series/name/fmt:css-id/packages-">
283 <thead>
284@@ -73,15 +89,19 @@
285 </tbody>
286 </table>
287
288- <ul class="table-actions"
289- tal:condition="series/menu:overview/ubuntupkg/linked">
290- <li>
291+ <ul class="table-actions" tal:condition="packagings">
292+ <li tal:condition="series/menu:overview/ubuntupkg/linked">
293 <a tal:replace="structure series/menu:overview/ubuntupkg/fmt:link" />
294 </li>
295 </ul>
296 </div>
297- </tal:series_packagings>
298- </tal:series_dict>
299+ </td>
300+ </tr>
301+ </table>
302+ <tal:multipage condition="batch_nav/has_multiple_pages">
303+ <tal:navigation
304+ replace="structure batch_nav/@@+navigation-links-lower"/>
305+ </tal:multipage>
306 </div>
307
308 <div class="portlet">