Merge lp:~allenap/launchpad/dont-update-dupe-bugs-bug-511276 into lp:launchpad

Proposed by Gavin Panella
Status: Merged
Approved by: Gavin Panella
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~allenap/launchpad/dont-update-dupe-bugs-bug-511276
Merge into: lp:launchpad
Diff against target: 167 lines (+90/-17)
2 files modified
lib/lp/bugs/model/bugwatch.py (+16/-14)
lib/lp/bugs/tests/test_bugwatch.py (+74/-3)
To merge this branch: bzr merge lp:~allenap/launchpad/dont-update-dupe-bugs-bug-511276
Reviewer Review Type Date Requested Status
Abel Deuring (community) code Approve
Review via email: mp+23113@code.launchpad.net

Commit message

Don't update bug task status or importance in duplicate bugs when a watch is updated.

Description of the change

This changes BugWatch.updateStatus() and BugWatch.updateImportance() to not modify the status when the linked bug tasks are part of a duplicate bug. I've done this by factoring out the selection of bug tasks to update into a new property, BugWatch.bugtasks_to_update.

To post a comment you must log in.
Revision history for this message
Abel Deuring (adeuring) wrote :

Nice branch! just one nit pick:

+ # If we add a task such that the existing task becomes a
+ # conjoined slave, only thr master task will be eligible for
+ # update.

s/thr/the/

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/bugs/model/bugwatch.py'
--- lib/lp/bugs/model/bugwatch.py 2010-03-23 12:55:05 +0000
+++ lib/lp/bugs/model/bugwatch.py 2010-04-09 15:32:31 +0000
@@ -92,6 +92,20 @@
92 return shortlist(tasks, 10, 100)92 return shortlist(tasks, 10, 100)
9393
94 @property94 @property
95 def bugtasks_to_update(self):
96 """Yield the bug tasks that are eligible for update."""
97 for bugtask in self.bugtasks:
98 # We don't update conjoined bug tasks; they must be
99 # updated through their conjoined masters.
100 if bugtask._isConjoinedBugTask():
101 continue
102 # We don't update tasks of duplicate bugs.
103 if bugtask.bug.duplicateof is not None:
104 continue
105 # Update this one.
106 yield bugtask
107
108 @property
95 def title(self):109 def title(self):
96 """See `IBugWatch`."""110 """See `IBugWatch`."""
97 return "%s #%s" % (self.bugtracker.title, self.remotebug)111 return "%s #%s" % (self.bugtracker.title, self.remotebug)
@@ -125,19 +139,12 @@
125 # Sync the object in order to convert the UTC_NOW sql139 # Sync the object in order to convert the UTC_NOW sql
126 # constant to a datetime value.140 # constant to a datetime value.
127 self.sync()141 self.sync()
128142 for linked_bugtask in self.bugtasks_to_update:
129 for linked_bugtask in self.bugtasks:
130 # We don't updated conjoined bug tasks; they must be updated
131 # through their conjoined masters.
132 if linked_bugtask._isConjoinedBugTask():
133 continue
134
135 old_bugtask = Snapshot(143 old_bugtask = Snapshot(
136 linked_bugtask, providing=providedBy(linked_bugtask))144 linked_bugtask, providing=providedBy(linked_bugtask))
137 linked_bugtask.transitionToImportance(145 linked_bugtask.transitionToImportance(
138 malone_importance,146 malone_importance,
139 getUtility(ILaunchpadCelebrities).bug_watch_updater)147 getUtility(ILaunchpadCelebrities).bug_watch_updater)
140
141 if linked_bugtask.importance != old_bugtask.importance:148 if linked_bugtask.importance != old_bugtask.importance:
142 event = ObjectModifiedEvent(149 event = ObjectModifiedEvent(
143 linked_bugtask, old_bugtask, ['importance'],150 linked_bugtask, old_bugtask, ['importance'],
@@ -152,12 +159,7 @@
152 # Sync the object in order to convert the UTC_NOW sql159 # Sync the object in order to convert the UTC_NOW sql
153 # constant to a datetime value.160 # constant to a datetime value.
154 self.sync()161 self.sync()
155 for linked_bugtask in self.bugtasks:162 for linked_bugtask in self.bugtasks_to_update:
156 # We don't updated conjoined bug tasks; they must be updated
157 # through their conjoined masters.
158 if linked_bugtask._isConjoinedBugTask():
159 continue
160
161 old_bugtask = Snapshot(163 old_bugtask = Snapshot(
162 linked_bugtask, providing=providedBy(linked_bugtask))164 linked_bugtask, providing=providedBy(linked_bugtask))
163 linked_bugtask.transitionToStatus(165 linked_bugtask.transitionToStatus(
164166
=== modified file 'lib/lp/bugs/tests/test_bugwatch.py'
--- lib/lp/bugs/tests/test_bugwatch.py 2010-03-26 14:49:24 +0000
+++ lib/lp/bugs/tests/test_bugwatch.py 2010-04-09 15:32:31 +0000
@@ -14,15 +14,16 @@
14from urlparse import urlunsplit14from urlparse import urlunsplit
1515
16from zope.component import getUtility16from zope.component import getUtility
17from zope.security.proxy import removeSecurityProxy
1718
18from canonical.launchpad.ftests import login, ANONYMOUS19from canonical.launchpad.ftests import login, ANONYMOUS
20from canonical.launchpad.scripts.garbo import BugWatchActivityPruner
19from canonical.launchpad.scripts.logger import QuietFakeLogger21from canonical.launchpad.scripts.logger import QuietFakeLogger
20from canonical.launchpad.webapp import urlsplit22from canonical.launchpad.webapp import urlsplit
21from canonical.launchpad.scripts.garbo import BugWatchActivityPruner
22from canonical.launchpad.scripts.logger import QuietFakeLogger
23from canonical.testing import (23from canonical.testing import (
24 DatabaseFunctionalLayer, LaunchpadFunctionalLayer, LaunchpadZopelessLayer)24 DatabaseFunctionalLayer, LaunchpadFunctionalLayer, LaunchpadZopelessLayer)
2525
26from lp.bugs.interfaces.bugtask import BugTaskImportance, BugTaskStatus
26from lp.bugs.interfaces.bugtracker import BugTrackerType, IBugTrackerSet27from lp.bugs.interfaces.bugtracker import BugTrackerType, IBugTrackerSet
27from lp.bugs.interfaces.bugwatch import (28from lp.bugs.interfaces.bugwatch import (
28 BugWatchActivityStatus, IBugWatchSet, NoBugTrackerFound,29 BugWatchActivityStatus, IBugWatchSet, NoBugTrackerFound,
@@ -31,7 +32,7 @@
31 BugWatchScheduler, MAX_SAMPLE_SIZE)32 BugWatchScheduler, MAX_SAMPLE_SIZE)
32from lp.registry.interfaces.person import IPersonSet33from lp.registry.interfaces.person import IPersonSet
3334
34from lp.testing import TestCaseWithFactory35from lp.testing import TestCaseWithFactory, login_person
3536
3637
37class ExtractBugTrackerAndBugTestBase:38class ExtractBugTrackerAndBugTestBase:
@@ -335,6 +336,76 @@
335 bug_id = '12345'336 bug_id = '12345'
336337
337338
339class TestBugWatch(TestCaseWithFactory):
340
341 layer = LaunchpadZopelessLayer
342
343 def test_bugtasks_to_update(self):
344 # The bugtasks_to_update property should yield the linked bug
345 # tasks which are not conjoined and for which the bug is not a
346 # duplicate.
347 product = self.factory.makeProductNoCommit()
348 bug = self.factory.makeBug(product=product, owner=product.owner)
349 product_task = bug.getBugTask(product)
350 watch = self.factory.makeBugWatch(bug=bug)
351 product_task.bugwatch = watch
352 # For a single-task bug the bug task is eligible for update.
353 self.failUnlessEqual(
354 [product_task], list(
355 removeSecurityProxy(watch).bugtasks_to_update))
356 # If we add a task such that the existing task becomes a
357 # conjoined slave, only thr master task will be eligible for
358 # update.
359 product_series_task = self.factory.makeBugTask(
360 bug=bug, target=product.development_focus)
361 product_series_task.bugwatch = watch
362 self.failUnlessEqual(
363 [product_series_task], list(
364 removeSecurityProxy(watch).bugtasks_to_update))
365 # But once the bug is marked as a duplicate,
366 # bugtasks_to_update yields nothing.
367 bug.markAsDuplicate(
368 self.factory.makeBug(product=product, owner=product.owner))
369 self.failUnlessEqual(
370 [], list(removeSecurityProxy(watch).bugtasks_to_update))
371
372 def test_updateStatus_with_duplicate_bug(self):
373 # Calling BugWatch.updateStatus() will not update the status
374 # of a task that is part of a duplicate bug.
375 bug = self.factory.makeBug()
376 bug.markAsDuplicate(self.factory.makeBug())
377 login_person(bug.owner)
378 bug_task = bug.default_bugtask
379 bug_task.bugwatch = self.factory.makeBugWatch()
380 bug_task_initial_status = bug_task.status
381 self.failIfEqual(BugTaskStatus.INPROGRESS, bug_task.status)
382 bug_task.bugwatch.updateStatus('foo', BugTaskStatus.INPROGRESS)
383 self.failUnlessEqual(bug_task_initial_status, bug_task.status)
384 # Once the task is no longer linked to a duplicate bug, the
385 # status will get updated.
386 bug.markAsDuplicate(None)
387 bug_task.bugwatch.updateStatus('foo', BugTaskStatus.INPROGRESS)
388 self.failUnlessEqual(BugTaskStatus.INPROGRESS, bug_task.status)
389
390 def test_updateImportance_with_duplicate_bug(self):
391 # Calling BugWatch.updateImportance() will not update the
392 # importance of a task that is part of a duplicate bug.
393 bug = self.factory.makeBug()
394 bug.markAsDuplicate(self.factory.makeBug())
395 login_person(bug.owner)
396 bug_task = bug.default_bugtask
397 bug_task.bugwatch = self.factory.makeBugWatch()
398 bug_task_initial_importance = bug_task.importance
399 self.failIfEqual(BugTaskImportance.HIGH, bug_task.importance)
400 bug_task.bugwatch.updateImportance('foo', BugTaskImportance.HIGH)
401 self.failUnlessEqual(bug_task_initial_importance, bug_task.importance)
402 # Once the task is no longer linked to a duplicate bug, the
403 # importance will get updated.
404 bug.markAsDuplicate(None)
405 bug_task.bugwatch.updateImportance('foo', BugTaskImportance.HIGH)
406 self.failUnlessEqual(BugTaskImportance.HIGH, bug_task.importance)
407
408
338class TestBugWatchSet(TestCaseWithFactory):409class TestBugWatchSet(TestCaseWithFactory):
339 """Tests for the bugwatch updating system."""410 """Tests for the bugwatch updating system."""
340411