Fix use of OPF class to generate a Metadata object and have OPF.smart_update also update user metadata

This commit is contained in:
Kovid Goyal 2010-09-15 21:50:06 -06:00
parent 6653fff4cd
commit 420db7851b
11 changed files with 27 additions and 20 deletions

View File

@ -226,8 +226,7 @@ class OPFMetadataReader(MetadataReaderPlugin):
def get_metadata(self, stream, ftype): def get_metadata(self, stream, ftype):
from calibre.ebooks.metadata.opf2 import OPF from calibre.ebooks.metadata.opf2 import OPF
from calibre.ebooks.metadata import MetaInformation return OPF(stream, os.getcwd()).to_book_metadata()
return MetaInformation(OPF(stream, os.getcwd()))
class PDBMetadataReader(MetadataReaderPlugin): class PDBMetadataReader(MetadataReaderPlugin):

View File

@ -692,7 +692,7 @@ OptionRecommendation(name='timestamp',
self.opts.read_metadata_from_opf) self.opts.read_metadata_from_opf)
opf = OPF(open(self.opts.read_metadata_from_opf, 'rb'), opf = OPF(open(self.opts.read_metadata_from_opf, 'rb'),
os.path.dirname(self.opts.read_metadata_from_opf)) os.path.dirname(self.opts.read_metadata_from_opf))
mi = MetaInformation(opf) mi = opf.to_book_metadata()
self.opts_to_mi(mi) self.opts_to_mi(mi)
if mi.cover: if mi.cover:
if mi.cover.startswith('http:') or mi.cover.startswith('https:'): if mi.cover.startswith('http:') or mi.cover.startswith('https:'):

View File

@ -109,7 +109,7 @@ def do_set_metadata(opts, mi, stream, stream_type):
from_opf = getattr(opts, 'from_opf', None) from_opf = getattr(opts, 'from_opf', None)
if from_opf is not None: if from_opf is not None:
from calibre.ebooks.metadata.opf2 import OPF from calibre.ebooks.metadata.opf2 import OPF
opf_mi = MetaInformation(OPF(open(from_opf, 'rb'))) opf_mi = OPF(open(from_opf, 'rb')).to_book_metadata()
mi.smart_update(opf_mi) mi.smart_update(opf_mi)
for pref in config().option_set.preferences: for pref in config().option_set.preferences:

View File

@ -167,7 +167,7 @@ def get_metadata(stream, extract_cover=True):
""" Return metadata as a :class:`Metadata` object """ """ Return metadata as a :class:`Metadata` object """
stream.seek(0) stream.seek(0)
reader = OCFZipReader(stream) reader = OCFZipReader(stream)
mi = MetaInformation(reader.opf) mi = reader.opf.to_book_metadata()
if extract_cover: if extract_cover:
try: try:
cdata = get_cover(reader.opf, reader.opf_path, stream, reader=reader) cdata = get_cover(reader.opf, reader.opf_path, stream, reader=reader)

View File

@ -6,7 +6,6 @@ Support for reading the metadata from a LIT file.
import cStringIO, os import cStringIO, os
from calibre.ebooks.metadata import MetaInformation
from calibre.ebooks.metadata.opf2 import OPF from calibre.ebooks.metadata.opf2 import OPF
def get_metadata(stream): def get_metadata(stream):
@ -16,7 +15,7 @@ def get_metadata(stream):
src = litfile.get_metadata().encode('utf-8') src = litfile.get_metadata().encode('utf-8')
litfile = litfile._litfile litfile = litfile._litfile
opf = OPF(cStringIO.StringIO(src), os.getcwd()) opf = OPF(cStringIO.StringIO(src), os.getcwd())
mi = MetaInformation(opf) mi = opf.to_book_metadata()
covers = [] covers = []
for item in opf.iterguide(): for item in opf.iterguide():
if 'cover' not in item.get('type', '').lower(): if 'cover' not in item.get('type', '').lower():

View File

@ -194,7 +194,7 @@ def opf_metadata(opfpath):
try: try:
opf = OPF(f, os.path.dirname(opfpath)) opf = OPF(f, os.path.dirname(opfpath))
if opf.application_id is not None: if opf.application_id is not None:
mi = MetaInformation(opf) mi = opf.to_book_metadata()
if hasattr(opf, 'cover') and opf.cover: if hasattr(opf, 'cover') and opf.cover:
cpath = os.path.join(os.path.dirname(opfpath), opf.cover) cpath = os.path.join(os.path.dirname(opfpath), opf.cover)
if os.access(cpath, os.R_OK): if os.access(cpath, os.R_OK):

View File

@ -530,7 +530,7 @@ class OPF(object): # {{{
self.read_user_metadata() self.read_user_metadata()
def read_user_metadata(self): def read_user_metadata(self):
self.user_metadata = {} self._user_metadata_ = {}
from calibre.utils.config import from_json from calibre.utils.config import from_json
elems = self.root.xpath('//*[name() = "meta" and starts-with(@name,' elems = self.root.xpath('//*[name() = "meta" and starts-with(@name,'
'"calibre:user_metadata:") and @content]') '"calibre:user_metadata:") and @content]')
@ -547,14 +547,21 @@ class OPF(object): # {{{
import traceback import traceback
traceback.print_exc() traceback.print_exc()
continue continue
self.user_metadata[name] = fm self._user_metadata_[name] = fm
def to_book_metadata(self):
ans = MetaInformation(self)
for n, v in self._user_metadata_.items():
ans.set_user_metadata(n, v)
return ans
def write_user_metadata(self): def write_user_metadata(self):
for elem in self.user_metadata_path(self.root): elems = self.root.xpath('//*[name() = "meta" and starts-with(@name,'
'"calibre:user_metadata:") and @content]')
for elem in elems:
elem.getparent().remove(elem) elem.getparent().remove(elem)
serialize_user_metadata(self.metadata, serialize_user_metadata(self.metadata,
self.user_metadata) self._user_metadata_)
def find_toc(self): def find_toc(self):
self.toc = None self.toc = None
@ -983,6 +990,9 @@ class OPF(object): # {{{
val = getattr(mi, attr, None) val = getattr(mi, attr, None)
if val is not None and val != [] and val != (None, None): if val is not None and val != [] and val != (None, None):
setattr(self, attr, val) setattr(self, attr, val)
temp = self.to_book_metadata()
temp.smart_update(mi, replace_metadata=replace_metadata)
self._user_metadata_ = temp.get_all_user_metadata(True)
# }}} # }}}
@ -1417,9 +1427,9 @@ def test_user_metadata():
opf = OPF(f) opf = OPF(f)
f2 = StringIO(raw2) f2 = StringIO(raw2)
opf2 = OPF(f2) opf2 = OPF(f2)
assert um == opf.user_metadata assert um == opf._user_metadata_
assert um == opf2.user_metadata assert um == opf2._user_metadata_
print raw print opf.render()
if __name__ == '__main__': if __name__ == '__main__':
test_user_metadata() test_user_metadata()

View File

@ -441,7 +441,7 @@ class MobiReader(object):
html.tostring(elem, encoding='utf-8') + '</package>' html.tostring(elem, encoding='utf-8') + '</package>'
stream = cStringIO.StringIO(raw) stream = cStringIO.StringIO(raw)
opf = OPF(stream) opf = OPF(stream)
self.embedded_mi = MetaInformation(opf) self.embedded_mi = opf.to_book_metadata()
if guide is not None: if guide is not None:
for ref in guide.xpath('descendant::reference'): for ref in guide.xpath('descendant::reference'):
if 'cover' in ref.get('type', '').lower(): if 'cover' in ref.get('type', '').lower():

View File

@ -126,10 +126,9 @@ class OEBReader(object):
def _metadata_from_opf(self, opf): def _metadata_from_opf(self, opf):
from calibre.ebooks.metadata.opf2 import OPF from calibre.ebooks.metadata.opf2 import OPF
from calibre.ebooks.metadata import MetaInformation
from calibre.ebooks.oeb.transforms.metadata import meta_info_to_oeb_metadata from calibre.ebooks.oeb.transforms.metadata import meta_info_to_oeb_metadata
stream = cStringIO.StringIO(etree.tostring(opf)) stream = cStringIO.StringIO(etree.tostring(opf))
mi = MetaInformation(OPF(stream)) mi = OPF(stream).to_book_metadata()
if not mi.language: if not mi.language:
mi.language = get_lang().replace('_', '-') mi.language = get_lang().replace('_', '-')
self.oeb.metadata.add('language', mi.language) self.oeb.metadata.add('language', mi.language)

View File

@ -138,7 +138,7 @@ class DBAdder(Thread): # {{{
self.critical[name] = open(opf, 'rb').read().decode('utf-8', 'replace') self.critical[name] = open(opf, 'rb').read().decode('utf-8', 'replace')
else: else:
try: try:
mi = MetaInformation(OPF(opf)) mi = OPF(opf).to_book_metadata()
except: except:
import traceback import traceback
mi = MetaInformation('', [_('Unknown')]) mi = MetaInformation('', [_('Unknown')])

View File

@ -448,7 +448,7 @@ def command_show_metadata(args, dbpath):
return 0 return 0
def do_set_metadata(db, id, stream): def do_set_metadata(db, id, stream):
mi = OPF(stream) mi = OPF(stream).to_book_metadata()
db.set_metadata(id, mi) db.set_metadata(id, mi)
db.clean() db.clean()
do_show_metadata(db, id, False) do_show_metadata(db, id, False)