From cb95122be5514debaa1c03128d8704d9c89c74ab Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 23 Sep 2017 13:01:37 -0400 Subject: [PATCH] Search honors field filters: implements print_rec_with_filter (#216) * Initial test of print_rec_with_filter * Replace dummy code to actually pass test * Call print_rec_with_filter if search options are used with --format * Call print_rec_with_filter in print_rec; add field_filters, update test * Add new format_filters to argparse arguments to --format * Update help for --format * Update man page and remove trailing whitespace * Fix test cases * Update README * Call print_single_rec from print_rec_with_filter if filt is 0 * Add create=True to buku.print mock * Update Help text * Update README * Update man page --- README.md | 3 +- buku.1 | 2 ++ buku.py | 79 +++++++++++++++++++++++++++++----------------- tests/test_buku.py | 62 ++++++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 5bf4a3a..9f75bac 100644 --- a/README.md +++ b/README.md @@ -216,7 +216,8 @@ POWER TOYS: -n shows the last n results (like tail) -f, --format N limit fields in -p or Json search output N=1: URL, N=2: URL and tag, N=3: title, - N=4: URL, title and tag + N=4: URL, title and tag. To omit DB index, + use N0, e.g, 10, 20, 30, 40. -j, --json Json formatted output for -p and search --colors COLORS set output colors in five-letter string --nc disable color output diff --git a/buku.1 b/buku.1 index 1242e4d..a6117e5 100644 --- a/buku.1 +++ b/buku.1 @@ -214,6 +214,8 @@ Show selective monochrome output with specific fields. Works with --print. Searc .br .I N = 4, show URL, title and tags in a single line +.br +To omit DB index from printed results, use N0, e.g., 10, 20, 30, 40. .TP .BI \-j " " \--json Output data formatted as json, works with --print output and search results. diff --git a/buku.py b/buku.py index cb685dd..99ef672 100755 --- a/buku.py +++ b/buku.py @@ -1561,17 +1561,7 @@ class BukuDb: return if not self.json: - for row in results: - if self.field_filter == 0: - print_single_rec(row) - elif self.field_filter == 1: - print('%s\t%s' % (row[0], row[1])) - elif self.field_filter == 2: - print('%s\t%s\t%s' % (row[0], row[1], row[3][1:-1])) - elif self.field_filter == 3: - print('%s\t%s' % (row[0], row[2])) - elif self.field_filter == 4: - print('%s\t%s\t%s\t%s' % (row[0], row[1], row[2], row[3][1:-1])) + print_rec_with_filter(results, self.field_filter) else: print(format_json(results, True, self.field_filter)) @@ -1585,21 +1575,7 @@ class BukuDb: return if not self.json: - if self.field_filter == 0: - for row in resultset: - print_single_rec(row) - elif self.field_filter == 1: - for row in resultset: - print('%s\t%s' % (row[0], row[1])) - elif self.field_filter == 2: - for row in resultset: - print('%s\t%s\t%s' % (row[0], row[1], row[3][1:-1])) - elif self.field_filter == 3: - for row in resultset: - print('%s\t%s' % (row[0], row[2])) - elif self.field_filter == 4: - for row in resultset: - print('%s\t%s\t%s\t%s' % (row[0], row[1], row[2], row[3][1:-1])) + print_rec_with_filter(resultset, self.field_filter) else: print(format_json(resultset, field_filter=self.field_filter)) @@ -3234,6 +3210,48 @@ def prompt(obj, results, noninteractive=False, deep=False, subprompt=False, sugg break +def print_rec_with_filter(records, field_filter=0): + """Print records filtered by field. + + User determines which fields in the records to display + by using the --format option. + + Parameters + ---------- + records : list or sqlite3.Cursor object + List of bookmark records to print + field_filter : int + Integer indicating which fields to print. + """ + + if field_filter == 0: + for row in records: + print_single_rec(row) + elif field_filter == 1: + for row in records: + print('%s\t%s' % (row[0], row[1])) + elif field_filter == 2: + for row in records: + print('%s\t%s\t%s' % (row[0], row[1], row[3][1:-1])) + elif field_filter == 3: + for row in records: + print('%s\t%s' % (row[0], row[2])) + elif field_filter == 4: + for row in records: + print('%s\t%s\t%s\t%s' % (row[0], row[1], row[2], row[3][1:-1])) + elif field_filter == 10: + for row in records: + print(row[1]) + elif field_filter == 20: + for row in records: + print('%s\t%s' % (row[1], row[3][1:-1])) + elif field_filter == 30: + for row in records: + print(row[2]) + elif field_filter == 40: + for row in records: + print('%s\t%s\t%s' % (row[1], row[2], row[3][1:-1])) + def print_single_rec(row, idx=0): # NOQA """Print a single DB record. @@ -3927,7 +3945,8 @@ POSITIONAL ARGUMENTS: -n shows the last n results (like tail) -f, --format N limit fields in -p or Json search output N=1: URL, N=2: URL and tag, N=3: title, - N=4: URL, title and tag + N=4: URL, title and tag. To omit DB index, + use N0, e.g., 10, 20, 30, 40. -j, --json Json formatted output for -p and search --colors COLORS set output colors in five-letter string --nc disable color output @@ -3950,7 +3969,7 @@ POSITIONAL ARGUMENTS: addarg('-e', '--export', nargs=1, help=HIDE) addarg('-i', '--import', nargs=1, dest='importfile', help=HIDE) addarg('-p', '--print', nargs='*', help=HIDE) - addarg('-f', '--format', type=int, default=0, choices={1, 2, 3, 4}, help=HIDE) + addarg('-f', '--format', type=int, default=0, choices={1, 2, 3, 4, 10, 20, 30, 40}, help=HIDE) addarg('-j', '--json', action='store_true', help=HIDE) addarg('--colors', dest='colorstr', type=argparser.is_colorstr, default=colorstr_env if colorstr_env else 'oKlxm', metavar='COLORS', help=HIDE) @@ -4163,8 +4182,10 @@ POSITIONAL ARGUMENTS: oneshot = True update_search_results = True - if not args.json: + if not args.json and not args.format: prompt(bdb, search_results, oneshot, args.deep) + elif not args.json: + print_rec_with_filter(search_results, field_filter=args.format) else: # Printing in Json format is non-interactive print(format_json(search_results, field_filter=args.format)) diff --git a/tests/test_buku.py b/tests/test_buku.py index 6c80765..fb3ac47 100644 --- a/tests/test_buku.py +++ b/tests/test_buku.py @@ -107,6 +107,68 @@ def test_parse_tags(keywords, exp_res): assert res == exp_res +@pytest.mark.parametrize( + 'records, field_filter, exp_res', + [ + [ + [(1, 'http://url1.com', 'title1', ',tag1,'), + (2, 'http://url2.com', 'title2', ',tag1,tag2,')], + 1, + ['1\thttp://url1.com', '2\thttp://url2.com'] + ], + [ + [(1, 'http://url1.com', 'title1', ',tag1,'), + (2, 'http://url2.com', 'title2', ',tag1,tag2,')], + 2, + ['1\thttp://url1.com\ttag1', '2\thttp://url2.com\ttag1,tag2'] + ], + [ + [(1, 'http://url1.com', 'title1', ',tag1,'), + (2, 'http://url2.com', 'title2', ',tag1,tag2,')], + 3, + ['1\ttitle1', '2\ttitle2'] + ], + [ + [(1, 'http://url1.com', 'title1', ',tag1,'), + (2, 'http://url2.com', 'title2', ',tag1,tag2,')], + 4, + ['1\thttp://url1.com\ttitle1\ttag1', '2\thttp://url2.com\ttitle2\ttag1,tag2'] + ], + [ + [(1, 'http://url1.com', 'title1', ',tag1,'), + (2, 'http://url2.com', 'title2', ',tag1,tag2,')], + 10, + ['http://url1.com', 'http://url2.com'] + ], + [ + [(1, 'http://url1.com', 'title1', ',tag1,'), + (2, 'http://url2.com', 'title2', ',tag1,tag2,')], + 20, + ['http://url1.com\ttag1', 'http://url2.com\ttag1,tag2'] + ], + [ + [(1, 'http://url1.com', 'title1', ',tag1,'), + (2, 'http://url2.com', 'title2', ',tag1,tag2,')], + 30, + ['title1', 'title2'] + ], + [ + [(1, 'http://url1.com', 'title1', ',tag1,'), + (2, 'http://url2.com', 'title2', ',tag1,tag2,')], + 40, + ['http://url1.com\ttitle1\ttag1', 'http://url2.com\ttitle2\ttag1,tag2'] + ] + ] +) +def test_print_rec_with_filter(records, field_filter, exp_res): + """test func.""" + with mock.patch('buku.print', create=True) as m_print: + import buku + buku.print_rec_with_filter(records, field_filter) + for res in exp_res: + m_print.assert_any_call(res) + + @pytest.mark.parametrize( 'taglist, exp_res', [