Merge lp:~deryck/launchpad/has-bug-heat-interface-529846 into lp:launchpad

Proposed by Deryck Hodge
Status: Merged
Approved by: Guilherme Salgado
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~deryck/launchpad/has-bug-heat-interface-529846
Merge into: lp:launchpad
Diff against target: 530 lines (+124/-97)
11 files modified
lib/lp/bugs/interfaces/bugtarget.py (+15/-10)
lib/lp/bugs/model/bugtarget.py (+51/-46)
lib/lp/registry/configure.zcml (+15/-3)
lib/lp/registry/model/distribution.py (+7/-4)
lib/lp/registry/model/distributionsourcepackage.py (+6/-3)
lib/lp/registry/model/distroseries.py (+7/-5)
lib/lp/registry/model/person.py (+0/-10)
lib/lp/registry/model/product.py (+7/-4)
lib/lp/registry/model/productseries.py (+6/-5)
lib/lp/registry/model/project.py (+4/-3)
lib/lp/registry/model/sourcepackage.py (+6/-4)
To merge this branch: bzr merge lp:~deryck/launchpad/has-bug-heat-interface-529846
Reviewer Review Type Date Requested Status
Guilherme Salgado (community) Approve
Review via email: mp+21731@code.launchpad.net

Commit message

Imlement IHasBugHeat interface for targets which can have bug heat.

Description of the change

This branch fixes bug 529846. It creates an IHasBugHeat interface and
makes use of this for bug targets that should have bug heat. It is not
used for IPerson, for example.

There is no functionality changed here; this just cleans up the code a bit.

To test:

./bin/test -cvvt test_bugheat

= Launchpad lint =

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/lp/registry/model/distributionsourcepackage.py
  lib/lp/registry/model/project.py
  lib/lp/registry/model/productseries.py
  lib/lp/registry/configure.zcml
  lib/lp/bugs/model/bugtarget.py
  lib/lp/bugs/interfaces/bugtarget.py
  lib/lp/registry/model/sourcepackage.py
  lib/lp/registry/model/product.py
  lib/lp/registry/model/person.py
  lib/lp/registry/model/distroseries.py
  lib/lp/registry/model/distribution.py

To post a comment you must log in.
Revision history for this message
Guilherme Salgado (salgado) wrote :

Looks good to me; just one minor nitpick below

 review approve
 status approved

On Fri, 2010-03-19 at 15:41 +0000, Deryck Hodge wrote:
> === modified file 'lib/lp/bugs/model/bugtarget.py'
> --- lib/lp/bugs/model/bugtarget.py 2010-03-09 15:13:40 +0000
> +++ lib/lp/bugs/model/bugtarget.py 2010-03-19 15:41:50 +0000
> @@ -9,6 +9,7 @@
> __all__ = [
> 'BugTargetBase',
> 'HasBugsBase',
> + 'HasBugHeatMixin',
> 'OfficialBugTag',
> 'OfficialBugTagTargetMixin',
> ]
> @@ -162,8 +163,57 @@
>
> return self.searchTasks(all_tasks_query)
>
> + @property
> + def has_bugtasks(self):
> + """See `IHasBugs`."""
> + # Check efficiently if any bugtasks exist. We should avoid
> + # expensive calls like all_bugtasks.count(). all_bugtasks
> + # returns a storm.SQLObjectResultSet instance, and this
> + # class does not provide methods like is_empty(). But we can
> + # indirectly call SQLObjectResultSet._result_set.is_empty()
> + # by converting all_bugtasks into a boolean object.
> + return bool(self.all_bugtasks)
> +
> + def getBugCounts(self, user, statuses=None):
> + """See `IHasBugs`."""
> + if statuses is None:
> + statuses = BugTaskStatus.items
> + statuses = list(statuses)
> +
> + count_column = """
> + COUNT (CASE WHEN BugTask.status = %s
> + THEN BugTask.id ELSE NULL END)"""
> + select_columns = [count_column % sqlvalues(status)
> + for status in statuses]
> + conditions = [
> + '(%s)' % self._getBugTaskContextClause(),
> + 'BugTask.bug = Bug.id',
> + 'Bug.duplicateof is NULL']
> + privacy_filter = get_bug_privacy_filter(user)
> + if privacy_filter:
> + conditions.append(privacy_filter)
> +
> + cur = cursor()
> + cur.execute(
> + "SELECT %s FROM BugTask, Bug WHERE %s" % (
> + ', '.join(select_columns), ' AND '.join(conditions)))
> + counts = cur.fetchone()
> + return dict(zip(statuses, counts))
> +
> +
> +

One blank line too much here.

> +class BugTargetBase(HasBugsBase):
> + """Standard functionality for IBugTargets.
> +
> + All IBugTargets should inherit from this class.
> + """
> +
> +

--
Guilherme Salgado <email address hidden>

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/interfaces/bugtarget.py'
2--- lib/lp/bugs/interfaces/bugtarget.py 2010-03-10 14:14:38 +0000
3+++ lib/lp/bugs/interfaces/bugtarget.py 2010-03-24 13:00:54 +0000
4@@ -12,6 +12,7 @@
5 'BugDistroSeriesTargetDetails',
6 'IBugTarget',
7 'IHasBugs',
8+ 'IHasBugHeat',
9 'IHasOfficialBugTags',
10 'IOfficialBugTag',
11 'IOfficialBugTagTarget',
12@@ -56,10 +57,8 @@
13 "A list of unassigned BugTasks for this target.")
14 all_bugtasks = Attribute(
15 "A list of all BugTasks ever reported for this target.")
16- max_bug_heat = Attribute(
17- "The current highest bug heat value for this target.")
18 has_bugtasks = Attribute(
19- "True if at least one BugTask has ever been reported for this target.")
20+ "True if a BugTask has ever been reported for this target.")
21
22 @call_with(search_params=None, user=REQUEST_USER)
23 @operation_parameters(
24@@ -211,13 +210,6 @@
25 None, all statuses will be included.
26 """
27
28- def setMaxBugHeat(heat):
29- """Set the max_bug_heat for this context."""
30-
31- def recalculateMaxBugHeat():
32- """Recalculate and set the max_bug_heat for this context."""
33-
34-
35
36 class IBugTarget(IHasBugs):
37 """An entity on which a bug can be reported.
38@@ -257,6 +249,19 @@
39 LAZR_WEBSERVICE_EXPORTED)['params']['target'].schema = IBugTarget
40
41
42+class IHasBugHeat(Interface):
43+ """An entity which has bug heat."""
44+
45+ max_bug_heat = Attribute(
46+ "The current highest bug heat value for this entity.")
47+
48+ def setMaxBugHeat(heat):
49+ """Set the max_bug_heat for this context."""
50+
51+ def recalculateMaxBugHeat():
52+ """Recalculate and set the max_bug_heat for this context."""
53+
54+
55 class BugDistroSeriesTargetDetails:
56 """The details of a bug targeted to a specific IDistroSeries.
57
58
59=== modified file 'lib/lp/bugs/model/bugtarget.py'
60--- lib/lp/bugs/model/bugtarget.py 2010-03-09 15:13:40 +0000
61+++ lib/lp/bugs/model/bugtarget.py 2010-03-24 13:00:54 +0000
62@@ -9,6 +9,7 @@
63 __all__ = [
64 'BugTargetBase',
65 'HasBugsBase',
66+ 'HasBugHeatMixin',
67 'OfficialBugTag',
68 'OfficialBugTagTargetMixin',
69 ]
70@@ -162,8 +163,56 @@
71
72 return self.searchTasks(all_tasks_query)
73
74+ @property
75+ def has_bugtasks(self):
76+ """See `IHasBugs`."""
77+ # Check efficiently if any bugtasks exist. We should avoid
78+ # expensive calls like all_bugtasks.count(). all_bugtasks
79+ # returns a storm.SQLObjectResultSet instance, and this
80+ # class does not provide methods like is_empty(). But we can
81+ # indirectly call SQLObjectResultSet._result_set.is_empty()
82+ # by converting all_bugtasks into a boolean object.
83+ return bool(self.all_bugtasks)
84+
85+ def getBugCounts(self, user, statuses=None):
86+ """See `IHasBugs`."""
87+ if statuses is None:
88+ statuses = BugTaskStatus.items
89+ statuses = list(statuses)
90+
91+ count_column = """
92+ COUNT (CASE WHEN BugTask.status = %s
93+ THEN BugTask.id ELSE NULL END)"""
94+ select_columns = [count_column % sqlvalues(status)
95+ for status in statuses]
96+ conditions = [
97+ '(%s)' % self._getBugTaskContextClause(),
98+ 'BugTask.bug = Bug.id',
99+ 'Bug.duplicateof is NULL']
100+ privacy_filter = get_bug_privacy_filter(user)
101+ if privacy_filter:
102+ conditions.append(privacy_filter)
103+
104+ cur = cursor()
105+ cur.execute(
106+ "SELECT %s FROM BugTask, Bug WHERE %s" % (
107+ ', '.join(select_columns), ' AND '.join(conditions)))
108+ counts = cur.fetchone()
109+ return dict(zip(statuses, counts))
110+
111+
112+class BugTargetBase(HasBugsBase):
113+ """Standard functionality for IBugTargets.
114+
115+ All IBugTargets should inherit from this class.
116+ """
117+
118+
119+class HasBugHeatMixin:
120+ """Standard functionality for objects implementing IHasBugHeat."""
121+
122 def setMaxBugHeat(self, heat):
123- """See `IHasBugs`."""
124+ """See `IHasBugHeat`."""
125 if (IDistribution.providedBy(self)
126 or IProduct.providedBy(self)
127 or IProjectGroup.providedBy(self)
128@@ -174,7 +223,7 @@
129 raise NotImplementedError
130
131 def recalculateMaxBugHeat(self):
132- """See `IHasBugs`."""
133+ """See `IHasBugHeat`."""
134 if IProductSeries.providedBy(self):
135 return self.product.recalculateMaxBugHeat()
136 if IDistroSeries.providedBy(self):
137@@ -239,50 +288,6 @@
138 if IProduct.providedBy(self) and self.project is not None:
139 self.project.recalculateMaxBugHeat()
140
141- @property
142- def has_bugtasks(self):
143- """See `IHasBugs`."""
144- # Check efficiently if any bugtasks exist. We should avoid
145- # expensive calls like all_bugtasks.count(). all_bugtasks
146- # returns a storm.SQLObjectResultSet instance, and this
147- # class does not provide methods like is_empty(). But we can
148- # indirectly call SQLObjectResultSet._result_set.is_empty()
149- # by converting all_bugtasks into a boolean object.
150- return bool(self.all_bugtasks)
151-
152- def getBugCounts(self, user, statuses=None):
153- """See `IHasBugs`."""
154- if statuses is None:
155- statuses = BugTaskStatus.items
156- statuses = list(statuses)
157-
158- count_column = """
159- COUNT (CASE WHEN BugTask.status = %s
160- THEN BugTask.id ELSE NULL END)"""
161- select_columns = [count_column % sqlvalues(status)
162- for status in statuses]
163- conditions = [
164- '(%s)' % self._getBugTaskContextClause(),
165- 'BugTask.bug = Bug.id',
166- 'Bug.duplicateof is NULL']
167- privacy_filter = get_bug_privacy_filter(user)
168- if privacy_filter:
169- conditions.append(privacy_filter)
170-
171- cur = cursor()
172- cur.execute(
173- "SELECT %s FROM BugTask, Bug WHERE %s" % (
174- ', '.join(select_columns), ' AND '.join(conditions)))
175- counts = cur.fetchone()
176- return dict(zip(statuses, counts))
177-
178-
179-
180-class BugTargetBase(HasBugsBase):
181- """Standard functionality for IBugTargets.
182-
183- All IBugTargets should inherit from this class.
184- """
185
186
187 class OfficialBugTagTargetMixin:
188
189=== modified file 'lib/lp/registry/configure.zcml'
190--- lib/lp/registry/configure.zcml 2010-03-08 09:38:21 +0000
191+++ lib/lp/registry/configure.zcml 2010-03-24 13:00:54 +0000
192@@ -107,6 +107,8 @@
193 <allow
194 interface="lp.registry.interfaces.distroseries.IDistroSeriesPublic"/>
195 <allow
196+ interface="lp.bugs.interfaces.bugtarget.IHasBugHeat"/>
197+ <allow
198 interface="canonical.launchpad.interfaces.IHasQueueItems"/>
199 <allow
200 interface="lp.translations.interfaces.translationimportqueue.IHasTranslationImports"/>
201@@ -270,6 +272,8 @@
202 <allow
203 interface="lp.registry.interfaces.projectgroup.IProjectGroupPublic"/>
204 <allow
205+ interface="lp.bugs.interfaces.bugtarget.IHasBugHeat"/>
206+ <allow
207 interface="canonical.launchpad.interfaces.IFAQCollection"/>
208 <allow
209 interface="canonical.launchpad.interfaces.IQuestionCollection"/>
210@@ -358,6 +362,8 @@
211 <class
212 class="lp.registry.model.distributionsourcepackage.DistributionSourcePackage">
213 <allow
214+ interface="lp.bugs.interfaces.bugtarget.IHasBugHeat"/>
215+ <allow
216 interface="lp.translations.interfaces.customlanguagecode.IHasCustomLanguageCodes"/>
217
218 <allow
219@@ -408,9 +414,7 @@
220 official_bug_tags
221 findRelatedArchives
222 findRelatedArchivePublications
223- userHasBugSubscriptions
224- max_bug_heat
225- recalculateMaxBugHeat"/>
226+ userHasBugSubscriptions"/>
227 <require
228 permission="launchpad.AnyPerson"
229 attributes="
230@@ -1067,6 +1071,8 @@
231 <allow
232 interface="lp.registry.interfaces.product.IProductPublic"/>
233 <allow
234+ interface="lp.bugs.interfaces.bugtarget.IHasBugHeat"/>
235+ <allow
236 interface="lp.translations.interfaces.translationimportqueue.IHasTranslationImports"/>
237 <allow
238 interface="lp.translations.interfaces.customlanguagecode.IHasCustomLanguageCodes"/>
239@@ -1312,6 +1318,8 @@
240 permission="launchpad.Edit"
241 interface="lp.registry.interfaces.productseries.IProductSeriesEditRestricted"/>
242 <allow
243+ interface="lp.bugs.interfaces.bugtarget.IHasBugHeat"/>
244+ <allow
245 interface="lp.translations.interfaces.translationimportqueue.IHasTranslationImports"/>
246 <allow
247 interface="lp.translations.interfaces.potemplate.IHasTranslationTemplates"/>
248@@ -1380,6 +1388,8 @@
249 <allow
250 interface="lp.registry.interfaces.distribution.IDistributionPublic"/>
251 <allow
252+ interface="lp.bugs.interfaces.bugtarget.IHasBugHeat"/>
253+ <allow
254 interface="lp.translations.interfaces.translationimportqueue.IHasTranslationImports"/>
255 <require
256 permission="launchpad.Edit"
257@@ -1510,6 +1520,8 @@
258 <allow
259 interface="lp.registry.interfaces.sourcepackage.ISourcePackage"/>
260 <allow
261+ interface="lp.bugs.interfaces.bugtarget.IHasBugHeat"/>
262+ <allow
263 interface="canonical.launchpad.interfaces.IHasBuildRecords"/>
264 <allow
265 interface="lp.translations.interfaces.translationimportqueue.IHasTranslationImports"/>
266
267=== modified file 'lib/lp/registry/model/distribution.py'
268--- lib/lp/registry/model/distribution.py 2010-03-23 15:14:41 +0000
269+++ lib/lp/registry/model/distribution.py 2010-03-24 13:00:54 +0000
270@@ -37,7 +37,7 @@
271 from lp.bugs.model.bug import (
272 BugSet, get_bug_tags, get_bug_tags_open_count)
273 from lp.bugs.model.bugtarget import (
274- BugTargetBase, OfficialBugTagTargetMixin)
275+ BugTargetBase, HasBugHeatMixin, OfficialBugTagTargetMixin)
276 from lp.bugs.model.bugtask import BugTask
277 from lp.soyuz.model.build import Build
278 from lp.registry.model.distributionmirror import DistributionMirror
279@@ -78,6 +78,7 @@
280 from lp.soyuz.interfaces.archivepermission import (
281 IArchivePermissionSet)
282 from lp.bugs.interfaces.bugsupervisor import IHasBugSupervisor
283+from lp.bugs.interfaces.bugtarget import IHasBugHeat
284 from lp.bugs.interfaces.bugtask import (
285 BugTaskStatus, UNRESOLVED_BUGTASK_STATUSES)
286 from lp.soyuz.interfaces.build import IBuildSet
287@@ -121,11 +122,13 @@
288 HasSpecificationsMixin, HasSprintsMixin, HasAliasMixin,
289 HasTranslationImportsMixin, KarmaContextMixin,
290 OfficialBugTagTargetMixin, QuestionTargetMixin,
291- StructuralSubscriptionTargetMixin, HasMilestonesMixin):
292+ StructuralSubscriptionTargetMixin, HasMilestonesMixin,
293+ HasBugHeatMixin):
294 """A distribution of an operating system, e.g. Debian GNU/Linux."""
295 implements(
296- IDistribution, IFAQTarget, IHasBugSupervisor, IHasBuildRecords,
297- IHasIcon, IHasLogo, IHasMugshot, ILaunchpadUsage, IQuestionTarget)
298+ IDistribution, IFAQTarget, IHasBugHeat, IHasBugSupervisor,
299+ IHasBuildRecords, IHasIcon, IHasLogo, IHasMugshot, ILaunchpadUsage,
300+ IQuestionTarget)
301
302 _table = 'Distribution'
303 _defaultOrder = 'name'
304
305=== modified file 'lib/lp/registry/model/distributionsourcepackage.py'
306--- lib/lp/registry/model/distributionsourcepackage.py 2010-03-09 16:26:04 +0000
307+++ lib/lp/registry/model/distributionsourcepackage.py 2010-03-24 13:00:54 +0000
308@@ -29,8 +29,9 @@
309 from canonical.launchpad.interfaces.lpstorm import IStore
310 from canonical.lazr.utils import smartquote
311 from lp.answers.interfaces.questiontarget import IQuestionTarget
312+from lp.bugs.interfaces.bugtarget import IHasBugHeat
313 from lp.bugs.model.bug import BugSet, get_bug_tags_open_count
314-from lp.bugs.model.bugtarget import BugTargetBase
315+from lp.bugs.model.bugtarget import BugTargetBase, HasBugHeatMixin
316 from lp.bugs.model.bugtask import BugTask
317 from lp.code.model.hasbranches import HasBranchesMixin, HasMergeProposalsMixin
318 from lp.registry.interfaces.distributionsourcepackage import (
319@@ -58,7 +59,8 @@
320 StructuralSubscriptionTargetMixin,
321 HasBranchesMixin,
322 HasCustomLanguageCodesMixin,
323- HasMergeProposalsMixin):
324+ HasMergeProposalsMixin,
325+ HasBugHeatMixin):
326 """This is a "Magic Distribution Source Package". It is not an
327 SQLObject, but instead it represents a source package with a particular
328 name in a particular distribution. You can then ask it all sorts of
329@@ -67,7 +69,8 @@
330 """
331
332 implements(
333- IDistributionSourcePackage, IHasCustomLanguageCodes, IQuestionTarget)
334+ IDistributionSourcePackage, IHasBugHeat, IHasCustomLanguageCodes,
335+ IQuestionTarget)
336
337 def __init__(self, distribution, sourcepackagename):
338 self.distribution = distribution
339
340=== modified file 'lib/lp/registry/model/distroseries.py'
341--- lib/lp/registry/model/distroseries.py 2010-03-17 04:05:42 +0000
342+++ lib/lp/registry/model/distroseries.py 2010-03-24 13:00:54 +0000
343@@ -45,8 +45,9 @@
344 BinaryPackageRelease)
345 from lp.bugs.model.bug import (
346 get_bug_tags, get_bug_tags_open_count)
347-from lp.bugs.model.bugtarget import BugTargetBase
348+from lp.bugs.model.bugtarget import BugTargetBase, HasBugHeatMixin
349 from lp.bugs.model.bugtask import BugTask
350+from lp.bugs.interfaces.bugtarget import IHasBugHeat
351 from lp.bugs.interfaces.bugtask import UNRESOLVED_BUGTASK_STATUSES
352 from lp.soyuz.model.component import Component
353 from lp.soyuz.model.distroarchseries import (
354@@ -126,11 +127,11 @@
355 class DistroSeries(SQLBase, BugTargetBase, HasSpecificationsMixin,
356 HasTranslationImportsMixin, HasTranslationTemplatesMixin,
357 HasMilestonesMixin, SeriesMixin,
358- StructuralSubscriptionTargetMixin):
359+ StructuralSubscriptionTargetMixin, HasBugHeatMixin):
360 """A particular series of a distribution."""
361 implements(
362- ICanPublishPackages, IDistroSeries, IHasBuildRecords, IHasQueueItems,
363- IHasTranslationTemplates)
364+ ICanPublishPackages, IDistroSeries, IHasBugHeat, IHasBuildRecords,
365+ IHasQueueItems, IHasTranslationTemplates)
366
367 _table = 'DistroSeries'
368 _defaultOrder = ['distribution', 'version']
369@@ -1943,7 +1944,8 @@
370 result_set = store.using((DistroSeries, POTemplate)).find(
371 DistroSeries,
372 DistroSeries.hide_all_translations == False,
373- DistroSeries.id == POTemplate.distroseriesID).config(distinct=True)
374+ DistroSeries.id == POTemplate.distroseriesID).config(
375+ distinct=True)
376 # XXX: henninge 2009-02-11 bug=217644: Convert to sequence right here
377 # because ResultSet reports a wrong count() when using DISTINCT. Also
378 # ResultSet does not implement __len__(), which would make it more
379
380=== modified file 'lib/lp/registry/model/person.py'
381--- lib/lp/registry/model/person.py 2010-03-11 20:59:17 +0000
382+++ lib/lp/registry/model/person.py 2010-03-24 13:00:54 +0000
383@@ -837,16 +837,6 @@
384 """No-op, to satisfy a requirement of HasBugsBase."""
385 pass
386
387- @property
388- def max_bug_heat(self):
389- """Return None as this attribute is not implemented for a person.
390-
391- XXX deryck 2010-02-28 bug=529846
392- This requires a DB patch to be done correctly, and we're
393- near release and tests are failing.
394- """
395- return None
396-
397 def searchTasks(self, search_params, *args, **kwargs):
398 """See `IHasBugs`."""
399 if search_params is None and len(args) == 0:
400
401=== modified file 'lib/lp/registry/model/product.py'
402--- lib/lp/registry/model/product.py 2010-02-24 15:28:07 +0000
403+++ lib/lp/registry/model/product.py 2010-03-24 13:00:54 +0000
404@@ -34,10 +34,11 @@
405 from lp.code.model.branchvisibilitypolicy import (
406 BranchVisibilityPolicyMixin)
407 from lp.code.model.hasbranches import HasBranchesMixin, HasMergeProposalsMixin
408+from lp.bugs.interfaces.bugtarget import IHasBugHeat
409 from lp.bugs.model.bug import (
410 BugSet, get_bug_tags, get_bug_tags_open_count)
411 from lp.bugs.model.bugtarget import (
412- BugTargetBase, OfficialBugTagTargetMixin)
413+ BugTargetBase, HasBugHeatMixin, OfficialBugTagTargetMixin)
414 from lp.bugs.model.bugtask import BugTask
415 from lp.bugs.model.bugtracker import BugTracker
416 from lp.bugs.model.bugwatch import BugWatch
417@@ -169,13 +170,15 @@
418 QuestionTargetMixin, HasTranslationImportsMixin,
419 HasAliasMixin, StructuralSubscriptionTargetMixin,
420 HasMilestonesMixin, OfficialBugTagTargetMixin, HasBranchesMixin,
421- HasCustomLanguageCodesMixin, HasMergeProposalsMixin):
422+ HasCustomLanguageCodesMixin, HasMergeProposalsMixin,
423+ HasBugHeatMixin):
424
425 """A Product."""
426
427 implements(
428- IFAQTarget, IHasBugSupervisor, IHasCustomLanguageCodes, IHasIcon,
429- IHasLogo, IHasMugshot, ILaunchpadUsage, IProduct, IQuestionTarget)
430+ IFAQTarget, IHasBugHeat, IHasBugSupervisor, IHasCustomLanguageCodes,
431+ IHasIcon, IHasLogo, IHasMugshot, ILaunchpadUsage, IProduct,
432+ IQuestionTarget)
433
434 _table = 'Product'
435
436
437=== modified file 'lib/lp/registry/model/productseries.py'
438--- lib/lp/registry/model/productseries.py 2010-03-23 00:39:45 +0000
439+++ lib/lp/registry/model/productseries.py 2010-03-24 13:00:54 +0000
440@@ -26,7 +26,8 @@
441 from canonical.database.enumcol import EnumCol
442 from canonical.database.sqlbase import (
443 SQLBase, quote, sqlvalues)
444-from lp.bugs.model.bugtarget import BugTargetBase
445+from lp.bugs.interfaces.bugtarget import IHasBugHeat
446+from lp.bugs.model.bugtarget import BugTargetBase, HasBugHeatMixin
447 from lp.bugs.model.bug import (
448 get_bug_tags, get_bug_tags_open_count)
449 from lp.bugs.model.bugtask import BugTask
450@@ -78,12 +79,12 @@
451 return date + landmark['name']
452
453
454-class ProductSeries(SQLBase, BugTargetBase, HasMilestonesMixin,
455- HasSpecificationsMixin, HasTranslationImportsMixin,
456- HasTranslationTemplatesMixin,
457+class ProductSeries(SQLBase, BugTargetBase, HasBugHeatMixin,
458+ HasMilestonesMixin, HasSpecificationsMixin,
459+ HasTranslationImportsMixin, HasTranslationTemplatesMixin,
460 StructuralSubscriptionTargetMixin, SeriesMixin):
461 """A series of product releases."""
462- implements(IProductSeries, IHasTranslationTemplates)
463+ implements(IHasBugHeat, IProductSeries, IHasTranslationTemplates)
464
465 _table = 'ProductSeries'
466
467
468=== modified file 'lib/lp/registry/model/project.py'
469--- lib/lp/registry/model/project.py 2010-02-24 15:28:07 +0000
470+++ lib/lp/registry/model/project.py 2010-03-24 13:00:54 +0000
471@@ -44,9 +44,10 @@
472 from lp.code.model.branchvisibilitypolicy import (
473 BranchVisibilityPolicyMixin)
474 from lp.code.model.hasbranches import HasBranchesMixin, HasMergeProposalsMixin
475+from lp.bugs.interfaces.bugtarget import IHasBugHeat
476 from lp.bugs.model.bug import (
477 get_bug_tags, get_bug_tags_open_count)
478-from lp.bugs.model.bugtarget import BugTargetBase
479+from lp.bugs.model.bugtarget import BugTargetBase, HasBugHeatMixin
480 from lp.bugs.model.bugtask import BugTask
481 from lp.answers.model.faq import FAQ, FAQSearch
482 from lp.registry.model.karma import KarmaContextMixin
483@@ -72,10 +73,10 @@
484 MakesAnnouncements, HasSprintsMixin, HasAliasMixin,
485 KarmaContextMixin, BranchVisibilityPolicyMixin,
486 StructuralSubscriptionTargetMixin,
487- HasBranchesMixin, HasMergeProposalsMixin):
488+ HasBranchesMixin, HasMergeProposalsMixin, HasBugHeatMixin):
489 """A Project"""
490
491- implements(IProjectGroup, IFAQCollection, IHasIcon, IHasLogo,
492+ implements(IProjectGroup, IFAQCollection, IHasBugHeat, IHasIcon, IHasLogo,
493 IHasMugshot, ISearchableByQuestionOwner)
494
495 _table = "Project"
496
497=== modified file 'lib/lp/registry/model/sourcepackage.py'
498--- lib/lp/registry/model/sourcepackage.py 2010-03-08 12:53:59 +0000
499+++ lib/lp/registry/model/sourcepackage.py 2010-03-24 13:00:54 +0000
500@@ -24,8 +24,9 @@
501 from lp.buildmaster.interfaces.buildbase import BuildStatus
502 from lp.code.model.branch import Branch
503 from lp.code.model.hasbranches import HasBranchesMixin, HasMergeProposalsMixin
504+from lp.bugs.interfaces.bugtarget import IHasBugHeat
505 from lp.bugs.model.bug import get_bug_tags_open_count
506-from lp.bugs.model.bugtarget import BugTargetBase
507+from lp.bugs.model.bugtarget import BugTargetBase, HasBugHeatMixin
508 from lp.bugs.model.bugtask import BugTask
509 from lp.soyuz.interfaces.archive import IArchiveSet, ArchivePurpose
510 from lp.soyuz.model.build import Build, BuildSet
511@@ -157,7 +158,8 @@
512
513 class SourcePackage(BugTargetBase, SourcePackageQuestionTargetMixin,
514 HasTranslationImportsMixin, HasTranslationTemplatesMixin,
515- HasBranchesMixin, HasMergeProposalsMixin):
516+ HasBranchesMixin, HasMergeProposalsMixin,
517+ HasBugHeatMixin):
518 """A source package, e.g. apache2, in a distroseries.
519
520 This object is not a true database object, but rather attempts to
521@@ -166,8 +168,8 @@
522 """
523
524 implements(
525- ISourcePackage, IHasBuildRecords, IHasTranslationTemplates,
526- IQuestionTarget)
527+ ISourcePackage, IHasBugHeat, IHasBuildRecords,
528+ IHasTranslationTemplates, IQuestionTarget)
529
530 classProvides(ISourcePackageFactory)
531