mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Make containers picklable
This commit is contained in:
parent
9f9e3478ee
commit
69adb0ae81
@ -90,9 +90,7 @@ def clone_container(container, dest_dir, container_class=None):
|
|||||||
dest_dir = os.path.abspath(os.path.realpath(dest_dir))
|
dest_dir = os.path.abspath(os.path.realpath(dest_dir))
|
||||||
clone_data = container.clone_data(dest_dir)
|
clone_data = container.clone_data(dest_dir)
|
||||||
container_class = container_class or type(container)
|
container_class = container_class or type(container)
|
||||||
if container_class is Container:
|
return container_class(log=container.log, clone_data=clone_data)
|
||||||
return container_class(None, None, container.log, clone_data=clone_data)
|
|
||||||
return container_class(None, container.log, clone_data=clone_data)
|
|
||||||
|
|
||||||
|
|
||||||
def name_to_abspath(name, root):
|
def name_to_abspath(name, root):
|
||||||
@ -151,8 +149,8 @@ class ContainerBase: # {{{
|
|||||||
#: The mode used to parse HTML and CSS (polishing uses tweak_mode=False and the editor uses tweak_mode=True)
|
#: The mode used to parse HTML and CSS (polishing uses tweak_mode=False and the editor uses tweak_mode=True)
|
||||||
tweak_mode = False
|
tweak_mode = False
|
||||||
|
|
||||||
def __init__(self, log):
|
def __init__(self, log=default_log):
|
||||||
self.log = log
|
self.log = log or default_log
|
||||||
self.parsed_cache = {}
|
self.parsed_cache = {}
|
||||||
self.mime_map = {}
|
self.mime_map = {}
|
||||||
self.encoding_map = {}
|
self.encoding_map = {}
|
||||||
@ -235,7 +233,7 @@ class Container(ContainerBase): # {{{
|
|||||||
def book_type_for_display(self):
|
def book_type_for_display(self):
|
||||||
return self.book_type.upper()
|
return self.book_type.upper()
|
||||||
|
|
||||||
def __init__(self, rootpath, opfpath, log, clone_data=None):
|
def __init__(self, rootpath=None, opfpath=None, log=default_log, clone_data=None):
|
||||||
ContainerBase.__init__(self, log)
|
ContainerBase.__init__(self, log)
|
||||||
self.root = clone_data['root'] if clone_data is not None else os.path.abspath(rootpath)
|
self.root = clone_data['root'] if clone_data is not None else os.path.abspath(rootpath)
|
||||||
|
|
||||||
@ -247,8 +245,7 @@ class Container(ContainerBase): # {{{
|
|||||||
self.href_to_name_cache = {}
|
self.href_to_name_cache = {}
|
||||||
|
|
||||||
if clone_data is not None:
|
if clone_data is not None:
|
||||||
self.cloned = True
|
for x in ('cloned', 'name_path_map', 'opf_name', 'mime_map', 'pretty_print', 'encoding_map', 'tweak_mode'):
|
||||||
for x in ('name_path_map', 'opf_name', 'mime_map', 'pretty_print', 'encoding_map', 'tweak_mode'):
|
|
||||||
setattr(self, x, clone_data[x])
|
setattr(self, x, clone_data[x])
|
||||||
self.opf_dir = os.path.dirname(self.name_path_map[self.opf_name])
|
self.opf_dir = os.path.dirname(self.name_path_map[self.opf_name])
|
||||||
return
|
return
|
||||||
@ -302,17 +299,25 @@ class Container(ContainerBase): # {{{
|
|||||||
'pretty_print': set(self.pretty_print),
|
'pretty_print': set(self.pretty_print),
|
||||||
'encoding_map': self.encoding_map.copy(),
|
'encoding_map': self.encoding_map.copy(),
|
||||||
'tweak_mode': self.tweak_mode,
|
'tweak_mode': self.tweak_mode,
|
||||||
|
'cloned': self.cloned,
|
||||||
'name_path_map': {
|
'name_path_map': {
|
||||||
name:os.path.join(dest_dir, os.path.relpath(path, self.root))
|
name: os.path.join(dest_dir, os.path.relpath(path, self.root)) for name, path in self.name_path_map.items()
|
||||||
for name, path in iteritems(self.name_path_map)}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def clone_data(self, dest_dir):
|
def clone_data(self, dest_dir):
|
||||||
Container.commit(self, keep_parsed=False)
|
Container.commit(self, keep_parsed=False)
|
||||||
self.cloned = True
|
|
||||||
clone_dir(self.root, dest_dir)
|
clone_dir(self.root, dest_dir)
|
||||||
|
self.cloned = True
|
||||||
return self.data_for_clone(dest_dir)
|
return self.data_for_clone(dest_dir)
|
||||||
|
|
||||||
|
def __getstate__(self):
|
||||||
|
Container.commit(self, keep_parsed=True)
|
||||||
|
return self.data_for_clone()
|
||||||
|
|
||||||
|
def __setstate__(self, state):
|
||||||
|
self.__init__(log=default_log, clone_data=state)
|
||||||
|
|
||||||
def add_name_to_manifest(self, name, process_manifest_item=None, suggested_id=''):
|
def add_name_to_manifest(self, name, process_manifest_item=None, suggested_id=''):
|
||||||
' Add an entry to the manifest for a file with the specified name. Returns the manifest id. '
|
' Add an entry to the manifest for a file with the specified name. Returns the manifest id. '
|
||||||
all_ids = {x.get('id') for x in self.opf_xpath('//*[@id]')}
|
all_ids = {x.get('id') for x in self.opf_xpath('//*[@id]')}
|
||||||
@ -1153,7 +1158,7 @@ class EpubContainer(Container):
|
|||||||
'rights.xml': False,
|
'rights.xml': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, pathtoepub, log, clone_data=None, tdir=None):
|
def __init__(self, pathtoepub=None, log=default_log, clone_data=None, tdir=None):
|
||||||
if clone_data is not None:
|
if clone_data is not None:
|
||||||
super().__init__(None, None, log, clone_data=clone_data)
|
super().__init__(None, None, log, clone_data=clone_data)
|
||||||
for x in ('pathtoepub', 'obfuscated_fonts', 'is_dir'):
|
for x in ('pathtoepub', 'obfuscated_fonts', 'is_dir'):
|
||||||
@ -1225,8 +1230,8 @@ class EpubContainer(Container):
|
|||||||
self.process_encryption()
|
self.process_encryption()
|
||||||
self.parsed_cache['META-INF/container.xml'] = container
|
self.parsed_cache['META-INF/container.xml'] = container
|
||||||
|
|
||||||
def clone_data(self, dest_dir):
|
def data_for_clone(self, dest_dir=None):
|
||||||
ans = super().clone_data(dest_dir)
|
ans = super().data_for_clone(dest_dir)
|
||||||
ans['pathtoepub'] = self.pathtoepub
|
ans['pathtoepub'] = self.pathtoepub
|
||||||
ans['obfuscated_fonts'] = self.obfuscated_fonts.copy()
|
ans['obfuscated_fonts'] = self.obfuscated_fonts.copy()
|
||||||
ans['is_dir'] = self.is_dir
|
ans['is_dir'] = self.is_dir
|
||||||
@ -1437,7 +1442,7 @@ class KEPUBContainer(EpubContainer):
|
|||||||
book_type = 'kepub'
|
book_type = 'kepub'
|
||||||
MAX_HTML_FILE_SIZE = 512 * 1024
|
MAX_HTML_FILE_SIZE = 512 * 1024
|
||||||
|
|
||||||
def __init__(self, pathtokepub, log, clone_data=None, tdir=None):
|
def __init__(self, pathtokepub=None, log=default_log, clone_data=None, tdir=None):
|
||||||
super().__init__(pathtokepub, log=log, clone_data=clone_data, tdir=tdir)
|
super().__init__(pathtokepub, log=log, clone_data=clone_data, tdir=tdir)
|
||||||
from calibre.ebooks.oeb.polish.kepubify import unkepubify_container
|
from calibre.ebooks.oeb.polish.kepubify import unkepubify_container
|
||||||
Container.commit(self, keep_parsed=True)
|
Container.commit(self, keep_parsed=True)
|
||||||
@ -1532,7 +1537,7 @@ class AZW3Container(Container):
|
|||||||
SUPPORTS_TITLEPAGES = False
|
SUPPORTS_TITLEPAGES = False
|
||||||
SUPPORTS_FILENAMES = False
|
SUPPORTS_FILENAMES = False
|
||||||
|
|
||||||
def __init__(self, pathtoazw3, log, clone_data=None, tdir=None):
|
def __init__(self, pathtoazw3=None, log=default_log, clone_data=None, tdir=None):
|
||||||
if clone_data is not None:
|
if clone_data is not None:
|
||||||
super().__init__(None, None, log, clone_data=clone_data)
|
super().__init__(None, None, log, clone_data=clone_data)
|
||||||
for x in ('pathtoazw3', 'obfuscated_fonts'):
|
for x in ('pathtoazw3', 'obfuscated_fonts'):
|
||||||
@ -1580,8 +1585,8 @@ class AZW3Container(Container):
|
|||||||
super().__init__(tdir, opf_path, log)
|
super().__init__(tdir, opf_path, log)
|
||||||
self.obfuscated_fonts = {x.replace(os.sep, '/') for x in obfuscated_fonts}
|
self.obfuscated_fonts = {x.replace(os.sep, '/') for x in obfuscated_fonts}
|
||||||
|
|
||||||
def clone_data(self, dest_dir):
|
def data_for_clone(self, dest_dir=None):
|
||||||
ans = super().clone_data(dest_dir)
|
ans = super().data_for_clone(dest_dir)
|
||||||
ans['pathtoazw3'] = self.pathtoazw3
|
ans['pathtoazw3'] = self.pathtoazw3
|
||||||
ans['obfuscated_fonts'] = self.obfuscated_fonts.copy()
|
ans['obfuscated_fonts'] = self.obfuscated_fonts.copy()
|
||||||
return ans
|
return ans
|
||||||
@ -1607,8 +1612,6 @@ class AZW3Container(Container):
|
|||||||
|
|
||||||
|
|
||||||
def get_container(path, log=None, tdir=None, tweak_mode=False, ebook_cls=None) -> Container:
|
def get_container(path, log=None, tdir=None, tweak_mode=False, ebook_cls=None) -> Container:
|
||||||
if log is None:
|
|
||||||
log = default_log
|
|
||||||
try:
|
try:
|
||||||
isdir = os.path.isdir(path)
|
isdir = os.path.isdir(path)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -5,6 +5,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import pickle
|
||||||
import subprocess
|
import subprocess
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
@ -71,6 +72,9 @@ class ContainerTests(BaseTest):
|
|||||||
x = base + 'out.' + fmt
|
x = base + 'out.' + fmt
|
||||||
for c in (c1, c2):
|
for c in (c1, c2):
|
||||||
c.commit(outpath=x)
|
c.commit(outpath=x)
|
||||||
|
c = pickle.loads(pickle.dumps(c1))
|
||||||
|
for attr in c1.data_for_clone():
|
||||||
|
self.assertEqual(getattr(c1, attr), getattr(c, attr))
|
||||||
|
|
||||||
def test_file_removal(self):
|
def test_file_removal(self):
|
||||||
' Test removal of files from the container '
|
' Test removal of files from the container '
|
||||||
|
Loading…
x
Reference in New Issue
Block a user