mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Edit Book: Automatically updated the modified timestamp when editing EPUB 3 books on save.
This commit is contained in:
parent
0a94c5420c
commit
b88c6580d7
@ -2,23 +2,32 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPLv3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPLv3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
from __future__ import (unicode_literals, division, absolute_import,
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
print_function)
|
|
||||||
|
import json
|
||||||
|
import re
|
||||||
from collections import defaultdict, namedtuple
|
from collections import defaultdict, namedtuple
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from future_builtins import map
|
from future_builtins import map
|
||||||
import re, json
|
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from calibre import prints
|
from calibre import prints
|
||||||
from calibre.ebooks.metadata import check_isbn, authors_to_string, string_to_authors
|
from calibre.ebooks.metadata import authors_to_string, check_isbn, string_to_authors
|
||||||
from calibre.ebooks.metadata.book.base import Metadata
|
from calibre.ebooks.metadata.book.base import Metadata
|
||||||
from calibre.ebooks.metadata.book.json_codec import object_to_unicode, decode_is_multiple, encode_is_multiple
|
from calibre.ebooks.metadata.book.json_codec import (
|
||||||
from calibre.ebooks.metadata.utils import parse_opf, pretty_print_opf, ensure_unique, normalize_languages, create_manifest_item
|
decode_is_multiple, encode_is_multiple, object_to_unicode
|
||||||
from calibre.ebooks.oeb.base import OPF2_NSMAP, OPF, DC
|
)
|
||||||
|
from calibre.ebooks.metadata.utils import (
|
||||||
|
create_manifest_item, ensure_unique, normalize_languages, parse_opf,
|
||||||
|
pretty_print_opf
|
||||||
|
)
|
||||||
|
from calibre.ebooks.oeb.base import DC, OPF, OPF2_NSMAP
|
||||||
from calibre.utils.config import from_json, to_json
|
from calibre.utils.config import from_json, to_json
|
||||||
from calibre.utils.date import parse_date as parse_date_, fix_only_date, is_date_undefined, isoformat
|
from calibre.utils.date import (
|
||||||
|
fix_only_date, is_date_undefined, isoformat, parse_date as parse_date_, utcnow,
|
||||||
|
w3cdtf
|
||||||
|
)
|
||||||
from calibre.utils.iso8601 import parse_iso8601
|
from calibre.utils.iso8601 import parse_iso8601
|
||||||
from calibre.utils.localization import canonicalize_lang
|
from calibre.utils.localization import canonicalize_lang
|
||||||
|
|
||||||
@ -575,23 +584,23 @@ def read_timestamp(root, prefixes, refines):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
def create_timestamp(m, val):
|
def create_timestamp(root, prefixes, m, val):
|
||||||
if not is_date_undefined(val):
|
if not is_date_undefined(val):
|
||||||
val = isoformat(val)
|
ensure_prefix(root, prefixes, 'calibre', CALIBRE_PREFIX)
|
||||||
|
ensure_prefix(root, prefixes, 'dcterms')
|
||||||
|
val = w3cdtf(val)
|
||||||
d = m.makeelement(OPF('meta'), attrib={'property':'calibre:timestamp', 'scheme':'dcterms:W3CDTF'})
|
d = m.makeelement(OPF('meta'), attrib={'property':'calibre:timestamp', 'scheme':'dcterms:W3CDTF'})
|
||||||
d.text = val
|
d.text = val
|
||||||
m.append(d)
|
m.append(d)
|
||||||
|
|
||||||
|
|
||||||
def set_timestamp(root, prefixes, refines, val):
|
def set_timestamp(root, prefixes, refines, val):
|
||||||
ensure_prefix(root, prefixes, 'calibre', CALIBRE_PREFIX)
|
|
||||||
ensure_prefix(root, prefixes, 'dcterms')
|
|
||||||
pq = '%s:timestamp' % CALIBRE_PREFIX
|
pq = '%s:timestamp' % CALIBRE_PREFIX
|
||||||
for meta in XPath('./opf:metadata/opf:meta')(root):
|
for meta in XPath('./opf:metadata/opf:meta')(root):
|
||||||
prop = expand_prefix(meta.get('property'), prefixes)
|
prop = expand_prefix(meta.get('property'), prefixes)
|
||||||
if prop.lower() == pq or meta.get('name') == 'calibre:timestamp':
|
if prop.lower() == pq or meta.get('name') == 'calibre:timestamp':
|
||||||
remove_element(meta, refines)
|
remove_element(meta, refines)
|
||||||
create_timestamp(XPath('./opf:metadata')(root)[0], val)
|
create_timestamp(root, prefixes, XPath('./opf:metadata')(root)[0], val)
|
||||||
|
|
||||||
|
|
||||||
def read_last_modified(root, prefixes, refines):
|
def read_last_modified(root, prefixes, refines):
|
||||||
@ -607,6 +616,23 @@ def read_last_modified(root, prefixes, refines):
|
|||||||
return parse_date(val, is_w3cdtf=scheme == sq)
|
return parse_date(val, is_w3cdtf=scheme == sq)
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
def set_last_modified(root, prefixes, refines, val=None):
|
||||||
|
pq = '%s:modified' % reserved_prefixes['dcterms']
|
||||||
|
sq = '%s:w3cdtf' % reserved_prefixes['dcterms']
|
||||||
|
val = w3cdtf(val or utcnow())
|
||||||
|
for meta in XPath('./opf:metadata/opf:meta[@property]')(root):
|
||||||
|
prop = expand_prefix(meta.get('property'), prefixes)
|
||||||
|
if prop.lower() == pq:
|
||||||
|
iid = meta.get('id')
|
||||||
|
if not iid or not refines[iid]:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
ensure_prefix(root, prefixes, 'dcterms')
|
||||||
|
m = XPath('./opf:metadata')(root)[0]
|
||||||
|
meta = m.makeelement(OPF('meta'), attrib={'property':'dcterms:modified', 'scheme':'dcterms:W3CDTF'})
|
||||||
|
m.append(meta)
|
||||||
|
meta.text = val
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
# Comments {{{
|
# Comments {{{
|
||||||
@ -933,6 +959,11 @@ def first_spine_item(root, prefixes, refines):
|
|||||||
return item.get('href') or None
|
return item.get('href') or None
|
||||||
|
|
||||||
|
|
||||||
|
def set_last_modified_in_opf(root):
|
||||||
|
prefixes, refines = read_prefixes(root), read_refines(root)
|
||||||
|
set_last_modified(root, prefixes, refines)
|
||||||
|
|
||||||
|
|
||||||
def read_metadata(root, ver=None, return_extra_data=False):
|
def read_metadata(root, ver=None, return_extra_data=False):
|
||||||
ans = Metadata(_('Unknown'), [_('Unknown')])
|
ans = Metadata(_('Unknown'), [_('Unknown')])
|
||||||
prefixes, refines = read_prefixes(root), read_refines(root)
|
prefixes, refines = read_prefixes(root), read_refines(root)
|
||||||
|
@ -1294,7 +1294,14 @@ class EpubContainer(Container):
|
|||||||
f.write(raw)
|
f.write(raw)
|
||||||
self.obfuscated_fonts[font] = (alg, tkey)
|
self.obfuscated_fonts[font] = (alg, tkey)
|
||||||
|
|
||||||
|
def update_modified_timestamp(self):
|
||||||
|
from calibre.ebooks.metadata.opf3 import set_last_modified_in_opf
|
||||||
|
set_last_modified_in_opf(self.opf)
|
||||||
|
self.dirty(self.opf_name)
|
||||||
|
|
||||||
def commit(self, outpath=None, keep_parsed=False):
|
def commit(self, outpath=None, keep_parsed=False):
|
||||||
|
if self.opf_version_parsed.major == 3:
|
||||||
|
self.update_modified_timestamp()
|
||||||
super(EpubContainer, self).commit(keep_parsed=keep_parsed)
|
super(EpubContainer, self).commit(keep_parsed=keep_parsed)
|
||||||
container_path = join(self.root, 'META-INF', 'container.xml')
|
container_path = join(self.root, 'META-INF', 'container.xml')
|
||||||
if not exists(container_path):
|
if not exists(container_path):
|
||||||
|
@ -193,6 +193,15 @@ def isoformat(date_time, assume_utc=False, as_utc=True, sep='T'):
|
|||||||
return unicode(date_time.isoformat(str(sep)))
|
return unicode(date_time.isoformat(str(sep)))
|
||||||
|
|
||||||
|
|
||||||
|
def w3cdtf(date_time, assume_utc=False):
|
||||||
|
if hasattr(date_time, 'tzinfo'):
|
||||||
|
if date_time.tzinfo is None:
|
||||||
|
date_time = date_time.replace(tzinfo=_utc_tz if assume_utc else
|
||||||
|
_local_tz)
|
||||||
|
date_time = date_time.astimezone(_utc_tz if as_utc else _local_tz)
|
||||||
|
return unicode(date_time.strftime('%Y-%M-%dT%H:%M:%SZ'))
|
||||||
|
|
||||||
|
|
||||||
def as_local_time(date_time, assume_utc=True):
|
def as_local_time(date_time, assume_utc=True):
|
||||||
if not hasattr(date_time, 'tzinfo'):
|
if not hasattr(date_time, 'tzinfo'):
|
||||||
return date_time
|
return date_time
|
||||||
|
Loading…
x
Reference in New Issue
Block a user