Miscellaneous API

This commit is contained in:
Kovid Goyal 2013-07-14 15:48:56 +05:30
parent 73536b6421
commit 34abccc4f1
3 changed files with 32 additions and 11 deletions

View File

@ -63,11 +63,13 @@ class LibraryDatabase(object):
cache = self.new_api = Cache(backend) cache = self.new_api = Cache(backend)
cache.init() cache.init()
self.data = View(cache) self.data = View(cache)
self.id = self.data.index_to_id
self.get_property = self.data.get_property self.get_property = self.data.get_property
self.last_update_check = self.last_modified() self.last_update_check = self.last_modified()
self.book_on_device_func = None self.book_on_device_func = None
self.is_case_sensitive = getattr(backend, 'is_case_sensitive', False)
def close(self): def close(self):
self.backend.close() self.backend.close()
@ -131,6 +133,10 @@ class LibraryDatabase(object):
for book_id in self.data.cache.all_book_ids(): for book_id in self.data.cache.all_book_ids():
yield book_id yield book_id
def is_empty(self):
with self.new_api.read_lock:
return not bool(self.new_api.fields['title'].table.book_col_map)
def get_usage_count_by_id(self, field): def get_usage_count_by_id(self, field):
return [[k, v] for k, v in self.new_api.get_usage_count_by_id(field).iteritems()] return [[k, v] for k, v in self.new_api.get_usage_count_by_id(field).iteritems()]
@ -161,7 +167,7 @@ class LibraryDatabase(object):
def path(self, index, index_is_id=False): def path(self, index, index_is_id=False):
'Return the relative path to the directory containing this books files as a unicode string.' 'Return the relative path to the directory containing this books files as a unicode string.'
book_id = index if index_is_id else self.data.index_to_id(index) book_id = index if index_is_id else self.id(index)
return self.new_api.field_for('path', book_id).replace('/', os.sep) return self.new_api.field_for('path', book_id).replace('/', os.sep)
def abspath(self, index, index_is_id=False, create_dirs=True): def abspath(self, index, index_is_id=False, create_dirs=True):
@ -224,7 +230,7 @@ class LibraryDatabase(object):
def add_format(self, index, fmt, stream, index_is_id=False, path=None, notify=True, replace=True, copy_function=None): def add_format(self, index, fmt, stream, index_is_id=False, path=None, notify=True, replace=True, copy_function=None):
''' path and copy_function are ignored by the new API ''' ''' path and copy_function are ignored by the new API '''
book_id = index if index_is_id else self.data.index_to_id(index) book_id = index if index_is_id else self.id(index)
try: try:
return self.new_api.add_format(book_id, fmt, stream, replace=replace, run_hooks=False, dbapi=self) return self.new_api.add_format(book_id, fmt, stream, replace=replace, run_hooks=False, dbapi=self)
except: except:
@ -234,7 +240,7 @@ class LibraryDatabase(object):
def add_format_with_hooks(self, index, fmt, fpath, index_is_id=False, path=None, notify=True, replace=True): def add_format_with_hooks(self, index, fmt, fpath, index_is_id=False, path=None, notify=True, replace=True):
''' path is ignored by the new API ''' ''' path is ignored by the new API '''
book_id = index if index_is_id else self.data.index_to_id(index) book_id = index if index_is_id else self.id(index)
try: try:
return self.new_api.add_format(book_id, fmt, fpath, replace=replace, run_hooks=True, dbapi=self) return self.new_api.add_format(book_id, fmt, fpath, replace=replace, run_hooks=True, dbapi=self)
except: except:
@ -268,12 +274,12 @@ class LibraryDatabase(object):
# }}} # }}}
def get_field(self, index, key, default=None, index_is_id=False): def get_field(self, index, key, default=None, index_is_id=False):
book_id = index if index_is_id else self.data.index_to_id(index) book_id = index if index_is_id else self.id(index)
mi = self.new_api.get_metadata(book_id, get_cover=key == 'cover') mi = self.new_api.get_metadata(book_id, get_cover=key == 'cover')
return mi.get(key, default) return mi.get(key, default)
def authors_sort_strings(self, index, index_is_id=False): def authors_sort_strings(self, index, index_is_id=False):
book_id = index if index_is_id else self.data.index_to_id(index) book_id = index if index_is_id else self.id(index)
with self.new_api.read_lock: with self.new_api.read_lock:
authors = self.new_api._field_ids_for('authors', book_id) authors = self.new_api._field_ids_for('authors', book_id)
adata = self.new_api._author_data(authors) adata = self.new_api._author_data(authors)
@ -283,7 +289,7 @@ class LibraryDatabase(object):
return ' & '.join(self.authors_sort_strings(index, index_is_id=index_is_id)) return ' & '.join(self.authors_sort_strings(index, index_is_id=index_is_id))
def authors_with_sort_strings(self, index, index_is_id=False): def authors_with_sort_strings(self, index, index_is_id=False):
book_id = index if index_is_id else self.data.index_to_id(index) book_id = index if index_is_id else self.id(index)
with self.new_api.read_lock: with self.new_api.read_lock:
authors = self.new_api._field_ids_for('authors', book_id) authors = self.new_api._field_ids_for('authors', book_id)
adata = self.new_api._author_data(authors) adata = self.new_api._author_data(authors)
@ -318,7 +324,7 @@ class LibraryDatabase(object):
return sorted(book_ids, key=lambda x:ff('series_index', x)) return sorted(book_ids, key=lambda x:ff('series_index', x))
def books_in_series_of(self, index, index_is_id=False): def books_in_series_of(self, index, index_is_id=False):
book_id = index if index_is_id else self.data.index_to_id(index) book_id = index if index_is_id else self.id(index)
series_ids = self.new_api.field_ids_for('series', book_id) series_ids = self.new_api.field_ids_for('series', book_id)
if not series_ids: if not series_ids:
return [] return []
@ -349,7 +355,7 @@ class LibraryDatabase(object):
self.new_api.delete_conversion_options((book_id,), fmt=fmt) self.new_api.delete_conversion_options((book_id,), fmt=fmt)
def set(self, index, field, val, allow_case_change=False): def set(self, index, field, val, allow_case_change=False):
book_id = self.data.index_to_id(index) book_id = self.id(index)
try: try:
return self.new_api.set_field(field, {book_id:val}, allow_case_change=allow_case_change) return self.new_api.set_field(field, {book_id:val}, allow_case_change=allow_case_change)
finally: finally:
@ -427,6 +433,9 @@ class LibraryDatabase(object):
if tag_ids: if tag_ids:
self.new_api._remove_items('tags', tag_ids) self.new_api._remove_items('tags', tag_ids)
def has_id(self, book_id):
return book_id in self.new_api.all_book_ids()
# Private interface {{{ # Private interface {{{
def __iter__(self): def __iter__(self):
for row in self.data.iterall(): for row in self.data.iterall():
@ -454,10 +463,13 @@ for prop in ('author_sort', 'authors', 'comment', 'comments', 'publisher',
return func return func
setattr(LibraryDatabase, prop, MT(getter(prop))) setattr(LibraryDatabase, prop, MT(getter(prop)))
LibraryDatabase.index = MT(lambda self, book_id, cache=False:self.data.id_to_index(book_id))
LibraryDatabase.has_cover = MT(lambda self, book_id:self.new_api.field_for('cover', book_id)) LibraryDatabase.has_cover = MT(lambda self, book_id:self.new_api.field_for('cover', book_id))
LibraryDatabase.get_tags = MT(lambda self, book_id:set(self.new_api.field_for('tags', book_id))) LibraryDatabase.get_tags = MT(lambda self, book_id:set(self.new_api.field_for('tags', book_id)))
LibraryDatabase.get_identifiers = MT( LibraryDatabase.get_identifiers = MT(
lambda self, index, index_is_id=False: self.new_api.field_for('identifiers', index if index_is_id else self.data.index_to_id(index))) lambda self, index, index_is_id=False: self.new_api.field_for('identifiers', index if index_is_id else self.id(index)))
LibraryDatabase.isbn = MT(
lambda self, index, index_is_id=False: self.get_identifiers(index, index_is_id=index_is_id).get('isbn', None))
# }}} # }}}
# Legacy setter API {{{ # Legacy setter API {{{

View File

@ -161,6 +161,10 @@ class LegacyTest(BaseTest):
'get_next_series_num_for': [('A Series One',)], 'get_next_series_num_for': [('A Series One',)],
'author_sort_from_authors': [(['Author One', 'Author Two', 'Unknown'],)], 'author_sort_from_authors': [(['Author One', 'Author Two', 'Unknown'],)],
'has_book':[(Metadata('title one'),), (Metadata('xxxx1111'),)], 'has_book':[(Metadata('title one'),), (Metadata('xxxx1111'),)],
'has_id':[(1,), (2,), (3,), (9999,)],
'id':[(1,), (2,), (0,),],
'index':[(1,), (2,), (3,), ],
'is_empty':[()],
'all_author_names':[()], 'all_author_names':[()],
'all_tag_names':[()], 'all_tag_names':[()],
'all_series_names':[()], 'all_series_names':[()],
@ -332,7 +336,7 @@ class LegacyTest(BaseTest):
'construct_path_name', 'clear_dirtied', 'commit_dirty_cache', 'initialize_database', 'initialize_dynamic', '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', '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', 'import_old_database', 'dirtied_lock', 'dirtied_cache', 'dirty_queue_length', 'dirty_books_referencing',
'windows_check_if_files_in_use', 'get_metadata_for_dump', 'get_a_dirtied_book', 'windows_check_if_files_in_use', 'get_metadata_for_dump', 'get_a_dirtied_book', 'dirtied_sequence',
} }
SKIP_ARGSPEC = { SKIP_ARGSPEC = {
'__init__', '__init__',
@ -432,7 +436,7 @@ class LegacyTest(BaseTest):
('set_author_sort', 3, 'new_aus'), ('set_author_sort', 3, 'new_aus'),
('set_comment', 1, ''), ('set_comment', 2, None), ('set_comment', 3, '<p>a comment</p>'), ('set_comment', 1, ''), ('set_comment', 2, None), ('set_comment', 3, '<p>a comment</p>'),
('set_has_cover', 1, True), ('set_has_cover', 2, True), ('set_has_cover', 3, 1), ('set_has_cover', 1, True), ('set_has_cover', 2, True), ('set_has_cover', 3, 1),
('set_identifiers', 2, {'test':'', 'a':'b'}), ('set_identifiers', 3, {'id':'1', 'url':'http://acme.com'}), ('set_identifiers', 1, {}), ('set_identifiers', 2, {'test':'', 'a':'b'}), ('set_identifiers', 3, {'id':'1', 'isbn':'9783161484100'}), ('set_identifiers', 1, {}),
('set_languages', 1, ('en',)), ('set_languages', 1, ('en',)),
('set_languages', 2, ()), ('set_languages', 2, ()),
('set_languages', 3, ('deu', 'spa', 'fra')), ('set_languages', 3, ('deu', 'spa', 'fra')),
@ -458,6 +462,7 @@ class LegacyTest(BaseTest):
('series', 0), ('series', 1), ('series', 2), ('series', 0), ('series', 1), ('series', 2),
('series_index', 0), ('series_index', 1), ('series_index', 2), ('series_index', 0), ('series_index', 1), ('series_index', 2),
('uuid', 0), ('uuid', 1), ('uuid', 2), ('uuid', 0), ('uuid', 1), ('uuid', 2),
('isbn', 0), ('isbn', 1), ('isbn', 2),
('@tags', 0), ('@tags', 1), ('@tags', 2), ('@tags', 0), ('@tags', 1), ('@tags', 2),
('@all_tags',), ('@all_tags',),
('@get_all_identifier_types',), ('@get_all_identifier_types',),
@ -516,3 +521,4 @@ class LegacyTest(BaseTest):
# }}} # }}}

View File

@ -161,6 +161,9 @@ class View(object):
def index_to_id(self, idx): def index_to_id(self, idx):
return self._map_filtered[idx] return self._map_filtered[idx]
def id_to_index(self, book_id):
return self._map.index(book_id)
def _get(self, field, idx, index_is_id=True, default_value=None, fmt=lambda x:x): def _get(self, field, idx, index_is_id=True, default_value=None, fmt=lambda x:x):
id_ = idx if index_is_id else self.index_to_id(idx) id_ = idx if index_is_id else self.index_to_id(idx)
if index_is_id and id_ not in self.cache.all_book_ids(): if index_is_id and id_ not in self.cache.all_book_ids():