Finish implementation of the rest of the import books API

This commit is contained in:
Kovid Goyal 2013-07-11 17:54:37 +05:30
parent 213a2136cf
commit 396c4a6131
3 changed files with 125 additions and 82 deletions

102
src/calibre/db/adding.py Normal file
View File

@ -0,0 +1,102 @@
#!/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.ebooks import BOOK_EXTENSIONS
def find_books_in_directory(dirpath, single_book_per_directory):
dirpath = os.path.abspath(dirpath)
if single_book_per_directory:
formats = []
for path in os.listdir(dirpath):
path = os.path.abspath(os.path.join(dirpath, path))
if os.path.isdir(path) or not os.access(path, os.R_OK):
continue
ext = os.path.splitext(path)[1]
if not ext:
continue
ext = ext[1:].lower()
if ext not in BOOK_EXTENSIONS and ext != 'opf':
continue
formats.append(path)
yield formats
else:
books = {}
for path in os.listdir(dirpath):
path = os.path.abspath(os.path.join(dirpath, path))
if os.path.isdir(path) or not os.access(path, os.R_OK):
continue
ext = os.path.splitext(path)[1]
if not ext:
continue
ext = ext[1:].lower()
if ext not in BOOK_EXTENSIONS:
continue
key = os.path.splitext(path)[0]
if key not in books:
books[key] = []
books[key].append(path)
for formats in books.values():
yield formats
def import_book_directory_multiple(db, dirpath, callback=None,
added_ids=None):
from calibre.ebooks.metadata.meta import metadata_from_formats
duplicates = []
for formats in find_books_in_directory(dirpath, False):
mi = metadata_from_formats(formats)
if mi.title is None:
continue
if db.has_book(mi):
duplicates.append((mi, formats))
continue
book_id = db.import_book(mi, formats)
if added_ids is not None:
added_ids.add(book_id)
if callable(callback):
if callback(mi.title):
break
return duplicates
def import_book_directory(db, dirpath, callback=None, added_ids=None):
from calibre.ebooks.metadata.meta import metadata_from_formats
dirpath = os.path.abspath(dirpath)
formats = find_books_in_directory(dirpath, True)
formats = list(formats)[0]
if not formats:
return
mi = metadata_from_formats(formats)
if mi.title is None:
return
if db.has_book(mi):
return [(mi, formats)]
book_id = db.import_book(mi, formats)
if added_ids is not None:
added_ids.add(book_id)
if callable(callback):
callback(mi.title)
def recursive_import(db, root, single_book_per_directory=True,
callback=None, added_ids=None):
root = os.path.abspath(root)
duplicates = []
for dirpath in os.walk(root):
res = (import_book_directory(db, dirpath[0], callback=callback,
added_ids=added_ids) if single_book_per_directory else
import_book_directory_multiple(db, dirpath[0],
callback=callback, added_ids=added_ids))
if res is not None:
duplicates.extend(res)
if callable(callback):
if callback(''):
break
return duplicates

View File

@ -11,6 +11,7 @@ from functools import partial
from future_builtins import zip from future_builtins import zip
from calibre.db import _get_next_series_num_for_list, _get_series_values from calibre.db import _get_next_series_num_for_list, _get_series_values
from calibre.db.adding import find_books_in_directory, import_book_directory_multiple, import_book_directory, recursive_import
from calibre.db.backend import DB from calibre.db.backend import DB
from calibre.db.cache import Cache from calibre.db.cache import Cache
from calibre.db.categories import CATEGORY_SORTS from calibre.db.categories import CATEGORY_SORTS
@ -160,6 +161,7 @@ class LibraryDatabase(object):
os.makedirs(path) os.makedirs(path)
return path return path
# Adding books {{{
def create_book_entry(self, mi, cover=None, add_duplicates=True, force_id=None): def create_book_entry(self, mi, cover=None, add_duplicates=True, force_id=None):
return self.new_api.create_book_entry(mi, cover=cover, add_duplicates=add_duplicates, force_id=force_id) return self.new_api.create_book_entry(mi, cover=cover, add_duplicates=add_duplicates, force_id=force_id)
@ -190,6 +192,21 @@ class LibraryDatabase(object):
self.notify('add', book_ids) self.notify('add', book_ids)
return book_ids[0] return book_ids[0]
def find_books_in_directory(self, dirpath, single_book_per_directory):
return find_books_in_directory(dirpath, single_book_per_directory)
def import_book_directory_multiple(self, dirpath, callback=None,
added_ids=None):
return import_book_directory_multiple(self, dirpath, callback=callback, added_ids=added_ids)
def import_book_directory(self, dirpath, callback=None, added_ids=None):
return import_book_directory(self, dirpath, callback=callback, added_ids=added_ids)
def recursive_import(self, root, single_book_per_directory=True,
callback=None, added_ids=None):
return recursive_import(self, root, single_book_per_directory=single_book_per_directory, callback=callback, added_ids=added_ids)
# }}}
# Private interface {{{ # Private interface {{{
def __iter__(self): def __iter__(self):

View File

@ -37,11 +37,12 @@ from calibre.utils.date import (utcnow, now as nowf, utcfromtimestamp,
from calibre.utils.config import prefs, tweaks, from_json, to_json from calibre.utils.config import prefs, tweaks, from_json, to_json
from calibre.utils.icu import sort_key, strcmp, lower from calibre.utils.icu import sort_key, strcmp, lower
from calibre.utils.search_query_parser import saved_searches, set_saved_searches from calibre.utils.search_query_parser import saved_searches, set_saved_searches
from calibre.ebooks import BOOK_EXTENSIONS, check_ebook_format from calibre.ebooks import check_ebook_format
from calibre.utils.magick.draw import save_cover_data_to from calibre.utils.magick.draw import save_cover_data_to
from calibre.utils.recycle_bin import delete_file, delete_tree from calibre.utils.recycle_bin import delete_file, delete_tree
from calibre.utils.formatter_functions import load_user_template_functions from calibre.utils.formatter_functions import load_user_template_functions
from calibre.db import _get_next_series_num_for_list, _get_series_values from calibre.db import _get_next_series_num_for_list, _get_series_values
from calibre.db.adding import find_books_in_directory, import_book_directory_multiple, import_book_directory, recursive_import
from calibre.db.errors import NoSuchFormat from calibre.db.errors import NoSuchFormat
from calibre.db.lazy import FormatMetadata, FormatsList from calibre.db.lazy import FormatMetadata, FormatsList
from calibre.db.categories import Tag, CATEGORY_SORTS from calibre.db.categories import Tag, CATEGORY_SORTS
@ -3728,95 +3729,18 @@ books_series_link feeds
return len(books) return len(books)
def find_books_in_directory(self, dirpath, single_book_per_directory): def find_books_in_directory(self, dirpath, single_book_per_directory):
dirpath = os.path.abspath(dirpath) return find_books_in_directory(dirpath, single_book_per_directory)
if single_book_per_directory:
formats = []
for path in os.listdir(dirpath):
path = os.path.abspath(os.path.join(dirpath, path))
if os.path.isdir(path) or not os.access(path, os.R_OK):
continue
ext = os.path.splitext(path)[1]
if not ext:
continue
ext = ext[1:].lower()
if ext not in BOOK_EXTENSIONS and ext != 'opf':
continue
formats.append(path)
yield formats
else:
books = {}
for path in os.listdir(dirpath):
path = os.path.abspath(os.path.join(dirpath, path))
if os.path.isdir(path) or not os.access(path, os.R_OK):
continue
ext = os.path.splitext(path)[1]
if not ext:
continue
ext = ext[1:].lower()
if ext not in BOOK_EXTENSIONS:
continue
key = os.path.splitext(path)[0]
if key not in books:
books[key] = []
books[key].append(path)
for formats in books.values():
yield formats
def import_book_directory_multiple(self, dirpath, callback=None, def import_book_directory_multiple(self, dirpath, callback=None,
added_ids=None): added_ids=None):
from calibre.ebooks.metadata.meta import metadata_from_formats return import_book_directory_multiple(self, dirpath, callback=callback, added_ids=added_ids)
duplicates = []
for formats in self.find_books_in_directory(dirpath, False):
mi = metadata_from_formats(formats)
if mi.title is None:
continue
if self.has_book(mi):
duplicates.append((mi, formats))
continue
book_id = self.import_book(mi, formats)
if added_ids is not None:
added_ids.add(book_id)
if callable(callback):
if callback(mi.title):
break
return duplicates
def import_book_directory(self, dirpath, callback=None, added_ids=None): def import_book_directory(self, dirpath, callback=None, added_ids=None):
from calibre.ebooks.metadata.meta import metadata_from_formats return import_book_directory(self, dirpath, callback=callback, added_ids=added_ids)
dirpath = os.path.abspath(dirpath)
formats = self.find_books_in_directory(dirpath, True)
formats = list(formats)[0]
if not formats:
return
mi = metadata_from_formats(formats)
if mi.title is None:
return
if self.has_book(mi):
return [(mi, formats)]
book_id = self.import_book(mi, formats)
if added_ids is not None:
added_ids.add(book_id)
if callable(callback):
callback(mi.title)
def recursive_import(self, root, single_book_per_directory=True, def recursive_import(self, root, single_book_per_directory=True,
callback=None, added_ids=None): callback=None, added_ids=None):
root = os.path.abspath(root) return recursive_import(self, root, single_book_per_directory=single_book_per_directory, callback=callback, added_ids=added_ids)
duplicates = []
for dirpath in os.walk(root):
res = (self.import_book_directory(dirpath[0], callback=callback,
added_ids=added_ids) if single_book_per_directory else
self.import_book_directory_multiple(dirpath[0],
callback=callback, added_ids=added_ids))
if res is not None:
duplicates.extend(res)
if callable(callback):
if callback(''):
break
return duplicates
def add_custom_book_data(self, book_id, name, val): def add_custom_book_data(self, book_id, name, val):
x = self.conn.get('SELECT id FROM books WHERE ID=?', (book_id,), all=False) x = self.conn.get('SELECT id FROM books WHERE ID=?', (book_id,), all=False)