Merge lp:~jcsackett/launchpad/deprecate-official_malone into lp:launchpad

Proposed by j.c.sackett on 2010-08-25
Status: Merged
Approved by: Edwin Grubbs on 2010-08-26
Approved revision: no longer in the source branch.
Merged at revision: 11493
Proposed branch: lp:~jcsackett/launchpad/deprecate-official_malone
Merge into: lp:launchpad
Diff against target: 979 lines (+148/-116)
25 files modified
lib/canonical/launchpad/doc/vocabularies.txt (+3/-3)
lib/canonical/launchpad/vocabularies/dbobjects.py (+8/-6)
lib/lp/bugs/browser/bugalsoaffects.py (+6/-4)
lib/lp/bugs/browser/bugtarget.py (+12/-7)
lib/lp/bugs/browser/bugtask.py (+24/-22)
lib/lp/bugs/browser/distribution_upstream_bug_report.py (+13/-8)
lib/lp/bugs/browser/tests/bugtask-adding-views.txt (+6/-6)
lib/lp/bugs/browser/tests/test_bugtarget_configure.py (+4/-1)
lib/lp/bugs/model/bug.py (+2/-1)
lib/lp/bugs/model/bugtask.py (+10/-7)
lib/lp/bugs/templates/bug-create-question.pt (+1/-1)
lib/lp/bugs/templates/bugtarget-macros-filebug.pt (+1/-1)
lib/lp/bugs/templates/bugtask-requestfix-upstream.pt (+3/-3)
lib/lp/bugs/templates/distribution-upstream-bug-report.pt (+6/-4)
lib/lp/bugs/tests/bugtarget-questiontarget.txt (+4/-4)
lib/lp/bugs/tests/test_bugs_webservice.py (+20/-12)
lib/lp/bugs/tests/test_bugtask_1.py (+8/-9)
lib/lp/registry/browser/sourcepackage.py (+5/-5)
lib/lp/registry/browser/tests/distribution-views.txt (+4/-4)
lib/lp/registry/browser/tests/sourcepackage-views.txt (+2/-2)
lib/lp/registry/doc/product.txt (+2/-2)
lib/lp/registry/templates/distribution-index.pt (+1/-1)
lib/lp/registry/templates/distribution-search.pt (+1/-1)
lib/lp/registry/templates/product-index.pt (+1/-1)
lib/lp/testing/factory.py (+1/-1)
To merge this branch: bzr merge lp:~jcsackett/launchpad/deprecate-official_malone
Reviewer Review Type Date Requested Status
Edwin Grubbs (community) code 2010-08-25 Approve on 2010-08-26
Review via email: mp+33694@code.launchpad.net

Commit Message

Deprecates usage of official_malone where possible in favor of bug_tracking_usage.

Description of the Change

= Summary =

Replaces, where possible, usage of official_malone with the bug_tracking_usage property.

== Proposed fix ==

Where code uses official_malone to drive a decision regarding presentation or action,
update the code to use bug_tracking_usage instead, so we can use the richer data
provided by the usage enums.

== Pre-implementation notes ==

Spoke with Curtis Hovey (sinzui) and Brad Crittenden (bac).

== Implementation details ==

As in Proposed fix.

SQL queries using official_malone have been left alone until data migration occurs.

Instances where an assignment is made to official_malone, no replacement is made as the official_malone
boolean is part of the data driving bug_tracking_usage.

== Tests ==

No new tests written.

To fully test the refactor:

bin/test -m lib.lp.registry
bin/test -m lib.lp.bugs

== Demo and Q/A ==

In Launchpad.dev, nothing should crash when reviewing bugs or performing bug related actions.

There are no changes to the UX or UI, I believe everything should function in the same fashion.

= Launchpad lint =

This touched enough old files that the lint output is huge. I will fix all valid lint errors before committing, but I didn't want to pollute the diff too much nor make this MP a wall of text.

To post a comment you must log in.
j.c.sackett (jcsackett) wrote :
Download full text (29.6 KiB)

I've noticed that the diff gets weird over time, so I'm snapshotting it near the beginning of this MP.

=== modified file 'lib/canonical/launchpad/doc/vocabularies.txt'
--- lib/canonical/launchpad/doc/vocabularies.txt 2010-02-17 11:13:06 +0000
+++ lib/canonical/launchpad/doc/vocabularies.txt 2010-08-25 14:36:51 +0000
@@ -251,9 +251,9 @@

     >>> mozilla_project = getUtility(IProjectGroupSet).getByName('mozilla')
     >>> for product in mozilla_project.products:
- ... print "%s: %s" % (product.name, product.official_malone)
- firefox: True
- thunderbird: False
+ ... print "%s: %s" % (product.name, product.bug_tracking_usage.name)
+ firefox: LAUNCHPAD
+ thunderbird: UNKNOWN

     >>> mozilla_products_vocabulary = vocabulary_registry.get(
     ... mozilla_project,'ProjectProductsUsingMalone')

=== modified file 'lib/canonical/launchpad/vocabularies/dbobjects.py'
--- lib/canonical/launchpad/vocabularies/dbobjects.py 2010-08-20 20:31:18 +0000
+++ lib/canonical/launchpad/vocabularies/dbobjects.py 2010-08-25 20:17:12 +0000
@@ -87,6 +87,7 @@
     SQLObjectVocabularyBase,
     )
 from lp.app.browser.stringformatter import FormattersAPI
+from lp.app.enums import ServiceUsage
 from lp.blueprints.interfaces.specification import SpecificationFilter
 from lp.blueprints.model.specification import Specification
 from lp.blueprints.model.sprint import Sprint
@@ -234,6 +235,7 @@
     These are branches that the user is guaranteed to be able to push
     to.
     """
+
     def __init__(self, context=None):
         """Pass a Person as context, or anything else for the current user."""
         super(HostedBranchRestrictedOnOwnerVocabulary, self).__init__(context)
@@ -341,6 +343,7 @@
     This vocabulary contains all the languages known to Launchpad,
     excluding English and non-visible languages.
     """
+
     def __contains__(self, language):
         """See `IVocabulary`.

@@ -382,7 +385,7 @@
     return SimpleVocabulary([
         SimpleTerm(product, product.name, title=product.displayname)
         for product in project.products
- if product.official_malone])
+ if product.bug_tracking_usage == ServiceUsage.LAUNCHPAD])

 class TranslationGroupVocabulary(NamedSQLObjectVocabulary):
@@ -741,7 +744,8 @@
         return Distribution.selectBy(official_malone=True).count()

     def __contains__(self, obj):
- return IDistribution.providedBy(obj) and obj.official_malone
+ return (IDistribution.providedBy(obj)
+ and obj.bug_tracking_usage == ServiceUsage.LAUNCHPAD)

     def getQuery(self):
         return None

=== modified file 'lib/lp/bugs/browser/bugalsoaffects.py'
--- lib/lp/bugs/browser/bugalsoaffects.py 2010-08-20 20:31:18 +0000
+++ lib/lp/bugs/browser/bugalsoaffects.py 2010-08-25 15:55:41 +0000
@@ -56,6 +56,7 @@
 from canonical.widgets.itemswidgets import LaunchpadRadioWidget
 from canonical.widgets.popup import SearchForUpstreamPopupWidget
 from canonical.widgets.textwidgets import StrippedTextWidget
+from lp.app.enums import ServiceUsage
 from lp.bugs.interfaces.bug import IBug
 from lp.bugs.interfaces.bugtask import (
     BugTaskImportance,
@@ -319,10 +320,11 @@
     ...

Edwin Grubbs (edwin-grubbs) wrote :
Download full text (15.0 KiB)

Hi JC,

This does not look like a fun branch, but it is very helpful. I have a
few questions and suggestions below.

-Edwin

>=== modified file 'lib/lp/bugs/browser/bugalsoaffects.py'
>--- lib/lp/bugs/browser/bugalsoaffects.py 2010-08-20 20:31:18 +0000
>+++ lib/lp/bugs/browser/bugalsoaffects.py 2010-08-25 21:42:02 +0000
>@@ -56,6 +56,7 @@
> from canonical.widgets.itemswidgets import LaunchpadRadioWidget
> from canonical.widgets.popup import SearchForUpstreamPopupWidget
> from canonical.widgets.textwidgets import StrippedTextWidget
>+from lp.app.enums import ServiceUsage
> from lp.bugs.interfaces.bug import IBug
> from lp.bugs.interfaces.bugtask import (
> BugTaskImportance,
>@@ -319,10 +320,11 @@
> if bug_watch is None:
> bug_watch = task_added.bug.addWatch(
> extracted_bugtracker, extracted_bug, self.user)
>- if not target.official_malone:
>+ if target.bug_tracking_usage != ServiceUsage.LAUNCHPAD:
> task_added.bugwatch = bug_watch
>
>- if (not target.official_malone and task_added.bugwatch is not None
>+ if (target.bug_tracking_usage != ServiceUsage.LAUNCHPAD

Whitespace at end of line.

>+ and task_added.bugwatch is not None
> and (task_added.bugwatch.bugtracker.bugtrackertype !=
> BugTrackerType.EMAILADDRESS)):
> # A remote bug task gets its status from a bug watch, so
>=== modified file 'lib/lp/bugs/browser/bugtarget.py'
>--- lib/lp/bugs/browser/bugtarget.py 2010-08-22 18:31:30 +0000
>+++ lib/lp/bugs/browser/bugtarget.py 2010-08-25 21:42:02 +0000
>@@ -96,7 +96,11 @@
> NotFoundError,
> UnexpectedFormData,
> )
>-from lp.app.interfaces.launchpad import ILaunchpadUsage
>+from lp.app.enums import ServiceUsage

lp.app.enums should be placed above lp.app.errors.

>+from lp.app.interfaces.launchpad import (
>+ ILaunchpadUsage,
>+ IServiceUsage,
>+ )
> from lp.bugs.browser.bugrole import BugRoleMixin
> from lp.bugs.browser.bugtask import BugTaskSearchListingView
> from lp.bugs.interfaces.apportjob import IProcessApportBlobJobSource
>@@ -384,7 +388,7 @@
> # actually uses Malone for its bug tracking.
> product_or_distro = self.getProductOrDistroFromContext()
> if (product_or_distro is not None and
>- not product_or_distro.official_malone):
>+ product_or_distro.bug_tracking_usage != ServiceUsage.LAUNCHPAD):
> self.setFieldError(
> 'bugtarget',
> "%s does not use Launchpad as its bug tracker " %
>@@ -426,10 +430,11 @@
> if IProjectGroup.providedBy(self.context):
> products_using_malone = [
> product for product in self.context.products
>- if product.official_malone]
>+ if product.bug_tracking_usage == ServiceUsage.LAUNCHPAD]
> return len(products_using_malone) > 0
> else:
>- return self.getMainContext().official_malone
>+ bug_tracking_usage = self.getMainContext().bug_tracking_usage
>+ return bug_tracking_usage == ServiceUsage.LAUNCHPAD

Does this mean that Projec...

review: Needs Information (code)
j.c.sackett (jcsackett) wrote :
Download full text (7.4 KiB)

Updated diff:

=== modified file 'lib/lp/bugs/browser/bugalsoaffects.py'
--- lib/lp/bugs/browser/bugalsoaffects.py 2010-08-25 15:56:26 +0000
+++ lib/lp/bugs/browser/bugalsoaffects.py 2010-08-26 15:10:32 +0000
@@ -323,7 +323,7 @@
             if target.bug_tracking_usage != ServiceUsage.LAUNCHPAD:
                 task_added.bugwatch = bug_watch

- if (target.bug_tracking_usage != ServiceUsage.LAUNCHPAD
+ if (target.bug_tracking_usage != ServiceUsage.LAUNCHPAD
             and task_added.bugwatch is not None
             and (task_added.bugwatch.bugtracker.bugtrackertype !=
                  BugTrackerType.EMAILADDRESS)):

=== modified file 'lib/lp/bugs/browser/bugtarget.py'
--- lib/lp/bugs/browser/bugtarget.py 2010-08-25 21:10:35 +0000
+++ lib/lp/bugs/browser/bugtarget.py 2010-08-26 15:11:23 +0000
@@ -92,11 +92,11 @@
     GhostWidget,
     ProductBugTrackerWidget,
     )
+from lp.app.enums import ServiceUsage
 from lp.app.errors import (
     NotFoundError,
     UnexpectedFormData,
     )
-from lp.app.enums import ServiceUsage
 from lp.app.interfaces.launchpad import (
     ILaunchpadUsage,
     IServiceUsage,

=== modified file 'lib/lp/bugs/browser/distribution_upstream_bug_report.py'
--- lib/lp/bugs/browser/distribution_upstream_bug_report.py 2010-08-25 17:45:19 +0000
+++ lib/lp/bugs/browser/distribution_upstream_bug_report.py 2010-08-26 15:42:38 +0000
@@ -146,7 +146,7 @@
         - dssp: an IDistributionSeriesSourcepackage
         - product: an IProduct
         - bugtracker: convenience holder for the product's bugtracker
- - bug_tracking_usage: convenience enum for
+ - bug_tracking_usage: convenience enum for
             IProduct.bug_tracking_usage
         - *_url: convenience URLs
     """
@@ -166,6 +166,7 @@

         self.bug_tracking_usage = product.bug_tracking_usage

+ # If a product is specified, build some convenient links to
         # pages which allow filling out required information. The
         # template ensures they are only visible to people who can
         # actually change the product.

=== modified file 'lib/lp/bugs/templates/distribution-upstream-bug-report.pt'
--- lib/lp/bugs/templates/distribution-upstream-bug-report.pt 2010-08-24 20:11:37 +0000
+++ lib/lp/bugs/templates/distribution-upstream-bug-report.pt 2010-08-26 15:45:23 +0000
@@ -166,10 +166,12 @@
                 </td>
               </tal:has-bugtracker>
               <tal:has-no-bugtracker condition="not: item/bugtracker">
- <td tal:condition="item/bug_tracking_usage/enumvalue:LAUNCHPAD" align="center">
+ <td tal:condition="item/bug_tracking_usage/enumvalue:LAUNCHPAD"
+ align="center">
                     <img src="/@@/yes" title="Launchpad" />
                 </td>
- <td tal:condition="not: item/bug_tracking_usage/enumvalue:LAUNCHPAD" align="center">
+ <td tal:condition="not: item/bug_tracking_usage/enumvalue:LAUNCHPAD"
+ align="center">
                     <img src="/@@/no" title="Unknown" />
                     <a tal:condition="item/product/required:launchpad.Edit"
                        tal:attributes="href it...

Read more...

j.c.sackett (jcsackett) wrote :
Download full text (8.1 KiB)

>> + if (target.bug_tracking_usage != ServiceUsage.LAUNCHPAD
>
>
> Whitespace at end of line.

Taken care of.

>> -from lp.app.interfaces.launchpad import ILaunchpadUsage
>> +from lp.app.enums import ServiceUsage
>
>
> lp.app.enums should be placed above lp.app.errors.

Agreed, and done.

>> @@ -426,10 +430,11 @@
>> if IProjectGroup.providedBy(self.context):
>> products_using_malone = [
>> product for product in self.context.products
>> - if product.official_malone]
>> + if product.bug_tracking_usage == ServiceUsage.LAUNCHPAD]
>> return len(products_using_malone) > 0
>> else:
>> - return self.getMainContext().official_malone
>> + bug_tracking_usage = self.getMainContext().bug_tracking_usage
>> + return bug_tracking_usage == ServiceUsage.LAUNCHPAD
>
>
>
> Does this mean that ProjectGroup will never implement IServiceUsage?

This may be ignorance of a better solution on my part, but as ProjectGroup didn't implement ILaunchpadUsage
(where the official_* attrs are largely defined) I didn't think it needed to implement IServiceUsage; at least not
within the scope of this branch. The mods above get to the usage_enum in the same way that the official_bool
was retrieved.

>> === modified file 'lib/lp/bugs/browser/bugtask.py'
>> --- lib/lp/bugs/browser/bugtask.py 2010-08-22 18:31:30 +0000
>> +++ lib/lp/bugs/browser/bugtask.py 2010-08-25 21:42:02 +0000
>> @@ -193,6 +193,7 @@
>> )
>> from canonical.widgets.project import ProjectScopeWidget
>> from lp.answers.interfaces.questiontarget import IQuestionTarget
>> +from lp.app.enums import ServiceUsage
>> from lp.app.errors import (
>> NotFoundError,
>> UnexpectedFormData,
>> @@ -1668,7 +1669,7 @@
>>
>> new_product = data.get('product')
>> if (old_product is None or old_product == new_product or
>> - not bugtask.pillar.official_malone):
>> + bugtask.pillar.bug_tracking_usage != ServiceUsage.LAUNCHPAD):
>> # Either the product wasn't changed, we're dealing with a #
>> # distro task, or the bugtask's product doesn't use Launchpad,
>> # which means the product can't be changed.
>
>
> The comment and the the if-statement don't make sense. Why would we
> care if the current bugtask.pillar doesn't use LP Bugs? It should check
> if the new_product uses LP Bugs. Can you ask the bugs team about this?

According to deryck, that's because it's checking the bugtask target, which may not actually be
old_ or new_ product and may be a distro.

There was some confusion on this point; I believe jml and deryck are still
looking into it, but seemed to believe it was correct.

>> === modified file 'lib/lp/bugs/browser/distribution_upstream_bug_report.py'
>> --- lib/lp/bugs/browser/distribution_upstream_bug_report.py 2010-08-20 20:31:18 +0000
>> +++ lib/lp/bugs/browser/distribution_upstream_bug_report.py 2010-08-25 21:42:02 +0000
>> @@ -17,6 +17,7 @@
>> LaunchpadView,
>> )
>> from canonical.launchpad.webapp.url import urlappend
>> +from lp.app.enums import ServiceUsage
>> from lp.bugs.browser.bugtask import get_bugl...

Read more...

Edwin Grubbs (edwin-grubbs) wrote :

Hi JC,

Thanks for making the changes. I just have one more item that should be changed before this lands.

-Edwin

> === modified file 'lib/lp/registry/adapters.py'
> --- lib/lp/registry/adapters.py 2010-08-24 20:09:56 +0000
> +++ lib/lp/registry/adapters.py 2010-08-26 15:53:05 +0000
> @@ -26,14 +34,12 @@
> )
>
>
> +@implementer(IServiceUsage)
> +@adapter(IDistroSeries)
> def distroseries_to_launchpadusage(distroseries):
> """Adapts `IDistroSeries` object to `ILaunchpadUsage`."""
> return distroseries.distribution
>
> -def distroseries_to_serviceusage(distroseries):
> - """Adapts `IDistroSeries` object to `IServiceUsage`."""
> - return distroseries.distribution
> -
> def person_from_principal(principal):
> """Adapt `ILaunchpadPrincipal` to `IPerson`."""
> if ILaunchpadPrincipal.providedBy(principal):

I like that you are trying to reuse the function, but I think it will confuse someone horribly if @implementer doesn't match the function name or the docstring. You might be able to get this to work with:

@implementer(ILaunchpadUsage, IServiceUsage)

and then the function name should be changed to distroseries_to_distribution(), which describes the object it's returning as opposed to the interface it's adapting to. The zcml could be trimmed for ILaunchpadUsage then also.

If this doesn't work easily, just add the old function back and put @implementer and @adapter above that.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/doc/vocabularies.txt'
2--- lib/canonical/launchpad/doc/vocabularies.txt 2010-08-26 08:02:08 +0000
3+++ lib/canonical/launchpad/doc/vocabularies.txt 2010-09-02 19:34:49 +0000
4@@ -259,9 +259,9 @@
5
6 >>> mozilla_project = getUtility(IProjectGroupSet).getByName('mozilla')
7 >>> for product in mozilla_project.products:
8- ... print "%s: %s" % (product.name, product.official_malone)
9- firefox: True
10- thunderbird: False
11+ ... print "%s: %s" % (product.name, product.bug_tracking_usage.name)
12+ firefox: LAUNCHPAD
13+ thunderbird: UNKNOWN
14
15 >>> mozilla_products_vocabulary = vocabulary_registry.get(
16 ... mozilla_project,'ProjectProductsUsingMalone')
17
18=== modified file 'lib/canonical/launchpad/vocabularies/dbobjects.py'
19--- lib/canonical/launchpad/vocabularies/dbobjects.py 2010-08-26 08:02:08 +0000
20+++ lib/canonical/launchpad/vocabularies/dbobjects.py 2010-09-02 19:34:49 +0000
21@@ -85,6 +85,7 @@
22 SQLObjectVocabularyBase,
23 )
24 from lp.app.browser.stringformatter import FormattersAPI
25+from lp.app.enums import ServiceUsage
26 from lp.blueprints.model.specification import Specification
27 from lp.blueprints.model.sprint import Sprint
28 from lp.bugs.interfaces.bugtask import IBugTask
29@@ -231,6 +232,7 @@
30 These are branches that the user is guaranteed to be able to push
31 to.
32 """
33+
34 def __init__(self, context=None):
35 """Pass a Person as context, or anything else for the current user."""
36 super(HostedBranchRestrictedOnOwnerVocabulary, self).__init__(context)
37@@ -338,6 +340,7 @@
38 This vocabulary contains all the languages known to Launchpad,
39 excluding English and non-visible languages.
40 """
41+
42 def __contains__(self, language):
43 """See `IVocabulary`.
44
45@@ -379,7 +382,7 @@
46 return SimpleVocabulary([
47 SimpleTerm(product, product.name, title=product.displayname)
48 for product in project.products
49- if product.official_malone])
50+ if product.bug_tracking_usage == ServiceUsage.LAUNCHPAD])
51
52
53 class TranslationGroupVocabulary(NamedSQLObjectVocabulary):
54@@ -413,14 +416,12 @@
55 if context.productseries != None:
56 self._filter = AND(
57 POTemplate.iscurrent == True,
58- POTemplate.productseries == context.productseries
59- )
60+ POTemplate.productseries == context.productseries)
61 else:
62 self._filter = AND(
63 POTemplate.iscurrent == True,
64 POTemplate.distroseries == context.distroseries,
65- POTemplate.sourcepackagename == context.sourcepackagename
66- )
67+ POTemplate.sourcepackagename == context.sourcepackagename)
68 super(TranslationTemplateVocabulary, self).__init__(context)
69
70 def toTerm(self, obj):
71@@ -661,7 +662,8 @@
72 return Distribution.selectBy(official_malone=True).count()
73
74 def __contains__(self, obj):
75- return IDistribution.providedBy(obj) and obj.official_malone
76+ return (IDistribution.providedBy(obj)
77+ and obj.bug_tracking_usage == ServiceUsage.LAUNCHPAD)
78
79 def getQuery(self):
80 return None
81
82=== modified file 'lib/lp/bugs/browser/bugalsoaffects.py'
83--- lib/lp/bugs/browser/bugalsoaffects.py 2010-08-20 20:31:18 +0000
84+++ lib/lp/bugs/browser/bugalsoaffects.py 2010-09-02 19:34:49 +0000
85@@ -56,6 +56,7 @@
86 from canonical.widgets.itemswidgets import LaunchpadRadioWidget
87 from canonical.widgets.popup import SearchForUpstreamPopupWidget
88 from canonical.widgets.textwidgets import StrippedTextWidget
89+from lp.app.enums import ServiceUsage
90 from lp.bugs.interfaces.bug import IBug
91 from lp.bugs.interfaces.bugtask import (
92 BugTaskImportance,
93@@ -319,10 +320,11 @@
94 if bug_watch is None:
95 bug_watch = task_added.bug.addWatch(
96 extracted_bugtracker, extracted_bug, self.user)
97- if not target.official_malone:
98+ if target.bug_tracking_usage != ServiceUsage.LAUNCHPAD:
99 task_added.bugwatch = bug_watch
100
101- if (not target.official_malone and task_added.bugwatch is not None
102+ if (target.bug_tracking_usage != ServiceUsage.LAUNCHPAD
103+ and task_added.bugwatch is not None
104 and (task_added.bugwatch.bugtracker.bugtrackertype !=
105 BugTrackerType.EMAILADDRESS)):
106 # A remote bug task gets its status from a bug watch, so
107@@ -371,7 +373,7 @@
108
109 if (not bug_url and
110 not self.request.get('ignore_missing_remote_bug') and
111- not target.official_malone):
112+ target.bug_tracking_usage != ServiceUsage.LAUNCHPAD):
113 # We have no URL for the remote bug and the target does not use
114 # Launchpad for bug tracking, so we warn the user this is not
115 # optimal and ask for his confirmation.
116@@ -404,7 +406,7 @@
117 """
118 target = self.getTarget(data)
119 bug_url = data.get('bug_url')
120- if bug_url and target.official_malone:
121+ if bug_url and target.bug_tracking_usage == ServiceUsage.LAUNCHPAD:
122 self.addError(
123 "Bug watches can not be added for %s, as it uses Launchpad"
124 " as its official bug tracker. Alternatives are to add a"
125
126=== modified file 'lib/lp/bugs/browser/bugtarget.py'
127--- lib/lp/bugs/browser/bugtarget.py 2010-08-22 18:31:30 +0000
128+++ lib/lp/bugs/browser/bugtarget.py 2010-09-02 19:34:49 +0000
129@@ -92,11 +92,15 @@
130 GhostWidget,
131 ProductBugTrackerWidget,
132 )
133+from lp.app.enums import ServiceUsage
134 from lp.app.errors import (
135 NotFoundError,
136 UnexpectedFormData,
137 )
138-from lp.app.interfaces.launchpad import ILaunchpadUsage
139+from lp.app.interfaces.launchpad import (
140+ ILaunchpadUsage,
141+ IServiceUsage,
142+ )
143 from lp.bugs.browser.bugrole import BugRoleMixin
144 from lp.bugs.browser.bugtask import BugTaskSearchListingView
145 from lp.bugs.interfaces.apportjob import IProcessApportBlobJobSource
146@@ -384,7 +388,7 @@
147 # actually uses Malone for its bug tracking.
148 product_or_distro = self.getProductOrDistroFromContext()
149 if (product_or_distro is not None and
150- not product_or_distro.official_malone):
151+ product_or_distro.bug_tracking_usage != ServiceUsage.LAUNCHPAD):
152 self.setFieldError(
153 'bugtarget',
154 "%s does not use Launchpad as its bug tracker " %
155@@ -426,10 +430,11 @@
156 if IProjectGroup.providedBy(self.context):
157 products_using_malone = [
158 product for product in self.context.products
159- if product.official_malone]
160+ if product.bug_tracking_usage == ServiceUsage.LAUNCHPAD]
161 return len(products_using_malone) > 0
162 else:
163- return self.getMainContext().official_malone
164+ bug_tracking_usage = self.getMainContext().bug_tracking_usage
165+ return bug_tracking_usage == ServiceUsage.LAUNCHPAD
166
167 def getMainContext(self):
168 if IDistributionSourcePackage.providedBy(self.context):
169@@ -1084,7 +1089,7 @@
170 def products_using_malone(self):
171 return [
172 product for product in self.context.products
173- if product.official_malone]
174+ if product.bug_tracking_usage == ServiceUsage.LAUNCHPAD]
175
176 @property
177 def default_product(self):
178@@ -1252,8 +1257,8 @@
179
180 :returns: boolean
181 """
182- launchpad_usage = ILaunchpadUsage(self.context)
183- return launchpad_usage.official_malone
184+ service_usage = IServiceUsage(self.context)
185+ return service_usage.bug_tracking_usage == ServiceUsage.LAUNCHPAD
186
187 @property
188 def external_bugtracker(self):
189
190=== modified file 'lib/lp/bugs/browser/bugtask.py'
191--- lib/lp/bugs/browser/bugtask.py 2010-08-31 18:15:15 +0000
192+++ lib/lp/bugs/browser/bugtask.py 2010-09-02 19:34:49 +0000
193@@ -119,15 +119,11 @@
194 SimpleVocabulary,
195 )
196 from zope.security.interfaces import Unauthorized
197-from zope.security.proxy import (
198- isinstance as zope_isinstance,
199- removeSecurityProxy,
200- )
201+from zope.security.proxy import isinstance as zope_isinstance
202 from zope.traversing.interfaces import IPathAdapter
203
204 from canonical.cachedproperty import cachedproperty
205 from canonical.config import config
206-from canonical.database.sqlbase import cursor
207 from canonical.launchpad import (
208 _,
209 helpers,
210@@ -193,6 +189,7 @@
211 )
212 from canonical.widgets.project import ProjectScopeWidget
213 from lp.answers.interfaces.questiontarget import IQuestionTarget
214+from lp.app.enums import ServiceUsage
215 from lp.app.errors import (
216 NotFoundError,
217 UnexpectedFormData,
218@@ -275,6 +272,7 @@
219 PersonFormatterAPI(context.assignee).link(None))
220 return render
221
222+
223 @component.adapter(IBugTask, IReference, IWebServiceClientRequest)
224 @implementer(IFieldHTMLRenderer)
225 def bugtarget_renderer(context, field, request):
226@@ -289,6 +287,7 @@
227 return html
228 return render
229
230+
231 def unique_title(title):
232 """Canonicalise a message title to help identify messages with new
233 information in their titles.
234@@ -1085,7 +1084,7 @@
235 activity_and_comments.append({
236 'activity': activity_dict,
237 'date': date,
238- 'person': activity_dict[0]['activity'][0].person
239+ 'person': activity_dict[0]['activity'][0].person,
240 })
241
242 activity_and_comments.sort(key=itemgetter('date'))
243@@ -1671,7 +1670,7 @@
244
245 new_product = data.get('product')
246 if (old_product is None or old_product == new_product or
247- not bugtask.pillar.official_malone):
248+ bugtask.pillar.bug_tracking_usage != ServiceUsage.LAUNCHPAD):
249 # Either the product wasn't changed, we're dealing with a #
250 # distro task, or the bugtask's product doesn't use Launchpad,
251 # which means the product can't be changed.
252@@ -1826,9 +1825,11 @@
253 # Launchpad status, but it's not trivial to do at the
254 # moment. I will fix this later.
255 bugtask.transitionToStatus(
256- BugTaskStatus.UNKNOWN, bug_importer)
257+ BugTaskStatus.UNKNOWN,
258+ bug_importer)
259 bugtask.transitionToImportance(
260- BugTaskImportance.UNKNOWN, bug_importer)
261+ BugTaskImportance.UNKNOWN,
262+ bug_importer)
263 bugtask.transitionToAssignee(None)
264
265 if changed:
266@@ -1997,7 +1998,7 @@
267 """
268 if not IProduct.providedBy(self.context):
269 return None
270- if self.context.official_malone:
271+ if self.context.bug_tracking_usage == ServiceUsage.LAUNCHPAD:
272 return None
273 return "%s?field.status_upstream=pending_bugwatch" % (
274 canonical_url(self.context, view_name='+bugs'))
275@@ -2084,7 +2085,7 @@
276 """
277 if not IProduct.providedBy(self.context):
278 return None
279- if self.context.official_malone:
280+ if self.context.bug_tracking_usage == ServiceUsage.LAUNCHPAD:
281 return None
282 params = get_default_search_params(self.user)
283 params.pending_bugwatch_elsewhere = True
284@@ -2362,9 +2363,12 @@
285 bugtask_listing_item.review_action_widget = CustomWidgetFactory(
286 NominationReviewActionWidget)
287 setUpWidget(
288- bugtask_listing_item, 'review_action',
289- review_action_field, IInputWidget,
290- value=NominatedBugReviewAction.NO_CHANGE, context=bug_nomination)
291+ bugtask_listing_item,
292+ 'review_action',
293+ review_action_field,
294+ IInputWidget,
295+ value=NominatedBugReviewAction.NO_CHANGE,
296+ context=bug_nomination)
297
298 return bugtask_listing_item
299
300@@ -2916,7 +2920,7 @@
301
302 if fieldname != "orderby":
303 sortlink += "%s&" % urllib.urlencode(
304- {fieldname : fieldvalue}, doseq=True)
305+ {fieldname: fieldvalue}, doseq=True)
306
307 sorted, ascending = self._getSortStatus(colname)
308 if sorted and ascending:
309@@ -3000,7 +3004,7 @@
310 """Is the context a Product that does not use Malone?"""
311 return (
312 IProduct.providedBy(self.context)
313- and not self.context.official_malone)
314+ and self.context.bug_tracking_usage != ServiceUsage.LAUNCHPAD)
315
316 def _upstreamContext(self):
317 """Is this page being viewed in an upstream context?
318@@ -3068,7 +3072,6 @@
319 return None
320
321
322-
323 class BugNominationsView(BugTaskSearchListingView):
324 """View for accepting/declining bug nominations."""
325
326@@ -3132,8 +3135,7 @@
327 declined += 1
328 else:
329 raise AssertionError(
330- 'Unknown NominatedBugReviewAction: %r' % (
331- review_action,))
332+ 'Unknown NominatedBugReviewAction: %r' % review_action)
333
334 if accepted > 0:
335 self.request.response.addInfoNotification(
336@@ -3200,7 +3202,7 @@
337 else:
338 raise AssertionError('Uknown context type: %s' % self.context)
339
340- return u"".join("%d\n" % bug_id for bug_id in
341+ return u"".join("%d\n" % bug_id for bug_id in
342 getUtility(IBugTaskSet).searchBugIds(search_params))
343
344
345@@ -3373,8 +3375,7 @@
346 self._getTableRowView(
347 nomination, is_converted_to_question, False)
348 for nomination in target_nominations
349- if nomination.status != BugNominationStatus.APPROVED
350- )
351+ if nomination.status != BugNominationStatus.APPROVED)
352
353 # Fill the ValidPersonOrTeamCache cache (using getValidPersons()),
354 # so that checking person.is_valid_person, when rendering the
355@@ -3852,6 +3853,7 @@
356
357 class BugTaskExpirableListingView(LaunchpadView):
358 """View for listing Incomplete bugs that can expire."""
359+
360 @property
361 def can_show_expirable_bugs(self):
362 """Return True or False if expirable bug listing can be shown."""
363
364=== modified file 'lib/lp/bugs/browser/distribution_upstream_bug_report.py'
365--- lib/lp/bugs/browser/distribution_upstream_bug_report.py 2010-08-20 20:31:18 +0000
366+++ lib/lp/bugs/browser/distribution_upstream_bug_report.py 2010-09-02 19:34:49 +0000
367@@ -6,8 +6,8 @@
368 __metaclass__ = type
369
370 __all__ = [
371- 'DistributionUpstreamBugReport'
372-]
373+ 'DistributionUpstreamBugReport',
374+ ]
375
376 from operator import attrgetter
377
378@@ -17,6 +17,7 @@
379 LaunchpadView,
380 )
381 from canonical.launchpad.webapp.url import urlappend
382+from lp.app.enums import ServiceUsage
383 from lp.bugs.browser.bugtask import get_buglisting_search_filter_url
384
385 # TODO: fix column sorting to work for the different colspans, or
386@@ -145,9 +146,11 @@
387 - dssp: an IDistributionSeriesSourcepackage
388 - product: an IProduct
389 - bugtracker: convenience holder for the product's bugtracker
390- - official_malone: convenience boolean for IProduct.official_malone
391+ - bug_tracking_usage: convenience enum for
392+ IProduct.bug_tracking_usage
393 - *_url: convenience URLs
394 """
395+
396 def __init__(self, dsp, dssp, product, open_bugs, triaged_bugs,
397 upstream_bugs, watched_bugs, bugs_with_upstream_patches):
398 BugReportData.__init__(self, open_bugs, triaged_bugs, upstream_bugs,
399@@ -162,9 +165,12 @@
400 self.open_bugs_url = urlappend(
401 dsp_bugs_url, get_buglisting_search_filter_url())
402
403- self.official_malone = bool(product and product.official_malone)
404- self.branch = (
405- product and product.development_focus.branch)
406+ if product is not None:
407+ self.bug_tracking_usage = product.bug_tracking_usage
408+ self.branch = product.development_focus.branch
409+ else:
410+ self.bug_tracking_usage = ServiceUsage.UNKNOWN
411+ self.branch = None
412
413 # If a product is specified, build some convenient links to
414 # pages which allow filling out required information. The
415@@ -180,7 +186,7 @@
416 # Create a 'bugtracker_name' attribute for searching.
417 if self.bugtracker is not None:
418 self.bugtracker_name = self.bugtracker.title
419- elif self.product.official_malone:
420+ elif self.product.bug_tracking_usage == ServiceUsage.LAUNCHPAD:
421 self.bugtracker_name = 'Launchpad'
422 else:
423 self.bugtracker_name = None
424@@ -374,4 +380,3 @@
425 dsp, dssp, product, open, triaged, upstream, watched,
426 bugs_with_upstream_patches)
427 self._data.append(item)
428-
429
430=== modified file 'lib/lp/bugs/browser/tests/bugtask-adding-views.txt'
431--- lib/lp/bugs/browser/tests/bugtask-adding-views.txt 2010-07-26 12:49:23 +0000
432+++ lib/lp/bugs/browser/tests/bugtask-adding-views.txt 2010-09-02 19:34:49 +0000
433@@ -224,8 +224,8 @@
434 offical bug tracker.
435
436 >>> evolution_task = bug_four.bugtasks[0]
437- >>> evolution_task.target.official_malone
438- True
439+ >>> evolution_task.target.bug_tracking_usage
440+ <DBItem ServiceUsage.LAUNCHPAD, (20) Launchpad>
441
442 >>> transaction.commit()
443
444@@ -275,8 +275,8 @@
445 are set to the default values.
446
447 >>> alsa_task = bug_four.bugtasks[0]
448- >>> alsa_task.target.official_malone
449- False
450+ >>> alsa_task.target.bug_tracking_usage
451+ <DBItem ServiceUsage.UNKNOWN, (10) Unknown>
452 >>> alsa_task.status.title
453 'New'
454 >>> alsa_task.importance.title
455@@ -368,8 +368,8 @@
456 >>> alsa_task = bug_four.bugtasks[0]
457 >>> alsa_task.bugtargetname
458 u'alsa-utils'
459- >>> alsa_task.product.official_malone
460- False
461+ >>> alsa_task.product.bug_tracking_usage
462+ <DBItem ServiceUsage.UNKNOWN, (10) Unknown>
463 >>> alsa_task.bugwatch == bug_four.watches[0]
464 True
465
466
467=== modified file 'lib/lp/bugs/browser/tests/test_bugtarget_configure.py'
468--- lib/lp/bugs/browser/tests/test_bugtarget_configure.py 2010-08-20 20:31:18 +0000
469+++ lib/lp/bugs/browser/tests/test_bugtarget_configure.py 2010-09-02 19:34:49 +0000
470@@ -6,6 +6,7 @@
471 __metaclass__ = type
472
473 from canonical.testing import DatabaseFunctionalLayer
474+from lp.app.enums import ServiceUsage
475 from lp.testing import (
476 login_person,
477 TestCaseWithFactory,
478@@ -59,7 +60,9 @@
479 self.assertEqual([], view.errors)
480 self.assertEqual(self.owner, self.product.bug_supervisor)
481 self.assertEqual(self.owner, self.product.security_contact)
482- self.assertTrue(self.product.official_malone)
483+ self.assertEqual(
484+ ServiceUsage.LAUNCHPAD,
485+ self.product.bug_tracking_usage)
486 self.assertTrue(self.product.enable_bug_expiration)
487 self.assertEqual('sf-boing', self.product.remote_product)
488 self.assertEqual('guidelines', self.product.bug_reporting_guidelines)
489
490=== modified file 'lib/lp/bugs/model/bug.py'
491--- lib/lp/bugs/model/bug.py 2010-08-31 23:22:19 +0000
492+++ lib/lp/bugs/model/bug.py 2010-09-02 19:34:49 +0000
493@@ -108,6 +108,7 @@
494 MAIN_STORE,
495 )
496 from lp.answers.interfaces.questiontarget import IQuestionTarget
497+from lp.app.enums import ServiceUsage
498 from lp.app.errors import (
499 NotFoundError,
500 UserCannotUnsubscribePerson,
501@@ -1198,7 +1199,7 @@
502 if len(non_invalid_bugtasks) != 1:
503 return None
504 [valid_bugtask] = non_invalid_bugtasks
505- if valid_bugtask.pillar.official_malone:
506+ if valid_bugtask.pillar.bug_tracking_usage == ServiceUsage.LAUNCHPAD:
507 return valid_bugtask
508 else:
509 return None
510
511=== modified file 'lib/lp/bugs/model/bugtask.py'
512--- lib/lp/bugs/model/bugtask.py 2010-08-30 19:30:45 +0000
513+++ lib/lp/bugs/model/bugtask.py 2010-09-02 19:34:49 +0000
514@@ -17,7 +17,8 @@
515 'bugtask_sort_key',
516 'get_bug_privacy_filter',
517 'get_related_bugtasks_search_params',
518- 'search_value_to_where_condition']
519+ 'search_value_to_where_condition',
520+ ]
521
522
523 import datetime
524@@ -92,6 +93,7 @@
525 IStoreSelector,
526 MAIN_STORE,
527 )
528+from lp.app.enums import ServiceUsage
529 from lp.app.errors import NotFoundError
530 from lp.bugs.interfaces.bug import IBugSet
531 from lp.bugs.interfaces.bugattachment import BugAttachmentType
532@@ -460,13 +462,14 @@
533 sourcepackagename=self.sourcepackagename,
534 distribution=self.distribution,
535 distroseries=self.distroseries)
536- utility_iface = {
537+ utility_iface_dict = {
538 'productID': IProductSet,
539 'productseriesID': IProductSeriesSet,
540 'sourcepackagenameID': ISourcePackageNameSet,
541 'distributionID': IDistributionSet,
542 'distroseriesID': IDistroSeriesSet,
543- }[attr]
544+ }
545+ utility_iface = utility_iface_dict[attr]
546 if value is None:
547 target_params[attr[:-2]] = None
548 else:
549@@ -655,7 +658,7 @@
550 # one thing they often have to filter for is completeness. We maintain
551 # this single canonical query string here so that it does not have to be
552 # cargo culted into Product, Distribution, ProductSeries etc
553- completeness_clause = """
554+ completeness_clause = """
555 BugTask.status IN ( %s )
556 """ % ','.join([str(a.value) for a in RESOLVED_BUGTASK_STATUSES])
557
558@@ -845,7 +848,7 @@
559 """See `IBugTask`"""
560 # XXX sinzui 2007-10-04 bug=149009:
561 # This property is not needed. Code should inline this implementation.
562- return self.pillar.official_malone
563+ return (self.pillar.bug_tracking_usage == ServiceUsage.LAUNCHPAD)
564
565 def transitionToMilestone(self, new_milestone, user):
566 """See `IBugTask`."""
567@@ -1178,7 +1181,7 @@
568 if IUpstreamBugTask.providedBy(self):
569 header_value = 'product=%s;' % self.target.name
570 elif IProductSeriesBugTask.providedBy(self):
571- header_value = 'product=%s; productseries=%s;' % (
572+ header_value = 'product=%s; productseries=%s;' % (
573 self.productseries.product.name, self.productseries.name)
574 elif IDistroBugTask.providedBy(self):
575 header_value = ((
576@@ -2219,7 +2222,7 @@
577 (BugTask, Product, SourcePackageName, Bug),
578 AutoTables(SQL("1=1"), tables),
579 query)
580- decorator=lambda row:bugtask_decorator(row[0])
581+ decorator=lambda row: bugtask_decorator(row[0])
582 resultset.order_by(orderby)
583 return DecoratedResultSet(resultset, result_decorator=decorator)
584
585
586=== modified file 'lib/lp/bugs/templates/bug-create-question.pt'
587--- lib/lp/bugs/templates/bug-create-question.pt 2009-08-31 09:58:28 +0000
588+++ lib/lp/bugs/templates/bug-create-question.pt 2010-09-02 19:34:49 +0000
589@@ -17,7 +17,7 @@
590 A question was already created from this bug.
591 </tal:question>
592 <tal:uses-malone
593- condition="not: context/pillar/official_malone">
594+ condition="not: context/pillar/bug_tracking_usage/enumvalue:LAUNCHPAD">
595 <tal:target
596 replace="context/target/displayname">Firefox</tal:target>
597 does not use Launchpad to track bugs.
598
599=== modified file 'lib/lp/bugs/templates/bugtarget-macros-filebug.pt'
600--- lib/lp/bugs/templates/bugtarget-macros-filebug.pt 2010-07-01 06:14:05 +0000
601+++ lib/lp/bugs/templates/bugtarget-macros-filebug.pt 2010-09-02 19:34:49 +0000
602@@ -298,7 +298,7 @@
603 </p>
604 </tal:singular>
605 <ul class="product-bug-options" tal:repeat="product context/products">
606- <li condition="product/official_malone">
607+ <li condition="product/bug_tracking_usage/enumvalue:LAUNCHPAD">
608 <tal:link replace="structure product/fmt:link" />
609 <ul class="bulleted">
610 <tal:external-tracker
611
612=== modified file 'lib/lp/bugs/templates/bugtask-requestfix-upstream.pt'
613--- lib/lp/bugs/templates/bugtask-requestfix-upstream.pt 2010-07-23 16:00:36 +0000
614+++ lib/lp/bugs/templates/bugtask-requestfix-upstream.pt 2010-09-02 19:34:49 +0000
615@@ -50,7 +50,7 @@
616 </div>
617 </div>
618
619- <div id="upstream-text" tal:condition="not: product/official_malone"
620+ <div id="upstream-text" tal:condition="not: product/bug_tracking_usage/enumvalue:LAUNCHPAD"
621 tal:define="widgets view/bugwatch_widgets;
622 bugtracker product/getExternalBugTracker">
623 <p tal:condition="bugtracker">
624@@ -156,14 +156,14 @@
625 </p>
626
627 <tal:no_bug_supervisor tal:condition="not:product/bug_supervisor">
628- <p tal:condition="product/official_malone">
629+ <p tal:condition="product/bug_tracking_usage/enumvalue:LAUNCHPAD">
630 <a tal:replace="structure product/owner/fmt:link">Sample Person</a>, the
631 <tal:product tal:replace="product/displayname">Firefox</tal:product>
632 registrant, will be notified about this bug.
633
634 </p>
635
636- <p tal:condition="not: product/official_malone">
637+ <p tal:condition="not: product/bug_tracking_usage/enumvalue:LAUNCHPAD">
638 There is no bug supervisor for
639 <tal:product tal:replace="product/displayname">Firefox</tal:product>.
640 This means that there is nobody upstream we can notify about
641
642=== modified file 'lib/lp/bugs/templates/distribution-upstream-bug-report.pt'
643--- lib/lp/bugs/templates/distribution-upstream-bug-report.pt 2010-02-16 17:59:59 +0000
644+++ lib/lp/bugs/templates/distribution-upstream-bug-report.pt 2010-09-02 19:34:49 +0000
645@@ -166,10 +166,12 @@
646 </td>
647 </tal:has-bugtracker>
648 <tal:has-no-bugtracker condition="not: item/bugtracker">
649- <td tal:condition="item/official_malone" align="center">
650+ <td tal:condition="item/bug_tracking_usage/enumvalue:LAUNCHPAD"
651+ align="center">
652 <img src="/@@/yes" title="Launchpad" />
653 </td>
654- <td tal:condition="not: item/official_malone" align="center">
655+ <td tal:condition="not: item/bug_tracking_usage/enumvalue:LAUNCHPAD"
656+ align="center">
657 <img src="/@@/no" title="Unknown" />
658 <a tal:condition="item/product/required:launchpad.Edit"
659 tal:attributes="href item/product_edit_url">
660@@ -225,11 +227,11 @@
661 tal:content="item/upstream_bugs_delta"></a>
662 </td>
663 <tal:upstream-in-launchpad
664- condition="item/official_malone">
665+ condition="item/bug_tracking_usage/enumvalue:LAUNCHPAD">
666 <td colspan="4" class="good">&nbsp;</td>
667 </tal:upstream-in-launchpad>
668 <tal:upstream-not-in-launchpad
669- condition="not: item/official_malone">
670+ condition="not: item/bug_tracking_usage/enumvalue:LAUNCHPAD">
671 <td tal:attributes="class string:amount ${item/watched_bugs_class}"
672 tal:content="item/watched_bugs" />
673 <td tal:attributes="class string:amount ${item/watched_bugs_class}"
674
675=== modified file 'lib/lp/bugs/tests/bugtarget-questiontarget.txt'
676--- lib/lp/bugs/tests/bugtarget-questiontarget.txt 2009-06-12 16:36:02 +0000
677+++ lib/lp/bugs/tests/bugtarget-questiontarget.txt 2010-09-02 19:34:49 +0000
678@@ -43,8 +43,8 @@
679 prerequisite for a bug to become a question is that the bugtarget's
680 pillar must use Launchpad to track bugs.
681
682- >>> bug.affected_pillars[0].official_malone
683- True
684+ >>> bug.affected_pillars[0].bug_tracking_usage
685+ <DBItem ServiceUsage.LAUNCHPAD, (20) Launchpad>
686 >>> bug.canBeAQuestion()
687 True
688
689@@ -56,8 +56,8 @@
690 >>> firefox = firefox_bug.bugtasks[0].target
691 >>> IQuestionTarget.providedBy(firefox)
692 True
693- >>> firefox.distribution.official_malone
694- False
695+ >>> firefox.distribution.bug_tracking_usage
696+ <DBItem ServiceUsage.UNKNOWN, (10) Unknown>
697 >>> firefox_bug.canBeAQuestion()
698 False
699
700
701=== modified file 'lib/lp/bugs/tests/test_bugs_webservice.py'
702--- lib/lp/bugs/tests/test_bugs_webservice.py 2010-08-30 05:19:46 +0000
703+++ lib/lp/bugs/tests/test_bugs_webservice.py 2010-09-02 19:34:49 +0000
704@@ -10,6 +10,7 @@
705 from BeautifulSoup import BeautifulSoup
706 from lazr.lifecycle.interfaces import IDoNotSnapshot
707 from simplejson import dumps
708+from storm.store import Store
709 from testtools.matchers import (
710 Equals,
711 LessThan,
712@@ -147,33 +148,40 @@
713 layer = LaunchpadFunctionalLayer
714
715 def test_attachments_query_counts_constant(self):
716+ # XXX j.c.sackett 2010-09-02 bug=619017
717+ # This test was being thrown off by the reference bug. To get around
718+ # the problem, flush and reset are called on the bug storm cache
719+ # before each call to the webservice. When lp's storm is updated
720+ # to release the committed fix for this bug, please see about
721+ # updating this test.
722 login(USER_EMAIL)
723 self.bug = self.factory.makeBug()
724- self.factory.makeBugAttachment(self.bug)
725- self.factory.makeBugAttachment(self.bug)
726+ store = Store.of(self.bug)
727+ self.factory.makeBugAttachment(self.bug)
728+ self.factory.makeBugAttachment(self.bug)
729+ person = self.factory.makePerson()
730 webservice = LaunchpadWebServiceCaller(
731 'launchpad-library', 'salgado-change-anything')
732 collector = QueryCollector()
733 collector.register()
734 self.addCleanup(collector.unregister)
735 url = '/bugs/%d/attachments' % self.bug.id
736+ #First request
737+ store.flush()
738+ store.reset()
739 response = webservice.get(url)
740 self.assertThat(collector, HasQueryCount(LessThan(24)))
741 with_2_count = collector.count
742 self.failUnlessEqual(response.status, 200)
743 login(USER_EMAIL)
744- self.factory.makeBugAttachment(self.bug)
745+ for i in range(5):
746+ self.factory.makeBugAttachment(self.bug)
747 logout()
748+ #Second request
749+ store.flush()
750+ store.reset()
751 response = webservice.get(url)
752- # XXX: Permit the second call to be == or less, because storm
753- # caching bugs (such as) https://bugs.launchpad.net/storm/+bug/619017
754- # which can cause spurious queries. There was an EC2 failure landing
755- # with this set to strictly equal which I could not reproduce locally,
756- # and the ec2 test did not report the storm egg used, so could not
757- # confidently rule out some form of skew.
758- self.assertThat(collector, HasQueryCount(MatchesAny(
759- Equals(with_2_count),
760- LessThan(with_2_count))))
761+ self.assertThat(collector, HasQueryCount(Equals(with_2_count+1)))
762
763
764 class TestBugMessages(TestCaseWithFactory):
765
766=== modified file 'lib/lp/bugs/tests/test_bugtask_1.py'
767--- lib/lp/bugs/tests/test_bugtask_1.py 2010-08-20 20:31:18 +0000
768+++ lib/lp/bugs/tests/test_bugtask_1.py 2010-09-02 19:34:49 +0000
769@@ -17,6 +17,7 @@
770 )
771 from canonical.launchpad.webapp.interfaces import ILaunchBag
772 from canonical.testing import DatabaseFunctionalLayer
773+from lp.app.enums import ServiceUsage
774 from lp.bugs.interfaces.bug import IBugSet
775 from lp.bugs.interfaces.bugtask import (
776 BugTaskStatus,
777@@ -73,7 +74,9 @@
778 # Mark an upstream task on bug #1 "Fix Released"
779 bug_one = bugset.get(1)
780 firefox_upstream = self._getBugTaskByTarget(bug_one, firefox)
781- self.assert_(firefox_upstream.product.official_malone)
782+ self.assertEqual(
783+ ServiceUsage.LAUNCHPAD,
784+ firefox_upstream.product.bug_tracking_usage)
785 self.old_firefox_status = firefox_upstream.status
786 firefox_upstream.transitionToStatus(
787 BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user)
788@@ -127,12 +130,10 @@
789 """
790 non_malone_using_bugtasks = [
791 related_task for related_task in bugtask.related_tasks
792- if not related_task.target_uses_malone
793- ]
794+ if not related_task.target_uses_malone]
795 pending_bugwatch_bugtasks = [
796 related_bugtask for related_bugtask in non_malone_using_bugtasks
797- if related_bugtask.bugwatch is None
798- ]
799+ if related_bugtask.bugwatch is None]
800 self.assert_(
801 len(pending_bugwatch_bugtasks) > 0,
802 'Bugtask %s on %s has no related bug watches elsewhere.' % (
803@@ -166,8 +167,7 @@
804 resolved_related_tasks = [
805 related_task for related_task in bugtask.related_tasks
806 if (_is_resolved_upstream_task(related_task) or
807- _is_resolved_bugwatch_task(related_task))
808- ]
809+ _is_resolved_bugwatch_task(related_task))]
810
811 self.assert_(len(resolved_related_tasks) > 0)
812 self.assert_(
813@@ -203,8 +203,7 @@
814 open_related_tasks = [
815 related_task for related_task in bugtask.related_tasks
816 if (_is_open_upstream_task(related_task) or
817- _is_open_bugwatch_task(related_task))
818- ]
819+ _is_open_bugwatch_task(related_task))]
820
821 self.assert_(
822 len(open_related_tasks) > 0,
823
824=== modified file 'lib/lp/registry/browser/sourcepackage.py'
825--- lib/lp/registry/browser/sourcepackage.py 2010-08-23 22:29:52 +0000
826+++ lib/lp/registry/browser/sourcepackage.py 2010-09-02 19:34:49 +0000
827@@ -73,6 +73,7 @@
828 from canonical.launchpad.webapp.publisher import LaunchpadView
829 from canonical.lazr.utils import smartquote
830 from canonical.widgets import LaunchpadRadioWidget
831+from lp.app.enums import ServiceUsage
832 from lp.answers.browser.questiontarget import (
833 QuestionTargetAnswersMenu,
834 QuestionTargetFacetMixin,
835@@ -283,8 +284,7 @@
836 self.product = getUtility(IProductSet)[product_name]
837 series_list = [
838 series for series in self.product.series
839- if series.status != SeriesStatus.OBSOLETE
840- ]
841+ if series.status != SeriesStatus.OBSOLETE]
842
843 # If the product is not being changed, then the current
844 # productseries can be the default choice. Otherwise,
845@@ -306,8 +306,7 @@
846 series_list.remove(dev_focus)
847 vocab_terms = [
848 SimpleTerm(series, series.name, series.name)
849- for series in series_list
850- ]
851+ for series in series_list]
852 dev_focus_term = SimpleTerm(
853 dev_focus, dev_focus.name, "%s (Recommended)" % dev_focus.name)
854 vocab_terms.insert(0, dev_focus_term)
855@@ -339,6 +338,7 @@
856 next_url = None
857
858 main_action_label = u'Change'
859+
860 def main_action(self, data):
861 productseries = data['productseries']
862 # Because it is part of a multistep view, the next_url can't
863@@ -575,7 +575,7 @@
864 if self.context.productseries is None:
865 return False
866 product = self.context.productseries.product
867- if product.official_malone:
868+ if product.bug_tracking_usage == ServiceUsage.LAUNCHPAD:
869 return True
870 bugtracker = product.bugtracker
871 if bugtracker is None:
872
873=== modified file 'lib/lp/registry/browser/tests/distribution-views.txt'
874--- lib/lp/registry/browser/tests/distribution-views.txt 2010-06-16 08:22:00 +0000
875+++ lib/lp/registry/browser/tests/distribution-views.txt 2010-09-02 19:34:49 +0000
876@@ -106,8 +106,8 @@
877
878 The view accepts most of the distribution fields.
879
880- >>> distribution.official_malone
881- False
882+ >>> distribution.bug_tracking_usage
883+ <DBItem ServiceUsage.UNKNOWN, (10) Unknown>
884
885 >>> view.field_names
886 ['displayname', 'title', 'summary', 'description',
887@@ -130,8 +130,8 @@
888 >>> print distribution.bug_reporting_guidelines
889 guidelines
890
891- >>> distribution.official_malone
892- True
893+ >>> distribution.bug_tracking_usage
894+ <DBItem ServiceUsage.LAUNCHPAD, (20) Launchpad>
895
896 Only admins and owners can access the view.
897
898
899=== modified file 'lib/lp/registry/browser/tests/sourcepackage-views.txt'
900--- lib/lp/registry/browser/tests/sourcepackage-views.txt 2010-08-04 05:27:22 +0000
901+++ lib/lp/registry/browser/tests/sourcepackage-views.txt 2010-09-02 19:34:49 +0000
902@@ -293,8 +293,8 @@
903 >>> view = create_initialized_view(
904 ... package, name='+upstream-connections')
905
906- >>> print product.official_malone
907- False
908+ >>> print product.bug_tracking_usage.name
909+ UNKNOWN
910 >>> print product.bugtracker
911 None
912 >>> print view.has_bugtracker
913
914=== modified file 'lib/lp/registry/doc/product.txt'
915--- lib/lp/registry/doc/product.txt 2010-08-22 19:46:19 +0000
916+++ lib/lp/registry/doc/product.txt 2010-09-02 19:34:49 +0000
917@@ -258,8 +258,8 @@
918 one.
919
920 >>> firefox = getUtility(IProductSet).getByName('firefox')
921- >>> firefox.official_malone
922- True
923+ >>> firefox.bug_tracking_usage
924+ <DBItem ServiceUsage.LAUNCHPAD, (20) Launchpad>
925 >>> print firefox.bug_tracking_usage.name
926 LAUNCHPAD
927 >>> firefox.getExternalBugTracker() is None
928
929=== modified file 'lib/lp/registry/templates/distribution-index.pt'
930--- lib/lp/registry/templates/distribution-index.pt 2010-08-06 16:01:38 +0000
931+++ lib/lp/registry/templates/distribution-index.pt 2010-09-02 19:34:49 +0000
932@@ -55,7 +55,7 @@
933 tal:condition="context/official_answers" />
934
935 <div tal:replace="structure context/@@+portlet-latestbugs"
936- tal:condition="context/official_malone" />
937+ tal:condition="context/bug_tracking_usage/enumvalue:LAUNCHPAD" />
938
939 <div tal:replace="structure context/@@+portlet-top-contributors" />
940 </div>
941
942=== modified file 'lib/lp/registry/templates/distribution-search.pt'
943--- lib/lp/registry/templates/distribution-search.pt 2009-08-05 19:34:07 +0000
944+++ lib/lp/registry/templates/distribution-search.pt 2010-09-02 19:34:49 +0000
945@@ -69,7 +69,7 @@
946 tal:define="distribution package/distribution">
947 <a
948 tal:define="link package/menu:bugs/filebug"
949- tal:condition="distribution/official_malone"
950+ tal:condition="distribution/bug_tracking_usage/enumvalue:LAUNCHPAD"
951 tal:attributes="href link/url">
952 <img
953 tal:attributes="alt link/text"
954
955=== modified file 'lib/lp/registry/templates/product-index.pt'
956--- lib/lp/registry/templates/product-index.pt 2010-08-25 19:15:48 +0000
957+++ lib/lp/registry/templates/product-index.pt 2010-09-02 19:34:49 +0000
958@@ -218,7 +218,7 @@
959 tal:condition="context/official_answers" />
960
961 <div tal:content="structure context/@@+portlet-latestbugs"
962- tal:condition="context/official_malone" />
963+ tal:condition="context/bug_tracking_usage/enumvalue:LAUNCHPAD" />
964
965 <div tal:content="structure context/@@+portlet-top-contributors" />
966
967
968=== modified file 'lib/lp/testing/factory.py'
969--- lib/lp/testing/factory.py 2010-08-30 06:38:53 +0000
970+++ lib/lp/testing/factory.py 2010-09-02 19:34:49 +0000
971@@ -836,7 +836,7 @@
972 project=project,
973 registrant=registrant)
974 if official_malone is not None:
975- product.official_malone = official_malone
976+ removeSecurityProxy(product).official_malone = official_malone
977 if official_rosetta is not None:
978 removeSecurityProxy(product).official_rosetta = official_rosetta
979 if bug_supervisor is not None: