From e1cd1c84a58da12e46f98e9eaf47d70692d9b974 Mon Sep 17 00:00:00 2001 From: LeXofLeviafan Date: Sat, 7 Jan 2023 07:02:55 +0100 Subject: [PATCH] [jarun#652][jarun#653] changed BookmarkVar into a namedtuple & applied some minor refactoring --- buku | 341 +++++++++++++++++++++++----------------------- bukuserver/api.py | 38 +++--- 2 files changed, 189 insertions(+), 190 deletions(-) diff --git a/buku b/buku index 21a52e93..7f639615 100755 --- a/buku +++ b/buku @@ -44,7 +44,7 @@ import webbrowser from enum import Enum from itertools import chain from subprocess import DEVNULL, PIPE, Popen -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Dict, List, Optional, Tuple, NamedTuple import urllib3 from bs4 import BeautifulSoup @@ -95,6 +95,8 @@ COLORMAP = {k: '\x1b[%sm' % v for k, v in { 'x': '0', 'X': '1', 'y': '7', 'Y': '7;1', 'z': '2', }.items()} +[FLAG_NONE, FLAG_IMMUTABLE] = [0x00, 0x01] + USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/101.0' MYHEADERS = None # Default dictionary of headers MYPROXY = None # Default proxy @@ -362,9 +364,16 @@ class BukuCrypt: sys.exit(1) -BookmarkVar = Tuple[int, str, Optional[str], str, str, int] -# example: -# (1, 'http://example.com', 'example title', ',tags1,', 'randomdesc', 0)) +class BookmarkVar(NamedTuple): + """Bookmark data named tuple""" + id: int + url: str + title: Optional[str] = None + tags: str = '' + desc: str = '' + flags: int = FLAG_NONE + +bookmark_vars = lambda xs: (BookmarkVar(*x) for x in xs) class BukuDb: @@ -385,8 +394,8 @@ class BukuDb: """ def __init__( - self, json: Optional[str] = None, field_filter: Optional[int] = 0, chatty: Optional[bool] = False, - dbfile: Optional[str] = None, colorize: Optional[bool] = True) -> None: + self, json: Optional[str] = None, field_filter: int = 0, chatty: bool = False, + dbfile: Optional[str] = None, colorize: bool = True) -> None: """Database initialization API. Parameters @@ -395,11 +404,11 @@ class BukuDb: Empty string if results should be printed in JSON format to stdout. Nonempty string if results should be printed in JSON format to file. The string has to be a valid path. None if the results should be printed as human-readable plaintext. - field_filter : int, optional + field_filter : int Indicates format for displaying bookmarks. Default is 0. - chatty : bool, optional + chatty : bool Sets the verbosity of the APIs. Default is False. - colorize : bool, optional + colorize : bool Indicates whether color should be used in output. Default is True. """ @@ -439,7 +448,7 @@ class BukuDb: return os.path.join(data_home, 'buku') @staticmethod - def initdb(dbfile: Optional[str] = None, chatty: Optional[bool] = False) -> Tuple[sqlite3.Connection, sqlite3.Cursor]: + def initdb(dbfile: Optional[str] = None, chatty: bool = False) -> Tuple[sqlite3.Connection, sqlite3.Cursor]: """Initialize the database connection. Create DB file and/or bookmarks table if they don't exist. @@ -514,7 +523,7 @@ class BukuDb: def _fetch(self, query: str, *args) -> List[BookmarkVar]: self.cur.execute(query, args) - return self.cur.fetchall() + return [BookmarkVar(*x) for x in self.cur.fetchall()] def _fetch_first(self, query: str, *args) -> Optional[BookmarkVar]: rows = self._fetch(query + ' LIMIT 1', *args) @@ -562,7 +571,7 @@ class BukuDb: """ row = self._fetch_first('SELECT * FROM bookmarks WHERE url = ?', url) - return row and row[0] + return row and row.id def get_max_id(self) -> int: """Fetch the ID of the last record. @@ -582,9 +591,9 @@ class BukuDb: title_in: Optional[str] = None, tags_in: Optional[str] = None, desc: Optional[str] = None, - immutable: Optional[int] = 0, - delay_commit: Optional[bool] = False, - fetch: Optional[bool] = True) -> int: + immutable: int = FLAG_NONE, + delay_commit: bool = False, + fetch: bool = True) -> int: """Add a new bookmark. Parameters @@ -598,13 +607,13 @@ class BukuDb: Must start and end with comma. Default is None. desc : str, optional Description of the bookmark. Default is None. - immutable : int, optional + immutable : int Indicates whether to disable title fetch from web. - Default is 0. - delay_commit : bool, optional + Default is 0 ("no"); the "yes" value is 1. + delay_commit : bool True if record should not be committed to the DB, leaving commit responsibility to caller. Default is False. - fetch : bool, optional + fetch : bool Fetch page from web and parse for data Returns @@ -614,7 +623,7 @@ class BukuDb: """ # Return error for empty URL - if not url or url == '': + if not url: LOGERR('Invalid URL') return None @@ -650,8 +659,8 @@ class BukuDb: desc = '' if pdesc is None else pdesc try: - flagset = 0 - if immutable == 1: + flagset = FLAG_NONE + if immutable == FLAG_IMMUTABLE: flagset |= immutable qry = 'INSERT INTO bookmarks(URL, metadata, tags, desc, flags) VALUES (?, ?, ?, ?, ?)' @@ -674,7 +683,7 @@ class BukuDb: DB index of the record. 0 indicates all records. tags_in : str Comma-separated tags to add manually. - delay_commit : bool, optional + delay_commit : bool True if record should not be committed to the DB, leaving commit responsibility to caller. Default is False. @@ -722,10 +731,10 @@ class BukuDb: DB index of bookmark record. 0 indicates all records. tags_in : str Comma-separated tags to delete manually. - delay_commit : bool, optional + delay_commit : bool True if record should not be committed to the DB, leaving commit responsibility to caller. Default is False. - chatty: bool, optional + chatty: bool Skip confirmation when set to False. Returns @@ -792,7 +801,7 @@ class BukuDb: title_in: Optional[str] = None, tags_in: Optional[str] = None, desc: Optional[str] = None, - immutable: Optional[int] = -1, + immutable: int = -1, threads: int = 4) -> bool: """Update an existing record at index. @@ -813,9 +822,10 @@ class BukuDb: Prefix with '-,' to delete from current tags. desc : str, optional Description of bookmark. - immutable : int, optional - Disable title fetch from web if 1. Default is -1. - threads : int, optional + immutable : int + Disable title fetch from web if 1 (or enable if 0). + Default is -1 ("no change"). + threads : int Number of threads to use to refresh full DB. Default is 4. Returns @@ -871,15 +881,13 @@ class BukuDb: to_update = True # Update immutable flag if passed as argument - if immutable != -1: - flagset = 1 - if immutable == 1: + if immutable in {FLAG_NONE, FLAG_IMMUTABLE}: + if immutable == FLAG_IMMUTABLE: query += ' flags = flags | ?,' - elif immutable == 0: + arguments += (FLAG_IMMUTABLE,) + else: query += ' flags = flags & ?,' - flagset = ~flagset - - arguments += (flagset,) + arguments += (~FLAG_IMMUTABLE,) to_update = True # Update title @@ -1123,8 +1131,9 @@ class BukuDb: index : int DB index of the record. Last record, if index is -1. - immutable : int, optional - Diable title fetch from web if 1. Default is -1. + immutable : int + Diable title fetch from web if 1 (or enable if 0). + Default is -1 ("no change"). Returns ------- @@ -1151,14 +1160,13 @@ class BukuDb: # If reading from DB, show empty title and desc as empty lines. We have to convert because # even in case of add with a blank title or desc, '' is used as initializer to show '-'. - result = edit_rec(editor, rec[1], rec[2] if rec[2] != '' else None, - rec[3], rec[4] if rec[4] != '' else None) + result = edit_rec(editor, rec.url, rec.title or None, rec.tags, rec.desc or None) if result is not None: url, title, tags, desc = result return self.update_rec(index, url, title, tags, desc, immutable) - if immutable != -1: - return self.update_rec(index, immutable) + if immutable in {FLAG_NONE, FLAG_IMMUTABLE}: + return self.update_rec(index, immutable=immutable) return False @@ -1203,9 +1211,9 @@ class BukuDb: def searchdb( self, keywords: List[str], - all_keywords: Optional[bool] = False, - deep: Optional[bool] = False, - regex: Optional[bool] = False + all_keywords: bool = False, + deep: bool = False, + regex: bool = False ) -> List[BookmarkVar]: """Search DB for entries where tags, URL, or title fields match keywords. @@ -1213,12 +1221,12 @@ class BukuDb: ---------- keywords : list of str Keywords to search. - all_keywords : bool, optional + all_keywords : bool True to return records matching ALL keywords. False (default value) to return records matching ANY keyword. - deep : bool, optional + deep : bool True to search for matching substrings. Default is False. - regex : bool, optional + regex : bool Match a regular expression if True. Default is False. Returns @@ -1395,12 +1403,12 @@ class BukuDb: ---------- keywords : list of str Keywords to search. - all_keywords : bool, optional + all_keywords : bool True to return records matching ALL keywords. False to return records matching ANY keyword. - deep : bool, optional + deep : bool True to search for matching substrings. - regex : bool, optional + regex : bool Match a regular expression if True. stag : str String of tags to search for. @@ -1428,7 +1436,7 @@ class BukuDb: List of search results without : list of str Keywords to search. - deep : bool, optional + deep : bool True to search for matching substrings. Returns @@ -1447,7 +1455,7 @@ class BukuDb: ---------- index : int DB index of deleted entry. - delay_commit : bool, optional + delay_commit : bool True if record should not be committed to the DB, leaving commit responsibility to caller. Default is False. """ @@ -1465,12 +1473,12 @@ class BukuDb: if max_id > index: results = self._fetch(query1, max_id) for row in results: - self.cur.execute(query2, (row[0],)) - self.cur.execute(query3, (index, row[1], row[2], row[3], row[4], row[5])) + self.cur.execute(query2, (row.id,)) + self.cur.execute(query3, (index, row.url, row.title, row.tags, row.desc, row.flags)) if not delay_commit: self.conn.commit() if self.chatty: - print('Index %d moved to %d' % (row[0], index)) + print('Index %d moved to %d' % (row.id, index)) def delete_rec( self, @@ -1486,14 +1494,14 @@ class BukuDb: ---------- index : int, optional DB index of deleted entry. - low : int, optional + low : int Actual lower index of range. - high : int, optional + high : int Actual higher index of range. - is_range : bool, optional + is_range : bool A range is passed using low and high arguments. An index is ignored if is_range is True. - delay_commit : bool, optional + delay_commit : bool True if record should not be committed to the DB, leaving commit responsibility to caller. Default is False. @@ -1681,7 +1689,7 @@ class BukuDb: Parameters ---------- - delay_commit : bool, optional + delay_commit : bool True if record should not be committed to the DB, leaving commit responsibility to caller. Default is False. @@ -1731,13 +1739,13 @@ class BukuDb: Parameters ----------- - index : int, optional + index : int DB index of record to print. 0 prints all records. - low : int, optional + low : int Actual lower index of range. - high : int, optional + high : int Actual higher index of range. - is_range : bool, optional + is_range : bool A range is passed using low and high arguments. An index is ignored if is_range is True. @@ -1932,7 +1940,7 @@ class BukuDb: return parse_tags(tags) - def replace_tag(self, orig: str, new: Optional[List[str]] = None) -> bool: + def replace_tag(self, orig: str, new: List[str] = []) -> bool: """Replace original tag by new tags in all records. Remove original tag if new tag is empty. @@ -1950,11 +1958,8 @@ class BukuDb: True on success, False on failure. """ - newtags = DELIM - orig = delim_wrap(orig) - if new is not None: - newtags = parse_tags(new) + newtags = parse_tags(new) if new else DELIM if orig == newtags: print('Tags are same.') @@ -2226,7 +2231,7 @@ class BukuDb: outdb = BukuDb(dbfile=filepath) qry = 'INSERT INTO bookmarks(URL, metadata, tags, desc, flags) VALUES (?, ?, ?, ?, ?)' for row in resultset: - outdb.cur.execute(qry, (row[1], row[2], row[3], row[4], row[5])) + outdb.cur.execute(qry, (row.url, row.title, row.tags, row.desc, row.flags)) count += 1 outdb.conn.commit() outdb.close() @@ -2381,10 +2386,7 @@ class BukuDb: tags = parse_tags(formatted_tags) # get the title - if row[2]: - title = row[2] - else: - title = '' + title = row[2] or '' self.add_rec(url, title, tags, None, 0, True, False) try: @@ -2569,7 +2571,7 @@ class BukuDb: ---------- filepath : str Path to file to import. - tacit : bool, optional + tacit : bool If True, no questions asked and folder names are automatically imported as tags from bookmarks HTML. If True, automatic timestamp tag is NOT added. @@ -2709,8 +2711,8 @@ n: don't add parent folder as tag resultset = indb_cur.fetchall() if resultset: - for row in resultset: - self.add_rec(row[1], row[2], row[3], row[4], row[5], True, False) + for row in bookmark_vars(resultset): + self.add_rec(row.url, row.title, row.tags, row.desc, row.flags, True, False) self.conn.commit() @@ -2726,7 +2728,7 @@ n: don't add parent folder as tag self, index: Optional[int] = None, url: Optional[str] = None, - shorten: Optional[bool] = True) -> Optional[str]: + shorten: bool = True) -> Optional[str]: """Shorten a URL using Google URL shortener. Parameters @@ -2735,7 +2737,7 @@ n: don't add parent folder as tag DB index of the bookmark with the URL to shorten. Default is None. url : str, optional (if index is provided) URL to shorten. - shorten : bool, optional + shorten : bool True to shorten, False to expand. Default is False. Returns @@ -2894,7 +2896,7 @@ n: don't add parent folder as tag Parameters ---------- - exitval : int, optional + exitval : int Program exit value. """ @@ -2917,7 +2919,7 @@ class ExtendedArgumentParser(argparse.ArgumentParser): Parameters ---------- - file : file, optional + file : file File to write program info to. Default is sys.stdout. """ if sys.platform == 'win32' and file == sys.stdout: @@ -2941,7 +2943,7 @@ Webpage: https://github.com/jarun/buku Parameters ---------- - file : file, optional + file : file File to write program info to. Default is sys.stdout. """ file.write(''' @@ -3001,7 +3003,7 @@ PROMPT KEYS: Parameters ---------- - file : file, optional + file : file File to write program info to. Default is sys.stdout. """ super().print_help(file) @@ -3046,30 +3048,24 @@ def convert_bookmark_set( import html assert export_type in ['markdown', 'html', 'org', 'xbel'] # compatibility - resultset = bookmark_set + resultset = bookmark_vars(bookmark_set) count = 0 out = '' if export_type == 'markdown': for row in resultset: - if not row[2] or row[2] is None: - out += '- [Untitled](' + row[1] + ')' - else: - out += '- [' + row[2] + '](' + row[1] + ')' + out += '- [' + (row.title or 'Untitled') + '](' + row.url + ')' - if row[3] != DELIM: - out += ' \n'.format(row[3][1:-1]) + if row.tags != DELIM: + out += ' \n'.format(row.tags[1:-1]) else: out += '\n' count += 1 elif export_type == 'org': for row in resultset: - if not row[2]: - out += '* [[{}][Untitled]]'.format(row[1]) - else: - out += '* [[{}][{}]]'.format(row[1], row[2]) - out += convert_tags_to_org_mode_tags(row[3]) + out += '* [[{}][{}]]'.format(row.url, row.title or 'Untitled') + out += convert_tags_to_org_mode_tags(row.tags) count += 1 elif export_type == 'xbel': timestamp = str(int(time.time())) @@ -3081,11 +3077,11 @@ def convert_bookmark_set( '\n') for row in resultset: - out += '

\n'.format(timestamp)) for row in resultset: - out += '

Tuple[Optional[str], Optional[str], Optional[str], int, int]: """Handle server connection and redirections. @@ -3978,7 +3974,7 @@ def parse_tags(keywords=[]): Parameters ---------- - keywords : list, optional + keywords : list List of tags to parse. Default is empty list. Returns @@ -3994,7 +3990,7 @@ def parse_tags(keywords=[]): if keywords is None: return None - if not keywords or len(keywords) < 1 or not keywords[0]: + if not keywords or not keywords[0]: return DELIM tags = DELIM @@ -4114,7 +4110,7 @@ def edit_at_prompt(obj, nav, suggest=False): A valid instance of BukuDb class. nav : str Navigation command argument passed at prompt by user. - suggest : bool, optional + suggest : bool If True, suggest similar tags on new bookmark addition. """ @@ -4166,15 +4162,15 @@ def prompt(obj, results, noninteractive=False, deep=False, listtags=False, sugge A valid instance of BukuDb class. results : list Search result set from a DB query. - noninteractive : bool, optional + noninteractive : bool If True, does not seek user input. Shows all results. Default is False. - deep : bool, optional + deep : bool Use deep search. Default is False. - listtags : bool, optional + listtags : bool If True, list all tags. - suggest : bool, optional + suggest : bool If True, suggest similar tags on edit and add bookmark. - num : int, optional + num : int Number of results to show per page. Default is 10. """ @@ -4481,10 +4477,11 @@ def print_rec_with_filter(records, field_filter=0): records : list or sqlite3.Cursor object List of bookmark records to print field_filter : int - Integer indicating which fields to print. + Integer indicating which fields to print. Default is 0 ("all fields"). """ try: + records = bookmark_vars(records) if field_filter == 0: for row in records: try: @@ -4494,40 +4491,40 @@ def print_rec_with_filter(records, field_filter=0): print_single_rec(row, columns=columns) elif field_filter == 1: for row in records: - print('%s\t%s' % (row[0], row[1])) + print('%s\t%s' % (row.id, row.url)) elif field_filter == 2: for row in records: - print('%s\t%s\t%s' % (row[0], row[1], row[3][1:-1])) + print('%s\t%s\t%s' % (row.id, row.url, row.tags[1:-1])) elif field_filter == 3: for row in records: - print('%s\t%s' % (row[0], row[2])) + print('%s\t%s' % (row.id, row.title)) 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])) + print('%s\t%s\t%s\t%s' % (row.id, row.url, row.title, row.tags[1:-1])) elif field_filter == 5: for row in records: - print('%s\t%s\t%s' % (row[0], row[2], row[3][1:-1])) + print('%s\t%s\t%s' % (row.id, row.title, row.tags[1:-1])) elif field_filter == 10: for row in records: - print(row[1]) + print(row.url) elif field_filter == 20: for row in records: - print('%s\t%s' % (row[1], row[3][1:-1])) + print('%s\t%s' % (row.url, row.tags[1:-1])) elif field_filter == 30: for row in records: - print(row[2]) + print(row.title) elif field_filter == 40: for row in records: - print('%s\t%s\t%s' % (row[1], row[2], row[3][1:-1])) + print('%s\t%s\t%s' % (row.url, row.title, row.tags[1:-1])) elif field_filter == 50: for row in records: - print('%s\t%s' % (row[2], row[3][1:-1])) + print('%s\t%s' % (row.title, row.tags[1:-1])) except BrokenPipeError: sys.stdout = os.fdopen(1) sys.exit(1) -def print_single_rec(row: BookmarkVar, idx: Optional[int]=0, columns: Optional[int]=0): # NOQA +def print_single_rec(row: BookmarkVar, idx: int=0, columns: int=0): # NOQA """Print a single DB record. Handles both search results and individual record. @@ -4536,35 +4533,36 @@ def print_single_rec(row: BookmarkVar, idx: Optional[int]=0, columns: Optional[i ---------- row : tuple Tuple representing bookmark record data. - idx : int, optional + idx : int Search result index. If 0, print with DB index. Default is 0. - columns : int, optional + columns : int Number of columns to wrap comments to. Default is 0. """ str_list = [] + row = BookmarkVar(*row) # ensuring named tuple # Start with index and title if idx != 0: - id_title_res = ID_STR % (idx, row[2] if row[2] else 'Untitled', row[0]) + id_title_res = ID_STR % (idx, row.title or 'Untitled', row.id) else: - id_title_res = ID_DB_STR % (row[0], row[2] if row[2] else 'Untitled') + id_title_res = ID_DB_STR % (row.id, row.title or 'Untitled') # Indicate if record is immutable - if row[5] & 1: + if row.flags & FLAG_IMMUTABLE: id_title_res = MUTE_STR % (id_title_res) else: id_title_res += '\n' try: print(id_title_res, end='') - print(URL_STR % (row[1]), end='') + print(URL_STR % (row.url), end='') if columns == 0: - if row[4]: - print(DESC_STR % (row[4]), end='') - if row[3] != DELIM: - print(TAG_STR % (row[3][1:-1]), end='') + if row.desc: + print(DESC_STR % (row.desc), end='') + if row.tags != DELIM: + print(TAG_STR % (row.tags[1:-1]), end='') print() return @@ -4572,7 +4570,7 @@ def print_single_rec(row: BookmarkVar, idx: Optional[int]=0, columns: Optional[i ln_num = 1 fillwidth = columns - INDENT - for line in textwrap.wrap(row[4].replace('\n', ''), width=fillwidth): + for line in textwrap.wrap(row.desc.replace('\n', ''), width=fillwidth): if ln_num == 1: print(DESC_STR % line, end='') ln_num += 1 @@ -4580,7 +4578,7 @@ def print_single_rec(row: BookmarkVar, idx: Optional[int]=0, columns: Optional[i print(DESC_WRAP % (' ' * INDENT, line)) ln_num = 1 - for line in textwrap.wrap(row[3][1:-1].replace('\n', ''), width=fillwidth): + for line in textwrap.wrap(row.tags[1:-1].replace('\n', ''), width=fillwidth): if ln_num == 1: print(TAG_STR % line, end='') ln_num += 1 @@ -4590,11 +4588,11 @@ def print_single_rec(row: BookmarkVar, idx: Optional[int]=0, columns: Optional[i except UnicodeEncodeError: str_list = [] str_list.append(id_title_res) - str_list.append(URL_STR % (row[1])) - if row[4]: - str_list.append(DESC_STR % (row[4])) - if row[3] != DELIM: - str_list.append(TAG_STR % (row[3][1:-1])) + str_list.append(URL_STR % (row.url)) + if row.desc: + str_list.append(DESC_STR % (row.desc)) + if row.tags != DELIM: + str_list.append(TAG_STR % (row.tags[1:-1])) sys.stdout.buffer.write((''.join(str_list) + '\n').encode('utf-8')) except BrokenPipeError: sys.stdout = os.fdopen(1) @@ -4627,10 +4625,10 @@ def format_json(resultset, single_record=False, field_filter=0): ---------- resultset : list Search results from DB query. - single_record : bool, optional + single_record : bool If True, indicates only one record. Default is False. - field_filter : int, optional - Indicates format for displaying bookmarks. Default is 0. + field_filter : int + Indicates format for displaying bookmarks. Default is 0 ("all fields"). Returns ------- @@ -4638,44 +4636,45 @@ def format_json(resultset, single_record=False, field_filter=0): Record(s) in JSON format. """ + resultset = bookmark_vars(resultset) if single_record: marks = {} for row in resultset: if field_filter == 1: - marks['uri'] = row[1] + marks['uri'] = row.url elif field_filter == 2: - marks['uri'] = row[1] - marks['tags'] = row[3][1:-1] + marks['uri'] = row.url + marks['tags'] = row.tags[1:-1] elif field_filter == 3: - marks['title'] = row[2] + marks['title'] = row.title elif field_filter == 4: - marks['uri'] = row[1] - marks['tags'] = row[3][1:-1] - marks['title'] = row[2] + marks['uri'] = row.url + marks['tags'] = row.tags[1:-1] + marks['title'] = row.title else: - marks['index'] = row[0] - marks['uri'] = row[1] - marks['title'] = row[2] - marks['description'] = row[4] - marks['tags'] = row[3][1:-1] + marks['index'] = row.id + marks['uri'] = row.url + marks['title'] = row.title + marks['description'] = row.desc + marks['tags'] = row.tags[1:-1] else: marks = [] for row in resultset: if field_filter == 1: - record = {'uri': row[1]} + record = {'uri': row.url} elif field_filter == 2: - record = {'uri': row[1], 'tags': row[3][1:-1]} + record = {'uri': row.url, 'tags': row.tags[1:-1]} elif field_filter == 3: - record = {'title': row[2]} + record = {'title': row.title} elif field_filter == 4: - record = {'uri': row[1], 'title': row[2], 'tags': row[3][1:-1]} + record = {'uri': row.url, 'title': row.title, 'tags': row.tags[1:-1]} else: record = { - 'index': row[0], - 'uri': row[1], - 'title': row[2], - 'description': row[4], - 'tags': row[3][1:-1] + 'index': row.id, + 'uri': row.url, + 'title': row.title, + 'description': row.desc, + 'tags': row.tags[1:-1] } marks.append(record) @@ -4690,10 +4689,10 @@ def print_json_safe(resultset, single_record=False, field_filter=0): ---------- resultset : list Search results from DB query. - single_record : bool, optional + single_record : bool If True, indicates only one record. Default is False. - field_filter : int, optional - Indicates format for displaying bookmarks. Default is 0. + field_filter : int + Indicates format for displaying bookmarks. Default is 0 ("all fields"). Returns ------- diff --git a/bukuserver/api.py b/bukuserver/api.py index 5ab984ab..49fe8c15 100644 --- a/bukuserver/api.py +++ b/bukuserver/api.py @@ -111,13 +111,13 @@ def get(self, rec_id: Union[int, None]): result = {'bookmarks': []} # type: Dict[str, Any] for bookmark in all_bookmarks: result_bookmark = { - 'url': bookmark[1], - 'title': bookmark[2], - 'tags': [x for x in bookmark[3].split(',') if x], - 'description': bookmark[4] + 'url': bookmark.url, + 'title': bookmark.title, + 'tags': [x for x in bookmark.tags.split(',') if x], + 'description': bookmark.desc } if not request.path.startswith('/api/'): - result_bookmark['id'] = bookmark[0] + result_bookmark['id'] = bookmark.id result['bookmarks'].append(result_bookmark) res = jsonify(result) else: @@ -127,10 +127,10 @@ def get(self, rec_id: Union[int, None]): res = response_bad() else: res = jsonify({ - 'url': bookmark[1], - 'title': bookmark[2], - 'tags': [x for x in bookmark[3].split(',') if x], - 'description': bookmark[4] + 'url': bookmark.url, + 'title': bookmark.title, + 'tags': [x for x in bookmark.tags.split(',') if x], + 'description': bookmark.desc, }) return res @@ -178,10 +178,10 @@ def get(self, starting_id: int, ending_id: int): for i in range(starting_id, ending_id + 1, 1): bookmark = bukudb.get_rec_by_id(i) result['bookmarks'][i] = { - 'url': bookmark[1], - 'title': bookmark[2], - 'tags': [x for x in bookmark[3].split(',') if x], - 'description': bookmark[4] + 'url': bookmark.url, + 'title': bookmark.title, + 'tags': [x for x in bookmark.tags.split(',') if x], + 'description': bookmark.desc, } return jsonify(result) @@ -236,11 +236,11 @@ def get(self): res = None for bookmark in bukudb.searchdb(keywords, all_keywords, deep, regex): result_bookmark = { - 'id': bookmark[0], - 'url': bookmark[1], - 'title': bookmark[2], - 'tags': list(filter(lambda x: x, bookmark[3].split(','))), - 'description': bookmark[4] + 'id': bookmark.id, + 'url': bookmark.url, + 'title': bookmark.title, + 'tags': [x for x in bookmark.tags.split(',') if x], + 'description': bookmark.desc, } result['bookmarks'].append(result_bookmark) current_app.logger.debug('total bookmarks:{}'.format(len(result['bookmarks']))) @@ -266,7 +266,7 @@ def delete(self): bukudb = getattr(flask.g, 'bukudb', get_bukudb()) res = None for bookmark in bukudb.searchdb(keywords, all_keywords, deep, regex): - if not bukudb.delete_rec(bookmark[0]): + if not bukudb.delete_rec(bookmark.id): res = response_bad() return res or response_ok()