Skip to content

fix: apply column max widths when rendering tables (#88) - #542

Open
MohammadYusif wants to merge 1 commit into
python-poetry:mainfrom
MohammadYusif:fix/issue-88
Open

fix: apply column max widths when rendering tables (#88)#542
MohammadYusif wants to merge 1 commit into
python-poetry:mainfrom
MohammadYusif:fix/issue-88

Conversation

@MohammadYusif

Copy link
Copy Markdown

Summary

  • Table.set_column_max_width() wrote to _column_widths instead of _column_max_widths. Nothing else ever writes _column_max_widths, so the max-width and cell-wrapping code in _build_table_rows() was unreachable and setting a max width did nothing.
  • It was worse than a no-op: _get_cell_width() folds _column_widths in with max(), so the value actually acted as a minimum width — set_column_max_width(0, 20) padded a 2-character column out to 20, the inverse of the method name.
  • Making the branch reachable revealed a second latent defect. It asserted self._io is an Output, but Table is typed io: IO | Output and Command.table() passes an IO, which has no formatter property — so wrapping raised AssertionError for the common entry point. That assert had only ever satisfied mypy; it had never actually run.

Changes

  • src/cleo/ui/table.py: set_column_max_width() now writes _column_max_widths; the wrapping branch resolves the formatter from either an IO or an Output, mirroring how IO.remove_format() delegates.
  • tests/ui/test_table.py: added test_column_max_width_wraps_long_cells (a long cell is capped and wrapped) and test_column_max_width_does_not_widen_short_cells (a max width must not pad a narrow column). Both fail on main.
  • news/88.bugfix.md: news fragment.

I left _cleanup() alone on purpose — it resets _column_widths, but Symfony's Table::cleanup(), which this ports, resets neither. Happy to change that if you'd prefer both setters behave the same way.

Scope

Refs #88. To be precise about what this does and does not do: the literal ValueError from that 2020 report is already gone, since it came from stdlib textwrap, which no longer appears anywhere in cleo. What is still broken is that issue's own option C — cleo has the machinery to shrink a too-wide table, it just never runs. This makes it run. It does not add automatic fitting to terminal width (option A); a caller still has to set a max width explicitly. Leaving the issue open for that reason rather than auto-closing it.

`Table.set_column_max_width()` stored the width in `_column_widths`
instead of `_column_max_widths`. Since `_column_max_widths` was read in
`_build_table_rows()` and `_get_cell_width()` but never written, the
max-width and cell-wrapping machinery was unreachable: a wide column was
never capped, and because `_get_cell_width()` folds `_column_widths` in
with `max()`, the value acted as a *minimum* width and padded narrow
columns out instead.

Routing the setter to the right attribute exposes a second defect in the
now-reachable wrapping branch: it asserted the table's io was an
`Output`, but `Table` accepts `IO | Output` and `Command.table()` passes
an `IO`, so wrapping raised `AssertionError` for the common case. The
formatter is now resolved from either, mirroring `IO.remove_format()`.

This restores the documented way to fit a table that is wider than the
terminal.
@dosubot dosubot Bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Aug 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant