def cdb_copy_to_library(ctx, rd, target_library_id, library_id): db_src = get_db(ctx, rd, library_id) db_dest = get_db(ctx, rd, target_library_id) if ctx.restriction_for(rd, db_src) or ctx.restriction_for(rd, db_dest): raise HTTPForbidden( 'Cannot use the copy to library interface with a user who has per library restrictions' ) data = load_payload_data(rd) try: book_ids = {int(x) for x in data['book_ids']} move_books = bool(data.get('move', False)) preserve_date = bool(data.get('preserve_date', True)) duplicate_action = data.get('duplicate_action') or 'add' automerge_action = data.get('automerge_action') or 'overwrite' except Exception: raise HTTPBadRequest( 'Invalid encoded data, must be of the form: {book_ids: [id1, id2, ..]}' ) if duplicate_action not in ('add', 'add_formats_to_existing', 'ignore'): raise HTTPBadRequest( 'duplicate_action must be one of: add, add_formats_to_existing, ignore' ) if automerge_action not in ('overwrite', 'ignore', 'new record'): raise HTTPBadRequest( 'automerge_action must be one of: overwrite, ignore, new record') response = {} identical_books_data = None if duplicate_action != 'add': identical_books_data = db_dest.data_for_find_identical_books() to_remove = set() from calibre.db.copy_to_library import copy_one_book for book_id in book_ids: try: rdata = copy_one_book(book_id, db_src, db_dest, duplicate_action=duplicate_action, automerge_action=automerge_action, preserve_uuid=move_books, preserve_date=preserve_date, identical_books_data=identical_books_data) if move_books: to_remove.add(book_id) response[book_id] = {'ok': True, 'payload': rdata} except Exception: import traceback response[book_id] = { 'ok': False, 'payload': traceback.format_exc() } if to_remove: db_src.remove_books(to_remove, permanent=True) return response
def do_one(self, num, book_id, newdb): duplicate_action = 'add' if self.check_for_duplicates: duplicate_action = 'add_formats_to_existing' if prefs['add_formats_to_existing'] else 'ignore' rdata = copy_one_book( book_id, self.db, newdb, preserve_date=gprefs['preserve_date_on_ctl'], duplicate_action=duplicate_action, automerge_action=gprefs['automerge'], identical_books_data=self.find_identical_books_data, preserve_uuid=self.delete_after ) self.progress(num, rdata['title']) if rdata['action'] == 'automerge': self.auto_merged_ids[book_id] = _('%(title)s by %(author)s') % dict(title=rdata['title'], author=rdata['author']) elif rdata['action'] == 'duplicate': self.duplicate_ids[book_id] = (rdata['title'], rdata['authors']) self.processed.add(book_id)
def cdb_copy_to_library(ctx, rd, target_library_id, library_id): db_src = get_db(ctx, rd, library_id) db_dest = get_db(ctx, rd, target_library_id) if ctx.restriction_for(rd, db_src) or ctx.restriction_for(rd, db_dest): raise HTTPForbidden('Cannot use the copy to library interface with a user who has per library restrictions') data = load_payload_data(rd) try: book_ids = {int(x) for x in data['book_ids']} move_books = bool(data.get('move', False)) preserve_date = bool(data.get('preserve_date', True)) duplicate_action = data.get('duplicate_action') or 'add' automerge_action = data.get('automerge_action') or 'overwrite' except Exception: raise HTTPBadRequest('Invalid encoded data, must be of the form: {book_ids: [id1, id2, ..]}') if duplicate_action not in ('add', 'add_formats_to_existing', 'ignore'): raise HTTPBadRequest('duplicate_action must be one of: add, add_formats_to_existing, ignore') if automerge_action not in ('overwrite', 'ignore', 'new record'): raise HTTPBadRequest('automerge_action must be one of: overwrite, ignore, new record') response = {} identical_books_data = None if duplicate_action != 'add': identical_books_data = db_dest.data_for_find_identical_books() to_remove = set() from calibre.db.copy_to_library import copy_one_book for book_id in book_ids: try: rdata = copy_one_book( book_id, db_src, db_dest, duplicate_action=duplicate_action, automerge_action=automerge_action, preserve_uuid=move_books, preserve_date=preserve_date, identical_books_data=identical_books_data) if move_books: to_remove.add(book_id) response[book_id] = {'ok': True, 'payload': rdata} except Exception: import traceback response[book_id] = {'ok': False, 'payload': traceback.format_exc()} if to_remove: db_src.remove_books(to_remove, permanent=True) return response
def test_copy_to_library(self): # {{{ from calibre.db.copy_to_library import copy_one_book from calibre.ebooks.metadata import authors_to_string src_db = self.init_cache() dest_db = self.init_cache(self.cloned_library) def make_rdata(book_id=1, new_book_id=None, action='add'): return { 'title': src_db.field_for('title', book_id), 'authors': list(src_db.field_for('authors', book_id)), 'author': authors_to_string(src_db.field_for('authors', book_id)), 'book_id': book_id, 'new_book_id': new_book_id, 'action': action } def compare_field(field, func=self.assertEqual): func(src_db.field_for(field, rdata['book_id']), dest_db.field_for(field, rdata['new_book_id'])) rdata = copy_one_book(1, src_db, dest_db) self.assertEqual(rdata, make_rdata(new_book_id=max(dest_db.all_book_ids()))) compare_field('timestamp') compare_field('uuid', self.assertNotEqual) rdata = copy_one_book(1, src_db, dest_db, preserve_date=False, preserve_uuid=True) self.assertEqual(rdata, make_rdata(new_book_id=max(dest_db.all_book_ids()))) compare_field('timestamp', self.assertNotEqual) compare_field('uuid') rdata = copy_one_book(1, src_db, dest_db, duplicate_action='ignore') self.assertIsNone(rdata['new_book_id']) self.assertEqual(rdata['action'], 'duplicate') src_db.add_format(1, 'FMT1', BytesIO(b'replaced'), run_hooks=False) rdata = copy_one_book(1, src_db, dest_db, duplicate_action='add_formats_to_existing') self.assertEqual(rdata['action'], 'automerge') for new_book_id in (1, 4, 5): self.assertEqual(dest_db.format(new_book_id, 'FMT1'), b'replaced') src_db.add_format(1, 'FMT1', BytesIO(b'second-round'), run_hooks=False) rdata = copy_one_book(1, src_db, dest_db, duplicate_action='add_formats_to_existing', automerge_action='ignore') self.assertEqual(rdata['action'], 'automerge') for new_book_id in (1, 4, 5): self.assertEqual(dest_db.format(new_book_id, 'FMT1'), b'replaced') rdata = copy_one_book(1, src_db, dest_db, duplicate_action='add_formats_to_existing', automerge_action='new record') self.assertEqual(rdata['action'], 'automerge') for new_book_id in (1, 4, 5): self.assertEqual(dest_db.format(new_book_id, 'FMT1'), b'replaced') self.assertEqual(dest_db.format(rdata['new_book_id'], 'FMT1'), b'second-round')
def test_copy_to_library(self): # {{{ from calibre.db.copy_to_library import copy_one_book from calibre.ebooks.metadata import authors_to_string src_db = self.init_cache() dest_db = self.init_cache(self.cloned_library) def make_rdata(book_id=1, new_book_id=None, action='add'): return { 'title': src_db.field_for('title', book_id), 'authors': list(src_db.field_for('authors', book_id)), 'author': authors_to_string(src_db.field_for('authors', book_id)), 'book_id': book_id, 'new_book_id': new_book_id, 'action': action } def compare_field(field, func=self.assertEqual): func(src_db.field_for(field, rdata['book_id']), dest_db.field_for(field, rdata['new_book_id'])) rdata = copy_one_book(1, src_db, dest_db) self.assertEqual(rdata, make_rdata(new_book_id=max(dest_db.all_book_ids()))) compare_field('timestamp') compare_field('uuid', self.assertNotEqual) rdata = copy_one_book(1, src_db, dest_db, preserve_date=False, preserve_uuid=True) self.assertEqual(rdata, make_rdata(new_book_id=max(dest_db.all_book_ids()))) compare_field('timestamp', self.assertNotEqual) compare_field('uuid') rdata = copy_one_book(1, src_db, dest_db, duplicate_action='ignore') self.assertIsNone(rdata['new_book_id']) self.assertEqual(rdata['action'], 'duplicate') src_db.add_format(1, 'FMT1', BytesIO(b'replaced'), run_hooks=False) rdata = copy_one_book(1, src_db, dest_db, duplicate_action='add_formats_to_existing') self.assertEqual(rdata['action'], 'automerge') for new_book_id in (1, 4, 5): self.assertEqual(dest_db.format(new_book_id, 'FMT1'), b'replaced') src_db.add_format(1, 'FMT1', BytesIO(b'second-round'), run_hooks=False) rdata = copy_one_book(1, src_db, dest_db, duplicate_action='add_formats_to_existing', automerge_action='ignore') self.assertEqual(rdata['action'], 'automerge') for new_book_id in (1, 4, 5): self.assertEqual(dest_db.format(new_book_id, 'FMT1'), b'replaced') rdata = copy_one_book(1, src_db, dest_db, duplicate_action='add_formats_to_existing', automerge_action='new record') self.assertEqual(rdata['action'], 'automerge') for new_book_id in (1, 4, 5): self.assertEqual(dest_db.format(new_book_id, 'FMT1'), b'replaced') self.assertEqual(dest_db.format(rdata['new_book_id'], 'FMT1'), b'second-round')
def test_copy_to_library(self): # {{{ from calibre.db.copy_to_library import copy_one_book from calibre.ebooks.metadata import authors_to_string from calibre.utils.date import utcnow, EPOCH src_db = self.init_cache() dest_db = self.init_cache(self.cloned_library) def a(**kw): ts = utcnow() kw['timestamp'] = utcnow().isoformat() return kw, (ts - EPOCH).total_seconds() annot_list = [ a(type='bookmark', title='bookmark1 changed', seq=1), a(type='highlight', highlighted_text='text1', uuid='1', seq=2), a(type='highlight', highlighted_text='text2', uuid='2', seq=3, notes='notes2 some word changed again'), ] src_db.set_annotations_for_book(1, 'FMT1', annot_list) def make_rdata(book_id=1, new_book_id=None, action='add'): return { 'title': src_db.field_for('title', book_id), 'authors': list(src_db.field_for('authors', book_id)), 'author': authors_to_string(src_db.field_for('authors', book_id)), 'book_id': book_id, 'new_book_id': new_book_id, 'action': action } def compare_field(field, func=self.assertEqual): func(src_db.field_for(field, rdata['book_id']), dest_db.field_for(field, rdata['new_book_id'])) rdata = copy_one_book(1, src_db, dest_db) self.assertEqual(rdata, make_rdata(new_book_id=max(dest_db.all_book_ids()))) compare_field('timestamp') compare_field('uuid', self.assertNotEqual) self.assertEqual( src_db.all_annotations_for_book(1), dest_db.all_annotations_for_book(max(dest_db.all_book_ids()))) rdata = copy_one_book(1, src_db, dest_db, preserve_date=False, preserve_uuid=True) self.assertEqual(rdata, make_rdata(new_book_id=max(dest_db.all_book_ids()))) compare_field('timestamp', self.assertNotEqual) compare_field('uuid') rdata = copy_one_book(1, src_db, dest_db, duplicate_action='ignore') self.assertIsNone(rdata['new_book_id']) self.assertEqual(rdata['action'], 'duplicate') src_db.add_format(1, 'FMT1', BytesIO(b'replaced'), run_hooks=False) rdata = copy_one_book(1, src_db, dest_db, duplicate_action='add_formats_to_existing') self.assertEqual(rdata['action'], 'automerge') for new_book_id in (1, 4, 5): self.assertEqual(dest_db.format(new_book_id, 'FMT1'), b'replaced') src_db.add_format(1, 'FMT1', BytesIO(b'second-round'), run_hooks=False) rdata = copy_one_book(1, src_db, dest_db, duplicate_action='add_formats_to_existing', automerge_action='ignore') self.assertEqual(rdata['action'], 'automerge') for new_book_id in (1, 4, 5): self.assertEqual(dest_db.format(new_book_id, 'FMT1'), b'replaced') rdata = copy_one_book(1, src_db, dest_db, duplicate_action='add_formats_to_existing', automerge_action='new record') self.assertEqual(rdata['action'], 'automerge') for new_book_id in (1, 4, 5): self.assertEqual(dest_db.format(new_book_id, 'FMT1'), b'replaced') self.assertEqual(dest_db.format(rdata['new_book_id'], 'FMT1'), b'second-round')