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):