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 import check_isbn
|
||||||
from calibre.ebooks.metadata.book.base import Metadata
|
from calibre.ebooks.metadata.book.base import Metadata
|
||||||
from calibre.ebooks.metadata.utils import parse_opf
|
from calibre.ebooks.metadata.utils import parse_opf, pretty_print_opf
|
||||||
from calibre.ebooks.oeb.base import OPF2_NSMAP, OPF
|
from calibre.ebooks.oeb.base import OPF2_NSMAP, OPF, DC
|
||||||
|
|
||||||
# Utils {{{
|
# Utils {{{
|
||||||
# http://www.idpf.org/epub/vocab/package/pfx/
|
# http://www.idpf.org/epub/vocab/package/pfx/
|
||||||
@ -119,6 +119,32 @@ def read_identifiers(root, prefixes, refines):
|
|||||||
if scheme and val:
|
if scheme and val:
|
||||||
ans[scheme].append(val)
|
ans[scheme].append(val)
|
||||||
return ans
|
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):
|
def read_metadata(root):
|
||||||
@ -139,6 +165,18 @@ def get_metadata(stream):
|
|||||||
root = parse_opf(stream)
|
root = parse_opf(stream)
|
||||||
return read_metadata(root)
|
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__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
print(get_metadata(open(sys.argv[-1], 'rb')))
|
print(get_metadata(open(sys.argv[-1], 'rb')))
|
||||||
|
@ -10,10 +10,12 @@ import unittest
|
|||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from calibre.ebooks.metadata.opf3 import (
|
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
|
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):
|
class TestOPF3(unittest.TestCase):
|
||||||
|
|
||||||
@ -33,8 +35,11 @@ class TestOPF3(unittest.TestCase):
|
|||||||
self.ae(expand_prefix(raw, reserved_prefixes), expanded)
|
self.ae(expand_prefix(raw, reserved_prefixes), expanded)
|
||||||
|
|
||||||
def test_identifiers(self):
|
def test_identifiers(self):
|
||||||
def idt(val, scheme=None):
|
def idt(val, scheme=None, iid=''):
|
||||||
return '<dc:identifier {scheme}>{val}</dc:identifier>'.format(scheme=('opf:scheme="%s"'%scheme if scheme else ''), val=val)
|
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 (
|
for m, result in (
|
||||||
(idt('abc', 'ISBN'), {}),
|
(idt('abc', 'ISBN'), {}),
|
||||||
(idt('isbn:9780230739581'), {'isbn':['9780230739581']}),
|
(idt('isbn:9780230739581'), {'isbn':['9780230739581']}),
|
||||||
@ -45,11 +50,19 @@ class TestOPF3(unittest.TestCase):
|
|||||||
(idt('url:http://x'), {'url':['http://x']}),
|
(idt('url:http://x'), {'url':['http://x']}),
|
||||||
(idt('a:1')+idt('a:2'), {'a':['1', '2']}),
|
(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(
|
mi = read_metadata(self.get_opf(
|
||||||
metadata=idt('a:1')+idt('a:2')+idt('calibre:x')+idt('uuid:y')))
|
metadata=idt('a:1')+idt('a:2')+idt('calibre:x')+idt('uuid:y')))
|
||||||
self.ae(mi.application_id, 'x')
|
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):
|
class TestRunner(unittest.main):
|
||||||
|
|
||||||
def createTests(self):
|
def createTests(self):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user