From 3a9d90db92156b8ed7ea8db8d0aa51467abdae5d Mon Sep 17 00:00:00 2001 From: Marcel de Croock Date: Mon, 22 Jan 2024 01:06:20 +0100 Subject: [PATCH] fixed bug in Auto: missing pane that is too high --- selfdocprint/_layout_specs.py | 18 +--- selfdocprint/_printer.py | 148 +++++++++++------------------ selfdocprint/examples/basic_use.py | 112 +++++++--------------- selfdocprint/selfdocprint.py | 26 +++-- tests/global_test_values.py | 84 +++++++++++----- tests/test_printer.py | 10 +- tests/test_selfdocprint.py | 36 +++++-- 7 files changed, 201 insertions(+), 233 deletions(-) diff --git a/selfdocprint/_layout_specs.py b/selfdocprint/_layout_specs.py index 4a8c8dd..3730f25 100644 --- a/selfdocprint/_layout_specs.py +++ b/selfdocprint/_layout_specs.py @@ -11,12 +11,12 @@ class Layout: int_format: str = "" float_format: str = "" str_format: str = "" - head: str = "" - seperator: str = "" style: str = DEFAULT_STYLE pointer: str = "" - tail: str = "" literal_lbl: str = "" + head: str = "" + tail: str = "" + seperator: str = "" alt_layout: "Layout" = None max_width: int = None max_height: int = None @@ -34,7 +34,6 @@ class MinimalLayout(Layout): seperator: str = " " pointer: str = ":" - tail: str = "" @dataclass @@ -44,10 +43,8 @@ class InlineLayout(Layout): Multi-line value strings are properly aligned.""" str_format: str = "<{value_width}" - head: str = "\n" seperator: str = " " pointer: str = ": " - tail: str = "" @dataclass @@ -60,10 +57,8 @@ class DictLayout(Layout): int_format: str = "-8" float_format: str = "-12.3f" str_format: str = "<{value_width}" - head: str = "\n" seperator: str = "\n" pointer: str = " : " - tail: str = "" literal_lbl: str = "_" @@ -72,10 +67,8 @@ class ScrollLayout(Layout): """Prints a label above its value. Label/value pairs are printed from top to bottom.""" - head: str = "\n" - seperator: str = "\n\n" + seperator: str = "\n" pointer: str = ":\n" - tail: str = "\n" @dataclass @@ -85,7 +78,6 @@ class AutoLayout(Layout): using alt_layout.""" str_format: str = "<{value_width}" - head: str = "\n" seperator: str = " " pointer: str = ": " alt_layout: Layout = ScrollLayout @@ -99,7 +91,7 @@ class TableLayout(Layout): Label/value pairs are printed from left to right. Multi-line value strings are properly aligned.""" - head: str = "\n" + # head: str = "\n" # tail: str = " |" seperator: str = " | " lbl_format: str = ">{value_width}" diff --git a/selfdocprint/_printer.py b/selfdocprint/_printer.py index 2bff114..1a411e6 100644 --- a/selfdocprint/_printer.py +++ b/selfdocprint/_printer.py @@ -1,7 +1,6 @@ import ast import io import re -import sys from contextlib import closing from typing import Callable @@ -11,8 +10,14 @@ class _Pane: """Holds a formatted and layed-out label/value pair.""" - def __init__(self, layout: Layout, label: str, value: object, max_label_width: int, include_label: bool = True -): + def __init__( + self, + layout: Layout, + label: str, + value: object, + max_label_width: int, + include_label: bool = True, + ): # format the value if value is None: value_lines = [""] @@ -33,7 +38,7 @@ def __init__(self, layout: Layout, label: str, value: object, max_label_width: i format_spec = layout.str_format.replace("{value_width}", str(value_width)) value_lines = [format(v, format_spec) for v in value_lines] - if label is "": + if label == "": label_line = "" else: # format the label and apend the pointer @@ -47,12 +52,14 @@ def __init__(self, layout: Layout, label: str, value: object, max_label_width: i if _has_alignment(layout): # indent the value lines indent = " " * len(label_line) - value_lines = [s if i == 0 else indent + s for i, s in enumerate(value_lines)] + value_lines = [ + s if i == 0 else indent + s for i, s in enumerate(value_lines) + ] label_line = f"{sgr(layout.style)}{label_line}{sgr()}" else: # maybe TODO implement possible feature here: custom indents max_label_line_width = max(len(l) for l in label_line.split("\n")) - if max_label_line_width > value_width: + if _has_alignment(layout) and max_label_line_width > value_width: indent = " " * (max_label_line_width - value_width) value_lines = [indent + l for l in value_lines] label_line = f"{sgr(layout.style)}{label_line[:last_new_line_ofs]}{sgr()}{label_line[last_new_line_ofs:]}" @@ -65,7 +72,6 @@ def __init__(self, layout: Layout, label: str, value: object, max_label_width: i self.width: int = max(len(_strip_styles(l)) for l in self.lines) self.height: int = len(self.lines) - def __str__(self): return "\n".join(self.lines) @@ -83,98 +89,66 @@ def press( args: list[ast.expr], values: list[object], layout: Layout, - press_labels: bool = True + beg: str, + end: str, + press_labels: bool = True, ) -> str: labels = [_create_label(arg, layout.literal_lbl) for arg in args] max_lbl_width: int = _getlongest_line_len(labels) - beg, pre, post, end = _get_edges(layout.head, layout.tail) + _beg, pre, post, _end = _get_edges(beg + layout.head, layout.tail + end) with closing(io.StringIO("")) as buf: if press_labels: - buf.write(beg) - # if _isleft_to_right_layout(layout) and _has_alignment(layout): + buf.write(_beg) current_width = 0 - panes = [] - for lbl, val in zip(labels, values, strict=True): + pane_row = [] + for i, (lbl, val) in enumerate(zip(labels, values, strict=True)): pane = _Pane(layout, lbl, val, max_lbl_width, press_labels) - if (layout.max_width is not None and pane.width > layout.max_width) or ( - layout.max_height is not None and pane.height > layout.max_height - ): - # the pane is too high or too wide - if len(panes) > 0: - _write_panes_to_buf(panes, buf, layout.alt_layout) - buf.write("\n") + if _isleft_to_right_layout(layout) and _has_alignment(layout): + if (layout.max_width is not None and pane.width > layout.max_width) or ( + layout.max_height is not None and pane.height > layout.max_height + ): + # the pane is too high or too wide, it has to be placed in its own row + if len(pane_row) > 0: + pane_row = _flush_pane_row(pane_row, buf, layout, pre, post) + buf.write("\n") current_width = 0 - panes = [] - elif ( - layout.max_width is not None - and current_width + pane.width > layout.max_width - ): - # with the new pane the horizontal pane sequence would become too long - _write_panes_to_buf(panes, buf, layout, pre, post) - buf.write("\n") - current_width = pane.width - panes = [pane] - else: - current_width += pane.width - panes.append(pane) - _write_panes_to_buf(panes, buf, layout, pre, post) - # else: - # panes = [ - # _Pane(layout, lbl, val, max_lbl_width) - # for (lbl, val) in zip(labels, values) - # ] - # _write_panes_to_buf(panes, buf, layout) - buf.write(end) + alt_layout = layout.alt_layout() + alt_pane = _Pane(alt_layout, lbl, val, max_lbl_width, press_labels) + pane_row = _flush_pane_row([alt_pane], buf, alt_layout, pre, post) + buf.write("\n") + elif ( + layout.max_width is not None + and current_width + pane.width > layout.max_width + ): + # with the new pane the horizontal pane sequence would become too long + pane_row = _flush_pane_row(pane_row, buf, layout, pre, post) + buf.write("\n") + current_width = pane.width + pane_row.append(pane) + else: + current_width += pane.width + pane_row.append(pane) + else: # not _isleft_to_right_layout(layout) and _has_alignment(layout) + if i > 0: + buf.write(layout.seperator) + pane_row = _flush_pane_row([pane], buf, layout, pre, post) + + _flush_pane_row(pane_row, buf, layout, pre, post) + buf.write(_end) return buf.getvalue() -def _write_panes_to_buf(panes, buf, layout, pre="", post=""): - if len(panes) == 0: - return - - # beg, pre, post, end = _get_edges(layout.head, layout.tail) - if _isleft_to_right_layout(layout) and _has_alignment(layout): - max_lines = max([pane.height for pane in panes]) +def _flush_pane_row(pane_row, buf, layout, pre="", post=""): + if len(pane_row) > 0: + max_lines = max([pane.height for pane in pane_row]) for l in range(max_lines): buf.write(pre) - buf.write(layout.seperator.join(pane.get_line(l) for pane in panes)) + buf.write(layout.seperator.join(pane.get_line(l) for pane in pane_row)) buf.write(post) if l < max_lines - 1: buf.write("\n") - else: - buf.write(layout.seperator.join(str(pane) for pane in panes)) - - -# def format_objects( -# objects: list[any], int_format, float_format, str_format -# ) -> (list[list[str]], int): -# result_list = [] -# max_width = 0 -# for value in objects: -# if isinstance(value, bool): -# result_list.append(list(format(str(value), str_format))) -# elif isinstance(value, int): -# result_list.append(list(format(str(value), int_format))) -# elif isinstance(value, float): -# result_list.append(list(format(str(value), float_format))) -# else: -# value_lines = str(value).split("\n") -# max_value_line_len = max(len(vl) for vl in value_lines) -# value_format = _fixate_alignment_width(str_format, max_value_line_len) -# value_lines = [format(l, value_format) for l in value_lines] -# # if _has_alignment(layout): -# # val_str = ("\n" + " " * col_ofs).join(value_lines) -# # else: -# # val_str = ("\n").join(value_lines) -# return (result_list, max_width) - - -def iswithin_max_width(page: str, max_width) -> bool: - page = _strip_styles(page) - if _getlongest_line_len([page]) < max_width: - return True - return False + return [] def sgr(sgr_codes: str = None): @@ -188,8 +162,7 @@ def _has_alignment(layout: Layout): def _isleft_to_right_layout(layout: Layout) -> bool: - # for attr in ["seperator", "pointer"]: - for attr in ["seperator"]: # for next version with flexible tables + for attr in ["seperator"]: if "\n" in getattr(layout, attr): return False return True @@ -227,11 +200,6 @@ def _get_edges(beg: str, end: str): # count=1, # ) -# def _fixate_alignment_width(label_format:str, value_width:int, max_label_width:int): -# lf = label_format.replace("{value_width}", str(value_width)) -# lf = label_format.replace("{max_label_width}", str(max_label_width)) -# return lf - def _getlongest_line_len(strs: list[str]) -> int: """check each line in each string in strs and return the longest line""" @@ -294,4 +262,4 @@ def _create_label(arg: ast.expr, literal_str: str): return action(arg) else: raise ValueError(action) - return f"unknow arg encoutered: {arg}" + return f"unknow arg encountered: {arg}" diff --git a/selfdocprint/examples/basic_use.py b/selfdocprint/examples/basic_use.py index 8785347..feffc1f 100644 --- a/selfdocprint/examples/basic_use.py +++ b/selfdocprint/examples/basic_use.py @@ -1,12 +1,6 @@ # from selfdocprint import print -import numpy as np - import selfdocprint as sdp -from selfdocprint import print - -# from selfdocprint import DictLayout, InlineLayout, MinimalLayout, ScrollLayout, console, print -# from selfdocprint.selfdocprint import PrintFunc - +from selfdocprint import console, print # global test variables bf = False @@ -14,6 +8,7 @@ i = -99 f = 99.555555 s = "tic\ntacable\ntoes" +s_12_lines = "one\ntwo\nthree\nfour\nfive\nsix\nseven\neight\nnine\nten\neleven\ntwelve" formula = "The Ultimate Question of Life,\nthe Universe, and Everything" theta = 6.006 @@ -25,85 +20,44 @@ _set = {"a", "b", "c", "d"} -def standard(): - arr = np.random.randint(100, size=(6, 5)) - # print(theta, x) - print("test", formula, theta, x, "literal", theta * x, s, 1 / 3, 1 / 6, 1 / 9) - print("test\ngedeyg", f"test: {x}") - print("test\ngedeyg", f"test {x}", layout=None) +def auto_demo(): + print("\n*** AutoLayout examples ***\n") + + print("* normal row") + print(formula, theta, x, "literal", x * theta) + + print("\n* row with break because the row is longer than 140 characters") + print(formula, theta, x, "literal", x * theta, s, 1 / 3, 1 / 6, 1 / 9) + + print("\n* row with 2 breaks because the value: s_12_lines, has more than 10 lines") + print(formula, theta, x, "literal", x * theta, s_12_lines, s, 1 / 3, 1 / 6, 1 / 9) + + +def inline_demo(): + print("\n\n*** InlineLayout examples ***\n") + print(formula, theta, x, "literal", x * theta, layout=sdp.InlineLayout) + + +def scroll_demo(): + print(formula, theta, x, "literal", x * theta, layout=sdp.ScrollLayout) + + +def dict_demo(): + print(formula, theta, x, "literal", x * theta, layout=sdp.DictLayout) def table_demo(): - for i in range(10): - print(i, i**2, 1 / (i + 0.000001), i*2, layout=sdp.TableLayout) - - -# def demo(): -# console.clear() -# print("\n**************************************************") -# print("*** Normal print output ***") -# print("**************************************************") -# print() -# print(formula, theta, x, theta * x) -# print() -# print() -# print("**************************************************") -# print("*** Self-documented and layed-out print output ***") -# print("**************************************************") -# print( -# formula, -# theta, -# x, -# theta * x, -# beg="\n\n*** using inline layout ***\n", -# layout=InlineLayout(), -# ) -# print( -# formula, -# theta, -# x, -# theta * x, -# beg="\n\n*** using dict layout ***\n", -# layout=DictLayout(), -# ) -# print( -# formula, -# theta, -# x, -# theta * x, -# beg="\n\n*** using scroll layout ***\n", -# layout=ScrollLayout(), -# ) -# print( -# formula, -# theta, -# x, -# theta * x, -# beg="\n*** using minimal layout ***\n\n", -# layout=MinimalLayout(), -# end="\n\n\n", -# ) -# eval("print(x, layout=ScrollLayout)") -# eval( -# "print(x, layout=ScrollLayout)" -# ) - - -# def with_config(): -# print = PrintFunc(default_layout=MinimalLayout()) -# print(formula, theta, x, theta * x) - - -# def print_specs(): -# sdp.print_layout_specs() + for i in range(5): + print(i, i**2, 1 / (i + 0.000001), i * 2, layout=sdp.TableLayout) def main(): - standard() + console.clear(clear_buffer=True) + auto_demo() + inline_demo() + # scroll_demo() + # dict_demo() table_demo() - # demo() - # with_config() - # print_specs() if __name__ == "__main__": diff --git a/selfdocprint/selfdocprint.py b/selfdocprint/selfdocprint.py index ad1fc7c..2ca08e7 100644 --- a/selfdocprint/selfdocprint.py +++ b/selfdocprint/selfdocprint.py @@ -6,14 +6,14 @@ import selfdocprint._printer as printer from selfdocprint._layout_specs import ( DEFAULT_STYLE, - Layout, + AutoLayout, DefaultLayout, - InlineLayout, - ScrollLayout, DictLayout, + InlineLayout, + Layout, MinimalLayout, - AutoLayout, - TableLayout + ScrollLayout, + TableLayout, ) from selfdocprint._printer import sgr @@ -69,7 +69,7 @@ def __call__( return if type(layout) == type: - layout = layout() # create an instance if a class was given + layout = layout() # create an instance if a class was given try: call, _, pos = _get_call_info() @@ -83,22 +83,20 @@ def __call__( arg_exprs = _getargument_expressions(call) - if len(values) == 1 and _is_literal( - arg_exprs[0] - ): # print single literals normally + if all(_is_literal(arg_expr) for arg_expr in arg_exprs): + # print literals normally print(*values, end=end, sep=sep, file=file, flush=flush) return if isinstance(layout, TableLayout) and self._last_call_pos == pos: - page = printer.press(arg_exprs, values, layout, press_labels=False) + page = printer.press(arg_exprs, values, layout, beg, end, press_labels=False) else: self._last_call_pos = pos - page = printer.press(arg_exprs, values, layout) - + page = printer.press(arg_exprs, values, layout, beg, end) - print(beg, sep="", end="", file=file) + # print(beg, sep="", end="", file=file) print( - page, sep="", end=end, file=file, flush=flush + page, sep="", end="", file=file, flush=flush ) # sep is ignored when a layout is used diff --git a/tests/global_test_values.py b/tests/global_test_values.py index 88f1e33..d3eb90f 100644 --- a/tests/global_test_values.py +++ b/tests/global_test_values.py @@ -7,6 +7,7 @@ i = -99 f = 99.555555 s = "tic\ntacable\ntoes" +s_12_lines = "one\ntwo\nthree\nfour\nfive\nsix\nzeven\neight\nnine\nten\neleven\ntwelve" formula = "The Ultimate Question of Life,\nthe Universe, and Everything" theta = 6.006 x = 7 @@ -23,33 +24,26 @@ sto = "\x1B[0m" layouts_expected_output = { # expected results for the different layout test - # "inline": { - # "integer": f"\n{sty}i: {sto} -99\n", - # "float": f"\n{sty}f: {sto} 99.556\n", - # "string": f"\n{sty}s: {sto}tic \n tacable\n toes \n", - # "expression": f"\n{sty}i * f: {sto} -9856.000\n", - # "all_values": f"\n{sty}i: {sto} -99 {sty}f: {sto} 99.556 {sty}s: {sto}tic \n tacable\n toes \n", - # }, "inline": { - "integer": f"\n{sty}i: {sto}-99\n", - "float": f"\n{sty}f: {sto}99.555555\n", - "string": f"\n{sty}s: {sto}tic \n tacable\n toes \n", - "expression": f"\n{sty}i * f: {sto}-9855.999945\n", - "all_values": f"\n{sty}i: {sto}-99 {sty}f: {sto}99.555555 {sty}s: {sto}tic \n tacable\n toes \n", + "integer": f"{sty}i: {sto}-99\n", + "float": f"{sty}f: {sto}99.555555\n", + "string": f"{sty}s: {sto}tic \n tacable\n toes \n", + "expression": f"{sty}i * f: {sto}-9855.999945\n", + "all_values": f"{sty}i: {sto}-99 {sty}f: {sto}99.555555 {sty}s: {sto}tic \n tacable\n toes \n", }, "dict": { - "integer": f"\n{sty}i : {sto} -99\n", - "float": f"\n{sty}f : {sto} 99.556\n", - "string": f"\n{sty}s : {sto}tic \n tacable\n toes \n", - "expression": f"\n{sty}i * f : {sto} -9856.000\n", - "all_values": f"\n{sty}i : {sto} -99\n{sty}f : {sto} 99.556\n{sty}s : {sto}tic \n tacable\n toes \n", + "integer": f"{sty}i : {sto} -99\n", + "float": f"{sty}f : {sto} 99.556\n", + "string": f"{sty}s : {sto}tic \n tacable\n toes \n", + "expression": f"{sty}i * f : {sto} -9856.000\n", + "all_values": f"{sty}i : {sto} -99\n{sty}f : {sto} 99.556\n{sty}s : {sto}tic \n tacable\n toes \n", }, "scroll": { - "integer": f"\n{sty}i:{sto}\n-99\n\n", - "float": f"\n{sty}f:{sto}\n99.555555\n\n", - "string": f"\n{sty}s:{sto}\ntic\ntacable\ntoes\n\n", - "expression": f"\n{sty}i * f:{sto}\n-9855.999945\n\n", - "all_values": f"\n{sty}i:{sto}\n-99\n\n{sty}f:{sto}\n99.555555\n\n{sty}s:{sto}\ntic\ntacable\ntoes\n\n", + "integer": f"{sty}i:{sto}\n-99\n", + "float": f"{sty}f:{sto}\n99.555555\n", + "string": f"{sty}s:{sto}\ntic\ntacable\ntoes\n", + "expression": f"{sty}i * f:{sto}\n-9855.999945\n", + "all_values": f"{sty}i:{sto}\n-99\n{sty}f:{sto}\n99.555555\n{sty}s:{sto}\ntic\ntacable\ntoes\n", }, "minimal": { "integer": f"{sty}i:{sto}-99\n", @@ -59,11 +53,51 @@ "all_values": f"{sty}i:{sto}-99 {sty}f:{sto}99.555555 {sty}s:{sto}tic\ntacable\ntoes\n", }, "auto": { # use _printer._strip_styles() before comparing - "new_row": """ -formula: The Ultimate Question of Life, theta: 6.006 x: 7 theta * x: 42.042 1 / 3: 0.3333333333333333 1 / 6: 0.16666666666666666 + "row_too_long": +"""formula: The Ultimate Question of Life, theta: 6.006 x: 7 theta * x: 42.042 1 / 3: 0.3333333333333333 1 / 6: 0.16666666666666666 the Universe, and Everything 1 / 9: 0.1111111111111111 """, - "alt_layout": "", + "value_too_high": +"""formula: The Ultimate Question of Life, theta: 6.006 x: 7 theta * x: 42.042 + the Universe, and Everything +s_12_lines: +one +two +three +four +five +six +zeven +eight +nine +ten +eleven +twelve +1 / 3: 0.3333333333333333 1 / 6: 0.16666666666666666 1 / 9: 0.1111111111111111 +""", + }, + "table": { + "normal": +""" i | i ** 2 | 1 / 0.01 | i * 2 + 0 | 0 | 100.000 | 0 + 1 | 1 | 100.000 | 2 + 2 | 4 | 100.000 | 4 + 3 | 9 | 100.000 | 6 + 4 | 16 | 100.000 | 8 +""", + "widened_columns": +""" i | i ** 2 | 1 / (i + 1e-06) | i * 2 + 0 | 0 | 1000000.000 | 0 + 1 | 1 | 1.000 | 2 + 2 | 4 | 0.500 | 4 + 3 | 9 | 0.333 | 6 + 4 | 16 | 0.250 | 8 +""", }, } + +# import selfdocprint as sdp +# from selfdocprint import print +# for i in range(5): +# print(i, i**2, 1 / 0.01, i * 2, layout=sdp.TableLayout) diff --git a/tests/test_printer.py b/tests/test_printer.py index bb13e5f..f5eec65 100644 --- a/tests/test_printer.py +++ b/tests/test_printer.py @@ -25,18 +25,18 @@ class Test_press_with_all_layouts: # inline def test_press_of_inline_layout_integer(self, capsys): - assert _strip_styles(press([i_expr], [i], InlineLayout)) == "\ni: -99" + assert _strip_styles(press([i_expr], [i], InlineLayout, beg="", end="")) == "i: -99" def test_press_of_inline_layout_string(self, capsys): assert ( - _strip_styles(press([s_expr], [s], InlineLayout)) - == "\ns: tic \n tacable\n toes " + _strip_styles(press([s_expr], [s], InlineLayout, beg="", end="")) + == "s: tic \n tacable\n toes " ) def test_press_of_inline_layout_integer_and_string(self, capsys): assert ( - _strip_styles(press([i_expr, s_expr], [i, s], InlineLayout)) - == "\ni: -99 s: tic \n tacable\n toes " + _strip_styles(press([i_expr, s_expr], [i, s], InlineLayout, beg="", end="")) + == "i: -99 s: tic \n tacable\n toes " ) diff --git a/tests/test_selfdocprint.py b/tests/test_selfdocprint.py index 46dbede..6c193eb 100644 --- a/tests/test_selfdocprint.py +++ b/tests/test_selfdocprint.py @@ -12,6 +12,7 @@ ) from selfdocprint._printer import _strip_styles from selfdocprint.selfdocprint import _context_warning +from selfdocprint.selfdocprint import _print as print from tests.global_test_values import ( _dict, _list, @@ -24,14 +25,28 @@ i, layouts_expected_output, s, + s_12_lines, theta, x, ) -print = PrintFunc() - class TestLayouts: + # auto + def test_auto_layout_new_row(self, capsys): + print(formula, theta, x, theta * x, 1/3, 1/6, 1/9) + assert ( + _strip_styles(capsys.readouterr().out) + == layouts_expected_output["auto"]["row_too_long"] + ) + + def test_auto_layout_too_high_value(self, capsys): + print(formula, theta, x, theta * x, s_12_lines, 1/3, 1/6, 1/9) + assert ( + _strip_styles(capsys.readouterr().out) + == layouts_expected_output["auto"]["value_too_high"] + ) + # inline def test_inline_layout_integer(self, capsys): print(i, layout=InlineLayout()) @@ -128,12 +143,19 @@ def test_minimal_layout_all_values(self, capsys): capsys.readouterr().out == layouts_expected_output["minimal"]["all_values"] ) - # auto - def test_auto_layout_new_row(self, capsys): - print(formula, theta, x, theta * x, 1/3, 1/6, 1/9, layout=AutoLayout()) + # table + def test_table_layout(self, capsys): + for i in range(5): + print(i, i**2, 1 / 0.01, i * 2, layout=sdp.TableLayout) assert ( - _strip_styles(capsys.readouterr().out) - == layouts_expected_output["auto"]["new_row"] + _strip_styles(capsys.readouterr().out) == layouts_expected_output["table"]["normal"] + ) + + def test_table_layout_widened_columns(self, capsys): + for i in range(5): + print(i, i**2, 1 / (i + 0.000001), i * 2, layout=sdp.TableLayout) + assert ( + _strip_styles(capsys.readouterr().out) == layouts_expected_output["table"]["widened_columns"] )