From 9ce7460ef44df9374df004c27caa1eb05885dfa1 Mon Sep 17 00:00:00 2001 From: "Roland C. Dowdeswell" Date: Mon, 4 Mar 2024 11:09:26 +0000 Subject: [PATCH 1/4] Provide TableFormat defaults --- tabulate/__init__.py | 113 +++++-------------------------------------- 1 file changed, 11 insertions(+), 102 deletions(-) diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 11bb8655..602c7d0d 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -98,7 +98,16 @@ def _is_file(f): "datarow", "padding", "with_header_hide", - ], + ], defaults = ( + None, + None, + None, + None, + DataRow("", " ", ""), + DataRow("", " ", ""), + 0, + None, + ), ) @@ -315,21 +324,9 @@ def escape_empty(val): linebelowheader=Line("", "-", " ", ""), linebetweenrows=None, linebelow=Line("", "-", " ", ""), - headerrow=DataRow("", " ", ""), - datarow=DataRow("", " ", ""), - padding=0, with_header_hide=["lineabove", "linebelow"], ), - "plain": TableFormat( - lineabove=None, - linebelowheader=None, - linebetweenrows=None, - linebelow=None, - headerrow=DataRow("", " ", ""), - datarow=DataRow("", " ", ""), - padding=0, - with_header_hide=None, - ), + "plain": TableFormat(), "grid": TableFormat( lineabove=Line("+", "-", "+", "+"), linebelowheader=Line("+", "=", "+", "+"), @@ -338,7 +335,6 @@ def escape_empty(val): headerrow=DataRow("|", "|", "|"), datarow=DataRow("|", "|", "|"), padding=1, - with_header_hide=None, ), "simple_grid": TableFormat( lineabove=Line("┌", "─", "┬", "┐"), @@ -348,7 +344,6 @@ def escape_empty(val): headerrow=DataRow("│", "│", "│"), datarow=DataRow("│", "│", "│"), padding=1, - with_header_hide=None, ), "rounded_grid": TableFormat( lineabove=Line("╭", "─", "┬", "╮"), @@ -358,7 +353,6 @@ def escape_empty(val): headerrow=DataRow("│", "│", "│"), datarow=DataRow("│", "│", "│"), padding=1, - with_header_hide=None, ), "heavy_grid": TableFormat( lineabove=Line("┏", "━", "┳", "┓"), @@ -368,7 +362,6 @@ def escape_empty(val): headerrow=DataRow("┃", "┃", "┃"), datarow=DataRow("┃", "┃", "┃"), padding=1, - with_header_hide=None, ), "mixed_grid": TableFormat( lineabove=Line("┍", "━", "┯", "┑"), @@ -378,7 +371,6 @@ def escape_empty(val): headerrow=DataRow("│", "│", "│"), datarow=DataRow("│", "│", "│"), padding=1, - with_header_hide=None, ), "double_grid": TableFormat( lineabove=Line("╔", "═", "╦", "╗"), @@ -388,7 +380,6 @@ def escape_empty(val): headerrow=DataRow("║", "║", "║"), datarow=DataRow("║", "║", "║"), padding=1, - with_header_hide=None, ), "fancy_grid": TableFormat( lineabove=Line("╒", "═", "╤", "╕"), @@ -398,83 +389,66 @@ def escape_empty(val): headerrow=DataRow("│", "│", "│"), datarow=DataRow("│", "│", "│"), padding=1, - with_header_hide=None, ), "outline": TableFormat( lineabove=Line("+", "-", "+", "+"), linebelowheader=Line("+", "=", "+", "+"), - linebetweenrows=None, linebelow=Line("+", "-", "+", "+"), headerrow=DataRow("|", "|", "|"), datarow=DataRow("|", "|", "|"), padding=1, - with_header_hide=None, ), "simple_outline": TableFormat( lineabove=Line("┌", "─", "┬", "┐"), linebelowheader=Line("├", "─", "┼", "┤"), - linebetweenrows=None, linebelow=Line("└", "─", "┴", "┘"), headerrow=DataRow("│", "│", "│"), datarow=DataRow("│", "│", "│"), padding=1, - with_header_hide=None, ), "rounded_outline": TableFormat( lineabove=Line("╭", "─", "┬", "╮"), linebelowheader=Line("├", "─", "┼", "┤"), - linebetweenrows=None, linebelow=Line("╰", "─", "┴", "╯"), headerrow=DataRow("│", "│", "│"), datarow=DataRow("│", "│", "│"), padding=1, - with_header_hide=None, ), "heavy_outline": TableFormat( lineabove=Line("┏", "━", "┳", "┓"), linebelowheader=Line("┣", "━", "╋", "┫"), - linebetweenrows=None, linebelow=Line("┗", "━", "┻", "┛"), headerrow=DataRow("┃", "┃", "┃"), datarow=DataRow("┃", "┃", "┃"), padding=1, - with_header_hide=None, ), "mixed_outline": TableFormat( lineabove=Line("┍", "━", "┯", "┑"), linebelowheader=Line("┝", "━", "┿", "┥"), - linebetweenrows=None, linebelow=Line("┕", "━", "┷", "┙"), headerrow=DataRow("│", "│", "│"), datarow=DataRow("│", "│", "│"), padding=1, - with_header_hide=None, ), "double_outline": TableFormat( lineabove=Line("╔", "═", "╦", "╗"), linebelowheader=Line("╠", "═", "╬", "╣"), - linebetweenrows=None, linebelow=Line("╚", "═", "╩", "╝"), headerrow=DataRow("║", "║", "║"), datarow=DataRow("║", "║", "║"), padding=1, - with_header_hide=None, ), "fancy_outline": TableFormat( lineabove=Line("╒", "═", "╤", "╕"), linebelowheader=Line("╞", "═", "╪", "╡"), - linebetweenrows=None, linebelow=Line("╘", "═", "╧", "╛"), headerrow=DataRow("│", "│", "│"), datarow=DataRow("│", "│", "│"), padding=1, - with_header_hide=None, ), "github": TableFormat( lineabove=Line("|", "-", "|", "|"), linebelowheader=Line("|", "-", "|", "|"), - linebetweenrows=None, - linebelow=None, headerrow=DataRow("|", "|", "|"), datarow=DataRow("|", "|", "|"), padding=1, @@ -483,72 +457,50 @@ def escape_empty(val): "pipe": TableFormat( lineabove=_pipe_line_with_colons, linebelowheader=_pipe_line_with_colons, - linebetweenrows=None, - linebelow=None, headerrow=DataRow("|", "|", "|"), datarow=DataRow("|", "|", "|"), padding=1, with_header_hide=["lineabove"], ), "orgtbl": TableFormat( - lineabove=None, linebelowheader=Line("|", "-", "+", "|"), - linebetweenrows=None, - linebelow=None, headerrow=DataRow("|", "|", "|"), datarow=DataRow("|", "|", "|"), padding=1, - with_header_hide=None, ), "jira": TableFormat( - lineabove=None, - linebelowheader=None, - linebetweenrows=None, - linebelow=None, headerrow=DataRow("||", "||", "||"), datarow=DataRow("|", "|", "|"), padding=1, - with_header_hide=None, ), "presto": TableFormat( - lineabove=None, linebelowheader=Line("", "-", "+", ""), - linebetweenrows=None, - linebelow=None, headerrow=DataRow("", "|", ""), datarow=DataRow("", "|", ""), padding=1, - with_header_hide=None, ), "pretty": TableFormat( lineabove=Line("+", "-", "+", "+"), linebelowheader=Line("+", "-", "+", "+"), - linebetweenrows=None, linebelow=Line("+", "-", "+", "+"), headerrow=DataRow("|", "|", "|"), datarow=DataRow("|", "|", "|"), padding=1, - with_header_hide=None, ), "psql": TableFormat( lineabove=Line("+", "-", "+", "+"), linebelowheader=Line("|", "-", "+", "|"), - linebetweenrows=None, linebelow=Line("+", "-", "+", "+"), headerrow=DataRow("|", "|", "|"), datarow=DataRow("|", "|", "|"), padding=1, - with_header_hide=None, ), "rst": TableFormat( lineabove=Line("", "=", " ", ""), linebelowheader=Line("", "=", " ", ""), - linebetweenrows=None, linebelow=Line("", "=", " ", ""), headerrow=DataRow("", " ", ""), datarow=DataRow("", " ", ""), - padding=0, - with_header_hide=None, ), "mediawiki": TableFormat( lineabove=Line( @@ -562,113 +514,76 @@ def escape_empty(val): linebelow=Line("|}", "", "", ""), headerrow=partial(_mediawiki_row_with_attrs, "!"), datarow=partial(_mediawiki_row_with_attrs, "|"), - padding=0, - with_header_hide=None, ), "moinmoin": TableFormat( - lineabove=None, - linebelowheader=None, - linebetweenrows=None, - linebelow=None, headerrow=partial(_moin_row_with_attrs, "||", header="'''"), datarow=partial(_moin_row_with_attrs, "||"), padding=1, - with_header_hide=None, ), "youtrack": TableFormat( - lineabove=None, - linebelowheader=None, - linebetweenrows=None, - linebelow=None, headerrow=DataRow("|| ", " || ", " || "), datarow=DataRow("| ", " | ", " |"), padding=1, - with_header_hide=None, ), "html": TableFormat( lineabove=_html_begin_table_without_header, linebelowheader="", - linebetweenrows=None, linebelow=Line("\n", "", "", ""), headerrow=partial(_html_row_with_attrs, "th", False), datarow=partial(_html_row_with_attrs, "td", False), - padding=0, with_header_hide=["lineabove"], ), "unsafehtml": TableFormat( lineabove=_html_begin_table_without_header, linebelowheader="", - linebetweenrows=None, linebelow=Line("\n", "", "", ""), headerrow=partial(_html_row_with_attrs, "th", True), datarow=partial(_html_row_with_attrs, "td", True), - padding=0, with_header_hide=["lineabove"], ), "latex": TableFormat( lineabove=_latex_line_begin_tabular, linebelowheader=Line("\\hline", "", "", ""), - linebetweenrows=None, linebelow=Line("\\hline\n\\end{tabular}", "", "", ""), headerrow=_latex_row, datarow=_latex_row, padding=1, - with_header_hide=None, ), "latex_raw": TableFormat( lineabove=_latex_line_begin_tabular, linebelowheader=Line("\\hline", "", "", ""), - linebetweenrows=None, linebelow=Line("\\hline\n\\end{tabular}", "", "", ""), headerrow=partial(_latex_row, escrules={}), datarow=partial(_latex_row, escrules={}), padding=1, - with_header_hide=None, ), "latex_booktabs": TableFormat( lineabove=partial(_latex_line_begin_tabular, booktabs=True), linebelowheader=Line("\\midrule", "", "", ""), - linebetweenrows=None, linebelow=Line("\\bottomrule\n\\end{tabular}", "", "", ""), headerrow=_latex_row, datarow=_latex_row, padding=1, - with_header_hide=None, ), "latex_longtable": TableFormat( lineabove=partial(_latex_line_begin_tabular, longtable=True), linebelowheader=Line("\\hline\n\\endhead", "", "", ""), - linebetweenrows=None, linebelow=Line("\\hline\n\\end{longtable}", "", "", ""), headerrow=_latex_row, datarow=_latex_row, padding=1, - with_header_hide=None, ), "tsv": TableFormat( - lineabove=None, - linebelowheader=None, - linebetweenrows=None, - linebelow=None, headerrow=DataRow("", "\t", ""), datarow=DataRow("", "\t", ""), - padding=0, - with_header_hide=None, ), "textile": TableFormat( - lineabove=None, - linebelowheader=None, - linebetweenrows=None, - linebelow=None, headerrow=DataRow("|_. ", "|_.", "|"), datarow=_textile_row_with_attrs, padding=1, - with_header_hide=None, ), "asciidoc": TableFormat( lineabove=partial(_asciidoc_row, False), - linebelowheader=None, - linebetweenrows=None, linebelow=Line("|====", "", "", ""), headerrow=partial(_asciidoc_row, True), datarow=partial(_asciidoc_row, False), @@ -786,14 +701,8 @@ def simple_separated_format(separator): """ return TableFormat( - None, - None, - None, - None, headerrow=DataRow("", separator, ""), datarow=DataRow("", separator, ""), - padding=0, - with_header_hide=None, ) From 97422c4c79b0871e1e97832f647aa7486e0ef5fd Mon Sep 17 00:00:00 2001 From: "Roland C. Dowdeswell" Date: Mon, 4 Mar 2024 11:20:02 +0000 Subject: [PATCH 2/4] Add "align_columns" to TableFormat Also: The "html" TableFormat doesn't need the alignment padding. --- tabulate/__init__.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 602c7d0d..890ddc86 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -97,6 +97,7 @@ def _is_file(f): "headerrow", "datarow", "padding", + "align_columns", "with_header_hide", ], defaults = ( None, @@ -106,6 +107,7 @@ def _is_file(f): DataRow("", " ", ""), DataRow("", " ", ""), 0, + True, None, ), ) @@ -532,6 +534,7 @@ def escape_empty(val): headerrow=partial(_html_row_with_attrs, "th", False), datarow=partial(_html_row_with_attrs, "td", False), with_header_hide=["lineabove"], + align_columns=False, ), "unsafehtml": TableFormat( lineabove=_html_begin_table_without_header, @@ -540,6 +543,7 @@ def escape_empty(val): headerrow=partial(_html_row_with_attrs, "th", True), datarow=partial(_html_row_with_attrs, "td", True), with_header_hide=["lineabove"], + align_columns=False, ), "latex": TableFormat( lineabove=_latex_line_begin_tabular, @@ -2076,6 +2080,9 @@ def tabulate( is_multiline = False width_fn = _choose_width_fn(has_invisible, enable_widechars, is_multiline) + if not isinstance(tablefmt, TableFormat): + tablefmt = _table_formats.get(tablefmt, _table_formats["simple"]) + # format rows and columns, convert numeric values to strings cols = list(izip_longest(*list_of_lists)) numparses = _expand_numparse(disable_numparse, len(cols)) @@ -2128,10 +2135,11 @@ def tabulate( minwidths = ( [width_fn(h) + min_padding for h in headers] if headers else [0] * len(cols) ) - cols = [ - _align_column(c, a, minw, has_invisible, enable_widechars, is_multiline) - for c, a, minw in zip(cols, aligns, minwidths) - ] + if tablefmt.align_columns: + cols = [ + _align_column(c, a, minw, has_invisible, enable_widechars, is_multiline) + for c, a, minw in zip(cols, aligns, minwidths) + ] aligns_headers = None if headers: @@ -2168,9 +2176,6 @@ def tabulate( minwidths = [max(width_fn(cl) for cl in c) for c in cols] rows = list(zip(*cols)) - if not isinstance(tablefmt, TableFormat): - tablefmt = _table_formats.get(tablefmt, _table_formats["simple"]) - ra_default = rowalign if isinstance(rowalign, str) else None rowaligns = _expand_iterable(rowalign, len(rows), ra_default) _reinsert_separating_lines(rows, separating_lines) From 70859a67979cd383e2caeefb808409fb03f74fa5 Mon Sep 17 00:00:00 2001 From: "Roland C. Dowdeswell" Date: Mon, 4 Mar 2024 11:10:39 +0000 Subject: [PATCH 3/4] Add "elide_empty_columns" to TableFormat --- tabulate/__init__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 890ddc86..5589c11f 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -98,6 +98,7 @@ def _is_file(f): "datarow", "padding", "align_columns", + "elide_empty_columns", "with_header_hide", ], defaults = ( None, @@ -108,6 +109,7 @@ def _is_file(f): DataRow("", " ", ""), 0, True, + False, None, ), ) @@ -2319,6 +2321,14 @@ def _format_table(fmt, headers, headersaligns, rows, colwidths, colaligns, is_mu pad = fmt.padding headerrow = fmt.headerrow + if fmt.elide_empty_columns: + def elim_zero_len(row): + return list(zip(*filter(lambda x: x[0], zip(colwidths, row))))[1] + + if len(headers): + headers = elim_zero_len(headers) + rows = [elim_zero_len(row) for row in rows] + padded_widths = [(w + 2 * pad) for w in colwidths] if is_multiline: pad_row = lambda row, _: row # noqa do it later, in _append_multiline_row From d9762136a8839c96ebe0a7b8134c765361bb3480 Mon Sep 17 00:00:00 2001 From: "Roland C. Dowdeswell" Date: Sun, 3 Mar 2024 22:10:16 +0000 Subject: [PATCH 4/4] Add "flow" tablefmt which doesn't do any formatting --- tabulate/__init__.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 5589c11f..fe148b0a 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -331,6 +331,10 @@ def escape_empty(val): with_header_hide=["lineabove", "linebelow"], ), "plain": TableFormat(), + "flow": TableFormat( + align_columns=False, + elide_empty_columns=True, + ), "grid": TableFormat( lineabove=Line("+", "-", "+", "+"), linebelowheader=Line("+", "=", "+", "+"), @@ -1639,6 +1643,14 @@ def tabulate( eggs 451 ---- -------- + "flow" applies no formatting and outputs each column stripped of + leading and trailing whitespace only putting whitespace between + non-empty columns. + + >>> print(tabulate([["spam", " ", 41.9999], ["eggs", "a", "451.0"]], tablefmt="flow")) + spam 41.9999 + eggs a 451 + "grid" is similar to tables produced by Emacs table.el package or Pandoc grid_tables: