Skip to content
8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ widechars = ["wcwidth"]
[project.scripts]
tabulate = "tabulate:_main"

[tool.setuptools]
packages = ["tabulate"]
# [tool.setuptools]
# packages = ["tabulate"]

[tool.setuptools_scm]
write_to = "tabulate/version.py"
# [tool.setuptools_scm]
# write_to = "tabulate/version.py"
14 changes: 10 additions & 4 deletions tabulate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1638,7 +1638,7 @@ def _normalize_tabular_data(tabular_data, headers, showindex="default"):
return rows, headers, headers_pad


def _wrap_text_to_colwidths(list_of_lists, colwidths, numparses=True, break_long_words=_BREAK_LONG_WORDS, break_on_hyphens=_BREAK_ON_HYPHENS):
def _wrap_text_to_colwidths(list_of_lists, colwidths, numparses=True, missingval=_DEFAULT_MISSINGVAL, break_long_words=_BREAK_LONG_WORDS, break_on_hyphens=_BREAK_ON_HYPHENS):
if len(list_of_lists):
num_cols = len(list_of_lists[0])
else:
Expand All @@ -1656,7 +1656,13 @@ def _wrap_text_to_colwidths(list_of_lists, colwidths, numparses=True, break_long

if width is not None:
wrapper = _CustomTextWrap(width=width, break_long_words=break_long_words, break_on_hyphens=break_on_hyphens)
casted_cell = str(cell)
# Cast based on our internal type handling. Any future custom
# formatting of types (such as datetimes) may need to be more
# explicit than just `str` of the object. Also doesn't work for
# custom floatfmt/intfmt, nor with any missing/blank cells.
casted_cell = (
missingval if cell is None else str(cell) if cell == '' or _isnumber(cell) else _type(cell, numparse)(cell)
)
wrapped = [
"\n".join(wrapper.wrap(line))
for line in casted_cell.splitlines()
Expand Down Expand Up @@ -2258,7 +2264,7 @@ def tabulate(

numparses = _expand_numparse(disable_numparse, num_cols)
list_of_lists = _wrap_text_to_colwidths(
list_of_lists, maxcolwidths, numparses=numparses, break_long_words=break_long_words, break_on_hyphens=break_on_hyphens
list_of_lists, maxcolwidths, numparses=numparses, missingval=missingval, break_long_words=break_long_words, break_on_hyphens=break_on_hyphens
)

if maxheadercolwidths is not None:
Expand All @@ -2272,7 +2278,7 @@ def tabulate(

numparses = _expand_numparse(disable_numparse, num_cols)
headers = _wrap_text_to_colwidths(
[headers], maxheadercolwidths, numparses=numparses, break_long_words=break_long_words, break_on_hyphens=break_on_hyphens
[headers], maxheadercolwidths, numparses=numparses, missingval=missingval, break_long_words=break_long_words, break_on_hyphens=break_on_hyphens
)[0]

# empty values in the first column of RST tables should be escaped (issue #82)
Expand Down
44 changes: 44 additions & 0 deletions test/test_textwrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,50 @@ def test_wrap_datetime():
assert_equal(expected, result)


def test_wrap_none_value():
"""TextWrapper: Show that None can be wrapped without crashing"""
data = [["First Entry", None], ["Second Entry", None]]
headers = ["Title", "Value"]
result = tabulate(data, headers=headers, tablefmt="grid", maxcolwidths=[7, 5])

expected = [
"+---------+---------+",
"| Title | Value |",
"+=========+=========+",
"| First | |",
"| Entry | |",
"+---------+---------+",
"| Second | |",
"| Entry | |",
"+---------+---------+",
]
expected = "\n".join(expected)
assert_equal(expected, result)


def test_wrap_none_value_with_missingval():
"""TextWrapper: Show that None can be wrapped without crashing and with a missing value"""
data = [["First Entry", None], ["Second Entry", None]]
headers = ["Title", "Value"]
result = tabulate(
data, headers=headers, tablefmt="grid", maxcolwidths=[7, 5], missingval="???"
)

expected = [
"+---------+---------+",
"| Title | Value |",
"+=========+=========+",
"| First | ??? |",
"| Entry | |",
"+---------+---------+",
"| Second | ??? |",
"| Entry | |",
"+---------+---------+",
]
expected = "\n".join(expected)
assert_equal(expected, result)


def test_wrap_optional_bool_strs():
"""TextWrapper: Show that str bools and None can be wrapped without crashing"""
data = [
Expand Down