search.py
120 lines
| 4.5 KiB
| text/x-python
|
PythonLexer
r861 | # -*- coding: utf-8 -*- | |||
""" | ||||
rhodecode.controllers.search | ||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
Search controller for rhodecode | ||||
:created_on: Aug 7, 2010 | ||||
:author: marcink | ||||
:copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com> | ||||
:license: GPLv3, see COPYING for more details. | ||||
""" | ||||
r547 | # This program is free software; you can redistribute it and/or | |||
# modify it under the terms of the GNU General Public License | ||||
# as published by the Free Software Foundation; version 2 | ||||
# of the License or (at your opinion) any later version of the license. | ||||
# | ||||
# This program is distributed in the hope that it will be useful, | ||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
# GNU General Public License for more details. | ||||
# | ||||
# You should have received a copy of the GNU General Public License | ||||
# along with this program; if not, write to the Free Software | ||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | ||||
# MA 02110-1301, USA. | ||||
r861 | import logging | |||
import traceback | ||||
from pylons.i18n.translation import _ | ||||
r688 | from pylons import request, response, config, session, tmpl_context as c, url | |||
r547 | from pylons.controllers.util import abort, redirect | |||
r861 | ||||
r547 | from rhodecode.lib.auth import LoginRequired | |||
from rhodecode.lib.base import BaseController, render | ||||
r688 | from rhodecode.lib.indexers import SCHEMA, IDX_NAME, ResultWrapper | |||
r861 | ||||
r547 | from webhelpers.paginate import Page | |||
from webhelpers.util import update_params | ||||
r861 | ||||
r547 | from whoosh.index import open_dir, EmptyIndexError | |||
from whoosh.qparser import QueryParser, QueryParserError | ||||
from whoosh.query import Phrase | ||||
log = logging.getLogger(__name__) | ||||
class SearchController(BaseController): | ||||
@LoginRequired() | ||||
def __before__(self): | ||||
r688 | super(SearchController, self).__before__() | |||
r547 | ||||
def index(self, search_repo=None): | ||||
c.repo_name = search_repo | ||||
c.formated_results = [] | ||||
c.runtime = '' | ||||
c.cur_query = request.GET.get('q', None) | ||||
r556 | c.cur_type = request.GET.get('type', 'source') | |||
c.cur_search = search_type = {'content':'content', | ||||
'commit':'content', | ||||
'path':'path', | ||||
'repository':'repository'}\ | ||||
.get(c.cur_type, 'content') | ||||
r688 | ||||
r547 | if c.cur_query: | |||
cur_query = c.cur_query.lower() | ||||
r688 | ||||
r547 | if c.cur_query: | |||
p = int(request.params.get('page', 1)) | ||||
highlight_items = set() | ||||
try: | ||||
r688 | idx = open_dir(config['app_conf']['index_dir'] | |||
, indexname=IDX_NAME) | ||||
r547 | searcher = idx.searcher() | |||
r556 | qp = QueryParser(search_type, schema=SCHEMA) | |||
r547 | if c.repo_name: | |||
cur_query = u'repository:%s %s' % (c.repo_name, cur_query) | ||||
try: | ||||
query = qp.parse(unicode(cur_query)) | ||||
r688 | ||||
r547 | if isinstance(query, Phrase): | |||
highlight_items.update(query.words) | ||||
else: | ||||
for i in query.all_terms(): | ||||
if i[0] == 'content': | ||||
highlight_items.add(i[1]) | ||||
matcher = query.matcher(searcher) | ||||
r688 | ||||
r547 | log.debug(query) | |||
log.debug(highlight_items) | ||||
results = searcher.search(query) | ||||
res_ln = len(results) | ||||
c.runtime = '%s results (%.3f seconds)' \ | ||||
r556 | % (res_ln, results.runtime) | |||
r688 | ||||
r547 | def url_generator(**kw): | |||
r556 | return update_params("?q=%s&type=%s" \ | |||
% (c.cur_query, c.cur_search), **kw) | ||||
r547 | ||||
c.formated_results = Page( | ||||
r556 | ResultWrapper(search_type, searcher, matcher, | |||
highlight_items), | ||||
r547 | page=p, item_count=res_ln, | |||
items_per_page=10, url=url_generator) | ||||
r688 | ||||
r547 | except QueryParserError: | |||
c.runtime = _('Invalid search query. Try quoting it.') | ||||
searcher.close() | ||||
except (EmptyIndexError, IOError): | ||||
log.error(traceback.format_exc()) | ||||
log.error('Empty Index data') | ||||
r861 | c.runtime = _('There is no index to search in. ' | |||
'Please run whoosh indexer') | ||||
r688 | ||||
r547 | # Return a rendered template | |||
return render('/search/search.html') | ||||