%PDF- %PDF-
| Direktori : /lib/calibre/calibre/utils/ |
| Current File : //lib/calibre/calibre/utils/serialize.py |
#!/usr/bin/env python3
# License: GPLv3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
MSGPACK_MIME = 'application/x-msgpack'
CANARY = 'jPoAv3zOyHvQ5JFNYg4hJ9'
def encoded(typ, data, ExtType):
if ExtType is None:
return {CANARY: typ, 'v': data}
return ExtType(typ, msgpack_dumps(data))
def create_encoder(for_json=False):
from datetime import datetime
ExtType = None
if not for_json:
import msgpack
ExtType = msgpack.ExtType
def encoder(obj):
if isinstance(obj, datetime):
return encoded(0, str(obj.isoformat()), ExtType)
if isinstance(obj, (set, frozenset)):
return encoded(1, tuple(obj), ExtType)
if getattr(obj, '__calibre_serializable__', False):
from calibre.ebooks.metadata.book.base import Metadata
from calibre.library.field_metadata import FieldMetadata, fm_as_dict
from calibre.db.categories import Tag
if isinstance(obj, Metadata):
from calibre.ebooks.metadata.book.serialize import metadata_as_dict
return encoded(
2, metadata_as_dict(obj, encode_cover_data=for_json), ExtType
)
elif isinstance(obj, FieldMetadata):
return encoded(3, fm_as_dict(obj), ExtType)
elif isinstance(obj, Tag):
return encoded(4, obj.as_dict(), ExtType)
if for_json and isinstance(obj, bytes):
return obj.decode('utf-8')
raise TypeError(f'Cannot serialize objects of type {type(obj)}')
return encoder
def msgpack_dumps(obj):
import msgpack
return msgpack.packb(obj, default=create_encoder(), use_bin_type=True)
def json_dumps(data, **kw):
import json
kw['default'] = create_encoder(for_json=True)
kw['ensure_ascii'] = False
ans = json.dumps(data, **kw)
if not isinstance(ans, bytes):
ans = ans.encode('utf-8')
return ans
def decode_metadata(x, for_json):
from polyglot.binary import from_base64_bytes
from calibre.ebooks.metadata.book.serialize import metadata_from_dict
obj = metadata_from_dict(x)
if for_json and obj.cover_data and obj.cover_data[1]:
obj.cover_data = obj.cover_data[0], from_base64_bytes(obj.cover_data[1])
return obj
def decode_field_metadata(x, for_json):
from calibre.library.field_metadata import fm_from_dict
return fm_from_dict(x)
def decode_category_tag(x, for_json):
from calibre.db.categories import Tag
return Tag.from_dict(x)
def decode_datetime(x, fj):
from calibre.utils.iso8601 import parse_iso8601
return parse_iso8601(x, assume_utc=True)
decoders = (
decode_datetime,
lambda x, fj: set(x),
decode_metadata, decode_field_metadata, decode_category_tag
)
def json_decoder(obj):
typ = obj.get(CANARY)
if typ is None:
return obj
return decoders[typ](obj['v'], True)
def msgpack_decoder(code, data):
return decoders[code](msgpack_loads(data), False)
def msgpack_loads(dump, use_list=True):
# use_list controls whether msgpack arrays are unpacked as lists or tuples
import msgpack
return msgpack.unpackb(dump, ext_hook=msgpack_decoder, raw=False, use_list=use_list, strict_map_key=False)
def json_loads(data):
import json
return json.loads(data, object_hook=json_decoder)
def pickle_dumps(data):
import pickle
return pickle.dumps(data, -1)
def pickle_loads(dump):
import pickle
return pickle.loads(dump, encoding='utf-8')