diff --git a/src/globus_cli/termio/printers/folded_table_printer.py b/src/globus_cli/termio/printers/folded_table_printer.py index cf77a0e53..4fc80a8e0 100644 --- a/src/globus_cli/termio/printers/folded_table_printer.py +++ b/src/globus_cli/termio/printers/folded_table_printer.py @@ -180,7 +180,22 @@ def content_rows(self) -> tuple[Row, ...]: return self.rows[1:] def fits_in_width(self, width: int) -> bool: - return all(x.min_rendered_width <= width for x in self.rows) + return self.calculate_width() <= width + + def calculate_width(self) -> int: + """ + For each column, find the row where that column is the max width. + Sum those widths + the width of the separators (3 * (ncols-1)) + """ + max_widths = [] + for idx in range(self.num_columns): + max_widths.append(max(row.column_widths[idx] for row in self.rows)) + + decoration_length = 0 + if self.folded: + decoration_length = 4 + + return sum(max_widths) + (3 * (self.num_columns - 1)) + decoration_length def fold_rows(self, n: int) -> RowTable: """Produce a new table with folded rows.""" @@ -247,13 +262,6 @@ def _split_level( def is_folded(self) -> bool: return len(self.grid) > 1 - @functools.cached_property - def min_rendered_width(self) -> int: - decoration_length = 0 - if self.is_folded: - decoration_length = 4 - return sum(self.column_widths) + (3 * (self.num_cols - 1)) + decoration_length - @functools.cached_property def num_cols(self) -> int: return max(0, *(len(subrow) for subrow in self.grid)) diff --git a/tests/unit/termio/printer/test_folded_table_printer.py b/tests/unit/termio/printer/test_folded_table_printer.py index e9a48d3f7..1c54ae4bb 100644 --- a/tests/unit/termio/printer/test_folded_table_printer.py +++ b/tests/unit/termio/printer/test_folded_table_printer.py @@ -4,7 +4,7 @@ from globus_cli.termio import Field from globus_cli.termio.printers import FoldedTablePrinter -from globus_cli.termio.printers.folded_table_printer import Row +from globus_cli.termio.printers.folded_table_printer import Row, RowTable @pytest.mark.parametrize( @@ -197,3 +197,19 @@ def test_row_folding_with_remainder(): ("2", "5"), ("3",), ) + + +def test_row_table_width_computation_is_pessimal(): + """ + Given a table with lopsided rows, such that each row could fit in a narrow width, + but when column-aligned they are wider, the table should find the width based on + the justification of text. + """ + row1 = Row((("a" * 1000, "b"),)) + row2 = Row((("c", "d" * 1000),)) + + table = RowTable((row1, row2)) + + # it should be the max width for each column (1000) + the width of separators (in + # this case, 3 for the center divider) + assert table.calculate_width() == 2003