You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bloodhound.apache.org by as...@apache.org on 2013/05/29 22:02:51 UTC

svn commit: r1487624 - in /bloodhound/trunk: bloodhound_relations/bhrelations/ bloodhound_relations/bhrelations/tests/ bloodhound_search/bhsearch/

Author: astaric
Date: Wed May 29 20:02:51 2013
New Revision: 1487624

URL: http://svn.apache.org/r1487624
Log:
Update search index when relations are added/deleted.

Added:
    bloodhound/trunk/bloodhound_relations/bhrelations/tests/search.py
Modified:
    bloodhound/trunk/bloodhound_relations/bhrelations/search.py
    bloodhound/trunk/bloodhound_relations/bhrelations/tests/__init__.py
    bloodhound/trunk/bloodhound_relations/bhrelations/tests/api.py
    bloodhound/trunk/bloodhound_search/bhsearch/query_parser.py
    bloodhound/trunk/bloodhound_search/bhsearch/whoosh_backend.py

Modified: bloodhound/trunk/bloodhound_relations/bhrelations/search.py
URL: http://svn.apache.org/viewvc/bloodhound/trunk/bloodhound_relations/bhrelations/search.py?rev=1487624&r1=1487623&r2=1487624&view=diff
==============================================================================
--- bloodhound/trunk/bloodhound_relations/bhrelations/search.py (original)
+++ bloodhound/trunk/bloodhound_relations/bhrelations/search.py Wed May 29 20:02:51 2013
@@ -18,11 +18,15 @@
 #  specific language governing permissions and limitations
 #  under the License.
 
+from sqlite3 import OperationalError
+
 from trac.core import Component, implements
 
 from bhsearch.api import IDocIndexPreprocessor
+from bhsearch.search_resources.ticket_search import TicketIndexer
 
-from bhrelations.api import RelationsSystem, ResourceIdSerializer
+from bhrelations.api import RelationsSystem, ResourceIdSerializer,\
+    IRelationChangingListener, TicketRelationsSpecifics
 
 
 class RelationsDocPreprocessor(Component):
@@ -32,18 +36,45 @@ class RelationsDocPreprocessor(Component
         resource_id = ':'.join([
             doc.get('product', ''), doc.get('type', ''), doc.get('id')])
 
-        rls = RelationsSystem(self.env)
-        relations = []
-        for relation in rls._select_relations(resource_id):
-            relations.extend(self._format_relations(relation))
-        doc['relations'] = ' '.join(relations)
+        try:
+            rls = RelationsSystem(self.env)
+            relations = []
+            for relation in rls._select_relations(resource_id):
+                relations.extend(self._format_relations(relation))
+            doc['relations'] = ','.join(relations)
+        except OperationalError:
+            # If bhrelations and bhsearch are installed at the same time and
+            # bhsearch is upgraded before bhrelations, table
+            # bloodhound_relations will be missing, thus causing the
+            # OperationalError. As this means that the relations do not
+            # exist yet, just skip indexing them.
+            self.log.debug("Not indexing relations for %s", resource_id)
 
     def _format_relations(self, relation):
         ris = ResourceIdSerializer
         product, realm, res_id = ris.split_full_id(relation.destination)
 
         if realm == 'ticket':
-            yield '%s:%s-%s' % (relation.type, product, res_id)
             yield '%s:#%s' % (relation.type, res_id)
+            yield '%s:#%s-%s' % (relation.type, product, res_id)
         elif realm == 'wiki':
             yield '%s:%s' % (relation.type, res_id)
+
+
+class RelationSearchUpdater(Component):
+    implements(IRelationChangingListener)
+
+    def adding_relation(self, relation):
+        self._reindex_endpoints(relation)
+
+    def deleting_relation(self, relation, when):
+        self._reindex_endpoints(relation)
+
+    def _reindex_endpoints(self, relation):
+        trs = TicketRelationsSpecifics(self.env)
+        ticket_indexer = TicketIndexer(self.env)
+        for resource in map(ResourceIdSerializer.get_resource_by_id,
+                            (relation.source, relation.destination)):
+            if resource.realm == 'ticket':
+                ticket = trs._create_ticket_by_full_id(resource)
+                ticket_indexer._index_ticket(ticket)

Modified: bloodhound/trunk/bloodhound_relations/bhrelations/tests/__init__.py
URL: http://svn.apache.org/viewvc/bloodhound/trunk/bloodhound_relations/bhrelations/tests/__init__.py?rev=1487624&r1=1487623&r2=1487624&view=diff
==============================================================================
--- bloodhound/trunk/bloodhound_relations/bhrelations/tests/__init__.py (original)
+++ bloodhound/trunk/bloodhound_relations/bhrelations/tests/__init__.py Wed May 29 20:02:51 2013
@@ -25,11 +25,15 @@
 #     import unittest
 import unittest
 
-from bhrelations.tests import api
+from bhrelations.tests import api, notification, search, validation
 
 def suite():
     test_suite = unittest.TestSuite()
     test_suite.addTest(api.suite())
+    test_suite.addTest(notification.suite())
+    test_suite.addTest(search.suite())
+    test_suite.addTest(validation.suite())
+
     return test_suite
 
 if __name__ == '__main__':

Modified: bloodhound/trunk/bloodhound_relations/bhrelations/tests/api.py
URL: http://svn.apache.org/viewvc/bloodhound/trunk/bloodhound_relations/bhrelations/tests/api.py?rev=1487624&r1=1487623&r2=1487624&view=diff
==============================================================================
--- bloodhound/trunk/bloodhound_relations/bhrelations/tests/api.py (original)
+++ bloodhound/trunk/bloodhound_relations/bhrelations/tests/api.py Wed May 29 20:02:51 2013
@@ -40,10 +40,11 @@ except ImportError:
 
 
 class BaseApiApiTestCase(MultiproductTestCase):
-    def setUp(self):
+    def setUp(self, enabled=()):
         env = EnvironmentStub(
             default_data=True,
-            enable=['trac.*', 'multiproduct.*', 'bhrelations.*']
+            enable=(['trac.*', 'multiproduct.*', 'bhrelations.*'] +
+                    list(enabled))
         )
         env.config.set('bhrelations', 'global_validators',
                        'NoSelfReferenceValidator,ExclusiveValidator,'

Added: bloodhound/trunk/bloodhound_relations/bhrelations/tests/search.py
URL: http://svn.apache.org/viewvc/bloodhound/trunk/bloodhound_relations/bhrelations/tests/search.py?rev=1487624&view=auto
==============================================================================
--- bloodhound/trunk/bloodhound_relations/bhrelations/tests/search.py (added)
+++ bloodhound/trunk/bloodhound_relations/bhrelations/tests/search.py Wed May 29 20:02:51 2013
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+import shutil
+import tempfile
+import unittest
+
+from bhrelations.tests.api import BaseApiApiTestCase
+from bhsearch.api import BloodhoundSearchApi
+
+# TODO: Figure how to get trac to load components from these modules
+import bhsearch.query_parser, bhsearch.search_resources.ticket_search, \
+    bhsearch.whoosh_backend
+import bhrelations.search
+
+
+class SearchIntegrationTestCase(BaseApiApiTestCase):
+    def setUp(self):
+        BaseApiApiTestCase.setUp(self, enabled=['bhsearch.*'])
+        self.global_env.path = tempfile.mkdtemp('bhrelations-tempenv')
+        self.search_api = BloodhoundSearchApi(self.env)
+        self.search_api.upgrade_environment(self.env.db_transaction)
+
+    def tearDown(self):
+        shutil.rmtree(self.env.path)
+        BaseApiApiTestCase.tearDown(self)
+
+    def test_relations_are_indexed_on_creation(self):
+        t1 = self._insert_and_load_ticket("Foo")
+        t2 = self._insert_and_load_ticket("Bar")
+
+        self.relations_system.add(t1, t2, 'dependent')
+
+        result = self.search_api.query('dependent:#2')
+        self.assertEqual(result.hits, 1)
+
+    def test_relations_are_indexed_on_deletion(self):
+        t1 = self._insert_and_load_ticket("Foo")
+        t2 = self._insert_and_load_ticket("Bar")
+
+        self.relations_system.add(t1, t2, 'dependent')
+        relations = self.relations_system.get_relations(t1)
+        self.relations_system.delete(relations[0]["relation_id"])
+
+        result = self.search_api.query('dependent:#2')
+        self.assertEqual(result.hits, 0)
+
+    def test_different_types_of_queries(self):
+        t1 = self._insert_and_load_ticket("Foo")
+        t2 = self._insert_and_load_ticket("Bar")
+
+        self.relations_system.add(t1, t2, 'dependent')
+
+        self.assertEqual(self.search_api.query('dependent:#2').hits, 1)
+        self.assertEqual(self.search_api.query('dependent:#tp1-2').hits, 1)
+
+
+def suite():
+    test_suite = unittest.TestSuite()
+    test_suite.addTest(unittest.makeSuite(SearchIntegrationTestCase, 'test'))
+    return test_suite
+
+if __name__ == '__main__':
+    unittest.main()

Modified: bloodhound/trunk/bloodhound_search/bhsearch/query_parser.py
URL: http://svn.apache.org/viewvc/bloodhound/trunk/bloodhound_search/bhsearch/query_parser.py?rev=1487624&r1=1487623&r2=1487624&view=diff
==============================================================================
--- bloodhound/trunk/bloodhound_search/bhsearch/query_parser.py (original)
+++ bloodhound/trunk/bloodhound_search/bhsearch/query_parser.py Wed May 29 20:02:51 2013
@@ -92,6 +92,7 @@ class DefaultQueryParser(Component):
         changes = 1,
         message = 1,
         query_suggestion_basket = 0,
+        relations = 1,
     )
 
     meta_keyword_parsers = ExtensionPoint(IMetaKeywordParser)

Modified: bloodhound/trunk/bloodhound_search/bhsearch/whoosh_backend.py
URL: http://svn.apache.org/viewvc/bloodhound/trunk/bloodhound_search/bhsearch/whoosh_backend.py?rev=1487624&r1=1487623&r2=1487624&view=diff
==============================================================================
--- bloodhound/trunk/bloodhound_search/bhsearch/whoosh_backend.py (original)
+++ bloodhound/trunk/bloodhound_search/bhsearch/whoosh_backend.py Wed May 29 20:02:51 2013
@@ -114,7 +114,7 @@ class WhooshBackend(Component):
                   analyzer=analysis.SimpleAnalyzer()),
         query_suggestion_basket=TEXT(analyzer=analysis.SimpleAnalyzer(),
                                      spelling=True),
-        relations=TEXT(analyzer=analysis.SimpleAnalyzer()),
+        relations=KEYWORD(lowercase=True, commas=True),
     )
 
     def __init__(self):