diff --git a/src/calibre/ebooks/metadata/opf.py b/src/calibre/ebooks/metadata/opf.py index ce93c09531..105841917b 100644 --- a/src/calibre/ebooks/metadata/opf.py +++ b/src/calibre/ebooks/metadata/opf.py @@ -8,7 +8,7 @@ from __future__ import (unicode_literals, division, absolute_import, from lxml import etree from calibre.ebooks.metadata.opf2 import OPF, pretty_print -from calibre.ebooks.metadata.opf3 import apply_metadata +from calibre.ebooks.metadata.opf3 import apply_metadata, read_metadata from calibre.ebooks.metadata.utils import parse_opf, normalize_languages, create_manifest_item, parse_opf_version from calibre.ebooks.metadata import MetaInformation @@ -20,13 +20,19 @@ class DummyFile(object): def read(self): return self.raw +def get_metadata2(root, ver): + opf = OPF(None, preparsed_opf=root, read_toc=False) + return opf.to_book_metadata(), ver, opf.raster_cover, opf.first_spine_item() + +def get_metadata3(root, ver): + return read_metadata(root, ver=ver, return_extra_data=True) + def get_metadata(stream): if isinstance(stream, bytes): stream = DummyFile(stream) root = parse_opf(stream) ver = parse_opf_version(root.get('version')) - opf = OPF(None, preparsed_opf=root, read_toc=False) - return opf.to_book_metadata(), ver, opf.raster_cover, opf.first_spine_item() + return get_metadata2(root, ver) def set_metadata_opf2(root, cover_prefix, mi, opf_version, cover_data=None, apply_null=False, update_timestamp=False, force_identifiers=False, add_missing_cover=True): diff --git a/src/calibre/ebooks/metadata/opf3.py b/src/calibre/ebooks/metadata/opf3.py index 9e944f0efa..28ae691d11 100644 --- a/src/calibre/ebooks/metadata/opf3.py +++ b/src/calibre/ebooks/metadata/opf3.py @@ -825,7 +825,13 @@ def ensure_is_only_raster_cover(root, prefixes, refines, raster_cover_item_href) # Reading/setting Metadata objects {{{ -def read_metadata(root): +def first_spine_item(root, prefixes, refines): + for i in XPath('./opf:spine/opf:itemref/@idref')(root): + for item in XPath('./opf:manifest/opf:item')(root): + if item.get('id') == i: + return item.get('href') or None + +def read_metadata(root, ver=None, return_extra_data=False): ans = Metadata(_('Unknown'), [_('Unknown')]) prefixes, refines = read_prefixes(root), read_refines(root) identifiers = read_identifiers(root, prefixes, refines) @@ -869,6 +875,8 @@ def read_metadata(root): ans.user_categories = read_user_categories(root, prefixes, refines) or ans.user_categories for name, fm in (read_user_metadata(root, prefixes, refines) or {}).iteritems(): ans.set_user_metadata(name, fm) + if return_extra_data: + ans = ans, ver, read_raster_cover(root, prefixes, refines), first_spine_item(root, prefixes, refines) return ans def get_metadata(stream): diff --git a/src/calibre/ebooks/metadata/opf3_test.py b/src/calibre/ebooks/metadata/opf3_test.py index 947a4b8847..853226cd85 100644 --- a/src/calibre/ebooks/metadata/opf3_test.py +++ b/src/calibre/ebooks/metadata/opf3_test.py @@ -486,20 +486,22 @@ class TestOPF3(unittest.TestCase): "label": "date", "table": "custom_column_2", "is_multiple": null, "is_category": false}"/> - + ''' # }}} def compare_metadata(mi2, mi3): self.ae(mi2.get_all_user_metadata(False), mi3.get_all_user_metadata(False)) for field in ALL_METADATA_FIELDS: - if field != 'manifest': + if field not in 'manifest spine': v2, v3 = getattr(mi2, field, None), getattr(mi3, field, None) self.ae(v2, v3, '%s: %r != %r' % (field, v2, v3)) mi2 = OPF(BytesIO(raw.encode('utf-8'))).to_book_metadata() root = etree.fromstring(raw) root.set('version', '3.0') - mi3 = read_metadata(root) + mi3, _, raster_cover, first_spine_item = read_metadata(root, return_extra_data=True) + self.assertIsNone(raster_cover) + self.ae('start.html', first_spine_item) compare_metadata(mi2, mi3) apply_metadata(root, mi3, force_identifiers=True) nmi = read_metadata(root)