Tag: RST

  • This probably exist but I couldn’t find it. I wanted to export a bunch of data from a Python/Django application into something a non-coder could understand. The data was not going to be a plain CSV, but a document, with various tables and explanations of what each table is. Because ReStructured Text seems to be the winning format in the Python world I decided to go with that.

    Generating the text part was easy and straightforward. The question was how to export tables. I decided to represent tables as lists of dicts and thus, I ended up building this little module:

    def dict_to_rst_table(data):
        field_names, column_widths = _get_fields(data)
        with StringIO() as output:
            output.write(_generate_header(field_names, column_widths))
            for row in data:
                output.write(_generate_row(row, field_names, column_widths))
            return output.getvalue()
    
    
    def _generate_header(field_names, column_widths):
        with StringIO() as output:
            for field_name in field_names:
                output.write(f"+-{'-' * column_widths[field_name]}-")
            output.write("+\n")
            for field_name in field_names:
                output.write(
                    f"| {field_name} {' ' * (column_widths[field_name] - len(field_name))}"
                )
            output.write("|\n")
            for field_name in field_names:
                output.write(f"+={'=' * column_widths[field_name]}=")
            output.write("+\n")
            return output.getvalue()
    
    
    def _generate_row(row, field_names, column_widths):
        with StringIO() as output:
            for field_name in field_names:
                output.write(
                    f"| {row[field_name]}{' ' * (column_widths[field_name] - len(str(row[field_name])))} "
                )
            output.write("|\n")
            for field_name in field_names:
                output.write(f"+-{'-' * column_widths[field_name]}-")
            output.write("+\n")
            return output.getvalue()
    
    
    def _get_fields(data):
        field_names = []
        column_widths = defaultdict(lambda: 0)
        for row in data:
            for field_name in row:
                if field_name not in field_names:
                    field_names.append(field_name)
                column_widths[field_name] = max(
                    column_widths[field_name], len(field_name), len(str(row[field_name]))
                )
    return field_names, column_widths

    It’s straightforward and simple. It currently cannot deal very well with cases in which dicts have different set of columns.

    Should this be turned into a reusable library?