diff options
Diffstat (limited to 'port/tarball.py')
-rw-r--r-- | port/tarball.py | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/port/tarball.py b/port/tarball.py new file mode 100644 index 0000000..d07a3e1 --- /dev/null +++ b/port/tarball.py @@ -0,0 +1,154 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +"""Simplify tarfile module usage""" + +import os +import time +import tarfile +import cStringIO +import gtk +import zipfile +import tempfile +import shutil + +import port.pixbuf as pixbuf + +class TarballError(Exception): + """Base Tarball exception.""" + pass + +class BadDataTypeError(TarballError): + """Exception for unsupported data type in read/write methods.""" + pass + +class Tarball: + """ + Wrap standart tarfile module to simplify read/write operations with + most popular data types. + + In read mode Tarball can load zip files as well. + + Supprted types: + + * string + * gtk.gdk.Pixbuf + + Write usage: + + # create Tarball object + # to see all supported modes use + # http://docs.python.org/library/tarfile.html#tarfile.open + tar = Tarball(tarfile, 'w') + + # write string to file in tarball + tar.write('name within tarball', 'string to write') + + # write pixbuf to file in tarball + tar.write('name within tarball', pixbuf_object) + + # save and close tarball file + tar.close() + + Read usage: + + # create Tarball object + tar = Tarball(tarfile) + + # read content of file in tarball to string + str_content = tar.read('name within tarball') + + # read content of file in tarball to pixbuf object + pixbuf_content = tar.read_pixbuf('name within tarball') + """ + + def __init__(self, name=None, mode='r', mtime=None): + if not mode.startswith('r') or tarfile.is_tarfile(name): + self.__tar = tarfile.TarFile(name=name, mode=mode) + else: + # convert for tar + + if not zipfile.is_zipfile(name): + raise tarfile.ReadError() + + try: + tmp_dir = tempfile.mkdtemp() + tmp_fd, tmp_name = tempfile.mkstemp() + tmp_fo = os.fdopen(tmp_fd, 'w') + + zip = zipfile.ZipFile(name) + zip.extractall(tmp_dir) + + tar = tarfile.TarFile(fileobj=tmp_fo, mode='w') + tar.add(tmp_dir, arcname='') + tar.close() + + self.__tar = tarfile.TarFile(name=tmp_name, mode=mode) + finally: + tmp_fo.close() + os.unlink(tmp_name) + shutil.rmtree(tmp_dir) + + if mtime: + self.mtime = mtime + else: + self.mtime = time.time() + + def close(self): + """Save(if 'r' mode was given) and close tarball file.""" + self.__tar.close() + + def getnames(self): + """Return names of members sorted by creation order.""" + return self.__tar.getnames() + + def read(self, arcname): + """Returns sring with content of given file from tarball.""" + file_o = self.__tar.extractfile(arcname.encode('utf8')) + if not file_o: + return None + out = file_o.read() + file_o.close() + return out + + def read_pixbuf(self, arcname): + """Returns pixbuf object of given file from tarball.""" + return pixbuf.from_str(self.read(arcname)) + + def write(self, arcname, data, mode=0644): + """ + Stores given object to file in tarball. + Raises BadDataTypeError exception If data type isn't supported. + """ + info = tarfile.TarInfo(arcname.encode('utf8')) + info.mode = mode + info.mtime = self.mtime + + if isinstance(data, str): + self.__write_str(info, data) + elif isinstance(data, gtk.gdk.Pixbuf): + self.__write_pixbuf(info, data) + else: + raise BadDataTypeError() + + def __write_str(self, info, data): + info.size = len(data) + self.__tar.addfile(info, cStringIO.StringIO(data)) + + def __write_pixbuf(self, info, data): + buffer = pixbuf.to_file(data) + buffer.seek(0, os.SEEK_END) + info.size = buffer.tell() + buffer.seek(0) + self.__tar.addfile(info, buffer) |