""" open/dulcinea/lib/ui/lib/search.qpy """ from dulcinea.ui.table import Table from qp.pub.common import get_path, header, footer, get_request from qp.fill.form import Form from qp.fill.html import href, url_with_query, url_unquote from qp.fill.widget import HiddenWidget, OptionSelectWidget from qp.fill.widget import StringWidget from qp.http.request import parse_query from qpy import xml import re def format_context(keywords, context, delta=40, length=80): sample = '' for keyword in keywords.split(): pos = context.lower().find(keyword.lower()) if pos >= 0: start = max(0, pos - delta) k = start while k < pos: if context[k] == '\n': start = k + 1 break k += 1 if k == pos: k = start while k < pos: if context[k] == ' ': start = k + 1 break k += 1 if k < pos: sample = context[start:start + length] break while sample and sample[-1] not in ' \n': sample = sample[:-1] return highlight_keywords(sample, keywords) def highlight_keywords(content, keywords): if keywords: pat = '|'.join([url_unquote(keyword) for keyword in keywords.split()]) try: regex = re.compile(pat, re.IGNORECASE) except re.error: return xml(content) def highlight_match:xml(matchobj): return '%s' % matchobj.group(0) content, count = regex.subn(highlight_match, content) return xml(content) def keywords_from_query:xml(): query = parse_query(get_request().get_query(), 'ascii') if 'keywords' in query: query['keywords'] class SearchForm (object): def __init__(self, search_space, matches_per_page=20, require_keywords=False, show_all_option=False, exports=None): if show_all_option: search_space = list(search_space) self.form, self.keywords, matches = self.get_form_keywords_matches( search_space, matches_per_page=matches_per_page, require_keywords=require_keywords, show_all_option=show_all_option) try: page_size = int(self.form.get('page_size')) if 0 < page_size <= len(search_space): matches_per_page = page_size except (TypeError, ValueError): pass self.matches_per_page = matches_per_page self.exports = exports self.pages = [] page = [] for item in matches: page.append(item) if len(page) == matches_per_page: self.pages.append(page) page = [] if page: self.pages.append(page) pages = len(self.pages) if pages == 0: self.page_number = None elif pages == 1: self.page_number = 0 else: self.form.add(HiddenWidget, 'page_number', value='0') try: self.page_number = int(self.form.get('page_number') or '0') except ValueError: self.page_number = 0 else: if self.page_number >= pages or self.page_number < 0: self.page_number = 0 def gen_matches(self, search_space, keywords): re_keywords = [re.compile(r'\b%s\b' % re.escape(keyword), re.I).search for keyword in keywords.split()] for item in search_space: text = self.get_search_text(item) for pattern_search in re_keywords: if not pattern_search(text): break else: yield item def get_form_keywords_matches(self, search_space, matches_per_page=20, require_keywords=False, show_all_option=False): if self.get_title(): title = ' ' + self.get_title() else: title = '' search_title = "Search" + title form = Form(method='get', use_tokens=False) form.add(StringWidget, 'keywords', size=40, onfocus="this.value=''", value="Search" + title) keywords = form.get('keywords') or '' if keywords == search_title: keywords = '' if require_keywords and not keywords: matches = [] elif search_space and not keywords or keywords == '*': matches = list(search_space) else: matches = list(self.gen_matches(search_space, keywords)) page_size_options = set([10, 20, 50, 100]) if matches_per_page not in page_size_options: page_size_options.add(matches_per_page) if show_all_option: page_size_options.add(len(search_space)) page_size_options = sorted(page_size_options) form.add(OptionSelectWidget, 'page_size', value=matches_per_page, hint="per page", options=page_size_options) return form, keywords, matches def format_context(self, context, delta=40, length=80): return format_context(self.keywords, context, delta=delta, length=length) def get_search_text(self, item): return " ".join(self.get_search_text_fields(item)) def get_search_text_fields(self, item): return item.get_search_text_fields() def get_title(self): raise RuntimeError('Abstract get_title() method called') def header(self, title): return header(title) def format_no_matches:xml(self): '
There are no results that match your search terms.
''' else: '''Enter one or more search terms separated by spaces.
''' def format_search_results_headings:xml(self): raise RuntimeError('Abstract format_search_results_headings() method') def format_search_results_table_row:xml(self, item): raise RuntimeError('Abstract format_search_results_table_row() method') def footer(self, title): return footer(title) def format_matches:xml(self): '