diff --git a/src/prettytable/prettytable.py b/src/prettytable/prettytable.py index df1cb86..0204a7a 100644 --- a/src/prettytable/prettytable.py +++ b/src/prettytable/prettytable.py @@ -1558,13 +1558,18 @@ def _format_value(self, field, value): return formatter(field, value) def _compute_table_width(self, options): - table_width = 2 if options["vrules"] in (FRAME, ALL) else 0 + if options["vrules"] == FRAME: + table_width = 2 + if options["vrules"] == ALL: + table_width = 1 + else: + table_width = 0 per_col_padding = sum(self._get_padding_widths(options)) for index, fieldname in enumerate(self.field_names): if not options["fields"] or ( options["fields"] and fieldname in options["fields"] ): - table_width += self._widths[index] + per_col_padding + table_width += self._widths[index] + per_col_padding + 1 return table_width def _compute_widths(self, rows, options) -> None: @@ -1590,21 +1595,22 @@ def _compute_widths(self, rows, options) -> None: widths[index] = max(widths[index], self.min_width[fieldname]) self._widths = widths + per_col_padding = sum(self._get_padding_widths(options)) # Are we exceeding max_table_width? if self._max_table_width: table_width = self._compute_table_width(options) if table_width > self._max_table_width: # Shrink widths in proportion - scale = 1.0 * self._max_table_width / table_width - widths = [int(w * scale) for w in widths] - self._widths = widths + markup_chars = per_col_padding * len(widths) + len(widths) - 1 + scale = (self._max_table_width - markup_chars) / ( + table_width - markup_chars + ) + self._widths = [max(1, int(w * scale)) for w in widths] # Are we under min_table_width or title width? if self._min_table_width or options["title"]: if options["title"]: - title_width = len(options["title"]) + sum( - self._get_padding_widths(options) - ) + title_width = len(options["title"]) + per_col_padding if options["vrules"] in (FRAME, ALL): title_width += 2 else: @@ -1619,9 +1625,7 @@ def _compute_widths(self, rows, options) -> None: borders = 0 # Subtract padding for each column and borders - min_width -= ( - sum([sum(self._get_padding_widths(options)) for _ in widths]) + borders - ) + min_width -= sum([per_col_padding for _ in widths]) + borders # What is being scaled is content so we sum column widths content_width = sum(widths) or 1 diff --git a/tests/test_prettytable.py b/tests/test_prettytable.py index 214c5c0..594fdd3 100644 --- a/tests/test_prettytable.py +++ b/tests/test_prettytable.py @@ -2008,17 +2008,141 @@ def test_max_table_width(self) -> None: table.max_table_width = 5 table.add_row([0]) + # FIXME: Table is wider than table.max_table_width assert ( table.get_string().strip() == """ -+-----+ -| Fie | -+-----+ -| 0 | -+-----+ ++----+ +| Fi | ++----+ +| 0 | ++----+ """.strip() ) + def test_max_table_width_wide(self) -> None: + table = PrettyTable() + table.max_table_width = 52 + table.add_row( + [ + 0, + 0, + 0, + 0, + 0, + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam " + "nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam " + "erat, sed diam voluptua", + ] + ) + + assert ( + table.get_string().strip() + == """ ++---+---+---+---+---+------------------------------+ +| F | F | F | F | F | Field 6 | ++---+---+---+---+---+------------------------------+ +| 0 | 0 | 0 | 0 | 0 | Lorem ipsum dolor sit amet, | +| | | | | | consetetur sadipscing elitr, | +| | | | | | sed diam nonumy eirmod | +| | | | | | tempor invidunt ut labore et | +| | | | | | dolore magna aliquyam erat, | +| | | | | | sed diam voluptua | ++---+---+---+---+---+------------------------------+""".strip() + ) + + def test_max_table_width_wide2(self) -> None: + table = PrettyTable() + table.max_table_width = 70 + table.add_row( + [ + "Lorem", + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam ", + "ipsum", + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam ", + "dolor", + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam ", + ] + ) + + assert ( + table.get_string().strip() + == """ ++---+-----------------+---+-----------------+---+-----------------+ +| F | Field 2 | F | Field 4 | F | Field 6 | ++---+-----------------+---+-----------------+---+-----------------+ +| L | Lorem ipsum | i | Lorem ipsum | d | Lorem ipsum | +| o | dolor sit amet, | p | dolor sit amet, | o | dolor sit amet, | +| r | consetetur | s | consetetur | l | consetetur | +| e | sadipscing | u | sadipscing | o | sadipscing | +| m | elitr, sed diam | m | elitr, sed diam | r | elitr, sed diam | ++---+-----------------+---+-----------------+---+-----------------+""".strip() + ) + + def test_max_table_width_wide_vrules_frame(self) -> None: + table = PrettyTable() + table.max_table_width = 52 + table.vrules = FRAME + table.add_row( + [ + 0, + 0, + 0, + 0, + 0, + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam " + "nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam " + "erat, sed diam voluptua", + ] + ) + + assert ( + table.get_string().strip() + == """ ++--------------------------------------------------+ +| F F F F F Field 6 | ++--------------------------------------------------+ +| 0 0 0 0 0 Lorem ipsum dolor sit amet, | +| consetetur sadipscing elitr, | +| sed diam nonumy eirmod | +| tempor invidunt ut labore et | +| dolore magna aliquyam erat, | +| sed diam voluptua | ++--------------------------------------------------+""".strip() + ) + + def test_max_table_width_wide_vrules_none(self) -> None: + table = PrettyTable() + table.max_table_width = 52 + table.vrules = NONE + table.add_row( + [ + 0, + 0, + 0, + 0, + 0, + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam " + "nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam " + "erat, sed diam voluptua", + ] + ) + + assert ( + table.get_string().strip() + == """ +---------------------------------------------------- + F F F F F Field 6 +---------------------------------------------------- + 0 0 0 0 0 Lorem ipsum dolor sit amet, + consetetur sadipscing elitr, + sed diam nonumy eirmod + tempor invidunt ut labore et + dolore magna aliquyam erat, + sed diam voluptua +----------------------------------------------------""".strip() # noqa: W291 + ) + class TestRowEndSection: def test_row_end_section(self) -> None: