Merge lp:~kfogel/launchpad/255868-patches-view-from-bugs-page into lp:launchpad/db-devel

Proposed by Karl Fogel on 2010-02-16
Status: Merged
Approved by: Curtis Hovey on 2010-02-18
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~kfogel/launchpad/255868-patches-view-from-bugs-page
Merge into: lp:launchpad/db-devel
Diff against target: 547 lines (+206/-48)
5 files modified
lib/lp/bugs/browser/bugtask.py (+10/-1)
lib/lp/bugs/stories/patches-view/patches-view.txt (+89/-0)
lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt (+52/-46)
lib/lp/bugs/templates/bugtarget-portlet-bugfilters-content.pt (+10/-0)
lib/lp/bugs/tests/bug.py (+45/-1)
To merge this branch: bzr merge lp:~kfogel/launchpad/255868-patches-view-from-bugs-page
Reviewer Review Type Date Requested Status
Curtis Hovey (community) ui and code 2010-02-16 Approve on 2010-02-18
Review via email: mp+19438@code.launchpad.net
To post a comment you must log in.
Karl Fogel (kfogel) wrote :

Put a "bugs with patches" statistic in the upper right portlet box on the bugs page (for products, project groups, and any other foo that has a "bugs.launchpad.net/foo" page.

Karl Fogel (kfogel) wrote :

Requesting review on UI only right now, as still writing tests.

Karl Fogel (kfogel) wrote :

See the two most recent screenshots in the linked bug, for UI review.

9005. By Karl Fogel on 2010-02-17

Merge from db-devel.

Curtis Hovey (sinzui) wrote :

Hi Karl.

This UI change is consistent with the rest of the page, and I think it is good to land. As I said on IRC, this list is now long and I think we are committed to rethink the list if we want to add another report to this page--a problem we can solve in the future.

review: Approve (ui)
9006. By Karl Fogel on 2010-02-17

Tests for Bug #255868: link to "+patches" view from product bugs page.

* lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt:
  Extend test output to expect the new item.

9007. By Karl Fogel on 2010-02-18

Add tests for Bug #255868 (link to "+patches" view from product bugs page).

* lib/lp/bugs/tests/bug.py: Import print_table.
  (print_bugfilters_portlet_unfilled,
   print_bugfilters_portlet_filled): New functions.

* lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt:
  (print_portlet, print_portlet_contents): Remove, as these
  have now been moved to bug.py and renamed as per above.
  Use the replacements, and extend expected test output to
  include the new "bugs with patches" item.

* lib/lp/bugs/stories/patches-view/patches-view.txt:
  Add tests for the presence and accuracy of the new stats.

9008. By Karl Fogel on 2010-02-18

Merge from db-devel.

9009. By Karl Fogel on 2010-02-18

For bug #255868 (link to "+patches" view from product bugs page),
include all statuses in count of bugs with patches, and update
tests accordingly. Also, fix a missing import in one test file.

* lib/lp/bugs/browser/bugtask.py: Import RESOLVED_BUGTASK_STATUSES.
  (BugsStatsMixin.bugs_with_patches_count): Include all bugs in count.

* lib/lp/bugs/stories/patches-view/patches-view.txt: Expect
  5 bugs with patches now, instead of 4, due to above change.

* lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt: Import
  print_bugfilters_portlet_unfilled, print_bugfilters_portlet_filled.

Karl Fogel (kfogel) wrote :

I've now added tests for the feature. Also, I tweaked the behavior slightly after talking with Jorge Castro: it now shows the count of bugs-with-patches including both resolved and unresolved bugs. The reason for this is that it may be an upstream dev coming to look at patches, whereas the resolution might be set by a distro maintainer who doesn't necessarily have upstream in mind. (Also, this makes the bugfilter stats portlet count consistent with what we show on the +patches view page that the portlet links to.)

Jorge and I agree to check with users of the feature after a few weeks to see how things are working out.

Curtis Hovey (sinzui) wrote :

Thanks for providing the tests, and more thanks for refactoring them.

review: Approve (ui and code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/browser/bugtask.py'
2--- lib/lp/bugs/browser/bugtask.py 2010-02-16 15:08:03 +0000
3+++ lib/lp/bugs/browser/bugtask.py 2010-02-19 06:44:15 +0000
4@@ -109,7 +109,8 @@
5 IDistroSeriesBugTask, IFrontPageBugTaskSearch,
6 INominationsReviewTableBatchNavigator, INullBugTask, IPersonBugTaskSearch,
7 IProductSeriesBugTask, IRemoveQuestionFromBugTaskForm, IUpstreamBugTask,
8- IUpstreamProductBugTaskSearch, UNRESOLVED_BUGTASK_STATUSES)
9+ IUpstreamProductBugTaskSearch, UNRESOLVED_BUGTASK_STATUSES,
10+ RESOLVED_BUGTASK_STATUSES)
11 from lp.bugs.interfaces.bugtracker import BugTrackerType
12 from lp.bugs.interfaces.cve import ICveSet
13 from lp.registry.interfaces.distribution import IDistribution
14@@ -1848,6 +1849,14 @@
15 params.assignee = self.user
16 return self.context.searchTasks(params).count()
17
18+ @property
19+ def bugs_with_patches_count(self):
20+ """A count of unresolved bugs with patches."""
21+ return self.context.searchTasks(
22+ None, user=self.user,
23+ status=(UNRESOLVED_BUGTASK_STATUSES + RESOLVED_BUGTASK_STATUSES),
24+ omit_duplicates=True, has_patch=True).count()
25+
26
27 class BugListingPortletInfoView(LaunchpadView, BugsInfoMixin):
28 """Portlet containing available bug listings without stats."""
29
30=== modified file 'lib/lp/bugs/stories/patches-view/patches-view.txt'
31--- lib/lp/bugs/stories/patches-view/patches-view.txt 2010-02-03 19:54:01 +0000
32+++ lib/lp/bugs/stories/patches-view/patches-view.txt 2010-02-19 06:44:15 +0000
33@@ -402,3 +402,92 @@
34 Hierarchy: Patchy Person > Patch attachments for Patchy Person
35 Tabs: ...
36 Main heading: Patch attachments for Patchy Person
37+
38+Reaching the Patches View
39+-------------------------
40+
41+The patches view is linked to from a portlet on the product bugs page.
42+
43+ >>> from lp.bugs.tests.bug import (
44+ ... print_bugfilters_portlet_unfilled,
45+ ... print_bugfilters_portlet_filled)
46+ >>> print_bugfilters_portlet_unfilled(anon_browser, 'patchy-product-1')
47+ Open bugs
48+ Critical bugs
49+ Bugs fixed elsewhere
50+ New bugs
51+ Open CVE bugs - CVE reports
52+ Bugs need forwarding upstream
53+ Bugs with patches
54+ Subscribe to bug mail
55+ --> http://bugs.launchpad.dev/patchy-product-1/+subscribe
56+
57+ >>> print_bugfilters_portlet_filled(anon_browser, 'patchy-product-1')
58+ 3 Open bugs
59+ 1 Critical bugs
60+ 0 Bugs fixed elsewhere
61+ 1 New bugs
62+ 0 Open CVE bugs - CVE reports
63+ 3 Bugs need forwarding upstream
64+ 3 Bugs with patches
65+
66+It's also linked to from a portlet on the source package bugs page:
67+
68+ >>> print_bugfilters_portlet_filled(anon_browser, 'ubuntu/+source/a52dec')
69+ 1 Open bugs
70+ 0 Critical bugs
71+ 1 Bugs fixed elsewhere
72+ 0 New bugs
73+ 0 Open CVE bugs
74+ 1 Bug with a patch
75+
76+And from a portlet on the distro series bugs page:
77+
78+ >>> print_bugfilters_portlet_filled(anon_browser, 'ubuntu/hoary')
79+ 2 Open bugs
80+ 0 Critical bugs
81+ 0 Bugs fixed elsewhere
82+ 2 New bugs
83+ 1 Open CVE bugs - CVE reports
84+ 0 Incomplete bugs (can expire)
85+ 1 Bug with a patch
86+
87+And from a portlet on the distro bugs page:
88+
89+ >>> print_bugfilters_portlet_filled(anon_browser, 'ubuntu')
90+ 8 Open bugs
91+ 0 Critical bugs
92+ 2 Bugs fixed elsewhere
93+ 6 New bugs
94+ 2 Open CVE bugs - CVE reports
95+ 0 Incomplete bugs (can expire)
96+ 5 Bugs with patches
97+
98+The number of bugs with patches shown in the bugfilter stats portlet
99+might be lower than the number of bugs (bugtasks) listed on the
100+corresponding patches view page, because the latter shows resolved
101+bugs too.
102+
103+ >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu/+patches')
104+ >>> show_patches_view(anon_browser.contents)
105+ Bug Importance Status Package Patch Age
106+ Bug #18: bug_c title High Triaged a52dec ...second...
107+ From: Patchy Person
108+ Link: patch_f.diff
109+ description of patch f
110+ Bug #18: bug_c title Undecided New ubuntu ...second...
111+ From: Patchy Person
112+ Link: patch_f.diff
113+ description of patch f
114+ Bug #17: bug_b title Undecided New ubuntu ...second...
115+ From: Patchy Person
116+ Link: patch_c.diff
117+ description of patch c
118+ Bug #16: bug_a title Medium Fix Released evolution ...second...
119+ From: Patchy Person
120+ Link: patch_a.diff
121+ description of patch a
122+ Bug #16: bug_a title Undecided New ubuntu ...second...
123+ From: Patchy Person
124+ Link: patch_a.diff
125+ description of patch a
126
127=== modified file 'lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt'
128--- lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt 2009-11-27 17:25:33 +0000
129+++ lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt 2010-02-19 06:44:15 +0000
130@@ -6,27 +6,6 @@
131 served in a separate request; the request is issued via Javascript and
132 inserted into the page later.
133
134- >>> from BeautifulSoup import BeautifulSoup
135-
136- >>> def print_portlet(browser, path):
137- ... browser.open(
138- ... 'http://bugs.launchpad.dev/%s/+portlet-bugfilters' % path)
139- ... table = BeautifulSoup(browser.contents).find('table', 'bug-links')
140- ... tbody_info, tbody_links = table('tbody')
141- ... print_table(tbody_info)
142- ... for link in tbody_links('a'):
143- ... text = extract_text(link)
144- ... if len(text) > 0:
145- ... print "%s\n --> %s" % (text, link['href'])
146-
147- >>> def print_portlet_contents(browser, path):
148- ... browser.open(
149- ... 'http://bugs.launchpad.dev'
150- ... '/%s/+bugtarget-portlet-bugfilters-stats' % path)
151- ... table = BeautifulSoup('<table>%s</table>' % browser.contents)
152- ... print_table(table)
153-
154-
155 == Distribution ==
156
157 >>> path = 'debian'
158@@ -34,42 +13,49 @@
159 If the user is not logged-in a subscribe link is shown along with some
160 general stats.
161
162- >>> print_portlet(anon_browser, path)
163+ >>> from lp.bugs.tests.bug import (
164+ ... print_bugfilters_portlet_unfilled,
165+ ... print_bugfilters_portlet_filled)
166+ >>> print_bugfilters_portlet_unfilled(anon_browser, path)
167 Open bugs
168 Critical bugs
169 Bugs fixed elsewhere
170 New bugs
171 Open CVE bugs - CVE reports
172+ Bugs with patches
173 Subscribe to bug mail
174 --> http://bugs.launchpad.dev/debian/+subscribe
175
176- >>> print_portlet_contents(anon_browser, path)
177+ >>> print_bugfilters_portlet_filled(anon_browser, path)
178 3 Open bugs
179 0 Critical bugs
180 0 Bugs fixed elsewhere
181 1 New bugs
182 2 Open CVE bugs - CVE reports
183+ 0 Bugs with patches
184
185 Once the user has identified him or herself, information on assigned
186 bugs is also shown.
187
188- >>> print_portlet(user_browser, path)
189+ >>> print_bugfilters_portlet_unfilled(user_browser, path)
190 Open bugs
191 Bugs assigned to me
192 Critical bugs
193 Bugs fixed elsewhere
194 New bugs
195 Open CVE bugs - CVE reports
196+ Bugs with patches
197 Subscribe to bug mail
198 --> http://bugs.launchpad.dev/debian/+subscribe
199
200- >>> print_portlet_contents(user_browser, path)
201+ >>> print_bugfilters_portlet_filled(user_browser, path)
202 3 Open bugs
203 0 Bugs assigned to me
204 0 Critical bugs
205 0 Bugs fixed elsewhere
206 1 New bugs
207 2 Open CVE bugs - CVE reports
208+ 0 Bugs with patches
209
210 The content includes a link to the distribution CVE report.
211
212@@ -84,46 +70,50 @@
213 If the user is not logged-in general stats are shown. There is also a
214 link to review nominations.
215
216- >>> print_portlet(anon_browser, path)
217+ >>> print_bugfilters_portlet_unfilled(anon_browser, path)
218 Open bugs
219 Critical bugs
220 Bugs fixed elsewhere
221 New bugs
222 Open CVE bugs - CVE reports
223+ Bugs with patches
224 Subscribe to bug mail
225 --> http://bugs.launchpad.dev/debian/woody/+subscribe
226 Review nominations
227 --> http://bugs.launchpad.dev/debian/woody/+nominations
228
229- >>> print_portlet_contents(anon_browser, path)
230+ >>> print_bugfilters_portlet_filled(anon_browser, path)
231 2 Open bugs
232 0 Critical bugs
233 0 Bugs fixed elsewhere
234 2 New bugs
235 1 Open CVE bugs - CVE reports
236+ 0 Bugs with patches
237
238 Once the user has identified him or herself, information on assigned
239 bugs is also shown.
240
241- >>> print_portlet(user_browser, path)
242+ >>> print_bugfilters_portlet_unfilled(user_browser, path)
243 Open bugs
244 Bugs assigned to me
245 Critical bugs
246 Bugs fixed elsewhere
247 New bugs
248 Open CVE bugs - CVE reports
249+ Bugs with patches
250 Subscribe to bug mail
251 --> http://bugs.launchpad.dev/debian/woody/+subscribe
252 Review nominations
253 --> http://bugs.launchpad.dev/debian/woody/+nominations
254
255- >>> print_portlet_contents(user_browser, path)
256+ >>> print_bugfilters_portlet_filled(user_browser, path)
257 2 Open bugs
258 0 Bugs assigned to me
259 0 Critical bugs
260 0 Bugs fixed elsewhere
261 2 New bugs
262 1 Open CVE bugs - CVE reports
263+ 0 Bugs with patches
264
265 The content includes a link to the distribution CVE report.
266
267@@ -137,42 +127,46 @@
268
269 If the user is not logged-in general stats are shown.
270
271- >>> print_portlet(anon_browser, path)
272+ >>> print_bugfilters_portlet_unfilled(anon_browser, path)
273 Open bugs
274 Critical bugs
275 Bugs fixed elsewhere
276 New bugs
277 Open CVE bugs
278+ Bugs with patches
279 Subscribe to bug mail
280 --> http://bugs.launchpad.dev/debian/+source/mozilla-firefox/+subscribe
281
282- >>> print_portlet_contents(anon_browser, path)
283+ >>> print_bugfilters_portlet_filled(anon_browser, path)
284 3 Open bugs
285 0 Critical bugs
286 0 Bugs fixed elsewhere
287 1 New bugs
288 2 Open CVE bugs
289+ 0 Bugs with patches
290
291 Once the user has identified him or herself, information on assigned
292 bugs is also shown.
293
294- >>> print_portlet(user_browser, path)
295+ >>> print_bugfilters_portlet_unfilled(user_browser, path)
296 Open bugs
297 Bugs assigned to me
298 Critical bugs
299 Bugs fixed elsewhere
300 New bugs
301 Open CVE bugs
302+ Bugs with patches
303 Subscribe to bug mail
304 --> http://bugs.launchpad.dev/debian/+source/mozilla-firefox/+subscribe
305
306- >>> print_portlet_contents(user_browser, path)
307+ >>> print_bugfilters_portlet_filled(user_browser, path)
308 3 Open bugs
309 0 Bugs assigned to me
310 0 Critical bugs
311 0 Bugs fixed elsewhere
312 1 New bugs
313 2 Open CVE bugs
314+ 0 Bugs with patches
315
316 Note that the "CVE reports" link is not shown above; distribution
317 source packages do not have a CVE reports page.
318@@ -190,38 +184,42 @@
319 If the user is not logged-in general stats are shown. There is no
320 option to subscribe to bug mail.
321
322- >>> print_portlet(anon_browser, path)
323+ >>> print_bugfilters_portlet_unfilled(anon_browser, path)
324 Open bugs
325 Critical bugs
326 Bugs fixed elsewhere
327 New bugs
328 Open CVE bugs
329+ Bugs with patches
330
331- >>> print_portlet_contents(anon_browser, path)
332+ >>> print_bugfilters_portlet_filled(anon_browser, path)
333 2 Open bugs
334 0 Critical bugs
335 0 Bugs fixed elsewhere
336 2 New bugs
337 1 Open CVE bugs
338+ 0 Bugs with patches
339
340 Once the user has identified him or herself, information on assigned
341 bugs is also shown.
342
343- >>> print_portlet(user_browser, path)
344+ >>> print_bugfilters_portlet_unfilled(user_browser, path)
345 Open bugs
346 Bugs assigned to me
347 Critical bugs
348 Bugs fixed elsewhere
349 New bugs
350 Open CVE bugs
351-
352- >>> print_portlet_contents(user_browser, path)
353+ Bugs with patches
354+
355+ >>> print_bugfilters_portlet_filled(user_browser, path)
356 2 Open bugs
357 0 Bugs assigned to me
358 0 Critical bugs
359 0 Bugs fixed elsewhere
360 2 New bugs
361 1 Open CVE bugs
362+ 0 Bugs with patches
363
364 Note that the "CVE reports" link is not shown above; source packages
365 do not have a CVE reports page.
366@@ -238,42 +236,46 @@
367
368 If the user is not logged-in general stats are shown.
369
370- >>> print_portlet(anon_browser, path)
371+ >>> print_bugfilters_portlet_unfilled(anon_browser, path)
372 Open bugs
373 Critical bugs
374 Bugs fixed elsewhere
375 New bugs
376 Open CVE bugs
377+ Bugs with patches
378 Subscribe to bug mail
379 --> http://bugs.launchpad.dev/mozilla/+subscribe
380
381- >>> print_portlet_contents(anon_browser, path)
382+ >>> print_bugfilters_portlet_filled(anon_browser, path)
383 4 Open bugs
384 1 Critical bugs
385 0 Bugs fixed elsewhere
386 4 New bugs
387 1 Open CVE bugs
388+ 0 Bugs with patches
389
390 Once the user has identified him or herself, information on assigned
391 bugs is also shown.
392
393- >>> print_portlet(user_browser, path)
394+ >>> print_bugfilters_portlet_unfilled(user_browser, path)
395 Open bugs
396 Bugs assigned to me
397 Critical bugs
398 Bugs fixed elsewhere
399 New bugs
400 Open CVE bugs
401+ Bugs with patches
402 Subscribe to bug mail
403 --> http://bugs.launchpad.dev/mozilla/+subscribe
404
405- >>> print_portlet_contents(user_browser, path)
406+ >>> print_bugfilters_portlet_filled(user_browser, path)
407 4 Open bugs
408 0 Bugs assigned to me
409 1 Critical bugs
410 0 Bugs fixed elsewhere
411 4 New bugs
412 1 Open CVE bugs
413+ 0 Bugs with patches
414
415 Note that the "CVE reports" link is not shown above; project groups do
416 not have a CVE reports page.
417@@ -290,42 +292,46 @@
418
419 If the user is not logged-in general stats are shown.
420
421- >>> print_portlet(anon_browser, path)
422+ >>> print_bugfilters_portlet_unfilled(anon_browser, path)
423 Open bugs
424 Critical bugs
425 Bugs fixed elsewhere
426 New bugs
427 Open CVE bugs - CVE reports
428+ Bugs with patches
429 Subscribe to bug mail
430 --> http://bugs.launchpad.dev/firefox/+subscribe
431
432- >>> print_portlet_contents(anon_browser, path)
433+ >>> print_bugfilters_portlet_filled(anon_browser, path)
434 3 Open bugs
435 1 Critical bugs
436 0 Bugs fixed elsewhere
437 3 New bugs
438 1 Open CVE bugs - CVE reports
439+ 0 Bugs with patches
440
441 Once the user has identified him or herself, information on assigned
442 bugs is also shown.
443
444- >>> print_portlet(user_browser, path)
445+ >>> print_bugfilters_portlet_unfilled(user_browser, path)
446 Open bugs
447 Bugs assigned to me
448 Critical bugs
449 Bugs fixed elsewhere
450 New bugs
451 Open CVE bugs - CVE reports
452+ Bugs with patches
453 Subscribe to bug mail
454 --> http://bugs.launchpad.dev/firefox/+subscribe
455
456- >>> print_portlet_contents(user_browser, path)
457+ >>> print_bugfilters_portlet_filled(user_browser, path)
458 3 Open bugs
459 0 Bugs assigned to me
460 1 Critical bugs
461 0 Bugs fixed elsewhere
462 3 New bugs
463 1 Open CVE bugs - CVE reports
464+ 0 Bugs with patches
465
466
467 The content includes a link to the distribution CVE report.
468
469=== modified file 'lib/lp/bugs/templates/bugtarget-portlet-bugfilters-content.pt'
470--- lib/lp/bugs/templates/bugtarget-portlet-bugfilters-content.pt 2009-11-27 14:44:44 +0000
471+++ lib/lp/bugs/templates/bugtarget-portlet-bugfilters-content.pt 2010-02-19 06:44:15 +0000
472@@ -64,4 +64,14 @@
473 </a>
474 </td>
475 </tr>
476+ <tr tal:define="count view/bugs_with_patches_count|nothing;
477+ plural string: Bugs with patches;
478+ singular string: Bug with a patch;">
479+ <td class="bugs-count" tal:content="count"/>
480+ <td class="bugs-link">
481+ <a tal:attributes="href string:${context/fmt:url}/+patches">
482+ <metal:message use-macro="context/@@+base-layout-macros/plural-message"/>
483+ </a>
484+ </td>
485+ </tr>
486 </tal:portlet-bug-filters-content>
487
488=== modified file 'lib/lp/bugs/tests/bug.py'
489--- lib/lp/bugs/tests/bug.py 2010-01-19 20:45:38 +0000
490+++ lib/lp/bugs/tests/bug.py 2010-02-19 06:44:15 +0000
491@@ -16,7 +16,8 @@
492
493 from canonical.launchpad.ftests import sync
494 from canonical.launchpad.testing.pages import (
495- extract_text, find_tag_by_id, find_main_content, find_tags_by_class)
496+ extract_text, find_tag_by_id, find_main_content, find_tags_by_class,
497+ print_table)
498 from lp.bugs.interfaces.bug import CreateBugParams, IBugSet
499 from lp.bugs.interfaces.bugtask import BugTaskStatus, IBugTaskSet
500 from lp.bugs.interfaces.bugwatch import IBugWatchSet
501@@ -279,3 +280,46 @@
502 if text_field is not None:
503 text_control = browser.getControl(name=text_field.get('name'))
504 print ' [%s]' % text_control.value.ljust(10)
505+
506+
507+def print_bugfilters_portlet_unfilled(browser, target):
508+ """Print the raw, unfilled contents of the bugfilters portlet.
509+
510+ This is the contents before any actual data has been fetched.
511+ (The portlet is normally populated with data by a separate
512+ javascript call, to avoid delaying the overall page load. Use
513+ print_bugfilters_portlet_filled() to test the populated portlet.)
514+
515+ :param browser browser from which to extract the content.
516+ :param target entity from whose bugs page to fetch the portlet
517+ (e.g., http://bugs.launchpad.dev/TARGET/...)
518+ """
519+ browser.open(
520+ 'http://bugs.launchpad.dev/%s/+portlet-bugfilters' % target)
521+ table = BeautifulSoup(browser.contents).find('table', 'bug-links')
522+ tbody_info, tbody_links = table('tbody')
523+ print_table(tbody_info)
524+ for link in tbody_links('a'):
525+ text = extract_text(link)
526+ if len(text) > 0:
527+ print "%s\n --> %s" % (text, link['href'])
528+
529+
530+def print_bugfilters_portlet_filled(browser, target):
531+ """Print the filled-in contents of the bugfilters portlet.
532+
533+ This is the contents after the actual data has been fetched.
534+ (The portlet is normally populated with data by a separate
535+ javascript call, to avoid delaying the overall page load. Use
536+ print_bugfilters_portlet_unfilled() to test the unpopulated
537+ portlet.)
538+
539+ :param browser browser from which to extract the content.
540+ :param target entity from whose bugs page to fetch the portlet
541+ (e.g., http://bugs.launchpad.dev/TARGET/...)
542+ """
543+ browser.open(
544+ 'http://bugs.launchpad.dev'
545+ '/%s/+bugtarget-portlet-bugfilters-stats' % target)
546+ table = BeautifulSoup('<table>%s</table>' % browser.contents)
547+ print_table(table)

Subscribers

People subscribed via source and target branches

to status/vote changes: