def test_library_restrictions(self): # {{{ from calibre.srv.opts import Options from calibre.srv.handler import Handler from calibre.db.legacy import create_backend opts = Options(userdb=':memory:') Data = namedtuple('Data', 'username') with TemporaryDirectory() as base: l1, l2, l3 = map(lambda x: os.path.join(base, 'l' + x), '123') for l in (l1, l2, l3): create_backend(l).close() ctx = Handler((l1, l2, l3), opts).router.ctx um = ctx.user_manager def get_library(username=None, library_id=None): ans = ctx.get_library(Data(username), library_id=library_id) return os.path.basename(ans.backend.library_path) def library_info(username=None): lmap, defaultlib = ctx.library_info(Data(username)) lmap = {k:os.path.basename(v) for k, v in lmap.iteritems()} return lmap, defaultlib self.assertEqual(get_library(), 'l1') self.assertEqual(library_info()[0], {'l%d'%i:'l%d'%i for i in range(1, 4)}) self.assertEqual(library_info()[1], 'l1') self.assertRaises(HTTPForbidden, get_library, 'xxx') um.add_user('a', 'a') self.assertEqual(library_info('a')[0], {'l%d'%i:'l%d'%i for i in range(1, 4)}) um.update_user_restrictions('a', {'blocked_library_names': ['L2']}) self.assertEqual(library_info('a')[0], {'l%d'%i:'l%d'%i for i in range(1, 4) if i != 2}) um.update_user_restrictions('a', {'allowed_library_names': ['l3']}) self.assertEqual(library_info('a')[0], {'l%d'%i:'l%d'%i for i in range(1, 4) if i == 3}) self.assertEqual(library_info('a')[1], 'l3') self.assertRaises(HTTPForbidden, get_library, 'a', 'l1') self.assertRaises(HTTPForbidden, get_library, 'xxx')
def test_library_restrictions(self): # {{{ from calibre.srv.opts import Options from calibre.srv.handler import Handler from calibre.db.legacy import create_backend opts = Options(userdb=':memory:') Data = namedtuple('Data', 'username') with TemporaryDirectory() as base: l1, l2, l3 = map(lambda x: os.path.join(base, 'l' + x), '123') for l in (l1, l2, l3): create_backend(l).close() ctx = Handler((l1, l2, l3), opts).router.ctx um = ctx.user_manager def get_library(username=None, library_id=None): ans = ctx.get_library(Data(username), library_id=library_id) return os.path.basename(ans.backend.library_path) def library_info(username=None): lmap, defaultlib = ctx.library_info(Data(username)) lmap = {k:os.path.basename(v) for k, v in iteritems(lmap)} return lmap, defaultlib self.assertEqual(get_library(), 'l1') self.assertEqual(library_info()[0], {'l%d'%i:'l%d'%i for i in range(1, 4)}) self.assertEqual(library_info()[1], 'l1') self.assertRaises(HTTPForbidden, get_library, 'xxx') um.add_user('a', 'a') self.assertEqual(library_info('a')[0], {'l%d'%i:'l%d'%i for i in range(1, 4)}) um.update_user_restrictions('a', {'blocked_library_names': ['L2']}) self.assertEqual(library_info('a')[0], {'l%d'%i:'l%d'%i for i in range(1, 4) if i != 2}) um.update_user_restrictions('a', {'allowed_library_names': ['l3']}) self.assertEqual(library_info('a')[0], {'l%d'%i:'l%d'%i for i in range(1, 4) if i == 3}) self.assertEqual(library_info('a')[1], 'l3') self.assertRaises(HTTPForbidden, get_library, 'a', 'l1') self.assertRaises(HTTPForbidden, get_library, 'xxx')
def copy_to_library(self, loc, delete_after=False): rows = self.gui.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: return error_dialog(self.gui, _('Cannot copy'), _('No books selected'), show=True) ids = list(map(self.gui.library_view.model().id, rows)) db = self.gui.library_view.model().db if not db.exists_at(loc): return error_dialog(self.gui, _('No library'), _('No library found at %s')%loc, show=True) # Open the new db so we can check the custom columns. We use only the # backend since we only need the custom column definitions, not the # rest of the data in the db. We also do not want the user defined # formatter functions because loading them can poison the template cache global libraries_with_checked_columns from calibre.db.legacy import create_backend newdb = create_backend(loc, load_user_formatter_functions=False) continue_processing = True with closing(newdb): if newdb.library_id not in libraries_with_checked_columns[db.library_id]: newdb_meta = newdb.field_metadata.custom_field_metadata() incompatible_columns = [] missing_columns = [] for k, m in db.field_metadata.custom_iteritems(): if k not in newdb_meta: missing_columns.append(k) elif not self._column_is_compatible(m, newdb_meta[k]): # Note that composite columns are always assumed to be # compatible. No attempt is made to copy the template # from the source to the destination. incompatible_columns.append(k) if missing_columns or incompatible_columns: continue_processing = ask_about_cc_mismatch(self.gui, db, newdb, missing_columns, incompatible_columns) if continue_processing: libraries_with_checked_columns[db.library_id].add(newdb.library_id) newdb.close() del newdb if not continue_processing: return duplicate_ids = self.do_copy(ids, db, loc, delete_after, False) if duplicate_ids: d = DuplicatesQuestion(self.gui, duplicate_ids, loc) if d.exec_() == d.Accepted: ids = d.ids if ids: self.do_copy(list(ids), db, loc, delete_after, add_duplicates=True)
def create_db(self, library_path): from calibre.db.legacy import create_backend from calibre.db.cache import Cache d = os.path.dirname src = os.path.join(d(d(d(os.path.abspath(__file__)))), 'db', 'tests', 'metadata.db') dest = os.path.join(library_path, 'metadata.db') shutil.copy2(src, dest) db = Cache(create_backend(library_path)) db.init() db.set_cover({1:I('lt.png', data=True), 2:I('polish.png', data=True)}) db.add_format(1, 'FMT1', BytesIO(b'book1fmt1'), run_hooks=False) db.add_format(1, 'EPUB', open(P('quick_start/eng.epub'), 'rb'), run_hooks=False) db.add_format(1, 'FMT2', BytesIO(b'book1fmt2'), run_hooks=False) db.add_format(2, 'FMT1', BytesIO(b'book2fmt1'), run_hooks=False) db.backend.conn.close() return dest
def init_library(library_path): db = Cache(create_backend(library_path)) db.init() return db
def copy_to_library(self, loc, delete_after=False): rows = self.gui.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: return error_dialog(self.gui, _('Cannot copy'), _('No books selected'), show=True) ids = list(map(self.gui.library_view.model().id, rows)) db = self.gui.library_view.model().db if not db.exists_at(loc): return error_dialog(self.gui, _('No library'), _('No library found at %s')%loc, show=True) aname = _('Moving to') if delete_after else _('Copying to') dtitle = '%s %s'%(aname, os.path.basename(loc)) self.pd = ProgressDialog(dtitle, min=0, max=len(ids)-1, parent=self.gui, cancelable=False) def progress(idx, title): self.pd.set_msg(title) self.pd.set_value(idx) # Open the new db so we can check the custom columns. We use only the # backend since we only need the custom column definitions, not the # rest of the data in the db. global libraries_with_checked_columns from calibre.db.legacy import create_backend newdb = create_backend(loc) continue_processing = True with closing(newdb): if newdb.library_id not in libraries_with_checked_columns[db.library_id]: newdb_meta = newdb.field_metadata.custom_field_metadata() incompatible_columns = [] missing_columns = [] for k, m in db.field_metadata.custom_iteritems(): if m['datatype'] == 'composite': continue if k not in newdb_meta: missing_columns.append(k) elif not self._column_is_compatible(m, newdb_meta[k]): incompatible_columns.append(k) if missing_columns or incompatible_columns: continue_processing = ask_about_cc_mismatch(self.gui, db, newdb, missing_columns, incompatible_columns) if continue_processing: libraries_with_checked_columns[db.library_id].add(newdb.library_id) newdb.close() del newdb if not continue_processing: return self.worker = Worker(ids, db, loc, Dispatcher(progress), Dispatcher(self.pd.accept), delete_after) self.worker.start() self.pd.exec_() donemsg = _('Copied %(num)d books to %(loc)s') if delete_after: donemsg = _('Moved %(num)d books to %(loc)s') if self.worker.error is not None: e, tb = self.worker.error error_dialog(self.gui, _('Failed'), _('Could not copy books: ') + e, det_msg=tb, show=True) else: self.gui.status_bar.show_message(donemsg % dict(num=len(ids), loc=loc), 2000) if self.worker.auto_merged_ids: books = '\n'.join(self.worker.auto_merged_ids.itervalues()) info_dialog(self.gui, _('Auto merged'), _('Some books were automatically merged into existing ' 'records in the target library. Click Show ' 'details to see which ones. This behavior is ' 'controlled by the Auto merge option in ' 'Preferences->Adding books.'), det_msg=books, show=True) if delete_after and self.worker.processed: v = self.gui.library_view ci = v.currentIndex() row = None if ci.isValid(): row = ci.row() v.model().delete_books_by_id(self.worker.processed, permanent=True) self.gui.iactions['Remove Books'].library_ids_deleted( self.worker.processed, row)
def init_library(library_path, is_default_library): db = Cache( create_backend(library_path, load_user_formatter_functions=is_default_library)) db.init() return db
def init_library(library_path, is_default_library): db = Cache( create_backend( library_path, load_user_formatter_functions=is_default_library)) db.init() return db