← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~sinzui/launchpad/dsp-bug-counts-1 into lp:launchpad/devel

 

Curtis Hovey has proposed merging lp:~sinzui/launchpad/dsp-bug-counts-1 into lp:launchpad/devel.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)


This is my branch to fix the DSP bug counts shown on +needs-packaging.

    lp:~sinzui/launchpad/dsp-bug-counts-1
    Diff size: 90
    Launchpad bug:
          https://bugs.launchpad.net/bugs/613610
    Test command: ./bin/test -vv -t test_bugheat
    Pre-implementation: deryck (my hero)
    Target release: 10.09


Fix the DSP bug counts shown on +needs-packaging
-------------------------------------------------

The bug counts shown on +needs-packaging are for all bugs reported against
the DSP. We want to show the open bugs that the user can see when viewing
the DSPs bug page.

The recent fix to exclude closed bugs was not enough to address this issue.
The rules must also ignore duplicate bugs. The call to recalculateBugHeatCache
should be added to updateHeat so that bugtargets are updated when their bugs
change.


Rules
-----

    * Add condition to exclude duplicate bugs from bug heat cache
      calculations.
    * Call recalculateBugHeatCache in updateHeat so that bugtarget caches
      update when their bugs change.


QA
--

    * Subscribe to flashplugin-nonfree on staging. Verify the DSP's bug
      count goes down.
          SELECT bug_count FROM distributionsourcepackage
          WHERE distribution = 1
            AND sourcepackagename in (
                SELECT id FROM sourcepackagename
                WHERE name = 'flashplugin-nonfree');


Lint
----

Linting changed files:
  lib/lp/bugs/model/bug.py
  lib/lp/bugs/tests/test_bugheat.py
  lib/lp/registry/model/distributionsourcepackage.py


Test
----

    * lib/lp/bugs/tests/test_bugheat.py
      * Added a test to verify recalculateBugHeatCache is called during
        Bug.updateHeat. This may look evil, but messing with security
        proxies and monkey patching objects is more dangerous.
      * Add a duplicate bug to the test setup. The count (2) must not change.


Implementation
--------------

    * lib/lp/bugs/model/bug.py
      * Added a rule to iterate of the bug's tasks and call the
        task's recalculateBugHeatCache method. This is the same way
        setHeat works.
    * lib/lp/registry/model/distributionsourcepackage.py
      * Add a condition to ignore duplicate bugs in recalculateBugHeatCache.
-- 
https://code.launchpad.net/~sinzui/launchpad/dsp-bug-counts-1/+merge/33257
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~sinzui/launchpad/dsp-bug-counts-1 into lp:launchpad/devel.
=== modified file 'lib/lp/bugs/model/bug.py'
--- lib/lp/bugs/model/bug.py	2010-08-18 13:13:36 +0000
+++ lib/lp/bugs/model/bug.py	2010-08-20 19:41:52 +0000
@@ -1636,6 +1636,8 @@
 
         self.heat = SQL("calculate_bug_heat(%s)" % sqlvalues(self))
         self.heat_last_updated = UTC_NOW
+        for task in self.bugtasks:
+            task.target.recalculateBugHeatCache()
 
     @property
     def attachments(self):

=== modified file 'lib/lp/bugs/tests/test_bugheat.py'
--- lib/lp/bugs/tests/test_bugheat.py	2010-08-12 16:34:39 +0000
+++ lib/lp/bugs/tests/test_bugheat.py	2010-08-20 19:41:52 +0000
@@ -7,15 +7,47 @@
 
 import unittest
 
+from zope.interface import implements
+
 from storm.store import Store
 
+from lazr.delegates import delegates
+
 from canonical.testing import LaunchpadZopelessLayer
 
 from lp.bugs.interfaces.bugtask import BugTaskStatus
+from lp.registry.interfaces.distributionsourcepackage import (
+    IDistributionSourcePackage)
 from lp.testing import TestCaseWithFactory
 from lp.testing.factory import LaunchpadObjectFactory
 
 
+class BugUpdateHeat(TestCaseWithFactory):
+
+    layer = LaunchpadZopelessLayer
+
+    def test_updateHeat_calls_recalculateBugHeatCache(self):
+        # This requires some instrumentation. The updateHeat() method is
+        # called by many methods that may be involved in setting up a bug
+        # target.
+        class TestTarget:
+            implements(IDistributionSourcePackage)
+            delegates(IDistributionSourcePackage, context='target')
+
+            def __init__(self, target):
+                self.target = target
+                self.called = False
+
+            def recalculateBugHeatCache(self):
+                self.called = True
+
+        self.target = TestTarget(
+            self.factory.makeDistributionSourcePackage(with_db=True))
+        self.bugtask = self.factory.makeBugTask(target=self.target)
+        self.bugtask.bug.updateHeat()
+        self.assertTrue(self.target.called)
+
+
 class MaxHeatByTargetBase:
     """Base class for testing a bug target's max_bug_heat attribute."""
 
@@ -115,9 +147,12 @@
         self.bugtask1 = self.factory.makeBugTask(target=self.target)
         self.bugtask2 = self.factory.makeBugTask(target=self.target)
         self.bugtask3 = self.factory.makeBugTask(target=self.target)
+        self.bugtask4 = self.factory.makeBugTask(target=self.target)
         # A closed bug is not include in DSP bug heat calculations.
         self.bugtask3.transitionToStatus(
             BugTaskStatus.FIXRELEASED, self.target.distribution.owner)
+        # A duplicate bug is not include in DSP bug heat calculations.
+        self.bugtask4.bug.markAsDuplicate(self.bugtask1.bug)
         # Bug heat gets calculated by complicated rules in a db
         # stored procedure. We will override them here to avoid
         # testing inconsitencies if those values are calculated

=== modified file 'lib/lp/registry/model/distributionsourcepackage.py'
--- lib/lp/registry/model/distributionsourcepackage.py	2010-08-17 01:37:26 +0000
+++ lib/lp/registry/model/distributionsourcepackage.py	2010-08-20 19:41:52 +0000
@@ -191,6 +191,7 @@
             BugTask.bug == Bug.id,
             BugTask.distributionID == self.distribution.id,
             BugTask.sourcepackagenameID == self.sourcepackagename.id,
+            Bug.duplicateof == None,
             BugTask.status.is_in(UNRESOLVED_BUGTASK_STATUSES)).one()
 
         # Aggregate functions return NULL if zero rows match.