Merge lp:~adeuring/launchpad/bug-283941-show-patch-numbers-on-upstream-report into lp:launchpad/db-devel

Proposed by Abel Deuring
Status: Merged
Merged at revision: not available
Proposed branch: lp:~adeuring/launchpad/bug-283941-show-patch-numbers-on-upstream-report
Merge into: lp:launchpad/db-devel
Diff against target: 486 lines (+153/-51)
6 files modified
lib/lp/bugs/browser/bugtask.py (+4/-1)
lib/lp/bugs/browser/distribution_upstream_bug_report.py (+17/-5)
lib/lp/bugs/doc/distribution-upstream-bug-report.txt (+66/-25)
lib/lp/bugs/stories/distribution/xx-distribution-upstream-bug-report.txt (+32/-16)
lib/lp/bugs/templates/distribution-upstream-bug-report.pt (+21/-1)
lib/lp/registry/model/distribution.py (+13/-3)
To merge this branch: bzr merge lp:~adeuring/launchpad/bug-283941-show-patch-numbers-on-upstream-report
Reviewer Review Type Date Requested Status
Curtis Hovey (community) ui Approve
Brad Crittenden (community) code Approve
Review via email: mp+19405@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Abel Deuring (adeuring) wrote :
Download full text (4.5 KiB)

This branch adds another column "number of bugs in a distribution that have patches attached and which may be intersting for the upstream project" to the "upstream report" page. See also bug 283941.

While Jorge suggested in the report to add the new number in parentheses after the last number in each row, I opted to add another column so that we can display a column header. Having numbers without any explanation does IMHO not make much sense, and the page requires already a wiki page with lots of explanations.

Technical changes:

The last value of the current implementation of the page is the difference of the numbers in the columns "Upstream" and "Watch", giving the number of bugs in Ubuntu where the upstream project does not have a corresponding bug.

These numbers come from an SQL query in Distribution.getPackagesAndPublicUpstreamBugCounts(); the SQL expressions are

             COUNT(DISTINCT CASE WHEN Bugtask.status IN %(unresolved)s THEN
                   RelatedBugTask.bug END) AS bugs_affecting_upstream,

for "Upstream" and

             COUNT(DISTINCT CASE WHEN Bugtask.status in %(unresolved)s AND
                   (RelatedBugTask.bugwatch IS NOT NULL OR
                   RelatedProduct.official_malone IS TRUE) THEN
                   RelatedBugTask.bug END) AS bugs_with_upstream_bugwatch,

for "Watch".

We can get the difference between these numbers by inverting the expression

                  (RelatedBugTask.bugwatch IS NOT NULL OR
                   RelatedProduct.official_malone IS TRUE)

which is

                   RelatedBugTask.bugwatch IS NULL AND
                   RelatedProduct.official_malone IS FALSE

(Note that the value of the column RelatedProduct.official_malone may not be NULL). In plain words: "The number of bugs where we have a bugtask in the Launchpad project and in Ubuntu, but where the upstream project does not use Launchpad". IOW, the number of bugs that have been marked in Launchpad as affecting the upstream project, but where we don't know about a corresponding bug in the real upstream bug tracker.

From these bugs, we only want those that have a patch attached, so we add another term for this condition, giving this COUNT expression for the new column of the upstream report page:

             COUNT(DISTINCT CASE WHEN Bugtask.status in %(unresolved)s AND
                   RelatedBugTask.bugwatch IS NULL AND
                   RelatedProduct.official_malone IS FALSE AND
                   Bug.latest_patch_uploaded IS NOT NULL

The remaining changes are mostly mechanical:

The tuples returned by Distribution.getPackagesAndPublicUpstreamBugCounts() now have another element, so the callsite had to be changed DistributionUpstreamBugReport.initialize() had to be changed too.

The values of each displayed on the +upstreamreport gae are stored in insteances of class BugReportData, so this class is now also aware of the new number.

Finally, the number "bugs with patches interesting for upstream" is displayed as a link to a bug search oage. The link is the same as the one for the next column to the left, but with the additional parameter "show only bugs having patches".

The remaing changes are added and ...

Read more...

Revision history for this message
Brad Crittenden (bac) wrote :
Download full text (19.3 KiB)

Hi Abel,

Thanks for this branch. It looks good to me except for a couple of
questions. Please do have a UI review too.

--Brad

> === modified file 'lib/lp/bugs/browser/bugtask.py'
--- lib/lp/bugs/browser/bugtask.py 2010-02-03 21:11:53 +0000
> +++ lib/lp/bugs/browser/bugtask.py 2010-02-16 16:16:26 +0000
> @@ -1858,7 +1858,8 @@
>
>
> def get_buglisting_search_filter_url(
> - assignee=None, importance=None, status=None, status_upstream=None):
> + assignee=None, importance=None, status=None, status_upstream=None,
> + has_patches=None):
> """Return the given URL with the search parameters specified."""
> search_params = []
>
> @@ -1870,6 +1871,8 @@
> search_params.append(('field.status', status))
> if status_upstream is not None:
> search_params.append(('field.status_upstream', status_upstream))
> + if has_patches is not None:
> + search_params.append(('field.has_patch', 'on'))
>
> query_string = urllib.urlencode(search_params, doseq=True)
>

> === modified file 'lib/lp/bugs/browser/distribution_upstream_bug_report.py'
> --- lib/lp/bugs/browser/distribution_upstream_bug_report.py 2009-06-25 00:40:31 +0000
> +++ lib/lp/bugs/browser/distribution_upstream_bug_report.py 2010-02-16 16:16:26 +0000
> @@ -60,11 +60,12 @@
> BAD_THRESHOLD = 20
>
> def __init__(self, open_bugs=0, triaged_bugs=0, upstream_bugs=0,
> - watched_bugs=0):
> + watched_bugs=0, bugs_with_upstream_patches=0):
> self.open_bugs = open_bugs
> self.triaged_bugs = triaged_bugs
> self.upstream_bugs = upstream_bugs
> self.watched_bugs = watched_bugs
> + self.bugs_with_upstream_patches = bugs_with_upstream_patches
>
> @property
> def triaged_bugs_percentage(self):
> @@ -148,9 +149,9 @@
> - *_url: convenience URLs
> """
> def __init__(self, dsp, dssp, product, open_bugs, triaged_bugs,
> - upstream_bugs, watched_bugs):
> + upstream_bugs, watched_bugs, bugs_with_upstream_patches):
> BugReportData.__init__(self, open_bugs, triaged_bugs, upstream_bugs,
> - watched_bugs)
> + watched_bugs, bugs_with_upstream_patches)
> self.dsp = dsp
> self.dssp = dssp
> self.product = product
> @@ -235,6 +236,14 @@
> self.watched_bugs_delta_url = urlappend(
> dsp_bugs_url, unwatched_bugs_search_filter_url)
>
> + # The bugs with upstream patches URL links to all open upstream
> + # bugs that don't have a bugwatch but have patches attached.
> + bugs_with_upstream_patches_filter_url = (
> + get_buglisting_search_filter_url(
> + status_upstream='pending_bugwatch', has_patches=True))
> + self.bugs_with_upstream_patches_url = urlappend(
> + dsp_bugs_url, bugs_with_upstream_patches_filter_url)
> +
>
> class DistributionUpstreamBugReport(LaunchpadView):
> """Implements the actual upstream bug report.
> @@ -248,6 +257,7 @@
> valid_sort_keys = [
> 'bugtracker_name',
> 'bug_superviso...

review: Approve (code)
Revision history for this message
Abel Deuring (adeuring) wrote :
Download full text (4.3 KiB)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Brad,

thanks for your review!

On 16.02.2010 17:34, Brad Crittenden wrote:
> Review: Approve code
> Hi Abel,
>
> Thanks for this branch. It looks good to me except for a couple of
> questions. Please do have a UI review too.

Sure, I wont forget the UI review ;)

>
> --Brad
>
>

[...]
>> === modified file 'lib/lp/bugs/doc/distribution-upstream-bug-report.txt'
>> --- lib/lp/bugs/doc/distribution-upstream-bug-report.txt 2009-10-16 20:33:56 +0000
>> +++ lib/lp/bugs/doc/distribution-upstream-bug-report.txt 2010-02-16 16:16:26 +0000
>> @@ -131,20 +131,56 @@
>> >>> task = getUtility(IBugTaskSet).createTask(bug, name12, product=pmount)
>> >>> Store.of(task).flush()
>> >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))
>> - pmount pmount 2 2 1 0
>> - linux-source-2.6.15 None 1 0 0 0
>> - mozilla-firefox firefox 1 1 1 1
>> -
>> -Linking that task to a bugwatch makes the watch counts update:
>> + pmount pmount 2 2 1 0 0
>> + linux-source-2.6.15 None 1 0 0 0 0
>> + mozilla-firefox firefox 1 1 1 1 0
>> +
>> +The last column counts those bugs with upstream tasks that have patches
>> +attached but which don't have an upstream bugwatch. If we add a ordinary
>> +attachment to our pmount bug, the value of the last column does not
>> +change...
>> +
>> + >>> attachment = factory.makeBugAttachment(bug)
>> + >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))
>> + pmount pmount 2 2 1 0 0
>> + linux-source-2.6.15 None 1 0 0 0 0
>> + mozilla-firefox firefox 1 1 1 1 0
>> +
>> +...but when we make this attachment a patch, the value of the column
>> +increases.
>> +
>> + >>> from lp.bugs.interfaces.bugattachment import BugAttachmentType
>> + >>> attachment.type = BugAttachmentType.PATCH
>> + >>> Store.of(attachment).flush()
>> + >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))
>> + pmount pmount 2 2 1 0 1
>> + linux-source-2.6.15 None 1 0 0 0 0
>> + mozilla-firefox firefox 1 1 1 1 0
>> +
>> +Note that we count only bugs with patches for products that do not
>> +use Malone officially.
>> +
>> + >>> pmount.official_malone = True
>> + >>> Store.of(pmount).flush()
>> + >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))
>> + pmount pmount 2 2 1 1 0
>> + linux-source-2.6.15 None 1 0 0 0 0
>> + mozilla-firefox firefox 1 1 1 1 0
>
> I find having a '0' to be misleading. Would not using a '-' or some
> other indicator to show the data are not relevant be more appropriate?

Thanks, this is a nice idea -- but I prefer to implement this special
case in the template. Firstly, this keeps the code of the method
getPackagesAndPublicUpstreamBugCounts() (or the SQL query) a bit
simpler, and secondly, we calculate and display the sum over all rows
for all columns in the browser class. Having something other than a
number would make that code also more convoluted.

>> === modified file 'lib/lp/bugs/templates/distribution-upstream-bug-report.pt'
>> --- lib/l...

Read more...

Revision history for this message
Abel Deuring (adeuring) wrote :

screenshot: http://people.canonical.com/~adeuring/upstreamreport.png
The right-most column ("Patches for upstream") is new

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

This looks good to land.

review: Approve (ui)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/bugs/browser/bugtask.py'
--- lib/lp/bugs/browser/bugtask.py 2010-02-03 21:11:53 +0000
+++ lib/lp/bugs/browser/bugtask.py 2010-02-18 09:23:13 +0000
@@ -1858,7 +1858,8 @@
18581858
18591859
1860def get_buglisting_search_filter_url(1860def get_buglisting_search_filter_url(
1861 assignee=None, importance=None, status=None, status_upstream=None):1861 assignee=None, importance=None, status=None, status_upstream=None,
1862 has_patches=None):
1862 """Return the given URL with the search parameters specified."""1863 """Return the given URL with the search parameters specified."""
1863 search_params = []1864 search_params = []
18641865
@@ -1870,6 +1871,8 @@
1870 search_params.append(('field.status', status))1871 search_params.append(('field.status', status))
1871 if status_upstream is not None:1872 if status_upstream is not None:
1872 search_params.append(('field.status_upstream', status_upstream))1873 search_params.append(('field.status_upstream', status_upstream))
1874 if has_patches is not None:
1875 search_params.append(('field.has_patch', 'on'))
18731876
1874 query_string = urllib.urlencode(search_params, doseq=True)1877 query_string = urllib.urlencode(search_params, doseq=True)
18751878
18761879
=== modified file 'lib/lp/bugs/browser/distribution_upstream_bug_report.py'
--- lib/lp/bugs/browser/distribution_upstream_bug_report.py 2009-06-25 00:40:31 +0000
+++ lib/lp/bugs/browser/distribution_upstream_bug_report.py 2010-02-18 09:23:13 +0000
@@ -60,11 +60,12 @@
60 BAD_THRESHOLD = 2060 BAD_THRESHOLD = 20
6161
62 def __init__(self, open_bugs=0, triaged_bugs=0, upstream_bugs=0,62 def __init__(self, open_bugs=0, triaged_bugs=0, upstream_bugs=0,
63 watched_bugs=0):63 watched_bugs=0, bugs_with_upstream_patches=0):
64 self.open_bugs = open_bugs64 self.open_bugs = open_bugs
65 self.triaged_bugs = triaged_bugs65 self.triaged_bugs = triaged_bugs
66 self.upstream_bugs = upstream_bugs66 self.upstream_bugs = upstream_bugs
67 self.watched_bugs = watched_bugs67 self.watched_bugs = watched_bugs
68 self.bugs_with_upstream_patches = bugs_with_upstream_patches
6869
69 @property70 @property
70 def triaged_bugs_percentage(self):71 def triaged_bugs_percentage(self):
@@ -148,9 +149,9 @@
148 - *_url: convenience URLs149 - *_url: convenience URLs
149 """150 """
150 def __init__(self, dsp, dssp, product, open_bugs, triaged_bugs,151 def __init__(self, dsp, dssp, product, open_bugs, triaged_bugs,
151 upstream_bugs, watched_bugs):152 upstream_bugs, watched_bugs, bugs_with_upstream_patches):
152 BugReportData.__init__(self, open_bugs, triaged_bugs, upstream_bugs,153 BugReportData.__init__(self, open_bugs, triaged_bugs, upstream_bugs,
153 watched_bugs)154 watched_bugs, bugs_with_upstream_patches)
154 self.dsp = dsp155 self.dsp = dsp
155 self.dssp = dssp156 self.dssp = dssp
156 self.product = product157 self.product = product
@@ -235,6 +236,14 @@
235 self.watched_bugs_delta_url = urlappend(236 self.watched_bugs_delta_url = urlappend(
236 dsp_bugs_url, unwatched_bugs_search_filter_url)237 dsp_bugs_url, unwatched_bugs_search_filter_url)
237238
239 # The bugs with upstream patches URL links to all open upstream
240 # bugs that don't have a bugwatch but have patches attached.
241 bugs_with_upstream_patches_filter_url = (
242 get_buglisting_search_filter_url(
243 status_upstream='pending_bugwatch', has_patches=True))
244 self.bugs_with_upstream_patches_url = urlappend(
245 dsp_bugs_url, bugs_with_upstream_patches_filter_url)
246
238247
239class DistributionUpstreamBugReport(LaunchpadView):248class DistributionUpstreamBugReport(LaunchpadView):
240 """Implements the actual upstream bug report.249 """Implements the actual upstream bug report.
@@ -248,6 +257,7 @@
248 valid_sort_keys = [257 valid_sort_keys = [
249 'bugtracker_name',258 'bugtracker_name',
250 'bug_supervisor_name',259 'bug_supervisor_name',
260 'bugs_with_upstream_patches',
251 'dsp',261 'dsp',
252 'open_bugs',262 'open_bugs',
253 'product',263 'product',
@@ -344,7 +354,8 @@
344 packages_to_exclude = self.context.upstream_report_excluded_packages354 packages_to_exclude = self.context.upstream_report_excluded_packages
345 counts = self.context.getPackagesAndPublicUpstreamBugCounts(355 counts = self.context.getPackagesAndPublicUpstreamBugCounts(
346 limit=self.LIMIT, exclude_packages=packages_to_exclude)356 limit=self.LIMIT, exclude_packages=packages_to_exclude)
347 for (dsp, product, open, triaged, upstream, watched) in counts:357 for (dsp, product, open, triaged, upstream, watched,
358 bugs_with_upstream_patches) in counts:
348 # The +edit-packaging page is only available for359 # The +edit-packaging page is only available for
349 # IDistributionSeriesSourcepackages, so deduce one here. If360 # IDistributionSeriesSourcepackages, so deduce one here. If
350 # the distribution doesn't have series we can't offer a link361 # the distribution doesn't have series we can't offer a link
@@ -360,6 +371,7 @@
360 self.total.watched_bugs += watched371 self.total.watched_bugs += watched
361372
362 item = PackageBugReportData(373 item = PackageBugReportData(
363 dsp, dssp, product, open, triaged, upstream, watched)374 dsp, dssp, product, open, triaged, upstream, watched,
375 bugs_with_upstream_patches)
364 self._data.append(item)376 self._data.append(item)
365377
366378
=== modified file 'lib/lp/bugs/doc/distribution-upstream-bug-report.txt'
--- lib/lp/bugs/doc/distribution-upstream-bug-report.txt 2009-10-16 20:33:56 +0000
+++ lib/lp/bugs/doc/distribution-upstream-bug-report.txt 2010-02-18 09:23:13 +0000
@@ -34,20 +34,20 @@
34them.34them.
3535
36 >>> def print_report(data):36 >>> def print_report(data):
37 ... for dsp, product, open, triaged, upstream, watch in data:37 ... for dsp, product, open, triaged, upstream, watch, patch in data:
38 ... print dsp.name, product and product.name or None38 ... print dsp.name, product and product.name or None
39 ... print open, triaged, upstream, watch39 ... print open, triaged, upstream, watch, patch
4040
41A first set of reports, entirely based on sampledata. There are no41A first set of reports, entirely based on sampledata. There are no
42triaged bugs, but there are some upstream ones with watches:42triaged bugs, but there are some upstream ones with watches:
4343
44 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts())44 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts())
45 linux-source-2.6.15 None 1 0 0 045 linux-source-2.6.15 None 1 0 0 0 0
46 mozilla-firefox firefox 1 0 1 146 mozilla-firefox firefox 1 0 1 1 0
47 thunderbird None 1 0 1 147 thunderbird None 1 0 1 1 0
4848
49 >>> print_report(debian.getPackagesAndPublicUpstreamBugCounts())49 >>> print_report(debian.getPackagesAndPublicUpstreamBugCounts())
50 mozilla-firefox None 3 0 2 150 mozilla-firefox None 3 0 2 1 0
5151
52 >>> print_report(kubuntu.getPackagesAndPublicUpstreamBugCounts())52 >>> print_report(kubuntu.getPackagesAndPublicUpstreamBugCounts())
5353
@@ -58,8 +58,8 @@
5858
59 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(59 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(
60 ... exclude_packages=['linux-source-2.6.15']))60 ... exclude_packages=['linux-source-2.6.15']))
61 mozilla-firefox firefox 1 0 1 161 mozilla-firefox firefox 1 0 1 1 0
62 thunderbird None 1 0 1 162 thunderbird None 1 0 1 1 0
6363
64To get the list of excluded packages for a distribution we can look at64To get the list of excluded packages for a distribution we can look at
65its `upstream_report_excluded_packages` property. For Kubuntu and65its `upstream_report_excluded_packages` property. For Kubuntu and
@@ -88,9 +88,9 @@
88 >>> mf_bug.transitionToStatus(BugTaskStatus.TRIAGED, mark)88 >>> mf_bug.transitionToStatus(BugTaskStatus.TRIAGED, mark)
89 >>> sync(mf_bug)89 >>> sync(mf_bug)
90 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts())90 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts())
91 linux-source-2.6.15 None 1 0 0 091 linux-source-2.6.15 None 1 0 0 0 0
92 mozilla-firefox firefox 1 1 1 192 mozilla-firefox firefox 1 1 1 1 0
93 thunderbird None 1 1 1 193 thunderbird None 1 1 1 1 0
9494
95We add two new bugs to pmount in Ubuntu. From now on we'll limit the95We add two new bugs to pmount in Ubuntu. From now on we'll limit the
96results to 3 packages (as a demonstration of the API) so thunderbird96results to 3 packages (as a demonstration of the API) so thunderbird
@@ -106,9 +106,9 @@
106 ... status=BugTaskStatus.TRIAGED)106 ... status=BugTaskStatus.TRIAGED)
107 >>> ubuntu_pmount_task = bug.bugtasks[0]107 >>> ubuntu_pmount_task = bug.bugtasks[0]
108 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))108 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))
109 pmount None 2 2 0 0109 pmount None 2 2 0 0 0
110 linux-source-2.6.15 None 1 0 0 0110 linux-source-2.6.15 None 1 0 0 0 0
111 mozilla-firefox firefox 1 1 1 1111 mozilla-firefox firefox 1 1 1 1 0
112112
113As you can see, there is no packaging data for pmount in Ubuntu, so no113As you can see, there is no packaging data for pmount in Ubuntu, so no
114upstream is reported for it. Let's fix that:114upstream is reported for it. Let's fix that:
@@ -121,9 +121,9 @@
121 ... pmount.getSeries('trunk'), pmount_spn,121 ... pmount.getSeries('trunk'), pmount_spn,
122 ... ubuntu.currentseries, PackagingType.PRIME, name12)122 ... ubuntu.currentseries, PackagingType.PRIME, name12)
123 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))123 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))
124 pmount pmount 2 2 0 0124 pmount pmount 2 2 0 0 0
125 linux-source-2.6.15 None 1 0 0 0125 linux-source-2.6.15 None 1 0 0 0 0
126 mozilla-firefox firefox 1 1 1 1126 mozilla-firefox firefox 1 1 1 1 0
127127
128We then add an upstream task to the second pmount bug:128We then add an upstream task to the second pmount bug:
129129
@@ -131,20 +131,56 @@
131 >>> task = getUtility(IBugTaskSet).createTask(bug, name12, product=pmount)131 >>> task = getUtility(IBugTaskSet).createTask(bug, name12, product=pmount)
132 >>> Store.of(task).flush()132 >>> Store.of(task).flush()
133 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))133 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))
134 pmount pmount 2 2 1 0134 pmount pmount 2 2 1 0 0
135 linux-source-2.6.15 None 1 0 0 0135 linux-source-2.6.15 None 1 0 0 0 0
136 mozilla-firefox firefox 1 1 1 1136 mozilla-firefox firefox 1 1 1 1 0
137137
138Linking that task to a bugwatch makes the watch counts update:138The last column counts those bugs with upstream tasks that have patches
139attached but which don't have an upstream bugwatch. If we add a ordinary
140attachment to our pmount bug, the value of the last column does not
141change...
142
143 >>> attachment = factory.makeBugAttachment(bug)
144 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))
145 pmount pmount 2 2 1 0 0
146 linux-source-2.6.15 None 1 0 0 0 0
147 mozilla-firefox firefox 1 1 1 1 0
148
149...but when we make this attachment a patch, the value of the column
150increases.
151
152 >>> from lp.bugs.interfaces.bugattachment import BugAttachmentType
153 >>> attachment.type = BugAttachmentType.PATCH
154 >>> Store.of(attachment).flush()
155 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))
156 pmount pmount 2 2 1 0 1
157 linux-source-2.6.15 None 1 0 0 0 0
158 mozilla-firefox firefox 1 1 1 1 0
159
160Note that we count only bugs with patches for products that do not
161use Malone officially.
162
163 >>> pmount.official_malone = True
164 >>> Store.of(pmount).flush()
165 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))
166 pmount pmount 2 2 1 1 0
167 linux-source-2.6.15 None 1 0 0 0 0
168 mozilla-firefox firefox 1 1 1 1 0
169
170 >>> pmount.official_malone = False
171 >>> Store.of(pmount).flush()
172
173Linking that task to a bugwatch increases the watch counts and decreases
174the count of bugs having patches but no bug watch.
139175
140 >>> url = "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=666"176 >>> url = "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=666"
141 >>> [watch] = getUtility(IBugWatchSet).fromText(url, bug, name12)177 >>> [watch] = getUtility(IBugWatchSet).fromText(url, bug, name12)
142 >>> task.bugwatch = watch178 >>> task.bugwatch = watch
143 >>> sync(task)179 >>> sync(task)
144 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))180 >>> print_report(ubuntu.getPackagesAndPublicUpstreamBugCounts(limit=3))
145 pmount pmount 2 2 1 1181 pmount pmount 2 2 1 1 0
146 linux-source-2.6.15 None 1 0 0 0182 linux-source-2.6.15 None 1 0 0 0 0
147 mozilla-firefox firefox 1 1 1 1183 mozilla-firefox firefox 1 1 1 1 0
148184
149185
150Properties of BugReportData186Properties of BugReportData
@@ -488,6 +524,7 @@
488524
489 >>> print_sort_order_links(view)525 >>> print_sort_order_links(view)
490 bug_supervisor_name http://...?sort_by=bug_supervisor_name526 bug_supervisor_name http://...?sort_by=bug_supervisor_name
527 bugs_with_upstream_patches http:...?sort_by=bugs_with_upstream_patches
491 bugtracker_name http://...?sort_by=bugtracker_name528 bugtracker_name http://...?sort_by=bugtracker_name
492 dsp http://...?sort_by=dsp529 dsp http://...?sort_by=dsp
493 open_bugs http://...?sort_by=open_bugs530 open_bugs http://...?sort_by=open_bugs
@@ -517,6 +554,7 @@
517554
518 >>> print_sort_order_links(view)555 >>> print_sort_order_links(view)
519 bug_supervisor_name http://...?sort_by=-bug_supervisor_name556 bug_supervisor_name http://...?sort_by=-bug_supervisor_name
557 bugs_with_upstream_patches http:...?sort_by=bugs_with_upstream_patches
520 bugtracker_name http://...?sort_by=bugtracker_name...558 bugtracker_name http://...?sort_by=bugtracker_name...
521559
522Each sort_order_links dict has an 'arrow' key. This is the URL of the560Each sort_order_links dict has an 'arrow' key. This is the URL of the
@@ -524,6 +562,7 @@
524562
525 >>> print_sort_order_links(view, 'arrow')563 >>> print_sort_order_links(view, 'arrow')
526 bug_supervisor_name /@@/arrowUp564 bug_supervisor_name /@@/arrowUp
565 bugs_with_upstream_patches /@@/arrowBlank
527 bugtracker_name /@@/arrowBlank566 bugtracker_name /@@/arrowBlank
528 dsp /@@/arrowBlank567 dsp /@@/arrowBlank
529 open_bugs /@@/arrowBlank568 open_bugs /@@/arrowBlank
@@ -552,6 +591,7 @@
552591
553 >>> print_sort_order_links(view, 'arrow')592 >>> print_sort_order_links(view, 'arrow')
554 bug_supervisor_name /@@/arrowDown593 bug_supervisor_name /@@/arrowDown
594 bugs_with_upstream_patches /@@/arrowBlank
555 bugtracker_name /@@/arrowBlank...595 bugtracker_name /@@/arrowBlank...
556596
557 >>> form = {'sort_by': '-bugtracker_name'}597 >>> form = {'sort_by': '-bugtracker_name'}
@@ -562,6 +602,7 @@
562602
563 >>> print_sort_order_links(view, 'arrow')603 >>> print_sort_order_links(view, 'arrow')
564 bug_supervisor_name /@@/arrowBlank604 bug_supervisor_name /@@/arrowBlank
605 bugs_with_upstream_patches /@@/arrowBlank
565 bugtracker_name /@@/arrowDown...606 bugtracker_name /@@/arrowDown...
566607
567PS: This page is actually browser-tested in pagetests.distribution-608PS: This page is actually browser-tested in pagetests.distribution-
568609
=== modified file 'lib/lp/bugs/stories/distribution/xx-distribution-upstream-bug-report.txt'
--- lib/lp/bugs/stories/distribution/xx-distribution-upstream-bug-report.txt 2010-01-23 14:17:49 +0000
+++ lib/lp/bugs/stories/distribution/xx-distribution-upstream-bug-report.txt 2010-02-18 09:23:13 +0000
@@ -43,11 +43,11 @@
43 >>> table = find_tag_by_id(browser.contents, 'upstream-report-content')43 >>> table = find_tag_by_id(browser.contents, 'upstream-report-content')
44 >>> print extract_text(table, True)44 >>> print extract_text(table, True)
45 linux-source-2.6.15 Missing corresponding project. (find) (link)45 linux-source-2.6.15 Missing corresponding project. (find) (link)
46 2 2 100.00 0 2 100.00 0 1 50.00 146 2 2 100.00 0 2 100.00 0 1 50.00 1 -
47 mozilla-firefox Mozilla Firefox Launchpad Unspecified47 mozilla-firefox Mozilla Firefox Launchpad Unspecified
48 1 1 100.00 0 1 100.00 048 1 1 100.00 0 1 100.00 0
49 thunderbird Missing corresponding project. (find) (link)49 thunderbird Missing corresponding project. (find) (link)
50 1 1 100.00 0 1 100.00 0 1 100.00 050 1 1 100.00 0 1 100.00 0 1 100.00 0 -
5151
52XXX kiko 2008-02-01 bug=188020: One thing to note from the counts above52XXX kiko 2008-02-01 bug=188020: One thing to note from the counts above
53is that while the linux-source/tomcat task is counted as pending a53is that while the linux-source/tomcat task is counted as pending a
@@ -58,7 +58,7 @@
5858
59 >>> table = find_tag_by_id(browser.contents, 'upstream-report-totals')59 >>> table = find_tag_by_id(browser.contents, 'upstream-report-totals')
60 >>> print extract_text(table)60 >>> print extract_text(table)
61 Totals: 4 4 100.00 0 4 100.00 0 3 75.00 161 Totals: 4 4 100.00 0 4 100.00 0 3 75.00 1 0
6262
63This 3 in the watched column is caused by a problem similar to the63This 3 in the watched column is caused by a problem similar to the
64above; if you do a count of the values in the cells it would be 2, of64above; if you do a count of the values in the cells it would be 2, of
@@ -254,11 +254,27 @@
254 >>> table = find_tag_by_id(browser.contents, 'upstream-report-content')254 >>> table = find_tag_by_id(browser.contents, 'upstream-report-content')
255 >>> print extract_text(table, True)255 >>> print extract_text(table, True)
256 linux-source-2.6.15 Missing corresponding project. (find) (link)256 linux-source-2.6.15 Missing corresponding project. (find) (link)
257 2 2 100.00 0 2 100.00 0 0 0.00 2257 2 2 100.00 0 2 100.00 0 0 0.00 2 -
258 mozilla-firefox Mozilla Firefox The Mozilla.org Bug Tracker Unspecified258 mozilla-firefox Mozilla Firefox The Mozilla.org Bug Tracker Unspecified
259 1 1 100.00 0 1 100.00 0 0 0.00 1259 1 1 100.00 0 1 100.00 0 0 0.00 1 -
260 thunderbird Missing corresponding project. (find) (link)260 thunderbird Missing corresponding project. (find) (link)
261 1 1 100.00 0 1 100.00 0 1 100.00 0261 1 1 100.00 0 1 100.00 0 1 100.00 0 -
262
263If we now add an attachment to the bug we created earlier, the number
264of bugs with patches for upstream increases for linux-source-2.6.15.
265
266 >>> login('foo.bar@canonical.com')
267 >>> attachment = factory.makeBugAttachment(bug, is_patch=True)
268 >>> logout()
269 >>> browser.open("http://bugs.launchpad.dev/ubuntu/+upstreamreport")
270 >>> table = find_tag_by_id(browser.contents, 'upstream-report-content')
271 >>> print extract_text(table, True)
272 linux-source-2.6.15 Missing corresponding project. (find) (link)
273 2 2 100.00 0 2 100.00 0 0 0.00 2 1
274 mozilla-firefox Mozilla Firefox The Mozilla.org Bug Tracker Unspecified
275 1 1 100.00 0 1 100.00 0 0 0.00 1 -
276 thunderbird Missing corresponding project. (find) (link)
277 1 1 100.00 0 1 100.00 0 1 100.00 0 -
262278
263279
264The table of packages can be sorted by any of the columns. The column280The table of packages can be sorted by any of the columns. The column
@@ -298,11 +314,11 @@
298 >>> table = find_tag_by_id(browser.contents, 'upstream-report-content')314 >>> table = find_tag_by_id(browser.contents, 'upstream-report-content')
299 >>> print extract_text(table, True)315 >>> print extract_text(table, True)
300 mozilla-firefox Mozilla Firefox The Mozilla.org Bug Tracker Unspecified316 mozilla-firefox Mozilla Firefox The Mozilla.org Bug Tracker Unspecified
301 1 1 100.00 0 1 100.00 0 0 0.00 1317 1 1 100.00 0 1 100.00 0 0 0.00 1 -
302 thunderbird Missing corresponding project. (find) (link)318 thunderbird Missing corresponding project. (find) (link)
303 1 1 100.00 0 1 100.00 0 1 100.00 0319 1 1 100.00 0 1 100.00 0 1 100.00 0 -
304 linux-source-2.6.15 Missing corresponding project. (find) (link)320 linux-source-2.6.15 Missing corresponding project. (find) (link)
305 2 2 100.00 0 2 100.00 0 0 0.00 2321 2 2 100.00 0 2 100.00 0 0 0.00 2 1
306322
307An arrow next to the current sort header tells the user in which323An arrow next to the current sort header tells the user in which
308direction the table is sorted.324direction the table is sorted.
@@ -324,11 +340,11 @@
324 >>> table = find_tag_by_id(browser.contents, 'upstream-report-content')340 >>> table = find_tag_by_id(browser.contents, 'upstream-report-content')
325 >>> print extract_text(table, True)341 >>> print extract_text(table, True)
326 linux-source-2.6.15 Missing corresponding project. (find) (link)342 linux-source-2.6.15 Missing corresponding project. (find) (link)
327 2 2 100.00 0 2 100.00 0 0 0.00 2343 2 2 100.00 0 2 100.00 0 0 0.00 2 1
328 mozilla-firefox Mozilla Firefox The Mozilla.org Bug Tracker Unspecified344 mozilla-firefox Mozilla Firefox The Mozilla.org Bug Tracker Unspecified
329 1 1 100.00 0 1 100.00 0 0 0.00 1345 1 1 100.00 0 1 100.00 0 0 0.00 1 -
330 thunderbird Missing corresponding project. (find) (link)346 thunderbird Missing corresponding project. (find) (link)
331 1 1 100.00 0 1 100.00 0 1 100.00 0347 1 1 100.00 0 1 100.00 0 1 100.00 0 -
332348
333Finally, you can associate default branches to products. This is done by349Finally, you can associate default branches to products. This is done by
334specifying a branch for the product's main_series:350specifying a branch for the product's main_series:
@@ -360,11 +376,11 @@
360 >>> table = find_tag_by_id(browser.contents, 'upstream-report-content')376 >>> table = find_tag_by_id(browser.contents, 'upstream-report-content')
361 >>> print extract_text(table, True)377 >>> print extract_text(table, True)
362 mozilla-firefox Missing corresponding project. (find) (link)378 mozilla-firefox Missing corresponding project. (find) (link)
363 3 0 0.00 3 2 66.67 1 0 0.00 2379 3 0 0.00 3 2 66.67 1 0 0.00 2 -
364380
365 >>> table = find_tag_by_id(browser.contents, 'upstream-report-totals')381 >>> table = find_tag_by_id(browser.contents, 'upstream-report-totals')
366 >>> print extract_text(table)382 >>> print extract_text(table)
367 Totals: 3 0 0.00 3 2 66.67 1 0 0.00 2383 Totals: 3 0 0.00 3 2 66.67 1 0 0.00 2 0
368384
369 >>> browser.open("http://bugs.launchpad.dev/kubuntu/+upstreamreport")385 >>> browser.open("http://bugs.launchpad.dev/kubuntu/+upstreamreport")
370 >>> table = find_tag_by_id(browser.contents, 'upstream-report')386 >>> table = find_tag_by_id(browser.contents, 'upstream-report')
371387
=== modified file 'lib/lp/bugs/templates/distribution-upstream-bug-report.pt'
--- lib/lp/bugs/templates/distribution-upstream-bug-report.pt 2009-09-04 16:28:13 +0000
+++ lib/lp/bugs/templates/distribution-upstream-bug-report.pt 2010-02-18 09:23:13 +0000
@@ -131,6 +131,13 @@
131 <img id="sortarrow-watched-delta"131 <img id="sortarrow-watched-delta"
132 tal:attributes="src links/watched_bugs_delta/arrow" />132 tal:attributes="src links/watched_bugs_delta/arrow" />
133 </th>133 </th>
134 <th class="amount">
135 <a id="sort-bugs-with-upstream-patches"
136 tal:attributes="href links/bugs_with_upstream_patches/link"
137 >Patches for upstream</a>
138 <img id="sortarrow-bugs-with-upstream-patches"
139 tal:attributes="src links/bugs_with_upstream_patches/arrow" />
140 </th>
134 </tr>141 </tr>
135 </thead>142 </thead>
136 <tbody id="upstream-report-content">143 <tbody id="upstream-report-content">
@@ -219,7 +226,7 @@
219 </td>226 </td>
220 <tal:upstream-in-launchpad227 <tal:upstream-in-launchpad
221 condition="item/official_malone">228 condition="item/official_malone">
222 <td colspan="3" class="good">&nbsp;</td>229 <td colspan="4" class="good">&nbsp;</td>
223 </tal:upstream-in-launchpad>230 </tal:upstream-in-launchpad>
224 <tal:upstream-not-in-launchpad231 <tal:upstream-not-in-launchpad
225 condition="not: item/official_malone">232 condition="not: item/official_malone">
@@ -231,6 +238,17 @@
231 <a tal:attributes="href item/watched_bugs_delta_url"238 <a tal:attributes="href item/watched_bugs_delta_url"
232 tal:content="item/watched_bugs_delta"></a>239 tal:content="item/watched_bugs_delta"></a>
233 </td>240 </td>
241 <td tal:attributes="class string:amount ${item/watched_bugs_class}">
242 <tal:has-bugs-with-upstream-patches
243 condition="item/bugs_with_upstream_patches">
244 <a tal:attributes="href item/bugs_with_upstream_patches_url"
245 tal:content="item/bugs_with_upstream_patches"></a>
246 </tal:has-bugs-with-upstream-patches>
247 <tal:has-no-bugs-with-upstream-patches
248 condition="not: item/bugs_with_upstream_patches">
249 -
250 </tal:has-no-bugs-with-upstream-patches>
251 </td>
234 </tal:upstream-not-in-launchpad>252 </tal:upstream-not-in-launchpad>
235 </tr>253 </tr>
236 </tbody>254 </tbody>
@@ -257,6 +275,8 @@
257 tal:content="view/total/watched_bugs_percentage/fmt:float/.2" />275 tal:content="view/total/watched_bugs_percentage/fmt:float/.2" />
258 <td class="amount"276 <td class="amount"
259 tal:content="view/total/watched_bugs_delta" />277 tal:content="view/total/watched_bugs_delta" />
278 <td class="amount"
279 tal:content="view/total/bugs_with_upstream_patches" />
260 </tr>280 </tr>
261 </tfoot>281 </tfoot>
262 </table>282 </table>
263283
=== modified file 'lib/lp/registry/model/distribution.py'
--- lib/lp/registry/model/distribution.py 2010-02-11 19:17:52 +0000
+++ lib/lp/registry/model/distribution.py 2010-02-18 09:23:13 +0000
@@ -34,6 +34,7 @@
34from lp.soyuz.model.binarypackagename import BinaryPackageName34from lp.soyuz.model.binarypackagename import BinaryPackageName
35from lp.soyuz.model.binarypackagerelease import (35from lp.soyuz.model.binarypackagerelease import (
36 BinaryPackageRelease)36 BinaryPackageRelease)
37from lp.bugs.interfaces.bugattachment import BugAttachmentType
37from lp.bugs.model.bug import (38from lp.bugs.model.bug import (
38 BugSet, get_bug_tags, get_bug_tags_open_count)39 BugSet, get_bug_tags, get_bug_tags_open_count)
39from lp.bugs.model.bugtarget import (40from lp.bugs.model.bugtarget import (
@@ -1375,7 +1376,14 @@
1375 COUNT(DISTINCT CASE WHEN Bugtask.status in %(unresolved)s AND1376 COUNT(DISTINCT CASE WHEN Bugtask.status in %(unresolved)s AND
1376 (RelatedBugTask.bugwatch IS NOT NULL OR1377 (RelatedBugTask.bugwatch IS NOT NULL OR
1377 RelatedProduct.official_malone IS TRUE) THEN1378 RelatedProduct.official_malone IS TRUE) THEN
1378 RelatedBugTask.bug END) AS bugs_with_upstream_bugwatch1379 RelatedBugTask.bug END) AS bugs_with_upstream_bugwatch,
1380 COUNT(DISTINCT CASE WHEN Bugtask.status in %(unresolved)s AND
1381 RelatedBugTask.bugwatch IS NULL AND
1382 RelatedProduct.official_malone IS FALSE AND
1383 Bug.latest_patch_uploaded IS NOT NULL
1384 THEN
1385 RelatedBugTask.bug END)
1386 AS bugs_with_upstream_patches
1379 FROM1387 FROM
1380 SourcePackageName AS SPN1388 SourcePackageName AS SPN
1381 JOIN Bugtask ON SPN.id = Bugtask.sourcepackagename1389 JOIN Bugtask ON SPN.id = Bugtask.sourcepackagename
@@ -1453,7 +1461,8 @@
1453 # in a reasonable data structure.1461 # in a reasonable data structure.
1454 results = []1462 results = []
1455 for (spn_id, spn_name, open_bugs, bugs_triaged,1463 for (spn_id, spn_name, open_bugs, bugs_triaged,
1456 bugs_affecting_upstream, bugs_with_upstream_bugwatch) in counts:1464 bugs_affecting_upstream, bugs_with_upstream_bugwatch,
1465 bugs_with_upstream_patches) in counts:
1457 sourcepackagename = SourcePackageName.get(spn_id)1466 sourcepackagename = SourcePackageName.get(spn_id)
1458 dsp = self.getSourcePackage(sourcepackagename)1467 dsp = self.getSourcePackage(sourcepackagename)
1459 if spn_id in sources_to_products:1468 if spn_id in sources_to_products:
@@ -1463,7 +1472,8 @@
1463 product = None1472 product = None
1464 results.append(1473 results.append(
1465 (dsp, product, open_bugs, bugs_triaged,1474 (dsp, product, open_bugs, bugs_triaged,
1466 bugs_affecting_upstream, bugs_with_upstream_bugwatch))1475 bugs_affecting_upstream, bugs_with_upstream_bugwatch,
1476 bugs_with_upstream_patches))
1467 return results1477 return results
14681478
1469 def setBugSupervisor(self, bug_supervisor, user):1479 def setBugSupervisor(self, bug_supervisor, user):

Subscribers

People subscribed via source and target branches

to status/vote changes: