Support keyword filtering (records having keywords a and b but not c and d) (#256)
* Support keyword filtering (records having keywords a and b but not c and d) * Remove debug statements. * Left a pass statement by mistake. * Update cli help to show word list '[...]' after search options. * Add space after method doc. * Change cli option '-W --without' to '-x --exclude'
This commit is contained in:
parent
474c403521
commit
e12d2f95f0
39
buku.py
39
buku.py
@ -1273,6 +1273,25 @@ class BukuDb:
|
||||
stag_results = self.search_by_tag(''.join(stag))
|
||||
return list(set(keyword_results) & set(stag_results))
|
||||
|
||||
def exclude_results_from_search(self, search_results, without, deep):
|
||||
"""Excludes records that match keyword search using without parameters
|
||||
|
||||
Parameters
|
||||
----------
|
||||
search_results : list
|
||||
List of search results
|
||||
without : list of str
|
||||
Keywords to search.
|
||||
deep : bool, optional
|
||||
True to search for matching substrings.
|
||||
Returns
|
||||
-------
|
||||
list or None
|
||||
List of search results, or None if no matches.
|
||||
"""
|
||||
|
||||
return list(set(search_results) - set(self.searchdb(without, False, deep)))
|
||||
|
||||
def compactdb(self, index, delay_commit=False):
|
||||
"""When an entry at index is deleted, move the
|
||||
last entry in DB to index, if index is lesser.
|
||||
@ -4089,14 +4108,16 @@ POSITIONAL ARGUMENTS:
|
||||
|
||||
search_grp = argparser.add_argument_group(
|
||||
title='SEARCH OPTIONS',
|
||||
description=''' -s, --sany find records with ANY matching keyword
|
||||
description=''' -s, --sany [...] find records with ANY matching keyword
|
||||
this is the default search option
|
||||
-S, --sall find records matching ALL the keywords
|
||||
-S, --sall [...] find records matching ALL the keywords
|
||||
special keywords -
|
||||
"blank": entries with empty title/tag
|
||||
"immutable": entries with locked title
|
||||
-x, --exclude [...] combine with keyword search to exclude
|
||||
records
|
||||
--deep match substrings ('pen' matches 'opens')
|
||||
-r, --sreg run a regex search
|
||||
-r, --sreg [...] run a regex search
|
||||
-t, --stag [tag [,|+] ...] [- tag, ...]
|
||||
search bookmarks by tags
|
||||
use ',' to find entries matching ANY tag
|
||||
@ -4109,6 +4130,7 @@ POSITIONAL ARGUMENTS:
|
||||
addarg('-r', '--sreg', nargs='*', help=HIDE)
|
||||
addarg('--deep', action='store_true', help=HIDE)
|
||||
addarg('-t', '--stag', nargs='*', help=HIDE)
|
||||
addarg('-x', '--exclude', nargs='*', help=HIDE)
|
||||
|
||||
# ------------------------
|
||||
# ENCRYPTION OPTIONS GROUP
|
||||
@ -4352,6 +4374,7 @@ POSITIONAL ARGUMENTS:
|
||||
search_opted = True
|
||||
update_search_results = False
|
||||
tags_search = True if (args.stag is not None and len(args.stag)) else False
|
||||
exclude_results = True if (args.exclude is not None and len(args.exclude)) else False
|
||||
|
||||
if args.sany is not None:
|
||||
if len(args.sany):
|
||||
@ -4361,6 +4384,8 @@ POSITIONAL ARGUMENTS:
|
||||
else:
|
||||
# Search URLs, titles, tags for any keyword
|
||||
search_results = bdb.searchdb(args.sany, False, args.deep)
|
||||
if exclude_results:
|
||||
search_results = bdb.exclude_results_from_search(search_results, args.exclude, args.deep)
|
||||
else:
|
||||
logerr('no keyword')
|
||||
elif args.sall is not None:
|
||||
@ -4371,8 +4396,16 @@ POSITIONAL ARGUMENTS:
|
||||
else:
|
||||
# Search URLs, titles, tags with all keywords
|
||||
search_results = bdb.searchdb(args.sall, True, args.deep)
|
||||
if exclude_results:
|
||||
search_results = bdb.exclude_results_from_search(search_results, args.exclude, args.deep)
|
||||
else:
|
||||
logerr('no keyword')
|
||||
|
||||
elif args.exclude is not None:
|
||||
if len(args.exclude) and len(search_results):
|
||||
exclude_results = bdb.search_keywords_and_filter_by_tags(args.exclude, True, args.deep, False, None)
|
||||
search_results = list(set(search_results) - set(exclude_results))
|
||||
|
||||
elif args.sreg is not None:
|
||||
if len(args.sreg):
|
||||
# Apply tag filtering, if opted
|
||||
|
@ -1330,6 +1330,27 @@ def test_search_keywords_and_filter_by_tags(keyword_results, stag_results, exp_r
|
||||
assert exp_res == res
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'search_results, exclude_results, exp_res',
|
||||
[
|
||||
([], [], []),
|
||||
(['item1', 'item2'], ['item2'], ['item1']),
|
||||
(['item2'], ['item1'], ['item2']),
|
||||
(['item1', 'item2'], ['item1', 'item2'], []),
|
||||
]
|
||||
)
|
||||
def test_exclude_results_from_search(search_results, exclude_results, exp_res):
|
||||
"""test method."""
|
||||
# init
|
||||
import buku
|
||||
bdb = buku.BukuDb()
|
||||
bdb.searchdb = mock.Mock(return_value=exclude_results)
|
||||
# test
|
||||
res = bdb.exclude_results_from_search(
|
||||
search_results, [], True)
|
||||
assert exp_res == res
|
||||
|
||||
|
||||
# Helper functions for testcases
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user