From a3fa6442eca6a1ade10b222ac9caf888eab573e9 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 16 Jun 2008 12:51:48 -0700 Subject: [PATCH] Add support for getting and setting metadata to calibredb --- src/calibre/library/cli.py | 60 +++++++++++++++++++++++++++++++-- src/calibre/library/database.py | 23 +++++++++---- 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py index b1824ac278..451e91acc0 100644 --- a/src/calibre/library/cli.py +++ b/src/calibre/library/cli.py @@ -10,11 +10,10 @@ Command line interface to the calibre database. import sys, os from textwrap import TextWrapper -from PyQt4.QtCore import QVariant - from calibre import OptionParser, Settings, terminal_controller, preferred_encoding from calibre.gui2 import SingleApplication from calibre.ebooks.metadata.meta import get_metadata +from calibre.ebooks.metadata.opf import OPFCreator, OPFReader from calibre.library.database import LibraryDatabase, text_to_tokens FIELDS = set(['title', 'authors', 'publisher', 'rating', 'timestamp', 'size', 'tags', 'comments', 'series', 'series_index', 'formats']) @@ -304,9 +303,64 @@ do nothing. do_remove_format(get_db(dbpath, opts), id, fmt) return 0 +def do_show_metadata(db, id, as_opf): + if not db.has_id(id): + raise ValueError('Id #%d is not present in database.'%id) + mi = db.get_metadata(id, index_is_id=True) + if as_opf: + mi = OPFCreator(os.getcwd(), mi) + mi.render(sys.stdout) + else: + print mi + +def command_show_metadata(args, dbpath): + parser = get_parser(_( +''' +%prog show_metadata [options] id +Show the metadata stored in the calibre database for the book identified by id. +id is an id number from the list command. +''')) + parser.add_option('--as-opf', default=False, action='store_true', + help=_('Print metadata in OPF form (XML)')) + opts, args = parser.parse_args(sys.argv[1:]+args) + if len(args) < 2: + parser.print_help() + print + print _('You must specify an id') + return 1 + id = int(args[1]) + do_show_metadata(get_db(dbpath, opts), id, opts.as_opf) + return 0 + +def do_set_metadata(db, id, stream): + mi = OPFReader(stream) + db.set_metadata(id, mi) + do_show_metadata(db, id, False) + +def command_set_metadata(args, dbpath): + parser = get_parser(_( +''' +%prog set_metadata [options] id /path/to/metadata.opf + +Set the metadata stored in the calibre database for the book identified by id +from the OPF file metadata.opf. id is an id number from the list command. You +can get a quick feel for the OPF format by using the --as-opf switch to the +show_metadata command. +''')) + opts, args = parser.parse_args(sys.argv[1:]+args) + if len(args) < 3: + parser.print_help() + print + print _('You must specify an id and a metadata file') + return 1 + id, opf = int(args[1]), open(args[2], 'rb') + do_set_metadata(get_db(dbpath, opts), id, opf) + return 0 + def main(args=sys.argv): - commands = ('list', 'add', 'remove', 'add_format', 'remove_format') + commands = ('list', 'add', 'remove', 'add_format', 'remove_format', + 'show_metadata', 'set_metadata') parser = OptionParser(_( '''\ %%prog command [options] [arguments] diff --git a/src/calibre/library/database.py b/src/calibre/library/database.py index 580e4a327d..c357239fa5 100644 --- a/src/calibre/library/database.py +++ b/src/calibre/library/database.py @@ -919,13 +919,19 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE; def title(self, index, index_is_id=False): if not index_is_id: return self.data[index][1] - return self.conn.execute('SELECT title FROM meta WHERE id=?',(index,)).fetchone()[0] + try: + return self.conn.execute('SELECT title FROM meta WHERE id=?',(index,)).fetchone()[0] + except: + return _('Unknown') def authors(self, index, index_is_id=False): ''' Authors as a comma separated list or None''' if not index_is_id: return self.data[index][2] - return self.conn.execute('SELECT authors FROM meta WHERE id=?',(index,)).fetchone()[0] + try: + return self.conn.execute('SELECT authors FROM meta WHERE id=?',(index,)).fetchone()[0] + except: + pass def isbn(self, idx, index_is_id=False): id = idx if index_is_id else self.id(idx) @@ -937,22 +943,22 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE; def publisher(self, index, index_is_id=False): if index_is_id: - return self.conn.execute('SELECT publisher FROM meta WHERE id=?', (id,)).fetchone()[0] + return self.conn.execute('SELECT publisher FROM meta WHERE id=?', (index,)).fetchone()[0] return self.data[index][3] def rating(self, index, index_is_id=False): if index_is_id: - return self.conn.execute('SELECT rating FROM meta WHERE id=?', (id,)).fetchone()[0] + return self.conn.execute('SELECT rating FROM meta WHERE id=?', (index,)).fetchone()[0] return self.data[index][4] def timestamp(self, index, index_is_id=False): if index_is_id: - return self.conn.execute('SELECT timestamp FROM meta WHERE id=?', (id,)).fetchone()[0] + return self.conn.execute('SELECT timestamp FROM meta WHERE id=?', (index,)).fetchone()[0] return self.data[index][5] def max_size(self, index, index_is_id=False): if index_is_id: - return self.conn.execute('SELECT size FROM meta WHERE id=?', (id,)).fetchone()[0] + return self.conn.execute('SELECT size FROM meta WHERE id=?', (index,)).fetchone()[0] return self.data[index][6] def cover(self, index, index_is_id=False): @@ -1259,6 +1265,8 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE; ''' Set metadata for the book C{id} from the L{MetaInformation} object C{mi} ''' + if mi.title: + self.set_title(id, mi.title) if not mi.authors: mi.authors = ['Unknown'] authors = [] @@ -1524,6 +1532,9 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE; def has_book(self, mi): return bool(self.conn.execute('SELECT id FROM books where title=?', (mi.title,)).fetchone()) + def has_id(self, id): + return self.conn.execute('SELECT id FROM books where id=?', (id,)).fetchone() is not None + def recursive_import(self, root, single_book_per_directory=True): root = os.path.abspath(root) duplicates = []