Exemplo n.º 1
0
def _convert_table_rows(container, node, context, cell_style=None):
    for row in node:
        if row.tagname != "row":
            printwarn('node "%s" not supported in thead/tbody' % row.tagname)
            continue

        odf_row = odf_create_row()
        container.append(odf_row)

        for entry in row:
            if entry.tagname != "entry":
                printwarn('node "%s" not supported in row' % entry.tagname)
                continue

            # Create a new odf_cell
            odf_cell = odf_create_cell(cell_type="string", style=cell_style)
            odf_row.append(odf_cell)

            # XXX We don't add table:covered-table-cell !
            #     It's bad but OO can nevertheless load the file
            morecols = entry.get("morecols")
            if morecols is not None:
                morecols = int(morecols) + 1
                odf_cell.set_attribute('table:number-columns-spanned',
                                       str(morecols))
            morerows = entry.get("morerows")
            if morerows is not None:
                morerows = int(morerows) + 1
                odf_cell.set_attribute('table:number-rows-spanned',
                                       str(morerows))

            push_convert_pop(entry, odf_cell, context)
Exemplo n.º 2
0
def convert_list(node, context, list_type):
    # Reuse template styles
    if list_type == "enumerated":
        style_name = "Numbering_20_1"
    else:
        style_name = "List_20_1"

    odf_list = odf_create_list(style=style_name)
    context['top'].append(odf_list)

    # Save the current top
    old_top = context['top']

    for item in node:
        if item.tagname != "list_item":
            printwarn("node not supported: %s" % item.tagname)
            continue
        # Create a new item
        odf_item = odf_create_list_item()
        odf_list.append(odf_item)
        # A new top
        context['top'] = odf_item
        for child in item:
            convert_node(child, context)

    # And restore the top
    context['top'] = old_top
Exemplo n.º 3
0
def convert_definition_list(node, context):
    """Convert a list of term/definition pairs to styled paragraphs.

    The "Definition List Term" style is looked for term paragraphs, and the
    "Definition List Definition" style is looked for definition paragraphs.
    """
    styles = context['styles']
    term_style = _get_term_style(context).get_name()
    definition_style = _get_definition_style(context).get_name()

    for item in node:
        if item.tagname != "definition_list_item":
            printwarn('node "%s" not supported in definition_list' %
                      (item.tagname))
            continue
        for child in item:
            tagname = child.tagname
            if tagname == "term":
                paragraph = odf_create_paragraph(style=term_style)
                context['top'].append(paragraph)
                push_convert_pop(child, paragraph, context)
            elif tagname == "definition":
                # Push a style on the stack for next paragraphs to use
                styles['paragraph'] = definition_style
                for subchildren in child:
                    convert_node(subchildren, context)
                # Pop the paragraph style (may already be popped)
                styles.pop('paragraph', None)
            else:
                printwarn('node "%s" not supported in definition_list_item' %
                          tagname)
Exemplo n.º 4
0
def _convert_table_rows(container, node, context, cell_style=None):
    for row in node:
        if row.tagname != "row":
            printwarn('node "%s" not supported in thead/tbody' % row.tagname)
            continue

        odf_row = odf_create_row()
        container.append(odf_row)

        for entry in row:
            if entry.tagname != "entry":
                printwarn('node "%s" not supported in row' % entry.tagname)
                continue

            # Create a new odf_cell
            odf_cell = odf_create_cell(cell_type="string", style=cell_style)
            odf_row.append(odf_cell)

            # XXX We don't add table:covered-table-cell !
            #     It's bad but OO can nevertheless load the file
            morecols = entry.get("morecols")
            if morecols is not None:
                morecols = int(morecols) + 1
                odf_cell.set_attribute('table:number-columns-spanned',
                                       str(morecols))
            morerows = entry.get("morerows")
            if morerows is not None:
                morerows = int(morerows) + 1
                odf_cell.set_attribute('table:number-rows-spanned',
                                       str(morerows))

            push_convert_pop(entry, odf_cell, context)
Exemplo n.º 5
0
def convert_definition_list(node, context):
    """Convert a list of term/definition pairs to styled paragraphs.

    The "Definition List Term" style is looked for term paragraphs, and the
    "Definition List Definition" style is looked for definition paragraphs.
    """
    styles = context['styles']
    term_style = _get_term_style(context).get_name()
    definition_style = _get_definition_style(context).get_name()

    for item in node:
        if item.tagname != "definition_list_item":
            printwarn('node "%s" not supported in definition_list' % (
                item.tagname))
            continue
        for child in item:
            tagname = child.tagname
            if tagname == "term":
                paragraph = odf_create_paragraph(style=term_style)
                context['top'].append(paragraph)
                push_convert_pop(child, paragraph, context)
            elif tagname == "definition":
                # Push a style on the stack for next paragraphs to use
                styles['paragraph'] = definition_style
                for subchildren in child:
                    convert_node(subchildren, context)
                # Pop the paragraph style (may already be popped)
                styles.pop('paragraph', None)
            else:
                printwarn('node "%s" not supported in definition_list_item' %
                        tagname)
Exemplo n.º 6
0
def convert_list(node, context, list_type):
    # Reuse template styles
    if list_type == "enumerated":
        style_name = "Numbering_20_1"
    else:
        style_name = "List_20_1"

    odf_list = odf_create_list(style=style_name)
    context['top'].append(odf_list)

    # Save the current top
    old_top = context['top']

    for item in node:
        if item.tagname != "list_item":
            printwarn("node not supported: %s" % item.tagname)
            continue
        # Create a new item
        odf_item = odf_create_list_item()
        odf_list.append(odf_item)
        # A new top
        context['top'] = odf_item
        for child in item:
            convert_node(child, context)

    # And restore the top
    context['top'] = old_top
Exemplo n.º 7
0
def convert_node(node, context):
    tagname = node.tagname
    convert_method = convert_methods.get(tagname)
    if convert_method is not None:
        convert_method(node, context)
    else:
        printwarn("node not supported: %s" % tagname)
Exemplo n.º 8
0
def _add_image(image, caption, context, width=None, height=None):
    # Load the image to find its size
    encoding = stdout.encoding if stdout.encoding is not None else "utf-8"
    try:
        image_file = open(image.encode(encoding), 'rb')
        image_object = Image.open(image_file)
    except (UnicodeEncodeError, IOError, OverflowError), e:
        printwarn('unable to insert the image "%s": %s' % (image, e))
        return
Exemplo n.º 9
0
def _add_image(image, caption, context, width=None, height=None):
    # Load the image to find its size
    encoding = stdout.encoding if stdout.encoding is not None else "utf-8"
    try:
        image_file = open(image.encode(encoding), 'rb')
        image_object = Image.open(image_file)
    except (UnicodeEncodeError, IOError, OverflowError), e:
        printwarn('unable to insert the image "%s": %s' % (image, e))
        return
Exemplo n.º 10
0
def convert_node(node, context):
    tagname = node.tagname
    # From the context
    convert_method = context.get('convert_' + tagname)
    if convert_method is None:
        # Default method
        convert_method = __convert_methods.get(tagname)
    if convert_method is not None:
        return convert_method(node, context)
    message = "node not supported: %s" % tagname
    if context['strict']:
        raise ValueError, message
    printwarn(message)
Exemplo n.º 11
0
def convert_node(node, context):
    tagname = node.tagname
    # From the context
    convert_method = context.get('convert_' + tagname)
    if convert_method is None:
        # Default method
        convert_method = __convert_methods.get(tagname)
    if convert_method is not None:
        return convert_method(node, context)
    message = "node not supported: %s" % tagname
    if context['strict']:
        raise ValueError, message
    printwarn(message)
Exemplo n.º 12
0
def convert_topic(node, context):
    # Reset the top to body
    context['top'] = context['body']

    # Yet an other TOC ?
    if context['skip_toc']:
        return
    if context['toc'] is not None:
        printwarn("a TOC is already inserted")
        return
    title = node.next_node(condition=nodes.title).astext()
    toc = odf_create_toc(title=title)
    context['body'].append(toc)
    context['toc'] = toc
Exemplo n.º 13
0
 def __init__(self, path_or_file):
     want_folder = False
     if isinstance(path_or_file, basestring):
         # Path
         self.path = path = path_or_file
         if os.path.isdir(path):  # opening a folder
             want_folder = True
         else:
             file = open(path, 'rb')
     else:
         # File-like assumed
         self.path = None
         file = path_or_file
     if want_folder:
         self.__data = data = path
         self.__packaging = 'folder'
         try:
             mimetype, timestamp = self.__get_folder_part('mimetype')
         except:
             printwarn(
                 "corrupted or not an OpenDocument folder (missing mimetype)"
             )
             mimetype = ''
             timestamp = None
         if mimetype not in ODF_MIMETYPES:
             message = 'Document of unknown type "%s", trying with ODF_TEXT.' % mimetype
             printwarn(message)
             mimetype = ODF_EXTENSIONS['odt']
         self.__parts = {'mimetype': mimetype}
         self.__parts_ts = {'mimetype': timestamp}
     else:
         self.__data = data = file.read()
         zip_expected = data[:4] == 'PK\x03\x04'
         # Most probably zipped document
         try:
             mimetype = self.__get_zip_part('mimetype')
             self.__packaging = 'zip'
         except BadZipfile:
             if zip_expected:
                 raise ValueError, "corrupted or not an OpenDocument archive"
             # Maybe XML document
             try:
                 mimetype = self.__get_xml_part('mimetype')
             except ValueError:
                 raise ValueError, "bad OpenDocument format"
             self.__packaging = 'flat'
         if mimetype not in ODF_MIMETYPES:
             message = 'Document of unknown type "%s"' % mimetype
             raise ValueError, message
         self.__parts = {'mimetype': mimetype}
Exemplo n.º 14
0
def convert_topic(node, context):
    # Reset the top to body
    context['top'] = context['body']

    # Yet an other TOC ?
    if context['skip_toc']:
        return
    if context['toc'] is not None:
        printwarn("a TOC is already inserted")
        return
    title = node.next_node(condition=nodes.title).astext()
    toc = odf_create_toc(title=title)
    context['body'].append(toc)
    context['toc'] = toc
Exemplo n.º 15
0
 def __init__(self, path_or_file):
     want_folder = False
     if isinstance(path_or_file, basestring):
         # Path
         self.path = path = path_or_file
         if os.path.isdir(path): # opening a folder
             want_folder = True
         else:
             file = open(path, 'rb')
     else:
         # File-like assumed
         self.path = None
         file = path_or_file
     if want_folder:
         self.__data = data = path
         self.__packaging = 'folder'
         try:
             mimetype, timestamp = self.__get_folder_part('mimetype')
         except:
             printwarn ("corrupted or not an OpenDocument folder (missing mimetype)")
             mimetype = ''
             timestamp = None
         if mimetype not in ODF_MIMETYPES:
             message = 'Document of unknown type "%s", trying with ODF_TEXT.' % mimetype
             printwarn(message)
             mimetype = ODF_EXTENSIONS['odt']
         self.__parts = {'mimetype': mimetype}
         self.__parts_ts = {'mimetype': timestamp}
     else:
         self.__data = data = file.read()
         zip_expected = data[:4] == 'PK\x03\x04'
         # Most probably zipped document
         try:
             mimetype = self.__get_zip_part('mimetype')
             self.__packaging = 'zip'
         except BadZipfile:
             if zip_expected:
                 raise ValueError("corrupted or not an OpenDocument archive")
             # Maybe XML document
             try:
                 mimetype = self.__get_xml_part('mimetype')
             except ValueError:
                 raise ValueError("bad OpenDocument format")
             self.__packaging = 'flat'
         if mimetype not in ODF_MIMETYPES:
             message = 'Document of unknown type "%s"' % mimetype
             raise ValueError(message)
         self.__parts = {'mimetype': mimetype}
Exemplo n.º 16
0
 def _do_backup(self, target):
     parts = target.split('.', 1)
     if len(parts) == 1:
         back_file = target + '.backup'
     else:
         back_file = parts[0] + '.backup.' + parts[1]
     if os.path.exists(target):
         if os.path.isdir(back_file):
             try:
                 shutil.rmtree(back_file)
             except Exception as e:
                 printwarn(str(e))
         try:
             shutil.move(target, back_file)
         except Exception as e:
             printwarn(str(e))
Exemplo n.º 17
0
def convert_literal_block(node, context):
    paragraph = odf_create_paragraph(style="Preformatted_20_Text")
    context['top'].append(paragraph)

    # Convert
    for child in node:
        # Only text
        if child.tagname != "#text":
            printwarn('node "%s" not supported in literal block' % (
                child.tagname))
            continue
        text = child.astext()

        tmp = []
        spaces = 0
        for c in text:
            if c == '\n':
                if tmp:
                    tmp = u"".join(tmp)
                    paragraph.append(tmp)
                    tmp = []
                spaces = 0
                paragraph.append(odf_create_line_break())
            elif c == '\r':
                continue
            elif c == ' ':
                spaces += 1
            elif c == '\t':
                # Tab = 4 spaces
                spaces += 4
            else:
                if spaces >= 2:
                    if tmp:
                        tmp = u"".join(tmp)
                        paragraph.append(tmp)
                        tmp = []
                    paragraph.append(' ')
                    paragraph.append(
                              odf_create_spaces(spaces - 1))
                    spaces = 0
                elif spaces == 1:
                    tmp.append(' ')
                    spaces = 0
                tmp.append(c)
        if tmp:
            tmp = u"".join(tmp)
            paragraph.append(tmp)
Exemplo n.º 18
0
def convert_table(node, context):
    cell_style = _get_cell_style(context).get_name()

    for tgroup in node:
        if tgroup.tagname != "tgroup":
            printwarn('node "%s" not supported in table' % tgroup.tagname)
            continue
        columns_number = 0
        odf_table = None
        for child in tgroup:
            tagname = child.tagname
            if tagname == "thead" or tagname == "tbody":
                # Create a new table with the info columns_number
                if odf_table is None:
                    context['tables_number'] += 1
                    # TODO Make it possible directly with odf_create_table
                    odf_table = odf_create_table(name="table%d" %
                                                 context['tables_number'])
                    columns = odf_create_column(repeated=columns_number)
                    odf_table.append(columns)
                # Convert!
                if tagname == "thead":
                    header = odf_create_header_rows()
                    odf_table.append(header)

                    _convert_table_rows(header,
                                        child,
                                        context,
                                        cell_style=cell_style)
                else:
                    _convert_table_rows(odf_table,
                                        child,
                                        context,
                                        cell_style=cell_style)
            elif tagname == "colspec":
                columns_number += 1
            else:
                printwarn('node "%s" not supported in tgroup' %
                          (child.tagname))
                continue

        context['top'].append(odf_table)
Exemplo n.º 19
0
def convert_figure(node, context):
    image = None
    caption = None
    width = None
    height = None

    for child in node:
        tagname = child.tagname
        if tagname == "image":
            if image is not None:
                printwarn("unexpected duplicate image in a figure")
                continue
            image = child.get("uri")
            width = child.get('width')
            height = child.get('height')
        elif tagname == "caption":
            if caption is not None:
                printwarn("unexpected duplicate caption in a figure")
                continue
            caption = child.astext()

    _add_image(image, caption, context, width=width, height=height)
Exemplo n.º 20
0
def convert_figure(node, context):
    image = None
    caption = None
    width = None
    height = None

    for child in node:
        tagname = child.tagname
        if tagname == "image":
            if image is not None:
                printwarn("unexpected duplicate image in a figure")
                continue
            image = child.get("uri")
            width = child.get('width')
            height = child.get('height')
        elif tagname == "caption":
            if caption is not None:
                printwarn("unexpected duplicate caption in a figure")
                continue
            caption = child.astext()

    _add_image(image, caption, context, width=width, height=height)
Exemplo n.º 21
0
def convert_table(node, context):
    cell_style = _get_cell_style(context).get_name()

    for tgroup in node:
        if tgroup.tagname != "tgroup":
            printwarn('node "%s" not supported in table' % tgroup.tagname)
            continue
        columns_number = 0
        odf_table = None
        for child in tgroup:
            tagname = child.tagname
            if tagname == "thead" or tagname == "tbody":
                # Create a new table with the info columns_number
                if odf_table is None:
                    context['tables_number'] += 1
                    # TODO Make it possible directly with odf_create_table
                    odf_table = odf_create_table(name="table%d" %
                                                 context['tables_number'])
                    columns = odf_create_column(repeated=columns_number)
                    odf_table.append(columns)
                # Convert!
                if tagname == "thead":
                    header = odf_create_header_rows()
                    odf_table.append(header)

                    _convert_table_rows(header, child, context,
                            cell_style=cell_style)
                else:
                    _convert_table_rows(odf_table, child, context,
                            cell_style=cell_style)
            elif tagname == "colspec":
                columns_number += 1
            else:
                printwarn('node "%s" not supported in tgroup' % (
                    child.tagname))
                continue

        context['top'].append(odf_table)
Exemplo n.º 22
0
def convert_footnote(node, context):
    # XXX ids is a list ??
    refid = node.get("ids")[0]

    # Find the footnote
    footnotes = context['footnotes']
    if refid not in footnotes:
        printwarn('unknown footnote "%s"' % refid)
        return
    footnote_body = footnotes[refid].get_element("text:note-body")

    # Save the current top
    old_top = context['top']

    # Fill the note
    context['top'] = footnote_body
    for child in node:
        # We skip the label (already added)
        if child.tagname == "label":
            continue
        convert_node(child, context)

    # And restore the top
    context['top'] = old_top
Exemplo n.º 23
0
def convert_footnote(node, context):
    # XXX ids is a list ??
    refid = node.get("ids")[0]

    # Find the footnote
    footnotes = context['footnotes']
    if refid not in footnotes:
        printwarn('unknown footnote "%s"' % refid)
        return
    footnote_body = footnotes[refid].get_element("text:note-body")

    # Save the current top
    old_top = context['top']

    # Fill the note
    context['top'] = footnote_body
    for child in node:
        # We skip the label (already added)
        if child.tagname == "label":
            continue
        convert_node(child, context)

    # And restore the top
    context['top'] = old_top
Exemplo n.º 24
0
    def __save_folder(self, folder):
        """Save a folder ODF from the available parts.
        """
        encoding = sys.getfilesystemencoding()

        def dump(path, content):
            try:
                path = path.decode(encoding)
            except:
                pass
            file_name = os.path.join(folder, path)
            dir_name = os.path.dirname(file_name)
            if not os.path.exists(dir_name):
                os.makedirs(dir_name, mode=0755)
            if path.endswith(u'/') : # folder
                if not os.path.isdir(file_name):
                    os.makedirs(file_name.encode(encoding), mode=0777)
            else:
                open(file_name.encode(encoding), 'wb', 0666).write(content)

        if isinstance(folder, basestring) and not isinstance(folder, unicode):
            folder = folder.decode(encoding)
        # Parts were loaded by "save"
        parts = self.__parts
        # Parts to save, except manifest at the end
        part_names = parts.keys()
        try:
            part_names.remove(ODF_MANIFEST)
        except KeyError:
            printwarn(u"missing '%s'" % ODF_MANIFEST)
        # "Pretty-save" parts in some order
        # mimetype requires to be first and uncompressed
        try:
            dump('mimetype', parts['mimetype'])
            part_names.remove('mimetype')
        except:
            printwarn("missing 'mimetype'")
        # XML parts
        for path in ODF_CONTENT, ODF_META, ODF_SETTINGS, ODF_STYLES:
            if path not in parts:
                printwarn("missing '%s'" % path)
                continue
            dump(path, parts[path])
            part_names.remove(path)
        # Everything else
        for path in part_names:
            data = parts[path]
            if data is None:
                # Deleted
                continue
            dump(path, data)
        # Manifest
        dump(ODF_MANIFEST, parts[ODF_MANIFEST])
Exemplo n.º 25
0
 def __save_zip(self, file):
     """Save a Zip ODF from the available parts.
     """
     # Parts were loaded by "save"
     parts = self.__parts
     compression = ZIP_DEFLATED
     try:
         filezip = ZipFile(file, 'w', compression=compression)
     except RuntimeError:
         # No zlib module
         compression = ZIP_STORED
         filezip = ZipFile(file, 'w', compression=compression)
     # Parts to save, except manifest at the end
     part_names = parts.keys()
     try:
         part_names.remove(ODF_MANIFEST)
     except KeyError:
         printwarn("missing '%s'" % ODF_MANIFEST)
     # "Pretty-save" parts in some order
     # mimetype requires to be first and uncompressed
     filezip.compression = ZIP_STORED
     try:
         filezip.writestr('mimetype', parts['mimetype'])
         filezip.compression = compression
         part_names.remove('mimetype')
     except:
         printwarn("missing 'mimetype'")
     # XML parts
     for path in ODF_CONTENT, ODF_META, ODF_SETTINGS, ODF_STYLES:
         if path not in parts:
             printwarn("missing '%s'" % path)
             continue
         filezip.writestr(path, parts[path])
         part_names.remove(path)
     # Everything else
     for path in part_names:
         data = parts[path]
         if data is None:
             # Deleted
             continue
         filezip.writestr(path, data)
     # Manifest
     filezip.writestr(ODF_MANIFEST, parts[ODF_MANIFEST])
     filezip.close()
Exemplo n.º 26
0
    def save(self, target=None, packaging=None, backup=False):
        """Save the container to the given target, a path or a file-like
        object.

        Package the output document in the same format than this document,
        unless "packaging" is different.

        Arguments:

            target -- str or file-like

            packaging -- 'zip' or 'flat', or for debugging purpose 'folder'

            backup -- boolean
        """
        if isinstance(target, basestring) and not isinstance(target, unicode):
            encoding = sys.getfilesystemencoding()
            target = target.decode(encoding)
        parts = self.__parts
        # Packaging
        if packaging is None:
            if self.__packaging:
                packaging = self.__packaging
            else:
                packaging = 'zip' # default
        packaging = packaging.strip().lower()
        if packaging not in ('zip', 'flat', 'folder'):
            raise ValueError('packaging type "%s" not supported' % packaging)
        # Load parts else they will be considered deleted
        for path in self.get_parts():
            if path not in parts:
                self.get_part(path)
        # Open output file
        close_after = False
        if target is None:
            target = self.path
        if isinstance(target, basestring):
            while target.endswith(os.sep):
                target = target[:-1]
            while target.endswith('.folder'):
                target = target.split('.folder', 1)[0]
        if packaging in ('zip', 'flat'):
            if isinstance(target, basestring):
                if backup:
                    self._do_backup(target)
                dest_file = open(target, 'wb')
                close_after = True
            else:
                dest_file = target
        if packaging == 'folder':
            if not isinstance(target, basestring):
                raise ValueError("Saving in folder format requires a folder "
                                 "name, not %s." % target)
            if not target.endswith('.folder'):
                target = target + '.folder'
            if backup:
                self._do_backup(target)
            else:
                if os.path.exists(target):
                    try:
                        shutil.rmtree(target)
                    except Exception as e:
                        printwarn(str(e))

            os.mkdir(target, 0777)
            dest_file = target
        # Serialize
        if packaging == 'zip':
            self.__save_zip(dest_file)
        elif packaging == 'flat':
            self.__save_xml(dest_file)
        else: # folder
            self.__save_folder(dest_file)
        # Close files we opened ourselves
        if close_after:
            dest_file.close()