← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~stevenk/launchpad/pillarname-vocab into lp:launchpad

 

Steve Kowalik has proposed merging lp:~stevenk/launchpad/pillarname-vocab into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #541979 in Launchpad itself: "search project "ubuntu" returns nothing"
  https://bugs.launchpad.net/launchpad/+bug/541979

For more details, see:
https://code.launchpad.net/~stevenk/launchpad/pillarname-vocab/+merge/70091

This branch firstly Storm-ifies the PillarNameBase vocab. Secondly, we limit the number of searches to 100. Thirdly, we change the order results are returned in, with an exact match returned first with a rank of 100. The rest of the results are rank 50 and are mostly unordered. 
-- 
https://code.launchpad.net/~stevenk/launchpad/pillarname-vocab/+merge/70091
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/pillarname-vocab into lp:launchpad.
=== modified file 'lib/lp/registry/doc/vocabularies.txt'
--- lib/lp/registry/doc/vocabularies.txt	2011-07-13 05:31:42 +0000
+++ lib/lp/registry/doc/vocabularies.txt	2011-08-01 23:32:45 +0000
@@ -1170,7 +1170,7 @@
 token/name.
 
     >>> [term.token for term in vocab.searchForTerms(query='ubuntu')]
-    ['kubuntu', 'ubuntu', 'ubuntutest']
+    ['ubuntu', 'kubuntu', 'ubuntutest']
 
     >>> vocab.getTermByToken('ubuntu').token
     'ubuntu'

=== modified file 'lib/lp/registry/tests/test_pillar_vocabularies.py'
--- lib/lp/registry/tests/test_pillar_vocabularies.py	2010-12-22 20:44:25 +0000
+++ lib/lp/registry/tests/test_pillar_vocabularies.py	2011-08-01 23:32:45 +0000
@@ -18,7 +18,7 @@
 
 
 class TestPillarVocabularyBase(TestCaseWithFactory):
-    """Test that the ProductVocabulary behaves as expected."""
+    """Test that the PillarVocabulary behaves as expected."""
     layer = DatabaseFunctionalLayer
 
     def setUp(self):
@@ -48,11 +48,11 @@
             self.vocabulary.getTermByToken, 'does-notexist')
 
     def test_order_by_name(self):
-        # Results are ordered by name.
+        # Results are ordered by rank, with exact matches first.
         terms = self.vocabulary.searchForTerms('snark')
         result = [term.value for term in terms]
         self.assertEqual(
-            [self.project_group, self.product, self.distribution], result)
+            [self.product, self.distribution, self.project_group], result)
 
 
 class TestDistributionOrProductVocabulary(TestCaseWithFactory):
@@ -106,7 +106,7 @@
             self.product.active = False
         terms = self.vocabulary.searchForTerms('snark')
         result = [term.value for term in terms]
-        self.assertEqual([self.project_group, self.distribution], result)
+        self.assertEqual([self.distribution, self.project_group], result)
         self.assertFalse(self.product in self.vocabulary)
 
     def test_inactive_product_groups_are_excluded(self):

=== modified file 'lib/lp/registry/vocabularies.py'
--- lib/lp/registry/vocabularies.py	2011-07-26 19:09:48 +0000
+++ lib/lp/registry/vocabularies.py	2011-08-01 23:32:45 +0000
@@ -1870,10 +1870,12 @@
     """Active `IPillar` objects vocabulary."""
     displayname = 'Needs to be overridden'
     _table = PillarName
-    _orderBy = 'name'
+    _limit = 100
 
     def toTerm(self, obj):
         """See `IVocabulary`."""
+        if type(obj) == int:
+            return self.toTerm(PillarName.get(obj))
         if IPillarName.providedBy(obj):
             assert obj.active, 'Inactive object %s %d' % (
                     obj.__class__.__name__, obj.id)
@@ -1894,23 +1896,35 @@
     def __contains__(self, obj):
         raise NotImplementedError
 
+    def searchForTerms(self, query=None):
+        if not query:
+            return self.emptySelectResults()
+        query = ensure_unicode(query).lower()
+        store = IStore(PillarName)
+        equal_clauses = [PillarName.name == query]
+        like_clauses = [
+            PillarName.name != query, PillarName.name.contains_string(query)]
+        equal_clauses.extend(self._filter)
+        like_clauses.extend(self._filter)
+        ranked_results = store.execute(
+            Union(
+                Select(
+                    (PillarName.id, SQL('100 AS rank')),
+                    tables=[PillarName],
+                    where=And(*equal_clauses)),
+                Select(
+                    (PillarName.id, SQL('50 AS rank')),
+                    tables=[PillarName],
+                    where=And(*like_clauses)),
+                limit=self._limit, order_by='rank', all=True))
+        results = [row[0] for row in list(ranked_results)]
+        return self.iterator(len(results), results, self.toTerm)
+
 
 class DistributionOrProductVocabulary(PillarVocabularyBase):
     """Active `IDistribution` or `IProduct` objects vocabulary."""
     displayname = 'Select a project'
-    _filter = """
-        -- An active product/distro.
-        ((active IS TRUE
-         AND (product IS NOT NULL OR distribution IS NOT NULL)
-        )
-        OR
-        -- Or an alias for an active product/distro.
-        (alias_for IN (
-            SELECT id FROM PillarName
-            WHERE active IS TRUE AND
-                (product IS NOT NULL OR distribution IS NOT NULL))
-        ))
-        """
+    _filter = [PillarName.project == None, PillarName.active == True]
 
     def __contains__(self, obj):
         if IProduct.providedBy(obj):
@@ -1923,7 +1937,7 @@
 class DistributionOrProductOrProjectGroupVocabulary(PillarVocabularyBase):
     """Active `IProduct`, `IProjectGroup` or `IDistribution` vocabulary."""
     displayname = 'Select a project'
-    _filter = PillarName.q.active == True
+    _filter = [PillarName.active == True]
 
     def __contains__(self, obj):
         if IProduct.providedBy(obj) or IProjectGroup.providedBy(obj):