incubator-bloodhound-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From and...@apache.org
Subject svn commit: r1443531 - in /incubator/bloodhound/trunk: bloodhound_search/bhsearch/ bloodhound_search/bhsearch/search_resources/ bloodhound_search/bhsearch/templates/ bloodhound_search/bhsearch/tests/ bloodhound_theme/bhtheme/htdocs/
Date Thu, 07 Feb 2013 15:03:32 GMT
Author: andrej
Date: Thu Feb  7 15:03:31 2013
New Revision: 1443531

URL: http://svn.apache.org/viewvc?rev=1443531&view=rev
Log:
#361 Bloodhound Search add support or sort parameter

Modified:
    incubator/bloodhound/trunk/bloodhound_search/bhsearch/api.py
    incubator/bloodhound/trunk/bloodhound_search/bhsearch/search_resources/wiki_search.py
    incubator/bloodhound/trunk/bloodhound_search/bhsearch/templates/bhsearch.html
    incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/index_with_whoosh.py
    incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/ticket_search.py
    incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/web_ui.py
    incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/whoosh_backend.py
    incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/wiki_search.py
    incubator/bloodhound/trunk/bloodhound_search/bhsearch/web_ui.py
    incubator/bloodhound/trunk/bloodhound_theme/bhtheme/htdocs/bloodhound.css

Modified: incubator/bloodhound/trunk/bloodhound_search/bhsearch/api.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/bhsearch/api.py?rev=1443531&r1=1443530&r2=1443531&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/bhsearch/api.py (original)
+++ incubator/bloodhound/trunk/bloodhound_search/bhsearch/api.py Thu Feb  7 15:03:31 2013
@@ -245,6 +245,7 @@ class BloodhoundSearchApi(Component):
         for post_processor in self.result_post_processors:
             post_processor.post_process(query_result)
 
+        query_result.debug["api_parameters"] = query_parameters
         return query_result
 
 

Modified: incubator/bloodhound/trunk/bloodhound_search/bhsearch/search_resources/wiki_search.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/bhsearch/search_resources/wiki_search.py?rev=1443531&r1=1443530&r2=1443531&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/bhsearch/search_resources/wiki_search.py
(original)
+++ incubator/bloodhound/trunk/bloodhound_search/bhsearch/search_resources/wiki_search.py
Thu Feb  7 15:03:31 2013
@@ -114,7 +114,8 @@ class WikiSearchParticipant(BaseSearchPa
     default_grid_fields = [
         IndexFields.ID,
         IndexFields.TIME,
-        IndexFields.AUTHOR
+        IndexFields.AUTHOR,
+        IndexFields.CONTENT,
     ]
     prefix = WIKI_TYPE
 

Modified: incubator/bloodhound/trunk/bloodhound_search/bhsearch/templates/bhsearch.html
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/bhsearch/templates/bhsearch.html?rev=1443531&r1=1443530&r2=1443531&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/bhsearch/templates/bhsearch.html (original)
+++ incubator/bloodhound/trunk/bloodhound_search/bhsearch/templates/bhsearch.html Thu Feb
 7 15:03:31 2013
@@ -107,7 +107,7 @@
         </py:if>
 
         <div py:if="results" class="row">
-          <div class="span3">
+          <div class="span3 facets">
             <py:if test="facet_counts">
               <!--Render facet counts-->
               <h3>Facets</h3>

Modified: incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/index_with_whoosh.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/index_with_whoosh.py?rev=1443531&r1=1443530&r2=1443531&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/index_with_whoosh.py (original)
+++ incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/index_with_whoosh.py Thu Feb
 7 15:03:31 2013
@@ -19,7 +19,6 @@
 #  under the License.
 
 import unittest
-import tempfile
 import shutil
 from bhsearch.api import BloodhoundSearchApi
 from bhsearch.search_resources.milestone_search import MilestoneIndexer
@@ -27,13 +26,11 @@ from bhsearch.tests.base import BaseBloo
 from bhsearch.search_resources.ticket_search import TicketIndexer
 
 from bhsearch.whoosh_backend import WhooshBackend
-from trac.test import EnvironmentStub
 
 
 class IndexWhooshTestCase(BaseBloodhoundSearchTest):
     def setUp(self):
-        self.env = EnvironmentStub(enable=['bhsearch.*'])
-        self.env.path = tempfile.mkdtemp('bhsearch-tempenv')
+        super(IndexWhooshTestCase, self).setUp()
         self.whoosh_backend = WhooshBackend(self.env)
         self.whoosh_backend.recreate_index()
         self.search_api = BloodhoundSearchApi(self.env)

Modified: incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/ticket_search.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/ticket_search.py?rev=1443531&r1=1443530&r2=1443531&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/ticket_search.py (original)
+++ incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/ticket_search.py Thu Feb 
7 15:03:31 2013
@@ -18,20 +18,14 @@
 #  specific language governing permissions and limitations
 #  under the License.
 import unittest
-import tempfile
 
 from bhsearch.tests.base import BaseBloodhoundSearchTest
 from bhsearch.search_resources.ticket_search import TicketIndexer
 
-from trac.test import EnvironmentStub
-
-
 class TicketIndexerSilenceOnExceptionTestCase(BaseBloodhoundSearchTest):
     def setUp(self):
-        self.env = EnvironmentStub(
-            enable=['bhsearch.*'],
-            path=tempfile.mkdtemp('bhsearch-tempenv'),
-        )
+        super(TicketIndexerSilenceOnExceptionTestCase, self).setUp()
+        self.env.config.set('bhsearch', 'silence_on_error', "True")
         self.ticket_indexer = TicketIndexer(self.env)
 
     def tearDown(self):

Modified: incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/web_ui.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/web_ui.py?rev=1443531&r1=1443530&r2=1443531&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/web_ui.py (original)
+++ incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/web_ui.py Thu Feb  7 15:03:31
2013
@@ -18,17 +18,17 @@
 #  specific language governing permissions and limitations
 #  under the License.
 import unittest
-import tempfile
-import shutil
 
 from urllib import urlencode, unquote
+from bhsearch.api import ASC, DESC
 
 from bhsearch.tests.base import BaseBloodhoundSearchTest
 from bhsearch.web_ui import RequestParameters
 from bhsearch.whoosh_backend import WhooshBackend
 
-from trac.test import EnvironmentStub, Mock, MockPerm
+from trac.test import Mock, MockPerm
 from trac.ticket import Ticket
+from trac.core import TracError
 from trac.util.datefmt import FixedOffset
 from trac.util import format_datetime
 from trac.web import Href, arg_list_to_args, parse_arg_list, RequestDone
@@ -514,6 +514,21 @@ class WebUiTestCaseWithWhoosh(BaseBloodh
         #assert
         self.assertEqual("grid", data["active_view"])
 
+    def test_can_apply_sorting(self):
+        #arrange
+        self.insert_ticket("T1", component="c1", status="new", milestone="A")
+        self.insert_ticket("T2", component="c1", status="new", milestone="B")
+        self.insert_ticket("T3", component="c3", status="new", milestone="C")
+        #act
+        self.req.args[RequestParameters.QUERY] = "*"
+        self.req.args[RequestParameters.SORT] = "component, milestone desc"
+        data = self.process_request()
+        #assert
+        api_sort = data["debug"]["api_parameters"]["sort"]
+        self.assertEqual([("component", ASC), ("milestone", DESC)], api_sort)
+        ids = [item["summary"] for item in data["results"].items]
+        self.assertEqual(["T2", "T1", "T3"], ids)
+
 
     def _count_parameter_in_url(self, url, parameter_name, value):
         parameter_to_find = (parameter_name, value)
@@ -539,8 +554,53 @@ class WebUiTestCaseWithWhoosh(BaseBloodh
         for i in range(1, n+1):
             self.insert_wiki("test %s" % i)
 
+class RequestParametersTest(unittest.TestCase):
+    def setUp(self):
+        self.req = Mock(
+            perm=MockPerm(),
+            chrome={'logo': {}},
+            href=Href("/main"),
+            base_path=BASE_PATH,
+            args=arg_list_to_args([]),
+        )
+
+    def test_can_parse_multiple_sort_terms(self):
+        self.assertEqual(
+            None,
+            self._evaluate_sort("  "))
+        self.assertEqual(
+            None,
+            self._evaluate_sort(" ,  , "))
+        self.assertEqual(
+            [("f1", ASC),],
+            self._evaluate_sort(" f1 "))
+        self.assertEqual(
+            [("f1", ASC),],
+            self._evaluate_sort(" f1 asc"))
+        self.assertEqual(
+            [("f1", DESC),],
+            self._evaluate_sort("f1  desc"))
+        self.assertEqual(
+            [("f1", ASC), ("f2", DESC)],
+            self._evaluate_sort("f1, f2 desc"))
+
+    def test_can_raise_error_on_invalid_sort_term(self):
+        self.assertRaises(
+            TracError,
+            self._evaluate_sort,
+            "f1  desc bb")
+
+    def _evaluate_sort(self, sort_condition):
+        self.req.args[RequestParameters.SORT] = sort_condition
+        parameters = RequestParameters(self.req)
+        return parameters.sort
+
+
 def suite():
-    return unittest.makeSuite(WebUiTestCaseWithWhoosh, 'test')
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(WebUiTestCaseWithWhoosh, 'test'))
+    suite.addTest(unittest.makeSuite(RequestParametersTest, 'test'))
+    return suite
 
 if __name__ == '__main__':
     unittest.main()

Modified: incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/whoosh_backend.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/whoosh_backend.py?rev=1443531&r1=1443530&r2=1443531&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/whoosh_backend.py (original)
+++ incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/whoosh_backend.py Thu Feb
 7 15:03:31 2013
@@ -27,7 +27,6 @@ from bhsearch.query_parser import Defaul
 from bhsearch.tests.base import BaseBloodhoundSearchTest
 from bhsearch.whoosh_backend import (WhooshBackend,
     WhooshEmptyFacetErrorWorkaround)
-from trac.test import EnvironmentStub
 from trac.util.datefmt import FixedOffset, utc
 from whoosh import index, sorting, query
 from whoosh.fields import Schema, ID, TEXT, KEYWORD
@@ -37,8 +36,7 @@ from whoosh.qparser import MultifieldPlu
 
 class WhooshBackendTestCase(BaseBloodhoundSearchTest):
     def setUp(self):
-        self.env = EnvironmentStub(enable=['bhsearch.*'])
-        self.env.path = tempfile.mkdtemp('bhsearch-tempenv')
+        super(WhooshBackendTestCase, self).setUp()
         self.whoosh_backend = WhooshBackend(self.env)
         self.whoosh_backend.recreate_index()
         self.parser = DefaultQueryParser(self.env)
@@ -453,8 +451,7 @@ class WhooshFunctionalityTestCase(unitte
 
 class WhooshEmptyFacetErrorWorkaroundTestCase(BaseBloodhoundSearchTest):
     def setUp(self):
-        self.env = EnvironmentStub(enable=['bhsearch.*'])
-        self.env.path = tempfile.mkdtemp('bhsearch-tempenv')
+        super(WhooshEmptyFacetErrorWorkaroundTestCase, self).setUp()
         self.whoosh_backend = WhooshBackend(self.env)
         self.whoosh_backend.recreate_index()
         self.parser = DefaultQueryParser(self.env)

Modified: incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/wiki_search.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/wiki_search.py?rev=1443531&r1=1443530&r2=1443531&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/wiki_search.py (original)
+++ incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/wiki_search.py Thu Feb  7
15:03:31 2013
@@ -19,25 +19,21 @@
 #  under the License.
 import shutil
 import unittest
-import tempfile
 
 from bhsearch.api import BloodhoundSearchApi
 from bhsearch.query_parser import DefaultQueryParser
-from bhsearch.tests.utils import BaseBloodhoundSearchTest
+from bhsearch.tests.base import BaseBloodhoundSearchTest
 from bhsearch.whoosh_backend import WhooshBackend
 from bhsearch.search_resources.wiki_search import (
     WikiIndexer, WikiSearchParticipant)
 
-from trac.test import EnvironmentStub
 from trac.wiki import WikiSystem, WikiPage
 
 
 class WikiIndexerSilenceOnExceptionTestCase(BaseBloodhoundSearchTest):
     def setUp(self):
-        self.env = EnvironmentStub(
-            enable=['bhsearch.*'],
-            path=tempfile.mkdtemp('bhsearch-tempenv'),
-        )
+        super(WikiIndexerSilenceOnExceptionTestCase, self).setUp()
+        self.env.config.set('bhsearch', 'silence_on_error', "True")
         self.wiki_indexer = WikiIndexer(self.env)
 
     def tearDown(self):
@@ -57,9 +53,7 @@ class WikiIndexerEventsTestCase(BaseBloo
     DUMMY_PAGE_NAME = "dummyName"
 
     def setUp(self):
-        self.env = EnvironmentStub(enable=['bhsearch.*'])
-        self.env.path = tempfile.mkdtemp('bhsearch-tempenv')
-        self.env.config.set('bhsearch', 'silence_on_error', "False")
+        super(WikiIndexerEventsTestCase, self).setUp()
         self.wiki_system = WikiSystem(self.env)
         self.whoosh_backend = WhooshBackend(self.env)
         self.whoosh_backend.recreate_index()

Modified: incubator/bloodhound/trunk/bloodhound_search/bhsearch/web_ui.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/bhsearch/web_ui.py?rev=1443531&r1=1443530&r2=1443531&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/bhsearch/web_ui.py (original)
+++ incubator/bloodhound/trunk/bloodhound_search/bhsearch/web_ui.py Thu Feb  7 15:03:31 2013
@@ -43,8 +43,6 @@ from trac.wiki.formatter import extract_
 
 SEARCH_PERMISSION = 'SEARCH_VIEW'
 DEFAULT_RESULTS_PER_PAGE = 10
-DEFAULT_SORT = [(SCORE, ASC), ("time", DESC)]
-#VIEW_GRID = "grid"
 
 class RequestParameters(object):
     """
@@ -59,6 +57,7 @@ class RequestParameters(object):
     PAGELEN = "pagelen"
     FILTER_QUERY = "fq"
     VIEW = "view"
+    SORT = "sort"
 
     def __init__(self, req):
         self.req = req
@@ -76,14 +75,14 @@ class RequestParameters(object):
         self.filter_queries = self._remove_possible_duplications(
             self.filter_queries)
 
-        #TODO: retrieve sort from query string
-        self.sort = DEFAULT_SORT
+        sort_string = req.args.getfirst(self.SORT)
+        self.sort = self._parse_sort(sort_string)
 
         self.pagelen = int(req.args.getfirst(
             RequestParameters.PAGELEN,
             DEFAULT_RESULTS_PER_PAGE))
         self.page = int(req.args.getfirst(self.PAGE, '1'))
-        self.type = req.args.getfirst(self.TYPE, None)
+        self.type = req.args.getfirst(self.TYPE)
 
         self.params = {
             RequestParameters.FILTER_QUERY: []
@@ -103,6 +102,42 @@ class RequestParameters(object):
             self.params[self.TYPE] = self.type
         if self.filter_queries:
             self.params[RequestParameters.FILTER_QUERY] = self.filter_queries
+        if sort_string:
+            self.params[RequestParameters.SORT] = sort_string
+
+    def _parse_sort(self, sort_string):
+        if not sort_string:
+            return None
+        sort_terms = sort_string.split(",")
+        sort = []
+
+        def parse_sort_order(sort_order):
+            sort_order = sort_order.lower()
+            if sort_order == ASC:
+                return ASC
+            elif sort_order == DESC:
+                return DESC
+            else:
+                raise TracError(
+                    "Invalid sort order %s in sort parameter %s" %
+                    (sort_order, sort_string))
+
+        for term in sort_terms:
+            term = term.strip()
+            if not term:
+                continue
+            term_parts = term.split()
+            parts_count = len(term_parts)
+            if parts_count == 1:
+                sort.append((term_parts[0], ASC))
+            elif parts_count == 2:
+                sort.append((term_parts[0], parse_sort_order(term_parts[1])))
+            else:
+                raise TracError("Invalid sort term %s " % term)
+
+        return sort if sort else None
+
+
 
     def _remove_possible_duplications(self, parameters_list):
         seen = set()
@@ -169,8 +204,8 @@ class BloodhoundSearchModule(Component):
         DATA_VIEW_GRID: "Grid"
     }
     VIEWS_WITH_KNOWN_FIELDS = [DATA_VIEW_GRID]
-
     OBLIGATORY_FIELDS_TO_SELECT = [IndexFields.ID, IndexFields.TYPE]
+    DEFAULT_SORT = [(SCORE, ASC), ("time", DESC)]
 
     implements(INavigationContributor, IPermissionRequestor, IRequestHandler,
         ITemplateProvider,
@@ -261,12 +296,14 @@ class BloodhoundSearchModule(Component):
 
         facets = self._prepare_facets(parameters, allowed_participants)
 
+        sort = parameters.sort if parameters.sort else self.DEFAULT_SORT
+
         query_system = BloodhoundSearchApi(self.env)
         query_result = query_system.query(
             parameters.query,
             pagenum=parameters.page,
             pagelen=parameters.pagelen,
-            sort=parameters.sort,
+            sort=sort,
             fields=fields,
             facets=facets,
             filter=query_filter,
@@ -301,6 +338,7 @@ class BloodhoundSearchModule(Component):
             add_link(req, 'prev', prev_href, _('Previous Page'))
 
         data['results'] = results
+        data['debug'] = query_result.debug
 
         self._prepare_result_facet_counts(
             parameters,
@@ -572,7 +610,8 @@ class BloodhoundSearchModule(Component):
         ui_doc["href"] = req.href(doc['type'], doc['id'])
         #todo: perform content adaptation here
         if doc.has_key('content'):
-            ui_doc['excerpt'] = shorten_result(doc['content'])
+#            ui_doc['excerpt'] = shorten_result(doc['content'])
+            ui_doc['content'] = shorten_result(doc['content'])
         if doc.has_key('time'):
             ui_doc['date'] = user_time(req, format_datetime, doc['time'])
 

Modified: incubator/bloodhound/trunk/bloodhound_theme/bhtheme/htdocs/bloodhound.css
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_theme/bhtheme/htdocs/bloodhound.css?rev=1443531&r1=1443530&r2=1443531&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_theme/bhtheme/htdocs/bloodhound.css (original)
+++ incubator/bloodhound/trunk/bloodhound_theme/bhtheme/htdocs/bloodhound.css Thu Feb  7 15:03:31
2013
@@ -542,6 +542,12 @@ input[type="submit"].btn.btn-micro {
   }
 }
 
+@media (min-width: 1200px) {
+  .facets {
+      width: 220px;
+  }
+}
+
 @media (min-width: 979px) and (max-width: 1199px) {
   .main-nav ul {
     background-color: red;



Mime
View raw message