Пример #1
0
    def insert(self):
        if DEBUG:
            print("Adding list...")

        list_data = self.section.contents
        if isinstance(list_data, dict) and len(list_data) != 1:
            list_data = [list_data]

        if isinstance(list_data, dict) and len(list_data) == 1:
            # Create the parent title
            wrapper_table = self.cell_object.cell.add_table(rows=2, cols=1)
            title_cell = wrapper_table.cell(0, 0)
            title_text = list(list_data.keys())[0]
            insert_text(title_cell, title_text,
                        self.style['title'])

            # Create a list in a list because this is a grouped list
            co = CellObject(wrapper_table.cell(1, 0))

            table_data = list_data[title_text]
            invoke(co,
                   Section('list', table_data, self.section.layout,
                           {}))
        else:
            table.invoke(self.cell_object,
                         Section('table', list_data,
                                 self.section.layout,
                                 {'list_style': True}))
Пример #2
0
    def insert(self) -> None:
        """
        This is a standing barchart (bar goes up)
        """
        if DEBUG:
            print("Adding a column chart!")

        # Fix sizing
        size_w, size_h, dpi = utils.convert_plt_size(self.section)
        plt.figure(figsize=(size_w, size_h), dpi=dpi)

        data = self.section.contents
        objects = [i['name'] for i in data]

        y_axis = [i for i in range(len(objects))]
        x_axis = [i['data'][0] for i in data]

        colors = get_colors(self.section.layout, objects)

        rects = plt.bar(y_axis,
                        x_axis,
                        align='center',
                        alpha=DEFAULT_BAR_ALPHA,
                        width=DEFAULT_BAR_WIDTH,
                        color=colors)

        ax = plt.gca()
        remove_plot_borders(ax)

        # Fix the legend values to be "some_value (some_number)" instead of
        # just "some_value"
        ledgend_keys = [
            CHART_LABEL_NONE_STRING if i == '' else i for i in objects
        ]
        fixed_legends = [
            f'{v} ({x_axis[i]})' for i, v in enumerate(ledgend_keys)
        ]

        # Move legend
        legend_location = 'upper center'
        legend_location_relative_to_graph = (0.5, -0.35)
        a = ax.legend(rects,
                      fixed_legends,
                      loc=legend_location,
                      bbox_to_anchor=legend_location_relative_to_graph,
                      handlelength=0.7)

        self.section = change_legend_vertical_alignment(self.section, top=3)
        set_legend_style(a, self.section.layout[LEGEND_STYLE])

        ax.set_xlim(-len(objects), len(objects))

        set_axis_font(ax)
        plt.xticks(y_axis, objects)
        plt.title(self.section.extra['title'], **self.style['title'])

        plt_b64 = utils.plt_t0_b64(plt)

        s = Section('image', plt_b64, {}, {'should_shrink': True})
        image.invoke(self.cell_object, s)
Пример #3
0
    def insert(self):
        if DEBUG:
            print('Adding md (external) image...')

        url = self.section.extra['src']
        image_data = image_contents_from_url(url)
        img_section = Section('image', image_data, {}, {})
        image.invoke(self.cell_object, img_section)
Пример #4
0
    def insert(self):
        if DEBUG:
            print("Adding table...")

        table_data = self.section.contents
        if 'tableColumns' not in self.section.layout:
            return

        if 'readableHeaders' in self.section.layout:
            ordered = self.section.layout['tableColumns']
            readable_headers = self.section.layout['readableHeaders'].values()
            table_columns = fix_order(ordered, readable_headers)
        else:
            table_columns = self.section.layout['tableColumns']

        for i, header_text in enumerate(table_columns):
            if not isinstance(header_text, str):
                table_columns.remove(header_text)

        if 'title' in self.section.extra:
            table = self.cell_object.cell.add_table(rows=2,
                                                    cols=len(table_columns))
            title = table.cell(0, 0)
            title.merge(table.cell(0, len(table_columns) - 1))
            insert_text(title, self.section.extra['title'],
                        self.style['title'])

            hdr_cells = table.rows[1].cells
        else:
            table = self.cell_object.cell.add_table(rows=2,
                                                    cols=len(table_columns))
            hdr_cells = table.rows[0].cells

        table.style = DEFAULT_TABLE_STYLE

        if 'list_style' in self.section.extra and self.section.extra[
                'list_style']:
            table.style = None

        for i, header_text in enumerate(table_columns):
            insert_text(hdr_cells[i], header_text, self.style['text'])

        for r in table_data:
            row_cells = table.add_row().cells
            for i, header_text in enumerate(table_columns):
                if header_text not in r:
                    continue

                # Old json format can have 'Avatars', which are images
                if isinstance(r[header_text], dict) and \
                        r[header_text]['type'] == 'image':
                    row_temp = r[header_text]
                    s = Section(row_temp['type'], row_temp['data'], {}, {})
                    co = CellObject(row_cells[i], add_run=False)
                    image.invoke(co, s)
                else:
                    insert_text(row_cells[i], r[header_text],
                                self.style['text'])
Пример #5
0
    def _insert_section(cell_object: CellObject, section: Section) -> None:
        section_type = section.type

        # Fix the chart name
        if section_type == 'chart':
            section_type = section.layout['chartType'] + '_chart'
            section.type = section_type

        insert_by_type(section_type, cell_object, section)
Пример #6
0
def invoke(cell_object: CellObject,
           section: Section,
           invoked_from_wrapper=False):
    if section.type != 'markdown':
        section.contents = f'Called markdown but not markdown -  [{section}]'
        return error.invoke(cell_object, section)

    MarkdownWrapper(cell_object,
                    section).wrap(invoked_from_wrapper=invoked_from_wrapper)
Пример #7
0
    def add_header_logos(self):
        # Find the headers
        section = self.document.sections[0]
        section.header_distance = Pt(0)
        header = section.header
        table = header.add_table(rows=1, cols=2, width=Inches(24))
        table.alignment = WD_TABLE_ALIGNMENT.CENTER
        table.autofit = True

        left_cell = table.cell(0, 0)
        right_cell = table.cell(0, 1)

        # Add the left cell to the header
        left_image = CellObject(left_cell)
        left_cell.paragraphs[-1].alignment = WD_PARAGRAPH_ALIGNMENT.LEFT
        left_cell.vertical_alignment = 1

        # Add the right cell to the header
        right_image = CellObject(right_cell)
        right_cell.paragraphs[-1].alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
        right_cell.vertical_alignment = 1

        # Add the main logo
        left_logo_b64 = self.options.get('demistoLogo', XSOAR_LOGO_BASE64)
        s = Section('image', left_logo_b64, {}, {})
        image.invoke(left_image, s)

        # Add the customer logo
        right_logo_b64 = self.options.get('customerLogo', False)
        if right_logo_b64:
            s = Section(
                'image',
                right_logo_b64,
                {},
                {
                    'max_size': {
                        'height':
                        MAX_CUSTOMER_LOGO_HEIGHT_INCH,  # max size in inches
                        'width': MAX_CUSTOMER_LOGO_WIDTH_INCH
                    }
                })
            image.invoke(right_image, s)
Пример #8
0
def insert_header(cell_object: Union[CellObject, _Cell],
                  section: Union[str, Section],
                  style={}, add_run=False, header='h1'):

    if isinstance(section, str):
        section = Section('header', section, {}, {})
        section.set_style(style)

    section.extra = {**{'header_tag': header}, **section.extra}
    section.add_style(style)
    insert_elem(cell_object, section, add_run)
Пример #9
0
def insert_text(cell_object: Union[CellObject, _Cell],
                section: Union[str, Section],
                style={}, add_run=False):

    if isinstance(section, str):
        section = Section('text', section, {}, {})
        section.set_style(style)

    section.type = 'text'
    section.add_style(style)
    insert_elem(cell_object, section, add_run)
Пример #10
0
    def _insert_section(self, cell_object: CellObject,
                        section: Section) -> None:
        section_type = section.type

        # Fix the chart name
        if section_type == 'chart':
            section_type = section.layout['chartType'] + '_chart'
            section.type = section_type

        insert_by_type(section_type,
                       cell_object,
                       section,
                       trace=self.options.get('trace', False))
Пример #11
0
def _apply_cell_styling(cell_object: CellObject, section: Section):
    style = section.get_style()

    # Font size
    if PYDOCX_FONT_SIZE in style:
        cell_object.run.font.size = Pt(style[PYDOCX_FONT_SIZE])

    # Set default font
    cell_object.run.font.name = DEFAULT_WORD_FONT

    # Font family
    if PYDOCX_FONT in style:
        cell_object.run.font.name = style[PYDOCX_FONT]

    # Other characteristics
    if PYDOCX_FONT_BOLD in style:
        cell_object.run.font.bold = style[PYDOCX_FONT_BOLD]
    if PYDOCX_FONT_STRIKE in style:
        cell_object.run.font.strike = style[PYDOCX_FONT_STRIKE]
    if PYDOCX_FONT_UNDERLINE in style:
        cell_object.run.font.underline = style[PYDOCX_FONT_UNDERLINE]
    if PYDOCX_FONT_ITALIC in style:
        cell_object.run.font.italic = style[PYDOCX_FONT_ITALIC]

    # Font color
    if PYDOCX_FONT_COLOR in style:
        if style[PYDOCX_FONT_COLOR][0] != '#':
            cell_object.run.font.color.rgb = name_to_rgb(
                style[PYDOCX_FONT_COLOR])
        else:
            cell_object.run.font.color.rgb = hex_to_rgb(
                style[PYDOCX_FONT_COLOR])

    # Background color
    if 'backgroundColor' in style:
        cell_object.cell = insert_cell_background(
            cell_object.cell, style[PYDOCX_BACKGROUND_COLOR])

    # Paragraph styling
    if PYDOCX_TEXT_ALIGN in style:
        if style[PYDOCX_TEXT_ALIGN] == 'left':
            cell_object.paragraph.paragraph_format.alignment = ALIGN_LEFT
        elif style[PYDOCX_TEXT_ALIGN] == 'right':
            cell_object.paragraph.paragraph_format.alignment = ALIGN_RIGHT
        elif style[PYDOCX_TEXT_ALIGN] == 'center':
            cell_object.paragraph.paragraph_format.alignment = ALIGN_CENTER
        elif style[PYDOCX_TEXT_ALIGN] in [
                ALIGN_RIGHT, ALIGN_CENTER, ALIGN_CENTER
        ]:
            cell_object.paragraph.paragraph_format.alignment = int(
                style[PYDOCX_TEXT_ALIGN])
Пример #12
0
def test_error():
    """
        To check the xpath: rename the .elements to .zip and
         open word/document.xml
    """

    d = Document()
    t = d.add_table(1, 1)
    test_section = Section('tedxt', "some contents", {}, {})
    c = CellObject(t.cell(0, 0))

    # This will invoke an error element because of the wrong type:
    text.invoke(c, test_section)

    assert len(d.element.xpath('//w:p')) == 3

    # Styles or error
    assert len(d.element.xpath('//w:i[@w:val="0"]')) == 1
    assert len(d.element.xpath('//w:strike[@w:val="0"]')) == 1
    assert len(d.element.xpath('//w:color[@w:val="FF0013"]')) == 1
    assert len(d.element.xpath('//w:sz[@w:val="20"]')) == 1
    assert len(d.element.xpath('//w:u[@w:val="none"]')) == 1
Пример #13
0
    def insert(self):
        if DEBUG:
            print('Adding pie chart: ...')
        size_w, size_h, dpi = utils.convert_plt_size(self.section)
        fig, ax = plt.subplots(figsize=(size_w, size_h), dpi=dpi,
                               subplot_kw=dict(aspect="equal"))

        data = [int(i['data'][0]) for i in self.section.contents]
        objects = [i['name'] for i in self.section.contents]

        # Fix the unassigned key:
        objects = [i if i != "" else "Unassigned" for i in objects]

        # Generate the default colors
        colors = get_colors(self.section.layout, objects)
        unassigned_color = 'darkgrey'

        # If we have predefined colors, use them
        if 'legend' in self.section.layout and self.section.layout['legend']:
            for i in self.section.layout['legend']:
                if 'color' in i:
                    colors.append(i['color'])
                elif 'fill' in i:
                    colors.append(i['fill'])

        color_keys = {}
        for i, k in enumerate(objects):
            color_keys[k] = colors[i]
            if k == 'Unassigned':
                color_keys['Unassigned'] = unassigned_color

        final_colors = [color_keys[k] for k in objects]

        wedges, texts = ax.pie(data,
                               colors=final_colors,
                               startangle=90, pctdistance=0.85,
                               textprops=dict(color="w"), radius=1)

        keys_with_numbers = ['{}: {}'.format(k, data[i]) for i, k in
                             enumerate(objects)]

        # legend_location_relative_to_graph = (1, 0, 0.5, 1)
        # legend_location = self.section.layout['legendStyle']
        legend_location = 'upper center'
        legend_location_relative_to_graph = (0.5, 0)

        legend = ax.legend(wedges, keys_with_numbers,
                           title="",
                           loc=legend_location,
                           bbox_to_anchor=legend_location_relative_to_graph,
                           handlelength=0.7
                           )
        set_legend_style(legend, self.section.layout[LEGEND_STYLE])
        set_axis_font(ax)
        ax.set_title(self.section.extra['title'], **self.style['title'])
        circle = plt.Circle((0, 0), 0.7, fc='white')
        ax.add_artist(circle)

        plt_b64 = utils.plt_t0_b64(plt)

        s = Section('image', plt_b64, {}, {'should_shrink': True})
        image.invoke(self.cell_object, s)
Пример #14
0
def insert_table_image(item, item_key, insertion_cell):
    row_temp = item[item_key]
    s = Section(row_temp['type'], row_temp['data'], {}, {})
    co = CellObject(insertion_cell, add_run=False)
    image.invoke(co, s)
Пример #15
0
    def insert(self):
        """
            This is a bar chart on the side (bar goes right)
        """

        if DEBUG:
            print("Adding a bar chart")

        # Fix sizing
        size_w, size_h, dpi = utils.convert_plt_size(self.section,
                                                     self.cell_object)
        plt.figure(figsize=(size_w, size_h), dpi=dpi)

        data = self.section.contents
        x_axis = None

        if any([True for i in data if 'groups' in i and i['groups']]):
            # Note for future maintainer, I really really... hate stacked
            # bar charts, it made this file look like hell. I hope you cope
            # with matplotlib's shitt* implementation.
            # May the force be with you :pray:

            # Create the stacks
            agg = []
            y_axis = [i['name'] for i in data]
            max_labels_stacked = []
            for v in data:
                names = [i['name'] for i in v['groups']]
                max_labels_stacked = list(set(max_labels_stacked) | set(names))

            labels = sorted(max_labels_stacked)
            colors = get_colors(self.section.layout, labels)

            for v in data:
                current_labels = {i['name']: i['data'][0] for i in v['groups']}
                cols = []
                for l in labels:
                    if l in current_labels:
                        cols.append(current_labels[l])
                    else:
                        cols.append(0)
                agg.append(cols)

            stacked = [i for i in zip(*agg)]

            # Draw each stack
            rects = [
                plt.barh(y_axis,
                         stacked[0],
                         DEFAULT_BAR_WIDTH,
                         color=colors.pop(0))
            ]

            for i in range(1, len(stacked)):
                left_padding = [sum(i) for i in zip(*stacked[:i])]
                rects.append(
                    plt.barh(y_axis,
                             stacked[i],
                             DEFAULT_BAR_WIDTH,
                             left=left_padding,
                             color=colors.pop(0)))

            ax = plt.gca()
            legend_location = 'upper center'
            legend_location_relative_to_graph = (0.5, -0.35)
            a = ax.legend(rects,
                          labels,
                          loc=legend_location,
                          bbox_to_anchor=legend_location_relative_to_graph,
                          handlelength=0.7)

        else:
            objects = [i['name'] for i in data]
            colors = get_colors(self.section.layout, objects)

            y_axis = [i for i in range(len(objects))]
            x_axis = [i['data'][0] for i in data]

            # Fix height of bar when only one present
            if len(objects) == 1:
                plt.margins(y=2)

            rects = plt.barh(y_axis,
                             width=x_axis,
                             align='center',
                             alpha=DEFAULT_BAR_ALPHA,
                             color=colors,
                             height=DEFAULT_BAR_WIDTH)

            # Fix the legend values to be "some_value (some_number)" instead of
            # just "some_value"
            ledgend_keys = [
                CHART_LABEL_NONE_STRING if i == '' else i for i in objects
            ]
            fixed_legends = [
                f'{v} ({x_axis[i]})' for i, v in enumerate(ledgend_keys)
            ]

            # Create and move the legend outside
            ax = plt.gca()
            legend_location = 'upper center'
            legend_location_relative_to_graph = (0.5, -0.35)

            a = ax.legend(rects,
                          fixed_legends,
                          loc=legend_location,
                          bbox_to_anchor=legend_location_relative_to_graph,
                          handlelength=0.7)

            ax.set_yticklabels([])

        # Style the axis and labels
        self.section = change_legend_vertical_alignment(self.section, top=1)
        set_legend_style(a, self.section.layout[LEGEND_STYLE])

        # Fix the axises
        set_axis_font(ax)
        ax.set_yticks(y_axis)
        ax.set_xlabel('')
        ax.invert_yaxis()  # labels read top-to-bottom

        # Fix the xaxis ratio to fit biggest element
        if x_axis:
            ax.set_xlim(0, max(x_axis) + X_AXIS_PADDING)

        # Remove the bottom labels
        remove_plot_borders(ax)
        plt.tick_params(bottom='off')
        plt.title(self.section.extra['title'], **self.style['title'])

        plt_b64 = utils.plt_t0_b64(plt, (size_w, size_h), dpi)

        s = Section('image', plt_b64, {}, {'should_shrink': True})
        image.invoke(self.cell_object, s)
Пример #16
0
    def wrap(self, invoked_from_wrapper=False):
        # Handle called from another wrapper.
        md_section_list = None
        if isinstance(self.section.contents, list):
            md_section_list = self.section.contents

        elif invoked_from_wrapper and \
                isinstance(self.section.contents.contents, str):
            md_section_list = [self.section.contents]

        if not isinstance(md_section_list, list):
            raise ValueError('Markdown section does not have valid contents ' +
                             '(must be a list)')

        for section in md_section_list:
            # === Start wrappers ===
            if section.type == MD_TYPE_DIV:
                temp_section = MarkdownSection('markdown', section.contents,
                                               {}, {})
                invoke(self.cell_object, temp_section)
                continue

            if section.type == MD_TYPE_CODE:
                md_code.invoke(self.cell_object, section)
                self.cell_object.update_paragraph()
                continue

            if section.type == MD_TYPE_QUOTE:
                md_blockquote.invoke(self.cell_object, section)
                self.cell_object.update_paragraph()
                continue

            if section.type == MD_TYPE_UNORDERED_LIST:
                md_ul.invoke(self.cell_object, section)
                self.cell_object.update_paragraph()
                continue

            if section.type == MD_TYPE_ORDERED_LIST:
                md_ol.invoke(self.cell_object, section)
                self.cell_object.update_paragraph()
                continue

            if section.type == MD_TYPE_LIST_ITEM:
                md_li.invoke(self.cell_object, section)
                continue

            if section.type == MD_TYPE_TABLE:
                table_html = section.extra['original_html']
                t = PyQuery(table_html)
                headers = [i.find('th') for i in t.find('tr').items()][0]
                headers = [c.text() for c in headers.items()]

                rows = [
                    i.find('td') for i in t.find('tr').items() if i.find('td')
                ]
                data = []
                for row in rows:
                    r = {
                        headers[i]: c.text()
                        for i, c in enumerate(row.items())
                    }
                    data.append(r)
                s = Section("table", data, {"tableColumns": headers}, {})
                table.invoke(self.cell_object, s)
                continue

            # Fix wrapped:
            #   (Some times there are elements which contain other elements,
            #    but are not considered one of the declared wrappers)
            if isinstance(section.contents, list):
                is_inside_wrapper = False

                if 'inline' in section.extra:
                    is_inside_wrapper = True

                if section.type == 'span':
                    section.propagate_extra('check_newline',
                                            True,
                                            only_multiple_children=False)

                # TODO: Fix problem with H1 no newline even if in span.
                temp_section = MarkdownSection('markdown', section.contents,
                                               {}, section.extra,
                                               section.attrs)
                invoke(self.cell_object,
                       temp_section,
                       invoked_from_wrapper=is_inside_wrapper)
                continue

            # === Elements ===

            if section.type in SHOULD_NEW_LINE and section.get_extra(
                    'check_newline'):
                self.cell_object.add_paragraph()

            if section.type == MD_TYPE_HORIZONTAL_LINE:
                md_hr.invoke(self.cell_object, section)
                continue

            # Add a block (newline) if not called from a wrapper
            #  (Should come after hr)
            if not invoked_from_wrapper:
                self.cell_object.add_paragraph()

            if section.type in MD_TYPES_HEADERS:
                # We want to keep the h{1...6} for styling
                insert_header(self.cell_object,
                              section.contents,
                              header=section.type)

                continue

            if section.type in [MD_TYPE_TEXT, MD_TYPE_INLINE_TEXT]:
                if invoked_from_wrapper:
                    self.cell_object.add_run()

                insert_text(self.cell_object, section)
                continue

            if section.type == MD_TYPE_LINK:
                md_link.invoke(self.cell_object, section)
                continue

            if section.type == MD_TYPE_IMAGE:
                md_image.invoke(self.cell_object, section)
                continue

            raise ValueError(f'Section type is not defined: {section.type}')
Пример #17
0
    def insert(self):
        if DEBUG:
            print("Adding line chart...")

            # Fix sizing
        size_w, size_h, dpi = utils.convert_plt_size(self.section,
                                                     self.cell_object)
        figure(num=2, figsize=(size_w, size_h), dpi=dpi,
               constrained_layout=False)

        data = self.section.contents

        fix_data(data)

        # Make the groups look like:
        # groups = {
        #   'Type A': {
        #       dates: ['2000', '2001', '2002']
        #       values: ['1', '2', '3']
        #    }
        #   'Type B': {
        #         dates: ['2000', '2001', '2002'],
        #         values : ['4', '5', '6']
        # }
        groups = fix_data(data)

        # Fix empty key
        if '' in groups.keys():
            groups['None'] = groups.pop('')

        # Generate the default colors
        colors = get_colors(self.section.layout, groups.keys())
        unassigned_color = 'darkgrey'

        # If we have predefined colors, use them
        if 'legend' in self.section.layout and self.section.layout['legend']:
            for i in self.section.layout['legend']:
                if 'color' in i:
                    colors.append(i['color'])
                elif 'fill' in i:
                    colors.append(i['fill'])

        color_keys = {}
        for i, k in enumerate(groups.keys()):
            color_keys[k] = colors[i]
            if k == 'Unassigned':
                color_keys['Unassigned'] = unassigned_color

        final_colors = {k: color_keys[k] for k in groups.keys()}

        # Plot the lines
        for group, line in groups.items():
            x_axis = line['dates']
            y_axis = line['values']
            plt.plot(x_axis, y_axis, marker='', color=final_colors[group],
                     linewidth=2)

        # Create and move the legend outside
        ax = plt.gca()

        # Auto rotate the labels
        remove_plot_borders(ax)
        legend_location = 'upper center'
        legend_location_relative_to_graph = (0.5, -0.35)

        handles = [plt.Rectangle((0, 0), 1, 1, fc=final_colors[i]) for i in
                   groups.keys()]

        legend = ax.legend(handles, [i for i in groups.keys()],
                           loc=legend_location,
                           bbox_to_anchor=legend_location_relative_to_graph,
                           handlelength=0.7, handleheight=0.7, ncol=2)

        self.section = change_legend_vertical_alignment(self.section, top=1)

        # Set max ticks in xaxis to be MAX_AXIS_LABELS
        set_legend_max_count(ax, self.cell_object)

        set_legend_style(legend, self.section.layout[LEGEND_STYLE])
        set_axis_font(ax)
        ax.set_title(self.section.extra['title'], **self.style['title'])

        # Add to docx as image
        plt_b64 = utils.plt_t0_b64(plt, (size_w, size_h), dpi)
        s = Section('image', plt_b64, {}, {'should_shrink': True})
        image.invoke(self.cell_object, s)
Пример #18
0
    def insert(self):
        if DEBUG:
            print("Adding table...")

        table_data = self.section.contents

        if isinstance(table_data, dict):
            table_data = table_data.get('data', table_data)

        if 'tableColumns' not in self.section.layout:
            # Quick dirty fix for test - will be refactored in upcoming PR
            self.section.layout['tableColumns'] = list(table_data[0].keys())

        # Fix new lists
        if isinstance(table_data, dict):
            wrapper_table = self.cell_object.cell.add_table(
                rows=2, cols=len(table_data.keys()))
            i = 0

            # Add the wrapping headers
            for wrapper_header, table_contents in table_data.items():
                hdr = wrapper_table.cell(0, i)
                insert_text(hdr, wrapper_header, self.style['title'])
                body = wrapper_table.cell(1, i)
                c = CellObject(body)
                # Hacky but will do the job
                invoke(c, Section('table', table_contents, {}, {}))
                i += 1
            return

        if 'readableHeaders' in self.section.layout:
            ordered = self.section.layout['tableColumns']
            readable_headers = self.section.layout['readableHeaders']
            table_columns = fix_order(ordered, readable_headers)
        else:
            table_columns = self.section.layout['tableColumns']

        # Quick fix, word crashes on more than 64 columns.
        # See: https://stackoverflow.com/questions/36921010/docx-does-not-support-more-than-63-columns-in-a-table
        table_columns = table_columns[0:63]

        for i, header_text in enumerate(table_columns):
            if not isinstance(header_text, str):
                table_columns.remove(header_text)

        if 'title' in self.section.extra:
            table = self.cell_object.cell.add_table(rows=2,
                                                    cols=len(table_columns))
            title = table.cell(0, 0)
            title.merge(table.cell(0, len(table_columns) - 1))
            insert_text(title, self.section.extra['title'],
                        self.style['title'])

            hdr_cells = table.rows[1].cells
        else:
            table = self.cell_object.cell.add_table(rows=2,
                                                    cols=len(table_columns))
            hdr_cells = table.rows[0].cells

        table.style = DEFAULT_TABLE_STYLE

        if 'list_style' in self.section.extra and self.section.extra[
                'list_style']:
            table.style = None

        for i, header_text in enumerate(table_columns):
            insert_text(hdr_cells[i], header_text, self.style['text'])

        if len(table_columns) > 63:
            # TODO: add error.
            pass

        for r in table_data:
            row_cells = table.add_row().cells
            for i, header_text in enumerate(table_columns):
                if header_text not in r:
                    continue

                # Old json format can have 'Avatars', which are images
                if isinstance(r[header_text], dict) and \
                        r[header_text]['type'] == 'image':
                    row_temp = r[header_text]
                    s = Section(row_temp['type'], row_temp['data'], {}, {})
                    co = CellObject(row_cells[i], add_run=False)
                    image.invoke(co, s)
                else:
                    insert_text(row_cells[i], r[header_text],
                                self.style['text'])
Пример #19
0
def _attach_all_styles(section: Section, base_style: dict) -> Section:
    attribute_styles = {k: True for k in section.attrs}

    section.add_style(base_style, is_new=False)
    section.add_style(attribute_styles)
    return section