From 0f9fa43d8021d534ff9a5145aa8da0f458de341b Mon Sep 17 00:00:00 2001 From: Qynn Swaan Date: Sun, 12 Feb 2023 17:38:18 -0500 Subject: [PATCH] [#676] [bukuserver API] improve tag replacement/deletion --- buku | 13 +++++++------ bukuserver/api.py | 23 +++++++++++++++-------- bukuserver/server.py | 5 +++-- tests/test_server.py | 13 +++++++++---- 4 files changed, 34 insertions(+), 20 deletions(-) diff --git a/buku b/buku index 32756e6e..1d409303 100755 --- a/buku +++ b/buku @@ -1959,7 +1959,7 @@ class BukuDb: return parse_tags(tags) - def replace_tag(self, orig: str, new: List[str] = []) -> bool: + def replace_tag(self, orig: str, new: List[str] = [], chatty: bool = True) -> bool: """Replace original tag by new tags in all records. Remove original tag if new tag is empty. @@ -1970,6 +1970,8 @@ class BukuDb: Original tag. new : list Replacement tags. + chatty: bool + Skip confirmation when set to False. Returns ------- @@ -1977,16 +1979,15 @@ class BukuDb: True on success, False on failure. """ - orig = delim_wrap(orig) - newtags = parse_tags(new) if new else DELIM + newtags = DELIM.join(sorted(set(new))) if orig == newtags: print('Tags are same.') return False - # Remove original tag from DB if new tagset reduces to delimiter - if newtags == DELIM: - return self.delete_tag_at_index(0, orig) + # Remove original tag from DB if new tagset is empty + if newtags == []: + return self.delete_tag_at_index(0, orig, chatty=chatty) # Update bookmarks with original tag query = 'SELECT id, tags FROM bookmarks WHERE tags LIKE ?' diff --git a/bukuserver/api.py b/bukuserver/api.py index 171ffb8a..69384354 100644 --- a/bukuserver/api.py +++ b/bukuserver/api.py @@ -101,16 +101,23 @@ def get(self, tag: T.Optional[str]): return {"name": tag, "usage_count": tags[1][tag]} def put(self, tag: str): - bukudb = get_bukudb() try: - new_tags = request.data.get('tags') # type: ignore - if new_tags: - new_tags = new_tags.split(',') - else: - return response_bad() + new_tags = request.data.getlist('tags') # werkzeug.datastructures.MultiDict except AttributeError as e: - raise exceptions.ParseError(detail=str(e)) - return to_response(bukudb.replace_tag(tag, new_tags)) + new_tags = request.data.get('tags', []) # List[str] + if not isinstance(new_tags, list) or new_tags == []: + return response_bad() + bukudb = get_bukudb() + return to_response(bukudb.replace_tag(tag, new_tags, chatty=False)) + + def delete(self, tag: str): + bukudb = get_bukudb() + tags = search_tag(db=bukudb, stag=tag) + if tag not in tags[1]: + raise exceptions.NotFound() + if bukudb.delete_tag_at_index(0, tag, chatty=False): + return response_ok() + return response_bad() class ApiBookmarkView(MethodView): diff --git a/bukuserver/server.py b/bukuserver/server.py index 5b4be42f..44c82092 100644 --- a/bukuserver/server.py +++ b/bukuserver/server.py @@ -128,8 +128,8 @@ def shell_context(): # routing # api tag_api_view = api.ApiTagView.as_view('tag_api') - app.add_url_rule('/api/tags', defaults={'tag': None}, view_func=tag_api_view, methods=['GET']) - app.add_url_rule('/api/tags/', view_func=tag_api_view, methods=['GET', 'PUT']) + app.add_url_rule('/api/tags', defaults={'tag': None}, view_func=tag_api_view, methods=['GET'], strict_slashes=False) + app.add_url_rule('/api/tags/', view_func=tag_api_view, methods=['GET', 'PUT', 'DELETE']) bookmark_api_view = api.ApiBookmarkView.as_view('bookmark_api') app.add_url_rule('/api/bookmarks', defaults={'rec_id': None}, view_func=bookmark_api_view, methods=['GET', 'POST', 'DELETE']) app.add_url_rule('/api/bookmarks/', view_func=bookmark_api_view, methods=['GET', 'PUT', 'DELETE']) @@ -157,6 +157,7 @@ def favicon(): bukudb, 'Tags', page_size=per_page)) admin.add_view(views.StatisticView( bukudb, 'Statistic', endpoint='statistic')) + return app diff --git a/tests/test_server.py b/tests/test_server.py index 90a157e8..4bf454f8 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -86,22 +86,27 @@ def test_tag_api(client): rd = client.get('/api/tags/tag1') assert rd.status_code == 200 assert rd.get_json() == {'name': 'tag1', 'usage_count': 1} - rd = client.put('/api/tags/tag1', data={'tags': 'tag3,tag4'}) + rd = client.put('/api/tags/tag1', data={'tags': ['tag3', 'tag4']}) + print("\r\nrd", rd.__dict__, "\r\n") assert rd.status_code == 200 assert rd.get_json() == response_template['success'] rd = client.get('/api/tags') assert rd.status_code == 200 - assert rd.get_json() == {'tags': ['tag2', 'tag3 tag4']} + assert rd.get_json() == {'tags': ['tag2', 'tag3', 'tag4']} rd = client.put('/api/tags/tag2', data={'tags': 'tag5'}) assert rd.status_code == 200 assert rd.get_json() == response_template['success'] rd = client.get('/api/tags') assert rd.status_code == 200 - assert rd.get_json() == {'tags': ['tag3 tag4', 'tag5']} + assert rd.get_json() == {'tags': ['tag3', 'tag4', 'tag5']} + assert rd.status_code == 200 + rd = client.delete('/api/tags/tag4') + assert rd.status_code == 200 + assert rd.get_json() == response_template['success'] rd = client.get('/api/bookmarks/1') assert rd.status_code == 200 assert rd.get_json() == { - 'description': '', 'tags': ['tag3 tag4', 'tag5'], 'title': 'Google', + 'description': '', 'tags': ['tag3', 'tag5'], 'title': 'Google', 'url': 'http://google.com'}