mirror of
https://github.com/gryf/ebook-converter.git
synced 2026-03-03 07:15:53 +01:00
Removed unused code, stright up iso8601 parser
This commit is contained in:
@@ -3,68 +3,7 @@ Created on 4 Jun 2010
|
|||||||
|
|
||||||
@author: charles
|
@author: charles
|
||||||
"""
|
"""
|
||||||
import json, traceback
|
from ebook_converter.constants_old import preferred_encoding
|
||||||
from datetime import datetime, time
|
|
||||||
|
|
||||||
from ebook_converter.ebooks.metadata.book import SERIALIZABLE_FIELDS
|
|
||||||
from ebook_converter.constants_old import filesystem_encoding, preferred_encoding
|
|
||||||
from ebook_converter.library.field_metadata import FieldMetadata
|
|
||||||
from ebook_converter.polyglot.builtins import as_bytes
|
|
||||||
from ebook_converter.polyglot.binary import as_base64_unicode, from_base64_bytes
|
|
||||||
|
|
||||||
|
|
||||||
# Translate datetimes to and from strings. The string form is the datetime in
|
|
||||||
# UTC. The returned date is also UTC
|
|
||||||
|
|
||||||
|
|
||||||
def string_to_datetime(src):
|
|
||||||
from ebook_converter.utils.iso8601 import parse_iso8601
|
|
||||||
if src != "None":
|
|
||||||
try:
|
|
||||||
return parse_iso8601(src)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def datetime_to_string(dateval):
|
|
||||||
from ebook_converter.utils.date import isoformat, UNDEFINED_DATE, local_tz
|
|
||||||
if dateval is None:
|
|
||||||
return "None"
|
|
||||||
if not isinstance(dateval, datetime):
|
|
||||||
dateval = datetime.combine(dateval, time())
|
|
||||||
if hasattr(dateval, 'tzinfo') and dateval.tzinfo is None:
|
|
||||||
dateval = dateval.replace(tzinfo=local_tz)
|
|
||||||
if dateval <= UNDEFINED_DATE:
|
|
||||||
return "None"
|
|
||||||
return isoformat(dateval)
|
|
||||||
|
|
||||||
|
|
||||||
def encode_thumbnail(thumbnail):
|
|
||||||
'''
|
|
||||||
Encode the image part of a thumbnail, then return the 3 part tuple
|
|
||||||
'''
|
|
||||||
from ebook_converter.utils.imghdr import identify
|
|
||||||
if thumbnail is None:
|
|
||||||
return None
|
|
||||||
if not isinstance(thumbnail, (tuple, list)):
|
|
||||||
try:
|
|
||||||
width, height = identify(as_bytes(thumbnail))[1:]
|
|
||||||
if width < 0 or height < 0:
|
|
||||||
return None
|
|
||||||
thumbnail = (width, height, thumbnail)
|
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
return (thumbnail[0], thumbnail[1], as_base64_unicode(thumbnail[2]))
|
|
||||||
|
|
||||||
|
|
||||||
def decode_thumbnail(tup):
|
|
||||||
'''
|
|
||||||
Decode an encoded thumbnail into its 3 component parts
|
|
||||||
'''
|
|
||||||
if tup is None:
|
|
||||||
return None
|
|
||||||
return (tup[0], tup[1], from_base64_bytes(tup[2]))
|
|
||||||
|
|
||||||
|
|
||||||
def object_to_unicode(obj, enc=preferred_encoding):
|
def object_to_unicode(obj, enc=preferred_encoding):
|
||||||
@@ -75,7 +14,8 @@ def object_to_unicode(obj, enc=preferred_encoding):
|
|||||||
if isinstance(obj, bytes):
|
if isinstance(obj, bytes):
|
||||||
return dec(obj)
|
return dec(obj)
|
||||||
if isinstance(obj, (list, tuple)):
|
if isinstance(obj, (list, tuple)):
|
||||||
return [dec(x) if isinstance(x, bytes) else object_to_unicode(x) for x in obj]
|
return [dec(x) if isinstance(x, bytes) else object_to_unicode(x)
|
||||||
|
for x in obj]
|
||||||
if isinstance(obj, dict):
|
if isinstance(obj, dict):
|
||||||
ans = {}
|
ans = {}
|
||||||
for k, v in obj.items():
|
for k, v in obj.items():
|
||||||
@@ -94,7 +34,7 @@ def encode_is_multiple(fm):
|
|||||||
if dt == 'composite':
|
if dt == 'composite':
|
||||||
fm['is_multiple'] = ','
|
fm['is_multiple'] = ','
|
||||||
else:
|
else:
|
||||||
fm['is_multiple'] = '|'
|
fm['is_multiple'] = '|'
|
||||||
else:
|
else:
|
||||||
fm['is_multiple'] = None
|
fm['is_multiple'] = None
|
||||||
fm['is_multiple2'] = {}
|
fm['is_multiple2'] = {}
|
||||||
@@ -122,94 +62,3 @@ def decode_is_multiple(fm):
|
|||||||
elif im is None:
|
elif im is None:
|
||||||
im = {}
|
im = {}
|
||||||
fm['is_multiple'] = im
|
fm['is_multiple'] = im
|
||||||
|
|
||||||
|
|
||||||
class JsonCodec(object):
|
|
||||||
|
|
||||||
def __init__(self, field_metadata=None):
|
|
||||||
self.field_metadata = field_metadata or FieldMetadata()
|
|
||||||
|
|
||||||
def encode_to_file(self, file_, booklist):
|
|
||||||
data = json.dumps(self.encode_booklist_metadata(booklist), indent=2)
|
|
||||||
if not isinstance(data, bytes):
|
|
||||||
data = data.encode('utf-8')
|
|
||||||
file_.write(data)
|
|
||||||
|
|
||||||
def encode_booklist_metadata(self, booklist):
|
|
||||||
result = []
|
|
||||||
for book in booklist:
|
|
||||||
result.append(self.encode_book_metadata(book))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def encode_book_metadata(self, book):
|
|
||||||
result = {}
|
|
||||||
for key in SERIALIZABLE_FIELDS:
|
|
||||||
result[key] = self.encode_metadata_attr(book, key)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def encode_metadata_attr(self, book, key):
|
|
||||||
if key == 'user_metadata':
|
|
||||||
meta = book.get_all_user_metadata(make_copy=True)
|
|
||||||
for fm in meta.values():
|
|
||||||
if fm['datatype'] == 'datetime':
|
|
||||||
fm['#value#'] = datetime_to_string(fm['#value#'])
|
|
||||||
encode_is_multiple(fm)
|
|
||||||
return meta
|
|
||||||
if key in self.field_metadata:
|
|
||||||
datatype = self.field_metadata[key]['datatype']
|
|
||||||
else:
|
|
||||||
datatype = None
|
|
||||||
value = book.get(key)
|
|
||||||
if key == 'thumbnail':
|
|
||||||
return encode_thumbnail(value)
|
|
||||||
elif isinstance(value, bytes): # str includes bytes
|
|
||||||
enc = filesystem_encoding if key == 'lpath' else preferred_encoding
|
|
||||||
return object_to_unicode(value, enc=enc)
|
|
||||||
elif datatype == 'datetime':
|
|
||||||
return datetime_to_string(value)
|
|
||||||
else:
|
|
||||||
return object_to_unicode(value)
|
|
||||||
|
|
||||||
def decode_from_file(self, file_, booklist, book_class, prefix):
|
|
||||||
js = []
|
|
||||||
try:
|
|
||||||
js = json.load(file_, encoding='utf-8')
|
|
||||||
for item in js:
|
|
||||||
entry = self.raw_to_book(item, book_class, prefix)
|
|
||||||
if entry is not None:
|
|
||||||
booklist.append(entry)
|
|
||||||
except:
|
|
||||||
print('exception during JSON decode_from_file')
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
def raw_to_book(self, json_book, book_class, prefix):
|
|
||||||
try:
|
|
||||||
book = book_class(prefix, json_book.get('lpath', None))
|
|
||||||
for key,val in json_book.items():
|
|
||||||
meta = self.decode_metadata(key, val)
|
|
||||||
if key == 'user_metadata':
|
|
||||||
book.set_all_user_metadata(meta)
|
|
||||||
else:
|
|
||||||
if key == 'classifiers':
|
|
||||||
key = 'identifiers'
|
|
||||||
setattr(book, key, meta)
|
|
||||||
return book
|
|
||||||
except:
|
|
||||||
print('exception during JSON decoding')
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
def decode_metadata(self, key, value):
|
|
||||||
if key == 'classifiers':
|
|
||||||
key = 'identifiers'
|
|
||||||
if key == 'user_metadata':
|
|
||||||
for fm in value.values():
|
|
||||||
if fm['datatype'] == 'datetime':
|
|
||||||
fm['#value#'] = string_to_datetime(fm['#value#'])
|
|
||||||
decode_is_multiple(fm)
|
|
||||||
return value
|
|
||||||
elif key in self.field_metadata:
|
|
||||||
if self.field_metadata[key]['datatype'] == 'datetime':
|
|
||||||
return string_to_datetime(value)
|
|
||||||
if key == 'thumbnail':
|
|
||||||
return decode_thumbnail(value)
|
|
||||||
return value
|
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from dateutil.tz import tzlocal, tzutc, tzoffset
|
import dateutil.tz
|
||||||
|
import dateutil.parser
|
||||||
from ebook_converter.constants_old import plugins
|
|
||||||
# speedup, err = plugins['speedup']
|
|
||||||
# if not speedup:
|
|
||||||
# raise RuntimeError(err)
|
|
||||||
|
|
||||||
|
|
||||||
class SafeLocalTimeZone(tzlocal):
|
class SafeLocalTimeZone(dateutil.tz.tzlocal):
|
||||||
|
|
||||||
def _isdst(self, dt):
|
def _isdst(self, dt):
|
||||||
# This method in tzlocal raises ValueError if dt is out of range (in
|
# This method in tzlocal raises ValueError if dt is out of range (in
|
||||||
@@ -31,25 +27,18 @@ class SafeLocalTimeZone(tzlocal):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
utc_tz = tzutc()
|
utc_tz = dateutil.tz.tzutc()
|
||||||
local_tz = SafeLocalTimeZone()
|
local_tz = SafeLocalTimeZone()
|
||||||
del tzutc, tzlocal
|
UNDEFINED_DATE = datetime(101, 1, 1, tzinfo=utc_tz)
|
||||||
UNDEFINED_DATE = datetime(101,1,1, tzinfo=utc_tz)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_iso8601(date_string, assume_utc=False, as_utc=True):
|
def parse_iso8601(date_string, assume_utc=False, as_utc=True):
|
||||||
if not date_string:
|
if not date_string:
|
||||||
return UNDEFINED_DATE
|
return UNDEFINED_DATE
|
||||||
dt, aware, tzseconds = speedup.parse_iso8601(date_string)
|
dt = dateutil.parser.isoparse(date_string)
|
||||||
tz = utc_tz if assume_utc else local_tz
|
tz = utc_tz if assume_utc else local_tz
|
||||||
if aware: # timezone was specified
|
if not dt.tzinfo: # timezone wasn't specified
|
||||||
if tzseconds == 0:
|
dt = dt.replace(tzinfo=tz)
|
||||||
tz = utc_tz
|
|
||||||
else:
|
|
||||||
sign = '-' if tzseconds < 0 else '+'
|
|
||||||
description = "%s%02d:%02d" % (sign, abs(tzseconds) // 3600, (abs(tzseconds) % 3600) // 60)
|
|
||||||
tz = tzoffset(description, tzseconds)
|
|
||||||
dt = dt.replace(tzinfo=tz)
|
|
||||||
if as_utc and tz is utc_tz:
|
if as_utc and tz is utc_tz:
|
||||||
return dt
|
return dt
|
||||||
return dt.astimezone(utc_tz if as_utc else local_tz)
|
return dt.astimezone(utc_tz if as_utc else local_tz)
|
||||||
|
|||||||
Reference in New Issue
Block a user