Merge lp:~deryck/launchpad/has-bug-heat-interface-529846 into lp:launchpad
- has-bug-heat-interface-529846
- Merge into devel
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 | ||||
Related bugs: |
|
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/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
Preview Diff
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 |
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: bugs/model/ bugtarget. py' bugs/model/ bugtarget. py 2010-03-09 15:13:40 +0000 bugs/model/ bugtarget. py 2010-03-19 15:41:50 +0000 TargetMixin' , s(all_tasks_ query) count() . all_bugtasks ResultSet instance, and this Set._result_ set.is_ empty() all_bugtasks) kContextClause( ), privacy_ filter( user) append( privacy_ filter) select_ columns) , ' AND '.join( conditions) ))
> === modified file 'lib/lp/
> --- lib/lp/
> +++ lib/lp/
> @@ -9,6 +9,7 @@
> __all__ = [
> 'BugTargetBase',
> 'HasBugsBase',
> + 'HasBugHeatMixin',
> 'OfficialBugTag',
> 'OfficialBugTag
> ]
> @@ -162,8 +163,57 @@
>
> return self.searchTask
>
> + @property
> + def has_bugtasks(self):
> + """See `IHasBugs`."""
> + # Check efficiently if any bugtasks exist. We should avoid
> + # expensive calls like all_bugtasks.
> + # returns a storm.SQLObject
> + # class does not provide methods like is_empty(). But we can
> + # indirectly call SQLObjectResult
> + # by converting all_bugtasks into a boolean object.
> + return bool(self.
> +
> + 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._getBugTas
> + 'BugTask.bug = Bug.id',
> + 'Bug.duplicateof is NULL']
> + privacy_filter = get_bug_
> + if privacy_filter:
> + conditions.
> +
> + cur = cursor()
> + cur.execute(
> + "SELECT %s FROM BugTask, Bug WHERE %s" % (
> + ', '.join(
> + 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>