def test_full_build_and_search(self, with_admin_login, index_builder, index_searcher): index_builder.build_full_index() assert list(index_searcher.search("**")) == [ ("Change-dependent", [SearchResult(title="change_dependent", url="")]), ("Localization-dependent", [SearchResult(title="localization_dependent", url="")]), ]
def test_full_build_and_search( self, index_builder: IndexBuilder, index_searcher: IndexSearcher, ) -> None: index_builder.build_full_index() assert list(index_searcher.search("**")) == [ ("Change-dependent", [SearchResult(title="change_dependent", url="")]), ("Localization-dependent", [SearchResult(title="localization_dependent", url="")]), ]
def _generate_display_texts( self, elements: List[LivestatusResult]) -> List[SearchResult]: """Creates the text displayed to the user Analyzes all display texts and ensures that we have unique ones""" for element in elements: if self.livestatus_table == "services": element.display_text = element.row["description"] else: element.display_text = element.text_tokens[0][1] if self._element_texts_unique(elements): return [ SearchResult(title=e.display_text, url=e.url) for e in elements ] # Some (ugly) special handling when the results are not unique # Whenever this happens we try to find a fitting second value if self.livestatus_table in ["hostgroups", "servicegroups"]: # Discard redundant hostgroups results: List[SearchResult] = [] used_groups: Set[str] = set() for element in elements: if element.display_text in used_groups: continue results.append( SearchResult(title=element.display_text, url=element.url)) used_groups.add(element.display_text) return results # Add additional info to the display text for element in elements: hostname = element.row.get("host_name", element.row.get("name")) if "&host_regex=" not in element.url: element.url += "&host_regex=%s" % hostname for shortname, text in element.text_tokens: if shortname in ["h", "al" ] and text not in element.display_text: element.display_text += " <b>%s</b>" % text break else: element.display_text += " <b>%s</b>" % hostname return [ SearchResult(title=e.display_text, url=e.url) for e in elements ]
def search(self, query: SearchQuery) -> SearchResultsByTopic: query_lowercase = query.lower() results = DefaultDict(list) index = self._index_store.load_index() if self._current_language not in index.localization_dependent: build_and_store_index_background() raise IndexNotFoundException for topic, match_items in chain( index.localization_independent.items(), index.localization_dependent[self._current_language].items(), ): if not self._may_see_topic.get(topic, True): continue permissions_check = self._may_see_item_func.get( topic, lambda _: True) for match_item in match_items: if (any(query_lowercase in match_text for match_text in match_item.match_texts) and permissions_check(match_item.url)): results[match_item.topic].append( SearchResult( match_item.title, match_item.url, )) yield from self._sort_search_results(results)
def test_update_with_empty_and_search( self, monkeypatch: MonkeyPatch, match_item_generator_registry: MatchItemGeneratorRegistry, index_builder: IndexBuilder, index_searcher: IndexSearcher, ) -> None: """ Test if things can also be deleted from the index during an update """ def empty_match_item_gen(): yield from () index_builder.build_full_index() monkeypatch.setattr( match_item_generator_registry["change_dependent"], "generate_match_items", empty_match_item_gen, ) index_builder.build_changed_sub_indices("some_change_dependent_whatever") assert list(index_searcher.search("**")) == [ ("Localization-dependent", [SearchResult(title="localization_dependent", url="")]), ]
def _search_redis( self, query: str, key_categories: str, key_prefix_match_items: str, results: DefaultDict[str, List[SearchResult]], ) -> None: for category in self._redis_client.smembers(key_categories): if not self._may_see_category(category): continue prefix_category = IndexBuilder.add_to_prefix( key_prefix_match_items, category, ) permissions_check = self._may_see_item_func.get( category, lambda _: True) for _matched_text, idx_matched_item in self._redis_client.hscan_iter( IndexBuilder.key_match_texts(prefix_category), match=query, ): match_item_dict = self._redis_client.hgetall( IndexBuilder.add_to_prefix(prefix_category, idx_matched_item)) if not permissions_check(match_item_dict["url"]): continue results[match_item_dict["topic"]].append( SearchResult( match_item_dict["title"], match_item_dict["url"], ))
def test_sort_search_results(self) -> None: assert list( IndexSearcher._sort_search_results( { "Hosts": [SearchResult(title="host", url="")], "Setup": [SearchResult(title="setup_menu_entry", url="")], "Global settings": [SearchResult(title="global_setting", url="")], "Other topic": [SearchResult(title="other_item", url="")], "Another topic": [SearchResult(title="another_item", url="")], } ) ) == [ ("Setup", [SearchResult(title="setup_menu_entry", url="")]), ("Hosts", [SearchResult(title="host", url="")]), ("Another topic", [SearchResult(title="another_item", url="")]), ("Other topic", [SearchResult(title="other_item", url="")]), ("Global settings", [SearchResult(title="global_setting", url="")]), ]
def test_sort_search_results(self): assert list( IndexSearcher._sort_search_results({ "Hosts": [SearchResult(title="host", url="")], "Setup": [SearchResult(title="setup_menu_entry", url="")], "Global settings": [SearchResult(title="global_setting", url="")], "Other topic": [SearchResult(title="other_item", url="")], "Another topic": [SearchResult(title="another_item", url="")], })) == [ ('Setup', [SearchResult(title='setup_menu_entry', url='')]), ('Hosts', [SearchResult(title='host', url='')]), ('Another topic', [SearchResult(title='another_item', url='')]), ('Other topic', [SearchResult(title='other_item', url='')]), ('Global settings', [SearchResult(title='global_setting', url='')]), ]
def test_update_and_search_with_update( self, index_builder: IndexBuilder, index_searcher: IndexSearcher, ) -> None: index_builder._mark_index_as_built() index_builder.build_changed_sub_indices("some_change_dependent_whatever") assert list(index_searcher.search("**")) == [ ("Change-dependent", [SearchResult(title="change_dependent", url="")]), ]
def search(self, query: SearchQuery) -> SearchResultsByTopic: query_lowercase = query.lower() results: Dict[str, List[SearchResult]] = {} for match_item in self._index_store.all_match_items(): if any(query_lowercase in match_text for match_text in match_item.match_texts): results.setdefault( match_item.topic, [], ).append(SearchResult( match_item.title, match_item.url, )) return results
def _search_redis( self, query: str, key_categories: str, key_prefix_match_items: str, results: DefaultDict[str, List[SearchResult]], ) -> None: for category in self._redis_client.smembers(key_categories): if not self._may_see_category(category): continue prefix_category = IndexBuilder.add_to_prefix( key_prefix_match_items, category, ) permissions_check = self._may_see_item_func.get( category, lambda _: True) for _matched_text, idx_matched_item in self._redis_client.hscan_iter( IndexBuilder.key_match_texts(prefix_category), match=query, ): match_item_dict = self._redis_client.hgetall( IndexBuilder.add_to_prefix(prefix_category, idx_matched_item)) if not permissions_check(match_item_dict["url"]): continue # This call to i18n._ with a non-constant string is ok. Here, we translate the # topics of our search results. For localization-dependent search results, such as # rulesets, they are already localized anyway. However, for localization-independent # results, such as hosts, they are not. For example, "Hosts" in French is "Hôtes". # Without this call to i18n._, found hosts would be displayed under the topic # "Hosts" instead of "Hôtes" in the setup search. # pylint: disable=translation-of-non-string results[_(match_item_dict["topic"])].append( SearchResult( match_item_dict["title"], match_item_dict["url"], ))
def search(self, query: SearchQuery) -> SearchResultsByTopic: query_lowercase = query.lower() results = DefaultDict(list) for topic, match_items in self._index_store.load_index().items(): if not self._may_see_topic.get(topic, True): continue permissions_check = self._may_see_item_func.get( topic, lambda _: True) for match_item in match_items: if (any(query_lowercase in match_text for match_text in match_item.match_texts) and permissions_check(match_item.url)): results[match_item.topic].append( SearchResult( match_item.title, match_item.url, )) yield from self._sort_search_results(results)
def search(self, query: SearchQuery) -> SearchResultsByTopic: query_lowercase = query.lower() results: Dict[str, List[SearchResult]] = {} for topic, match_items in self._index_store.load_index().items(): if not self._may_see_topic.get(topic, True): continue permissions_check = self._may_see_item_func.get( topic, lambda _: True) for match_item in match_items: if (any(query_lowercase in match_text for match_text in match_item.match_texts) and permissions_check(match_item.url)): results.setdefault( match_item.topic, [], ).append(SearchResult( match_item.title, match_item.url, )) return results
def test_update_with_empty_and_search( self, with_admin_login, match_item_generator_registry, index_builder, index_searcher, ): """ Test if things can also be deleted from the index during an update """ def empty_match_item_gen(): yield from () index_builder.build_full_index() match_item_generator_registry[ "change_dependent"].generate_match_items = empty_match_item_gen index_builder.build_changed_sub_indices( "some_change_dependent_whatever") assert list(index_searcher.search("**")) == [ ("Localization-dependent", [SearchResult(title="localization_dependent", url="")]), ]