From 836e00211a4a6a24abe80efdc5b3242be49b6b4d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 22 Feb 2013 19:45:12 +0530 Subject: [PATCH] Implement writing custom series index fields --- src/calibre/db/cache.py | 6 ++++++ src/calibre/db/fields.py | 1 + src/calibre/db/tests/writing.py | 33 ++++++++++++++++++++++----------- src/calibre/db/write.py | 18 ++++++++++++++++-- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/calibre/db/cache.py b/src/calibre/db/cache.py index 236d25c3e9..af22db64d7 100644 --- a/src/calibre/db/cache.py +++ b/src/calibre/db/cache.py @@ -211,6 +211,12 @@ class Cache(object): self.fields['ondevice'] = create_field('ondevice', VirtualTable('ondevice')) + for name, field in self.fields.iteritems(): + if name[0] == '#' and name.endswith('_index'): + field.series_field = self.fields[name[:-len('_index')]] + elif name == 'series_index': + field.series_field = self.fields['series'] + @read_api def field_for(self, name, book_id, default_value=None): ''' diff --git a/src/calibre/db/fields.py b/src/calibre/db/fields.py index 46386b9ba5..dee312dbcd 100644 --- a/src/calibre/db/fields.py +++ b/src/calibre/db/fields.py @@ -46,6 +46,7 @@ class Field(object): elif name == 'languages': self.category_formatter = calibre_langcode_to_name self.writer = Writer(self) + self.series_field = None @property def metadata(self): diff --git a/src/calibre/db/tests/writing.py b/src/calibre/db/tests/writing.py index f6cf4d2d45..314d6fbb7a 100644 --- a/src/calibre/db/tests/writing.py +++ b/src/calibre/db/tests/writing.py @@ -22,7 +22,11 @@ class WritingTest(BaseTest): def create_getter(self, name, getter=None): if getter is None: - ans = lambda db:partial(db.get_custom, label=name[1:], + if name.endswith('_index'): + ans = lambda db:partial(db.get_custom_extra, index_is_id=True, + label=name[1:].replace('_index', '')) + else: + ans = lambda db:partial(db.get_custom, label=name[1:], index_is_id=True) else: ans = lambda db:partial(getattr(db, getter), index_is_id=True) @@ -53,22 +57,29 @@ class WritingTest(BaseTest): db = self.init_old(cl) getter = test.getter(db) sqlite_res = getter(1) - test.setter(db)(1, val) - old_cached_res = getter(1) - self.assertEqual(old_cached_res, cached_res, - 'Failed setting for %s with value %r, cached value not the same. Old: %r != New: %r'%( - test.name, val, old_cached_res, cached_res)) - db.refresh() - old_sqlite_res = getter(1) - self.assertEqual(old_sqlite_res, sqlite_res, - 'Failed setting for %s, sqlite value not the same: %r != %r'%( - test.name, old_sqlite_res, sqlite_res)) + if test.name.endswith('_index'): + val = float(val) if val is not None else 1.0 + self.assertEqual(sqlite_res, val, + 'Failed setting for %s with value %r, sqlite value not the same. val: %r != sqlite_val: %r'%( + test.name, val, val, sqlite_res)) + else: + test.setter(db)(1, val) + old_cached_res = getter(1) + self.assertEqual(old_cached_res, cached_res, + 'Failed setting for %s with value %r, cached value not the same. Old: %r != New: %r'%( + test.name, val, old_cached_res, cached_res)) + db.refresh() + old_sqlite_res = getter(1) + self.assertEqual(old_sqlite_res, sqlite_res, + 'Failed setting for %s, sqlite value not the same: %r != %r'%( + test.name, old_sqlite_res, sqlite_res)) del db def test_one_one(self): 'Test setting of values in one-one fields' tests = [self.create_test('#yesno', (True, False, 'true', 'false', None))] for name, getter, setter in ( + ('#series_index', None, None), ('series_index', 'series_index', 'set_series_index'), ('#float', None, None), ): diff --git a/src/calibre/db/write.py b/src/calibre/db/write.py index b3449f1387..cb710d271f 100644 --- a/src/calibre/db/write.py +++ b/src/calibre/db/write.py @@ -138,6 +138,21 @@ def one_one_in_other(book_id_val_map, db, field, *args): field.table.book_col_map.update(updated) return set(book_id_val_map) +def custom_series_index(book_id_val_map, db, field, *args): + series_field = field.series_field + sequence = [] + for book_id, sidx in book_id_val_map.iteritems(): + if sidx is None: + sidx = 1.0 + ids = series_field.ids_for_book(book_id) + if ids: + sequence.append((sidx, book_id, ids[0])) + field.table.book_col_map[book_id] = sidx + if sequence: + db.conn.executemany('UPDATE %s SET %s=? WHERE book=? AND value=?'%( + field.metadata['table'], field.metadata['column']), sequence) + return {s[0] for s in sequence} + def dummy(book_id_val_map, *args): return set() @@ -153,8 +168,7 @@ class Writer(object): 'id', 'cover', 'size', 'path', 'formats', 'news'}: self.set_books_func = dummy elif self.name[0] == '#' and self.name.endswith('_index'): - # TODO: Implement this - pass + self.set_books_func = custom_series_index elif field.is_many: # TODO: Implement this pass