mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
EPUB Metadata: Implement updating identifiers
EPUB Metadata: Implementing updating identifiers in the epub file from calibre when polishing or exporting the epub ebook-meta: Add an --identifier option to set identifiers.
This commit is contained in:
parent
61f5306019
commit
91e93871b1
@ -435,7 +435,7 @@ class EPUBMetadataWriter(MetadataWriterPlugin):
|
||||
|
||||
def set_metadata(self, stream, mi, type):
|
||||
from calibre.ebooks.metadata.epub import set_metadata
|
||||
set_metadata(stream, mi, apply_null=self.apply_null)
|
||||
set_metadata(stream, mi, apply_null=self.apply_null, force_identifiers=self.force_identifiers)
|
||||
|
||||
class FB2MetadataWriter(MetadataWriterPlugin):
|
||||
|
||||
@ -1695,7 +1695,7 @@ class StoreWHSmithUKStore(StoreBase):
|
||||
class StoreWolneLekturyStore(StoreBase):
|
||||
name = 'Wolne Lektury'
|
||||
author = u'Tomasz Długosz'
|
||||
description = u'Wolne Lektury to biblioteka internetowa czynna 24 godziny na dobę, 365 dni w roku, której zasoby dostępne są całkowicie za darmo. Wszystkie dzieła są odpowiednio opracowane - opatrzone przypisami, motywami i udostępnione w kilku formatach - HTML, TXT, PDF, EPUB, MOBI, FB2.'
|
||||
description = u'Wolne Lektury to biblioteka internetowa czynna 24 godziny na dobę, 365 dni w roku, której zasoby dostępne są całkowicie za darmo. Wszystkie dzieła są odpowiednio opracowane - opatrzone przypisami, motywami i udostępnione w kilku formatach - HTML, TXT, PDF, EPUB, MOBI, FB2.' # noqa
|
||||
actual_plugin = 'calibre.gui2.store.stores.wolnelektury_plugin:WolneLekturyStore'
|
||||
|
||||
headquarters = 'PL'
|
||||
|
@ -319,6 +319,19 @@ class ApplyNullMetadata(object):
|
||||
|
||||
apply_null_metadata = ApplyNullMetadata()
|
||||
|
||||
class ForceIdentifiers(object):
|
||||
|
||||
def __init__(self):
|
||||
self.force_identifiers = False
|
||||
|
||||
def __enter__(self):
|
||||
self.force_identifiers = True
|
||||
|
||||
def __exit__(self, *args):
|
||||
self.force_identifiers = False
|
||||
|
||||
force_identifiers = ForceIdentifiers()
|
||||
|
||||
def get_file_type_metadata(stream, ftype):
|
||||
mi = MetaInformation(None, None)
|
||||
|
||||
@ -346,6 +359,7 @@ def set_file_type_metadata(stream, mi, ftype):
|
||||
with plugin:
|
||||
try:
|
||||
plugin.apply_null = apply_null_metadata.apply_null
|
||||
plugin.force_identifiers = force_identifiers.force_identifiers
|
||||
plugin.set_metadata(stream, mi, ftype.lower().strip())
|
||||
break
|
||||
except:
|
||||
|
@ -9,7 +9,7 @@ ebook-meta
|
||||
import sys, os
|
||||
|
||||
from calibre.utils.config import StringConfig
|
||||
from calibre.customize.ui import metadata_readers, metadata_writers
|
||||
from calibre.customize.ui import metadata_readers, metadata_writers, force_identifiers
|
||||
from calibre.ebooks.metadata.meta import get_metadata, set_metadata
|
||||
from calibre.ebooks.metadata import string_to_authors, authors_to_sort_string, \
|
||||
title_sort, MetaInformation
|
||||
@ -63,6 +63,11 @@ def config():
|
||||
help=_('Set the rating. Should be a number between 1 and 5.'))
|
||||
c.add_opt('isbn', ['--isbn'],
|
||||
help=_('Set the ISBN of the book.'))
|
||||
c.add_opt('identifiers', ['--identifier'], action='append',
|
||||
help=_('Set the identifiers for the book, can be specified multiple times.'
|
||||
' For example: --identifier uri:http://acme.com --identifier isbn:12345'
|
||||
' To remove an identifier, specify no value, --identifier isbn:'
|
||||
' Note that for EPUB files, an identifier marked as the package identifier cannot be removed.'))
|
||||
c.add_opt('tags', ['--tags'],
|
||||
help=_('Set the tags for the book. Should be a comma separated list.'))
|
||||
c.add_opt('book_producer', ['-k', '--book-producer'],
|
||||
@ -114,7 +119,7 @@ def do_set_metadata(opts, mi, stream, stream_type):
|
||||
for pref in config().option_set.preferences:
|
||||
if pref.name in ('to_opf', 'from_opf', 'authors', 'title_sort',
|
||||
'author_sort', 'get_cover', 'cover', 'tags',
|
||||
'lrf_bookid'):
|
||||
'lrf_bookid', 'identifiers'):
|
||||
continue
|
||||
val = getattr(opts, pref.name, None)
|
||||
if val is not None:
|
||||
@ -136,11 +141,19 @@ def do_set_metadata(opts, mi, stream, stream_type):
|
||||
mi.series_index = float(opts.series_index.strip())
|
||||
if getattr(opts, 'pubdate', None) is not None:
|
||||
mi.pubdate = parse_date(opts.pubdate, assume_utc=False, as_utc=False)
|
||||
if getattr(opts, 'identifiers', None):
|
||||
val = {k.strip():v.strip() for k, v in (x.partition(':')[0::2] for x in opts.identifiers)}
|
||||
if val:
|
||||
orig = mi.get_identifiers()
|
||||
orig.update(val)
|
||||
val = {k:v for k, v in orig.iteritems() if k and v}
|
||||
mi.set_identifiers(val)
|
||||
|
||||
if getattr(opts, 'cover', None) is not None:
|
||||
ext = os.path.splitext(opts.cover)[1].replace('.', '').upper()
|
||||
mi.cover_data = (ext, open(opts.cover, 'rb').read())
|
||||
|
||||
with force_identifiers:
|
||||
set_metadata(stream, mi, stream_type)
|
||||
|
||||
|
||||
|
@ -250,7 +250,7 @@ def _write_new_cover(new_cdata, cpath):
|
||||
save_cover_data_to(new_cdata, new_cover.name)
|
||||
return new_cover
|
||||
|
||||
def update_metadata(opf, mi, apply_null=False, update_timestamp=False):
|
||||
def update_metadata(opf, mi, apply_null=False, update_timestamp=False, force_identifiers=False):
|
||||
for x in ('guide', 'toc', 'manifest', 'spine'):
|
||||
setattr(mi, x, None)
|
||||
if mi.languages:
|
||||
@ -274,10 +274,16 @@ def update_metadata(opf, mi, apply_null=False, update_timestamp=False):
|
||||
opf.isbn = None
|
||||
if not getattr(mi, 'comments', None):
|
||||
opf.comments = None
|
||||
if apply_null or force_identifiers:
|
||||
opf.set_identifiers(mi.get_identifiers())
|
||||
else:
|
||||
orig = opf.get_identifiers()
|
||||
orig.update(mi.get_identifiers())
|
||||
opf.set_identifiers({k:v for k, v in orig.iteritems() if k and v})
|
||||
if update_timestamp and mi.timestamp is not None:
|
||||
opf.timestamp = mi.timestamp
|
||||
|
||||
def set_metadata(stream, mi, apply_null=False, update_timestamp=False):
|
||||
def set_metadata(stream, mi, apply_null=False, update_timestamp=False, force_identifiers=False):
|
||||
stream.seek(0)
|
||||
reader = get_zip_reader(stream, root=os.getcwdu())
|
||||
raster_cover = reader.opf.raster_cover
|
||||
@ -308,7 +314,7 @@ def set_metadata(stream, mi, apply_null=False, update_timestamp=False):
|
||||
traceback.print_exc()
|
||||
|
||||
update_metadata(reader.opf, mi, apply_null=apply_null,
|
||||
update_timestamp=update_timestamp)
|
||||
update_timestamp=update_timestamp, force_identifiers=force_identifiers)
|
||||
|
||||
newopf = StringIO(reader.opf.render())
|
||||
if isinstance(reader.archive, LocalZipFile):
|
||||
|
@ -959,6 +959,33 @@ class OPF(object): # {{{
|
||||
identifiers['isbn'] = val
|
||||
return identifiers
|
||||
|
||||
def set_identifiers(self, identifiers):
|
||||
identifiers = identifiers.copy()
|
||||
uuid_id = None
|
||||
for attr in self.root.attrib:
|
||||
if attr.endswith('unique-identifier'):
|
||||
uuid_id = self.root.attrib[attr]
|
||||
break
|
||||
|
||||
for x in self.XPath(
|
||||
'descendant::*[local-name() = "identifier"]')(
|
||||
self.metadata):
|
||||
xid = x.get('id', None)
|
||||
is_package_identifier = uuid_id is not None and uuid_id == xid
|
||||
typ = {val for attr, val in x.attrib.iteritems() if attr.endswith('scheme')}
|
||||
if is_package_identifier:
|
||||
typ = tuple(typ)
|
||||
if typ and typ[0].lower() in identifiers:
|
||||
self.set_text(x, identifiers.pop(typ[0].lower()))
|
||||
continue
|
||||
if typ and not (typ & {'calibre', 'uuid'}):
|
||||
x.getparent().remove(x)
|
||||
|
||||
for typ, val in identifiers.iteritems():
|
||||
attrib = {'{%s}scheme'%self.NAMESPACES['opf']: typ.upper()}
|
||||
self.set_text(self.create_metadata_element(
|
||||
'identifier', attrib=attrib), unicode(val))
|
||||
|
||||
@dynamic_property
|
||||
def application_id(self):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user