view MoinMoin/converter/ @ 2960:b2417a0dd48f tip

trivial change to prevent traceback when 0 is passed to TableOfContents macro
author RogerHaase <>
date Thu, 18 Jun 2015 15:31:51 -0700
parents da84a2c42a92
line wrap: on
line source
# Copyright: 2010 MoinMoin:ThomasWaldmann
# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.

MoinMoin - Archives converter (e.g. zip, tar)

Make a DOM Tree representation of an archive (== list contents of it in a table).

from datetime import datetime
import tarfile
import zipfile

from ._table import TableMixin

from MoinMoin.i18n import _, L_, N_
from MoinMoin.util.iri import Iri
from MoinMoin.util.tree import moin_page, xlink

from MoinMoin import log
logging = log.getLogger(__name__)

class ArchiveException(Exception):
    exception class used in case of trouble with opening/listing an archive

class ArchiveConverter(TableMixin):
    Base class for archive converters, convert an archive to a DOM table
    with an archive listing.
    def _factory(cls, input, output, **kw):
        return cls()

    def process_name(self, member_name):
        name = unicode(member_name, 'utf-8')
        attrib = {
            xlink.href: Iri(scheme='wiki', authority='', path='/' + self.item_name,
        return moin_page.a(attrib=attrib, children=[name, ])

    def process_datetime(self, dt):
        return unicode(dt.isoformat(' '))

    def process_size(self, size):
        return unicode(size)

    def __call__(self, rev, contenttype=None, arguments=None):
        self.item_name =
            contents = self.list_contents(
            contents = [(self.process_size(size),
            ) for size, dt, name in contents]
            table = self.build_dom_table(contents, head=[_("Size"), _("Timestamp"), _("Name")], cls='zebra')
            body = moin_page.body(children=(table, ))
            return, ))
        except ArchiveException as err:
            logging.exception("An exception within archive file handling occurred:")
            # XXX we also use a table for error reporting, could be
            # something more adequate, though:
            return self.build_dom_table([[str(err)]])

    def list_contents(self, fileobj):
        analyze archive we get as fileobj and return data for table rendering.

        We return a list of rows, each row is a list of cells.

        Usually each row is [size, datetime, name] for each archive member.

        In case of problems, it shall raise ArchiveException(error_msg).
        raise NotImplementedError

class TarConverter(ArchiveConverter):
    Support listing tar files.
    def list_contents(self, fileobj):
            rows = []
            tf =, mode='r')
            for tinfo in tf.getmembers():
                if tinfo.isfile():
                    # display only normal files, not directories
            return rows
        except tarfile.TarError as err:
            raise ArchiveException(str(err))

class ZipConverter(ArchiveConverter):
    Support listing zip files.
    def list_contents(self, fileobj):
            rows = []
            zf = zipfile.ZipFile(fileobj, mode='r')
            for zinfo in zf.filelist:
                if not (zinfo.file_size == 0 and zinfo.filename.endswith('/')):
                    # display only normal files, not directories
                        datetime(*zinfo.date_time),  # y,m,d,h,m,s
            return rows
        except (RuntimeError, zipfile.BadZipfile) as err:
            # RuntimeError is raised by zipfile stdlib module in case of
            # problems (like inconsistent slash and backslash usage in the
            # archive or a defective zip file).
            raise ArchiveException(str(err))

from . import default_registry
from MoinMoin.util.mime import Type, type_moin_document
default_registry.register(TarConverter._factory, Type('application/x-tar'), type_moin_document)
default_registry.register(TarConverter._factory, Type('application/x-gtar'), type_moin_document)
default_registry.register(ZipConverter._factory, Type('application/zip'), type_moin_document)