Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions tabulate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1613,6 +1613,25 @@ def _normalize_tabular_data(tabular_data, headers, showindex="default"):
return rows, headers, headers_pad


def _validate_maxcolwidth(width):
"""Return a positive int column width, or None to leave the column unbound.

``bool`` is rejected (it is an ``int`` subclass): ``True`` previously wrapped
every character. Non-ints — including ``float('nan')`` — are rejected too;
``nan`` bypassed ``width <= 0`` (comparisons with NaN are false) and hung
inside ``textwrap`` forever.
"""
if width is None:
return None
if isinstance(width, bool) or not isinstance(width, int):
raise TypeError(
f"maxcolwidths values must be positive ints or None, got {width!r}"
)
if width <= 0:
raise ValueError(f"invalid width {width!r} (must be > 0)")
return width


def _wrap_text_to_colwidths(
list_of_lists,
colwidths,
Expand All @@ -1636,6 +1655,7 @@ def _wrap_text_to_colwidths(
new_row.append(cell)
continue

width = _validate_maxcolwidth(width)
if width is not None:
wrapper = _CustomTextWrap(
width=width,
Expand Down
21 changes: 20 additions & 1 deletion test/test_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from tabulate import DataRow, Line, TableFormat, tabulate

from common import assert_equal, skip
from common import assert_equal, raises, skip


def test_ansi_color_in_table_cells():
Expand Down Expand Up @@ -598,3 +598,22 @@ def test_github_escape_pipe_character():
result = tabulate([["foo|bar"]], headers=("spam|eggs",), tablefmt="github")
expected = "| spam\\|eggs |\n|:------------|\n| foo\\|bar |"
assert_equal(expected, result)

def test_maxcolwidths_rejects_bool_float_nan():
"maxcolwidths: reject bool/float/nan (bool wrapped every char; nan hung)"
import math

for bad in (True, [True], [0.5], [float("nan")], [math.inf]):
try:
tabulate([["hello"]], maxcolwidths=bad)
raise AssertionError(f"expected TypeError for {bad!r}")
except TypeError:
pass
try:
tabulate([["hello"]], maxcolwidths=[-1])
raise AssertionError("expected ValueError for -1")
except ValueError:
pass
# None still means unbound
result = tabulate([["hello"]], maxcolwidths=[None], tablefmt="plain")
assert_equal("hello", result)