mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk
This commit is contained in:
commit
648456293b
@ -306,7 +306,8 @@ class DB(object):
|
||||
|
||||
# Initialize database {{{
|
||||
|
||||
def __init__(self, library_path, default_prefs=None, read_only=False):
|
||||
def __init__(self, library_path, default_prefs=None, read_only=False,
|
||||
restore_all_prefs=False, progress_callback=lambda x, y:True):
|
||||
try:
|
||||
if isbytestring(library_path):
|
||||
library_path = library_path.decode(filesystem_encoding)
|
||||
@ -377,23 +378,27 @@ class DB(object):
|
||||
UPDATE authors SET sort=author_to_author_sort(name) WHERE sort IS NULL;
|
||||
''')
|
||||
|
||||
self.initialize_prefs(default_prefs)
|
||||
self.initialize_prefs(default_prefs, restore_all_prefs, progress_callback)
|
||||
self.initialize_custom_columns()
|
||||
self.initialize_tables()
|
||||
|
||||
def initialize_prefs(self, default_prefs): # {{{
|
||||
def initialize_prefs(self, default_prefs, restore_all_prefs, progress_callback): # {{{
|
||||
self.prefs = DBPrefs(self)
|
||||
|
||||
if default_prefs is not None and not self._exists:
|
||||
progress_callback(None, len(default_prefs))
|
||||
# Only apply default prefs to a new database
|
||||
for key in default_prefs:
|
||||
for i, key in enumerate(default_prefs):
|
||||
# be sure that prefs not to be copied are listed below
|
||||
if key not in frozenset(['news_to_be_synced']):
|
||||
if restore_all_prefs or key not in frozenset(['news_to_be_synced']):
|
||||
self.prefs[key] = default_prefs[key]
|
||||
progress_callback(_('restored preference ') + key, i+1)
|
||||
if 'field_metadata' in default_prefs:
|
||||
fmvals = [f for f in default_prefs['field_metadata'].values()
|
||||
if f['is_custom']]
|
||||
for f in fmvals:
|
||||
progress_callback(None, len(fmvals))
|
||||
for i, f in enumerate(fmvals):
|
||||
progress_callback(_('creating custom column ') + f['label'], i)
|
||||
self.create_custom_column(f['label'], f['name'],
|
||||
f['datatype'],
|
||||
(f['is_multiple'] is not None and
|
||||
@ -774,6 +779,11 @@ class DB(object):
|
||||
self._conn = Connection(self.dbpath)
|
||||
return self._conn
|
||||
|
||||
def close(self):
|
||||
if self._conn is not None:
|
||||
self._conn.close()
|
||||
del self._conn
|
||||
|
||||
@dynamic_property
|
||||
def user_version(self):
|
||||
doc = 'The user version of this database'
|
||||
|
77
src/calibre/db/legacy.py
Normal file
77
src/calibre/db/legacy.py
Normal file
@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=utf-8
|
||||
from __future__ import (unicode_literals, division, absolute_import,
|
||||
print_function)
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
import os
|
||||
|
||||
from calibre.db.backend import DB
|
||||
from calibre.db.cache import Cache
|
||||
from calibre.db.view import View
|
||||
|
||||
class LibraryDatabase(object):
|
||||
|
||||
PATH_LIMIT = DB.PATH_LIMIT
|
||||
WINDOWS_LIBRARY_PATH_LIMIT = DB.WINDOWS_LIBRARY_PATH_LIMIT
|
||||
|
||||
@classmethod
|
||||
def exists_at(cls, path):
|
||||
return path and os.path.exists(os.path.join(path, 'metadata.db'))
|
||||
|
||||
def __init__(self, library_path,
|
||||
default_prefs=None, read_only=False, is_second_db=False,
|
||||
progress_callback=lambda x, y:True, restore_all_prefs=False):
|
||||
|
||||
self.is_second_db = is_second_db # TODO: Use is_second_db
|
||||
|
||||
backend = self.backend = DB(library_path, default_prefs=default_prefs,
|
||||
read_only=read_only, restore_all_prefs=restore_all_prefs,
|
||||
progress_callback=progress_callback)
|
||||
cache = Cache(backend)
|
||||
cache.init()
|
||||
self.data = View(cache)
|
||||
|
||||
self.get_property = self.data.get_property
|
||||
self.all_ids = self.data.cache.all_book_ids
|
||||
|
||||
def close(self):
|
||||
self.backend.close()
|
||||
|
||||
def break_cycles(self):
|
||||
self.data.cache.backend = None
|
||||
self.data.cache = None
|
||||
self.data = self.backend = self.field_metadata = self.prefs = self.listeners = self.refresh_ondevice = None
|
||||
|
||||
# Library wide properties {{{
|
||||
@property
|
||||
def field_metadata(self):
|
||||
return self.backend.field_metadata
|
||||
|
||||
@property
|
||||
def user_version(self):
|
||||
return self.backend.user_version
|
||||
|
||||
@property
|
||||
def library_id(self):
|
||||
return self.backend.library_id
|
||||
|
||||
def last_modified(self):
|
||||
return self.backend.last_modified()
|
||||
|
||||
@property
|
||||
def custom_column_num_map(self):
|
||||
return self.backend.custom_column_num_map
|
||||
|
||||
@property
|
||||
def custom_column_label_map(self):
|
||||
return self.backend.custom_column_label_map
|
||||
|
||||
@property
|
||||
def FIELD_MAP(self):
|
||||
return self.backend.FIELD_MAP
|
||||
# }}}
|
||||
|
||||
|
@ -16,6 +16,9 @@ rmtree = partial(shutil.rmtree, ignore_errors=True)
|
||||
|
||||
class BaseTest(unittest.TestCase):
|
||||
|
||||
longMessage = True
|
||||
maxDiff = None
|
||||
|
||||
def setUp(self):
|
||||
self.library_path = self.mkdtemp()
|
||||
self.create_db(self.library_path)
|
||||
@ -40,10 +43,10 @@ class BaseTest(unittest.TestCase):
|
||||
db.conn.close()
|
||||
return dest
|
||||
|
||||
def init_cache(self, library_path):
|
||||
def init_cache(self, library_path=None):
|
||||
from calibre.db.backend import DB
|
||||
from calibre.db.cache import Cache
|
||||
backend = DB(library_path)
|
||||
backend = DB(library_path or self.library_path)
|
||||
cache = Cache(backend)
|
||||
cache.init()
|
||||
return cache
|
||||
@ -53,9 +56,13 @@ class BaseTest(unittest.TestCase):
|
||||
atexit.register(rmtree, ans)
|
||||
return ans
|
||||
|
||||
def init_old(self, library_path):
|
||||
def init_old(self, library_path=None):
|
||||
from calibre.library.database2 import LibraryDatabase2
|
||||
return LibraryDatabase2(library_path)
|
||||
return LibraryDatabase2(library_path or self.library_path)
|
||||
|
||||
def init_legacy(self, library_path=None):
|
||||
from calibre.db.legacy import LibraryDatabase
|
||||
return LibraryDatabase(library_path or self.library_path)
|
||||
|
||||
def clone_library(self, library_path):
|
||||
if not hasattr(self, 'clone_dir'):
|
||||
@ -81,7 +88,8 @@ class BaseTest(unittest.TestCase):
|
||||
'ondevice_col', 'last_modified', 'has_cover',
|
||||
'cover_data'}.union(allfk1)
|
||||
for attr in all_keys:
|
||||
if attr == 'user_metadata': continue
|
||||
if attr == 'user_metadata':
|
||||
continue
|
||||
attr1, attr2 = getattr(mi1, attr), getattr(mi2, attr)
|
||||
if attr == 'formats':
|
||||
attr1, attr2 = map(lambda x:tuple(x) if x else (), (attr1, attr2))
|
||||
|
53
src/calibre/db/tests/legacy.py
Normal file
53
src/calibre/db/tests/legacy.py
Normal file
@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=utf-8
|
||||
from __future__ import (unicode_literals, division, absolute_import,
|
||||
print_function)
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
from calibre.db.tests.base import BaseTest
|
||||
|
||||
class LegacyTest(BaseTest):
|
||||
|
||||
''' Test the emulation of the legacy interface. '''
|
||||
|
||||
def test_library_wide_properties(self): # {{{
|
||||
'Test library wide properties'
|
||||
old = self.init_old()
|
||||
props = ('user_version', 'is_second_db', 'library_id', 'field_metadata',
|
||||
'custom_column_label_map', 'custom_column_num_map')
|
||||
oldvals = {x:getattr(old, x) for x in props}
|
||||
oldvals['last_modified'] = old.last_modified()
|
||||
old.close()
|
||||
old = None
|
||||
db = self.init_legacy()
|
||||
newvals = {x:getattr(db, x) for x in props}
|
||||
newvals['last_modified'] = db.last_modified()
|
||||
self.assertEqual(oldvals, newvals)
|
||||
db.close()
|
||||
# }}}
|
||||
|
||||
def test_get_property(self): # {{{
|
||||
'Test the get_property interface for reading data'
|
||||
def get_values(db):
|
||||
ans = {}
|
||||
for label, loc in db.FIELD_MAP.iteritems():
|
||||
if isinstance(label, int):
|
||||
label = '#'+db.custom_column_num_map[label]['label']
|
||||
label = type('')(label)
|
||||
ans[label] = tuple(db.get_property(i, index_is_id=True, loc=loc)
|
||||
for i in db.all_ids())
|
||||
return ans
|
||||
|
||||
old = self.init_old()
|
||||
old_vals = get_values(old)
|
||||
old.close()
|
||||
old = None
|
||||
db = self.init_legacy()
|
||||
new_vals = get_values(db)
|
||||
db.close()
|
||||
self.assertEqual(old_vals, new_vals)
|
||||
|
||||
# }}}
|
||||
|
@ -72,6 +72,10 @@ class View(object):
|
||||
self._map = tuple(self.cache.all_book_ids())
|
||||
self._map_filtered = tuple(self._map)
|
||||
|
||||
def get_property(self, id_or_index, index_is_id=False, loc=-1):
|
||||
book_id = id_or_index if index_is_id else self._map_filtered[id_or_index]
|
||||
return self._field_getters[loc](book_id)
|
||||
|
||||
@property
|
||||
def field_metadata(self):
|
||||
return self.cache.field_metadata
|
||||
|
@ -117,7 +117,7 @@ class CreateVirtualLibrary(QDialog): # {{{
|
||||
'<a href="tag.{1}">{1}</a>, '
|
||||
'<a href="publisher.{2}">{2}</a>, '
|
||||
'<a href="series.{3}">{3}</a>, '
|
||||
'<a href="search.{4}">{4}</a>, ').format(_('Authors'), _('Tags'),
|
||||
'<a href="search.{4}">{4}</a>.').format(_('Authors'), _('Tags'),
|
||||
_('Publishers'), _('Series'), _('Saved Searches')))
|
||||
sl.setWordWrap(True)
|
||||
sl.setTextInteractionFlags(Qt.LinksAccessibleByMouse)
|
||||
|
Loading…
x
Reference in New Issue
Block a user