From e923fbcffd15e3243b4ca089356bb1400cc47af3 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 14 Jul 2013 13:05:15 +0530 Subject: [PATCH] More set_*() API --- src/calibre/db/legacy.py | 32 ++++++++++++++++++++++++++++++++ src/calibre/db/tables.py | 3 +++ src/calibre/db/tests/legacy.py | 26 ++++++++++++++++++++++---- src/calibre/db/write.py | 4 ++-- 4 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/calibre/db/legacy.py b/src/calibre/db/legacy.py index f21d938009..9d9e93c02b 100644 --- a/src/calibre/db/legacy.py +++ b/src/calibre/db/legacy.py @@ -18,6 +18,7 @@ from calibre.db.backend import DB from calibre.db.cache import Cache from calibre.db.categories import CATEGORY_SORTS from calibre.db.view import View +from calibre.db.write import clean_identifier from calibre.utils.date import utcnow class LibraryDatabase(object): @@ -340,6 +341,36 @@ class LibraryDatabase(object): finally: self.notify('metadata', [book_id]) + def set_identifier(self, book_id, typ, val, notify=True, commit=True): + with self.new_api.write_lock: + identifiers = self.new_api._field_for('identifiers', book_id) + typ, val = clean_identifier(typ, val) + if typ: + identifiers[typ] = val + self.new_api._set_field('identifiers', {book_id:identifiers}) + self.notify('metadata', [book_id]) + + def set_isbn(self, book_id, isbn, notify=True, commit=True): + self.set_identifier(book_id, 'isbn', isbn, notify=notify, commit=commit) + + def set_tags(self, book_id, tags, append=False, notify=True, commit=True, allow_case_change=False): + tags = tags or [] + with self.new_api.write_lock: + if append: + otags = self.new_api._field_for('tags', book_id) + existing = {icu_lower(x) for x in otags} + tags = list(otags) + [x for x in tags if icu_lower(x) not in existing] + ret = self.new_api._set_field('tags', {book_id:tags}, allow_case_change=allow_case_change) + if notify: + self.notify('metadata', [book_id]) + return ret + + def set_metadata(self, book_id, mi, ignore_errors=False, set_title=True, + set_authors=True, commit=True, force_changes=False, notify=True): + self.new_api.set_metadata(book_id, mi, ignore_errors=ignore_errors, set_title=set_title, set_authors=set_authors, force_changes=force_changes) + if notify: + self.notify('metadata', [book_id]) + # Private interface {{{ def __iter__(self): for row in self.data.iterall(): @@ -424,6 +455,7 @@ for func, field in {'all_authors':'authors', 'all_titles':'title', 'all_tags2':' setattr(LibraryDatabase, func, MT(getter(field))) LibraryDatabase.all_tags = MT(lambda self: list(self.all_tag_names())) +LibraryDatabase.get_all_identifier_types = MT(lambda self: list(self.new_api.fields['identifiers'].table.all_identifier_types())) LibraryDatabase.get_authors_with_ids = MT( lambda self: [[aid, adata['name'], adata['sort'], adata['link']] for aid, adata in self.new_api.author_data().iteritems()]) diff --git a/src/calibre/db/tables.py b/src/calibre/db/tables.py index 7715f6abef..46c4554586 100644 --- a/src/calibre/db/tables.py +++ b/src/calibre/db/tables.py @@ -420,3 +420,6 @@ class IdentifiersTable(ManyToManyTable): def remove_items(self, item_ids, db): raise NotImplementedError('Direct deletion of identifiers is not implemented') + def all_identifier_types(self): + return frozenset(k for k, v in self.col_book_map.iteritems() if v) + diff --git a/src/calibre/db/tests/legacy.py b/src/calibre/db/tests/legacy.py index 6c67fcea36..b0ef9fbe1e 100644 --- a/src/calibre/db/tests/legacy.py +++ b/src/calibre/db/tests/legacy.py @@ -49,7 +49,7 @@ def run_funcs(self, db, ndb, funcs): fmt = lambda x:x if meth[0] in {'!', '@', '#', '+'}: if meth[0] != '+': - fmt = {'!':dict, '@':frozenset, '#':lambda x:set((x or '').split(','))}[meth[0]] + fmt = {'!':dict, '@':lambda x:frozenset(x or ()), '#':lambda x:set((x or '').split(','))}[meth[0]] else: fmt = args[-1] args = args[:-1] @@ -168,6 +168,7 @@ class LegacyTest(BaseTest): '!all_authors':[()], '!all_tags2':[()], '@all_tags':[()], + '@get_all_identifier_types':[()], '!all_publishers':[()], '!all_titles':[()], '!all_series':[()], @@ -331,7 +332,7 @@ class LegacyTest(BaseTest): 'construct_path_name', 'clear_dirtied', 'commit_dirty_cache', 'initialize_database', 'initialize_dynamic', 'run_import_plugins', 'vacuum', 'set_path', 'row', 'row_factory', 'rows', 'rmtree', 'series_index_pat', 'import_old_database', 'dirtied_lock', 'dirtied_cache', 'dirty_queue_length', 'dirty_books_referencing', - 'windows_check_if_files_in_use', + 'windows_check_if_files_in_use', 'get_metadata_for_dump', 'get_a_dirtied_book', } SKIP_ARGSPEC = { '__init__', @@ -402,6 +403,7 @@ class LegacyTest(BaseTest): def test_legacy_setters(self): # {{{ 'Test methods that are directly equivalent in the old and new interface' + from calibre.ebooks.metadata.book.base import Metadata ndb = self.init_legacy(self.cloned_library) db = self.init_old(self.cloned_library) @@ -421,9 +423,8 @@ class LegacyTest(BaseTest): ('set_timestamp', 1, None), ('set_timestamp', 2, '2011-1-7'), ('set_uuid', 1, None), ('set_uuid', 2, 'a test uuid'), ('set_title', 1, 'title two'), ('set_title', 2, None), ('set_title', 3, 'The Test Title'), - + ('set_tags', 1, ['a1', 'a2'], True), ('set_tags', 2, ['b1', 'tag one'], False, False, False, True), ('set_tags', 3, ['A1']), (db.refresh,), - ('title', 0), ('title', 1), ('title', 2), ('title_sort', 0), ('title_sort', 1), ('title_sort', 2), ('authors', 0), ('authors', 1), ('authors', 2), @@ -437,12 +438,29 @@ class LegacyTest(BaseTest): ('series', 0), ('series', 1), ('series', 2), ('series_index', 0), ('series_index', 1), ('series_index', 2), ('uuid', 0), ('uuid', 1), ('uuid', 2), + ('@tags', 0), ('@tags', 1), ('@tags', 2), + ('@all_tags',), + ('@get_all_identifier_types',), ('set_title_sort', 1, 'Title Two'), ('set_title_sort', 2, None), ('set_title_sort', 3, 'The Test Title_sort'), ('set_series_index', 1, 2.3), ('set_series_index', 2, 0), ('set_series_index', 3, 8), + ('set_identifier', 1, 'moose', 'val'), ('set_identifier', 2, 'test', ''), ('set_identifier', 3, '', ''), (db.refresh,), ('series_index', 0), ('series_index', 1), ('series_index', 2), ('title_sort', 0), ('title_sort', 1), ('title_sort', 2), + ('get_identifiers', 0), ('get_identifiers', 1), ('get_identifiers', 2), + ('@get_all_identifier_types',), + + ('set_metadata', 1, Metadata('title', ('a1',)), False, False, False, True, True), + ('set_metadata', 3, Metadata('title', ('a1',))), + (db.refresh,), + ('title', 0), ('title', 1), ('title', 2), + ('title_sort', 0), ('title_sort', 1), ('title_sort', 2), + ('authors', 0), ('authors', 1), ('authors', 2), + ('author_sort', 0), ('author_sort', 1), ('author_sort', 2), + ('@tags', 0), ('@tags', 1), ('@tags', 2), + ('@all_tags',), + ('@get_all_identifier_types',), )) db.close() diff --git a/src/calibre/db/write.py b/src/calibre/db/write.py index a257788a60..5b35248353 100644 --- a/src/calibre/db/write.py +++ b/src/calibre/db/write.py @@ -107,8 +107,8 @@ def adapt_languages(to_tuple, x): return tuple(ans) def clean_identifier(typ, val): - typ = icu_lower(typ).strip().replace(':', '').replace(',', '') - val = val.strip().replace(',', '|').replace(':', '|') + typ = icu_lower(typ or '').strip().replace(':', '').replace(',', '') + val = (val or '').strip().replace(',', '|').replace(':', '|') return typ, val def adapt_identifiers(to_tuple, x):