From 17c520d1d911eb66a7cfa7e2b4820b2979061cb0 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 16 Jul 2013 16:11:04 +0530 Subject: [PATCH] Legacy rename API --- src/calibre/db/cache.py | 26 ++++++++++++++++---------- src/calibre/db/legacy.py | 15 ++++++++++++++- src/calibre/db/tests/legacy.py | 27 +++++++++++++++++++++++++++ src/calibre/db/tests/writing.py | 2 +- 4 files changed, 58 insertions(+), 12 deletions(-) diff --git a/src/calibre/db/cache.py b/src/calibre/db/cache.py index 178e4d3285..6564a9a9a2 100644 --- a/src/calibre/db/cache.py +++ b/src/calibre/db/cache.py @@ -30,7 +30,7 @@ from calibre.ebooks.metadata.book.base import Metadata from calibre.ebooks.metadata.opf2 import metadata_to_opf from calibre.ptempfile import (base_dir, PersistentTemporaryFile, SpooledTemporaryFile) -from calibre.utils.config import prefs +from calibre.utils.config import prefs, tweaks from calibre.utils.date import now as nowf, utcnow, UNDEFINED_DATE from calibre.utils.icu import sort_key @@ -1100,16 +1100,16 @@ class Cache(object): self._update_last_modified(tuple(formats_map.iterkeys())) @read_api - def get_next_series_num_for(self, series): + def get_next_series_num_for(self, series, field='series'): books = () - sf = self.fields['series'] + sf = self.fields[field] if series: q = icu_lower(series) - for val, book_ids in sf.iter_searchable_values(self._get_metadata, frozenset(self.all_book_ids())): + for val, book_ids in sf.iter_searchable_values(self._get_metadata, frozenset(self._all_book_ids())): if q == icu_lower(val): books = book_ids break - series_indices = sorted(self._field_for('series_index', book_id) for book_id in books) + series_indices = sorted(self._field_for(sf.index_field.name, book_id) for book_id in books) return _get_next_series_num_for_list(tuple(series_indices), unwrap=False) @read_api @@ -1223,24 +1223,30 @@ class Cache(object): return val_map @write_api - def rename_items(self, field, item_id_to_new_name_map): + def rename_items(self, field, item_id_to_new_name_map, change_index=True): + f = self.fields[field] try: - func = self.fields[field].table.rename_item + func = f.table.rename_item except AttributeError: raise ValueError('Cannot rename items for one-one fields: %s' % field) affected_books = set() + moved_books = set() id_map = {} for item_id, new_name in item_id_to_new_name_map.iteritems(): books, new_id = func(item_id, new_name, self.backend) affected_books.update(books) id_map[item_id] = new_id + if new_id != item_id: + moved_books.update(books) if affected_books: if field == 'authors': - self._set_field('author_sort', # also marks as dirty + self._set_field('author_sort', {k:' & '.join(v) for k, v in self._author_sort_strings_for_books(affected_books).iteritems()}) self._update_path(affected_books, mark_as_dirtied=False) - else: - self._mark_as_dirty(affected_books) + elif change_index and hasattr(f, 'index_field') and tweaks['series_index_auto_increment'] != 'no_change': + for book_id in moved_books: + self._set_field(f.index_field.name, {book_id:self._get_next_series_num_for(self._field_for(field, book_id), field=field)}) + self._mark_as_dirty(affected_books) return affected_books, id_map @write_api diff --git a/src/calibre/db/legacy.py b/src/calibre/db/legacy.py index 5df491eca3..a6e6bd9fa7 100644 --- a/src/calibre/db/legacy.py +++ b/src/calibre/db/legacy.py @@ -290,7 +290,7 @@ class LibraryDatabase(object): def authors_sort_strings(self, index, index_is_id=False): book_id = index if index_is_id else self.id(index) - return list(self.author_sort_strings_for_books.canonical_author_sort_for_books((book_id,))[book_id]) + return list(self.new_api.author_sort_strings_for_books((book_id,))[book_id]) def author_sort_from_book(self, index, index_is_id=False): return ' & '.join(self.authors_sort_strings(index, index_is_id=index_is_id)) @@ -500,6 +500,9 @@ class LibraryDatabase(object): book_id = index if index_is_id else self.id(index) return self.new_api.get_metadata(book_id, get_cover=get_cover, get_user_categories=get_user_categories, cover_as_data=cover_as_data) + def rename_series(self, old_id, new_name, change_index=True): + self.new_api.rename_items('series', {old_id:new_name}, change_index=change_index) + # Private interface {{{ def __iter__(self): for row in self.data.iterall(): @@ -582,6 +585,16 @@ for field in ( return func setattr(LibraryDatabase, 'set_%s' % field.replace('!', ''), MT(setter(field))) +for field in ('authors', 'tags', 'publisher'): + def renamer(field): + def func(self, old_id, new_name): + id_map = self.new_api.rename_items(field, {old_id:new_name})[1] + if field == 'authors': + return id_map[old_id] + return func + fname = field[:-1] if field in {'tags', 'authors'} else field + setattr(LibraryDatabase, 'rename_%s' % fname, MT(renamer(field))) + LibraryDatabase.update_last_modified = MT( lambda self, book_ids, commit=False, now=None: self.new_api.update_last_modified(book_ids, now=now)) diff --git a/src/calibre/db/tests/legacy.py b/src/calibre/db/tests/legacy.py index 725f6c3ad9..09ae756d10 100644 --- a/src/calibre/db/tests/legacy.py +++ b/src/calibre/db/tests/legacy.py @@ -472,6 +472,7 @@ class LegacyTest(BaseTest): nmi = [ndb.get_metadata(x) for x in (0, 1, 2)] self.assertEqual([x.author_sort_map for x in omi], [x.author_sort_map for x in nmi]) self.assertEqual([x.author_link_map for x in omi], [x.author_link_map for x in nmi]) + db.close() ndb = self.init_legacy(self.cloned_library) db = self.init_old(self.cloned_library) @@ -554,6 +555,7 @@ class LegacyTest(BaseTest): ('@all_tags',), ('#tags', 0), ('#tags', 1), ('#tags', 2), )) + db.close() ndb = self.init_legacy(self.cloned_library) db = self.init_old(self.cloned_library) @@ -563,6 +565,31 @@ class LegacyTest(BaseTest): ('@all_tags',), ('@tags', 0), ('@tags', 1), ('@tags', 2), )) + db.close() + + ndb = self.init_legacy(self.cloned_library) + db = self.init_old(self.cloned_library) + a = {v:k for k, v in ndb.new_api.get_id_map('authors').iteritems()}['Author One'] + t = {v:k for k, v in ndb.new_api.get_id_map('tags').iteritems()}['Tag One'] + s = {v:k for k, v in ndb.new_api.get_id_map('series').iteritems()}['A Series One'] + p = {v:k for k, v in ndb.new_api.get_id_map('publisher').iteritems()}['Publisher One'] + run_funcs(self, db, ndb, ( + ('rename_author', a, 'Author Two'), + ('rename_tag', t, 'News'), + ('rename_series', s, 'ss'), + ('rename_publisher', p, 'publisher one'), + (db.clean,), + (db.refresh,), + ('@all_tags',), + ('tags', 0), ('tags', 1), ('tags', 2), + ('series', 0), ('series', 1), ('series', 2), + ('publisher', 0), ('publisher', 1), ('publisher', 2), + ('series_index', 0), ('series_index', 1), ('series_index', 2), + ('authors', 0), ('authors', 1), ('authors', 2), + ('author_sort', 0), ('author_sort', 1), ('author_sort', 2), + )) + db.close() + # }}} diff --git a/src/calibre/db/tests/writing.py b/src/calibre/db/tests/writing.py index 9a882bbd03..26f73964df 100644 --- a/src/calibre/db/tests/writing.py +++ b/src/calibre/db/tests/writing.py @@ -541,5 +541,5 @@ class WritingTest(BaseTest): self.assertEqual(c.all_field_names('#series'), {'My Series Two'}) self.assertEqual(c.field_for('#series', 2), 'My Series Two') self.assertEqual(c.field_for('#series_index', 1), 3.0) - self.assertEqual(c.field_for('#series_index', 2), 1.0) + self.assertEqual(c.field_for('#series_index', 2), 4.0) # }}}