← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~adeuring/launchpad/bug-sorting-3 into lp:launchpad

 

Abel Deuring has proposed merging lp:~adeuring/launchpad/bug-sorting-3 into lp:launchpad with lp:~adeuring/launchpad/bug-sorting-2 as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~adeuring/launchpad/bug-sorting-3/+merge/82562

This branch allows to sort bugtask search results by bug tag and by linked blueprint. (see https://dev.launchpad.net/LEP/CustomBugListings)

"we want sorting by tag or blueprint" is a somewhat vague request: A bug may have more than one blueprint or more than one tag -- what exactly should we choose then for sorting? By all tags/blueprints, or just one?

After discussions with the Orange team I opted to sort by that tag/blueprint for a given bug that comes alpabetically first.

Joining the tables BugTag/Specification needs a somewhat convoluted ON clause to avoid that more than one  column appears in the result set for one bugtask. It seems to me that expressing this condition as a raw SQL subquery seems is better readable than an equivalent Storm expression.

tests:

./bin/test bugs -vvt lp.bugs.tests.test_bugtask_search..*test_sort_by_linked_specification
./bin/test bugs -vvt lp.bugs.tests.test_bugtask_search..*test_sort_by_tag

no lint
-- 
https://code.launchpad.net/~adeuring/launchpad/bug-sorting-3/+merge/82562
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~adeuring/launchpad/bug-sorting-3 into lp:launchpad.
=== modified file 'lib/lp/bugs/model/bugtask.py'
--- lib/lp/bugs/model/bugtask.py	2011-11-17 16:55:35 +0000
+++ lib/lp/bugs/model/bugtask.py	2011-11-17 16:55:38 +0000
@@ -162,6 +162,7 @@
 from lp.services import features
 from lp.services.propertycache import get_property_cache
 from lp.soyuz.enums import PackagePublishingStatus
+from lp.blueprints.model.specification import Specification
 
 
 debbugsseveritymap = {
@@ -3163,7 +3164,10 @@
         """See `IBugTaskSet`."""
         if BugTaskSet._ORDERBY_COLUMN is None:
             # Avoid circular imports.
-            from lp.bugs.model.bug import Bug
+            from lp.bugs.model.bug import (
+                Bug,
+                BugTag,
+                )
             from lp.registry.model.milestone import Milestone
             from lp.registry.model.person import Person
             Assignee = ClassAlias(Person)
@@ -3205,6 +3209,44 @@
                         (Bug, Join(Bug, BugTask.bug == Bug.id)),
                         (Reporter, Join(Reporter, Bug.owner == Reporter.id))
                         ]),
+                "tag": (
+                    BugTag.tag,
+                    [
+                        (Bug, Join(Bug, BugTask.bug == Bug.id)),
+                        (BugTag,
+                         LeftJoin(
+                             BugTag,
+                             BugTag.bug == Bug.id and
+                             # We want at most one tag per bug. Select the
+                             # tag that comes first in alphabetic order.
+                             BugTag.id == SQL("""
+                                 SELECT id FROM BugTag AS bt
+                                 WHERE bt.bug=bug.id ORDER BY bt.name LIMIT 1
+                                 """))),
+                        ]
+                    ),
+                "specification": (
+                    Specification.name,
+                    [
+                        (Bug, Join(Bug, BugTask.bug == Bug.id)),
+                        (Specification,
+                         LeftJoin(
+                             Specification,
+                             # We want at most one specification per bug.
+                             # Select the specification that comes first
+                             # in alphabetic order.
+                             Specification.id == SQL("""
+                                 SELECT Specification.id
+                                 FROM SpecificationBug
+                                 JOIN Specification
+                                     ON SpecificationBug.specification=
+                                         Specification.id
+                                 WHERE SpecificationBug.bug=Bug.id
+                                 ORDER BY Specification.name
+                                 LIMIT 1
+                                 """))),
+                        ]
+                    ),
                 }
         return BugTaskSet._ORDERBY_COLUMN[col_name]
 

=== modified file 'lib/lp/bugs/tests/test_bugtask_search.py'
--- lib/lp/bugs/tests/test_bugtask_search.py	2011-11-17 16:55:35 +0000
+++ lib/lp/bugs/tests/test_bugtask_search.py	2011-11-17 16:55:38 +0000
@@ -639,6 +639,37 @@
         params = self.getBugTaskSearchParams(user=None, orderby='-title')
         self.assertSearchFinds(params, expected)
 
+    def test_sort_by_tag(self):
+        with person_logged_in(self.owner):
+            self.bugtasks[2].bug.tags = ['tag-a', 'tag-d']
+            self.bugtasks[1].bug.tags = ['tag-b', 'tag-c']
+        params = self.getBugTaskSearchParams(user=None, orderby='tag')
+        expected = [self.bugtasks[2], self.bugtasks[1], self.bugtasks[0]]
+        self.assertSearchFinds(params, expected)
+        expected.reverse()
+        params = self.getBugTaskSearchParams(user=None, orderby='-tag')
+        self.assertSearchFinds(params, expected)
+
+    def test_sort_by_linked_specification(self):
+        with person_logged_in(self.owner):
+            spec_1 = self.factory.makeSpecification(
+                name='spec-1', owner=self.owner)
+            spec_1.linkBug(self.bugtasks[2].bug)
+            spec_1_1 = self.factory.makeSpecification(
+                name='spec-1-1', owner=self.owner)
+            spec_1_1.linkBug(self.bugtasks[2].bug)
+            spec_2 = self.factory.makeSpecification(
+                name='spec-2', owner=self.owner)
+            spec_2.linkBug(self.bugtasks[1].bug)
+        params = self.getBugTaskSearchParams(
+            user=None, orderby='specification')
+        expected = [self.bugtasks[2], self.bugtasks[1], self.bugtasks[0]]
+        self.assertSearchFinds(params, expected)
+        expected.reverse()
+        params = self.getBugTaskSearchParams(
+            user=None, orderby='-specification')
+        self.assertSearchFinds(params, expected)
+
 
 class DeactivatedProductBugTaskTestCase(TestCaseWithFactory):