mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Implement setting of identifiers
This commit is contained in:
parent
5cd5ba746c
commit
1d7eaaafac
@ -11,8 +11,8 @@ from lxml import etree
|
||||
|
||||
from calibre.ebooks.metadata import check_isbn
|
||||
from calibre.ebooks.metadata.book.base import Metadata
|
||||
from calibre.ebooks.metadata.utils import parse_opf
|
||||
from calibre.ebooks.oeb.base import OPF2_NSMAP, OPF
|
||||
from calibre.ebooks.metadata.utils import parse_opf, pretty_print_opf
|
||||
from calibre.ebooks.oeb.base import OPF2_NSMAP, OPF, DC
|
||||
|
||||
# Utils {{{
|
||||
# http://www.idpf.org/epub/vocab/package/pfx/
|
||||
@ -119,6 +119,32 @@ def read_identifiers(root, prefixes, refines):
|
||||
if scheme and val:
|
||||
ans[scheme].append(val)
|
||||
return ans
|
||||
|
||||
def set_identifiers(root, prefixes, refines, new_identifiers, force_identifiers=False):
|
||||
uid = root.get('unique-identifier')
|
||||
package_identifier = None
|
||||
for ident in XPath('./opf:metadata/dc:identifier')(root):
|
||||
if uid is not None and uid == ident.get('id'):
|
||||
package_identifier = ident
|
||||
continue
|
||||
val = (ident.text or '').strip()
|
||||
if not val:
|
||||
ident.getparent().remove(ident)
|
||||
continue
|
||||
scheme, val = parse_identifier(ident, val, refines)
|
||||
if not scheme or not val or force_identifiers or scheme in new_identifiers:
|
||||
ident.getparent().remove(ident)
|
||||
continue
|
||||
metadata = XPath('./opf:metadata')(root)[0]
|
||||
for scheme, val in new_identifiers.iteritems():
|
||||
ident = metadata.makeelement(DC('identifier'))
|
||||
ident.text = '%s:%s' % (scheme, val)
|
||||
if package_identifier is None:
|
||||
metadata.append(ident)
|
||||
else:
|
||||
p = package_identifier.getparent()
|
||||
p.insert(p.index(package_identifier), ident)
|
||||
|
||||
# }}}
|
||||
|
||||
def read_metadata(root):
|
||||
@ -139,6 +165,18 @@ def get_metadata(stream):
|
||||
root = parse_opf(stream)
|
||||
return read_metadata(root)
|
||||
|
||||
def apply_metadata(root, mi, cover_prefix='', cover_data=None, apply_null=False, update_timestamp=False, force_identifiers=False):
|
||||
prefixes, refines = read_prefixes(root), read_refines(root)
|
||||
set_identifiers(root, prefixes, refines, mi.identifiers, force_identifiers=force_identifiers)
|
||||
pretty_print_opf(root)
|
||||
|
||||
def set_metadata(stream, mi, cover_prefix='', cover_data=None, apply_null=False, update_timestamp=False, force_identifiers=False):
|
||||
root = parse_opf(stream)
|
||||
return apply_metadata(
|
||||
root, mi, cover_prefix=cover_prefix, cover_data=cover_data,
|
||||
apply_null=apply_null, update_timestamp=update_timestamp,
|
||||
force_identifiers=force_identifiers)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
print(get_metadata(open(sys.argv[-1], 'rb')))
|
||||
|
@ -10,10 +10,12 @@ import unittest
|
||||
from lxml import etree
|
||||
|
||||
from calibre.ebooks.metadata.opf3 import (
|
||||
parse_prefixes, reserved_prefixes, expand_prefix, read_identifiers, read_metadata
|
||||
parse_prefixes, reserved_prefixes, expand_prefix, read_identifiers,
|
||||
read_metadata, set_identifiers, XPath
|
||||
)
|
||||
|
||||
TEMPLATE = '''<package xmlns="http://www.idpf.org/2007/opf" version="3.0" unique-identifier="uid"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">{metadata}</metadata></package>''' # noqa
|
||||
default_refines = defaultdict(list)
|
||||
|
||||
class TestOPF3(unittest.TestCase):
|
||||
|
||||
@ -33,8 +35,11 @@ class TestOPF3(unittest.TestCase):
|
||||
self.ae(expand_prefix(raw, reserved_prefixes), expanded)
|
||||
|
||||
def test_identifiers(self):
|
||||
def idt(val, scheme=None):
|
||||
return '<dc:identifier {scheme}>{val}</dc:identifier>'.format(scheme=('opf:scheme="%s"'%scheme if scheme else ''), val=val)
|
||||
def idt(val, scheme=None, iid=''):
|
||||
return '<dc:identifier id="{id}" {scheme}>{val}</dc:identifier>'.format(scheme=('opf:scheme="%s"'%scheme if scheme else ''), val=val, id=iid)
|
||||
def ri(root):
|
||||
return dict(read_identifiers(root, reserved_prefixes, default_refines))
|
||||
|
||||
for m, result in (
|
||||
(idt('abc', 'ISBN'), {}),
|
||||
(idt('isbn:9780230739581'), {'isbn':['9780230739581']}),
|
||||
@ -45,11 +50,19 @@ class TestOPF3(unittest.TestCase):
|
||||
(idt('url:http://x'), {'url':['http://x']}),
|
||||
(idt('a:1')+idt('a:2'), {'a':['1', '2']}),
|
||||
):
|
||||
self.ae(result, dict(read_identifiers(self.get_opf(m), reserved_prefixes, defaultdict(list))))
|
||||
self.ae(result, ri(self.get_opf(m)))
|
||||
mi = read_metadata(self.get_opf(
|
||||
metadata=idt('a:1')+idt('a:2')+idt('calibre:x')+idt('uuid:y')))
|
||||
self.ae(mi.application_id, 'x')
|
||||
|
||||
root = self.get_opf(metadata=idt('i:1', iid='uid') + idt('r:1') + idt('o:1'))
|
||||
set_identifiers(root, reserved_prefixes, default_refines, {'i':'2', 'o':'2'})
|
||||
self.ae({'i':['2', '1'], 'r':['1'], 'o':['2']}, ri(root))
|
||||
self.ae(1, len(XPath('//dc:identifier[@id="uid"]')(root)))
|
||||
root = self.get_opf(metadata=idt('i:1', iid='uid') + idt('r:1') + idt('o:1'))
|
||||
set_identifiers(root, reserved_prefixes, default_refines, {'i':'2', 'o':'2'}, force_identifiers=True)
|
||||
self.ae({'i':['2', '1'], 'o':['2']}, ri(root))
|
||||
|
||||
class TestRunner(unittest.main):
|
||||
|
||||
def createTests(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user