"""archive_packer.py - Archive creation class."""
import os
import zipfile
import threading
from mcomix import log
class Packer:
"""Packer is a threaded class for packing files into ZIP archives.
It would be straight-forward to add support for more archive types,
but basically all other types are less well fitted for this particular
task than ZIP archives are (yes, really).
"""
def __init__(self, image_files, other_files, archive_path, base_name):
"""Setup a Packer object to create a ZIP archive at <archive_path>.
All files pointed to by paths in the sequences <image_files> and
<other_files> will be included in the archive when packed.
The files in <image_files> will be renamed on the form
"NN - <base_name>.ext", so that the lexical ordering of their
filenames match that of their order in the list.
The files in <other_files> will be included as they are,
assuming their filenames does not clash with other filenames in
the archive. All files are placed in the archive root.
"""
self._image_files = image_files
self._other_files = other_files
self._archive_path = archive_path
self._base_name = base_name
self._pack_thread = None
self._packing_successful = False
def pack(self):
"""Pack all the files in the file lists into the archive."""
self._pack_thread = threading.Thread(target=self._thread_pack)
self._pack_thread.setDaemon(False)
self._pack_thread.start()
def wait(self):
"""Block until the packer thread has finished. Return True if the
packer finished its work successfully.
"""
if self._pack_thread != None:
self._pack_thread.join()
return self._packing_successful
def _thread_pack(self):
try:
zfile = zipfile.ZipFile(self._archive_path, 'w')
except Exception:
log.error(_('! Could not create archive at path "%s"'),
self._archive_path)
return
used_names = []
pattern = '%%0%dd - %s%%s' % (len(str(len(self._image_files))),
self._base_name)
for i, path in enumerate(self._image_files):
filename = pattern % (i + 1, os.path.splitext(path)[1])
try:
zfile.write(path, filename, zipfile.ZIP_STORED)
except Exception:
log.error(_('! Could not add file %(sourcefile)s '
'to archive %(archivefile)s, aborting...'),
{ "sourcefile" : path,
"archivefile" : self._archive_path})
zfile.close()
try:
os.remove(self._archive_path)
except:
pass
return
used_names.append(filename)
for path in self._other_files:
filename = os.path.basename(path)
while filename in used_names:
filename = '_%s' % filename
try:
zfile.write(path, filename, zipfile.ZIP_DEFLATED)
except Exception:
log.error(_('! Could not add file %(sourcefile)s '
'to archive %(archivefile)s, aborting...'),
{ "sourcefile" : path,
"archivefile" : self._archive_path})
zfile.close()
try:
os.remove(self._archive_path)
except:
pass
return
used_names.append(filename)
zfile.close()
self._packing_successful = True
# vim: expandtab:sw=4:ts=4