From 3c6e4185f7f0d033074d1ed53f598c9cfc8abff1 Mon Sep 17 00:00:00 2001 From: George Schizas Date: Tue, 27 Feb 2024 13:28:48 +0200 Subject: [PATCH 1/3] Allow columns to wrap even if they have None values within them. --- tabulate/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 11bb865..f4bb2de 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -1529,7 +1529,7 @@ def _wrap_text_to_colwidths(list_of_lists, colwidths, numparses=True): # Any future custom formatting of types (such as datetimes) # may need to be more explicit than just `str` of the object casted_cell = ( - str(cell) if _isnumber(cell) else _type(cell, numparse)(cell) + '' if cell is None else str(cell) if _isnumber(cell) else _type(cell, numparse)(cell) ) wrapped = [ "\n".join(wrapper.wrap(line)) From 3b2b69505b3962ace99ac69ee96da1224b477f1a Mon Sep 17 00:00:00 2001 From: George Schizas Date: Tue, 27 Feb 2024 13:42:58 +0200 Subject: [PATCH 2/3] Added a simple test for wrapping None values in cells --- test/test_textwrapper.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/test_textwrapper.py b/test/test_textwrapper.py index f3070b1..9fd2660 100644 --- a/test/test_textwrapper.py +++ b/test/test_textwrapper.py @@ -184,3 +184,27 @@ def test_wrap_datetime(): ] expected = "\n".join(expected) 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) From 787851ffe4350a779ba8ecd1e58c570f20d28c34 Mon Sep 17 00:00:00 2001 From: George Schizas Date: Tue, 22 Oct 2024 23:31:51 +0300 Subject: [PATCH 3/3] Use missingval instead of empty string for None values --- tabulate/__init__.py | 8 ++++---- test/test_textwrapper.py | 28 ++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 520b60e..a782683 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -1623,7 +1623,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): +def _wrap_text_to_colwidths(list_of_lists, colwidths, numparses=True, missingval=_DEFAULT_MISSINGVAL): if len(list_of_lists): num_cols = len(list_of_lists[0]) else: @@ -1646,7 +1646,7 @@ def _wrap_text_to_colwidths(list_of_lists, colwidths, numparses=True): # explicit than just `str` of the object. Also doesn't work for # custom floatfmt/intfmt, nor with any missing/blank cells. casted_cell = ( - '' if cell is None else str(cell) if _isnumber(cell) else _type(cell, numparse)(cell) + missingval if cell is None else str(cell) if _isnumber(cell) else _type(cell, numparse)(cell) ) wrapped = [ "\n".join(wrapper.wrap(line)) @@ -2247,7 +2247,7 @@ def tabulate( numparses = _expand_numparse(disable_numparse, num_cols) list_of_lists = _wrap_text_to_colwidths( - list_of_lists, maxcolwidths, numparses=numparses + list_of_lists, maxcolwidths, numparses=numparses, missingval=missingval ) if maxheadercolwidths is not None: @@ -2261,7 +2261,7 @@ def tabulate( numparses = _expand_numparse(disable_numparse, num_cols) headers = _wrap_text_to_colwidths( - [headers], maxheadercolwidths, numparses=numparses + [headers], maxheadercolwidths, numparses=numparses, missingval=missingval )[0] # empty values in the first column of RST tables should be escaped (issue #82) diff --git a/test/test_textwrapper.py b/test/test_textwrapper.py index b47ea3e..02dcc41 100644 --- a/test/test_textwrapper.py +++ b/test/test_textwrapper.py @@ -224,10 +224,7 @@ def test_wrap_datetime(): def test_wrap_none_value(): """TextWrapper: Show that None can be wrapped without crashing""" - data = [ - ["First Entry", None], - ["Second Entry", None] - ] + data = [["First Entry", None], ["Second Entry", None]] headers = ["Title", "Value"] result = tabulate(data, headers=headers, tablefmt="grid", maxcolwidths=[7, 5]) @@ -244,3 +241,26 @@ def test_wrap_none_value(): ] 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)