From 3c6e4185f7f0d033074d1ed53f598c9cfc8abff1 Mon Sep 17 00:00:00 2001 From: George Schizas Date: Tue, 27 Feb 2024 13:28:48 +0200 Subject: [PATCH 1/6] 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 11bb8655..f4bb2de5 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/6] 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 f3070b18..9fd26603 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/6] 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 520b60ea..a7826832 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 b47ea3ec..02dcc415 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) From 5efffde6bbf1a72e526c2dc35b24a31bd0480562 Mon Sep 17 00:00:00 2001 From: George Schizas Date: Wed, 2 Apr 2025 21:23:06 +0300 Subject: [PATCH 4/6] Remove setuptools dependency --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4144f9b9..944106ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ -[build-system] -requires = ["setuptools>=61.2.0", "setuptools_scm[toml]>=3.4.3"] -build-backend = "setuptools.build_meta" +#[build-system] +#requires = ["setuptools>=61.2.0", "setuptools_scm[toml]>=3.4.3"] +#build-backend = "setuptools.build_meta" [project] name = "tabulate" From 5efa7e253326d011f04034b7309edd7d1f44dd9e Mon Sep 17 00:00:00 2001 From: George Schizas Date: Wed, 2 Apr 2025 21:24:11 +0300 Subject: [PATCH 5/6] Remove setuptools dependency --- pyproject.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 944106ba..6e5b6929 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ -#[build-system] -#requires = ["setuptools>=61.2.0", "setuptools_scm[toml]>=3.4.3"] -#build-backend = "setuptools.build_meta" +# [build-system] +# requires = ["setuptools>=61.2.0", "setuptools_scm[toml]>=3.4.3"] +# build-backend = "setuptools.build_meta" [project] name = "tabulate" @@ -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" From 3ef6249547368357e631f85fda22aedfd37f551b Mon Sep 17 00:00:00 2001 From: George Schizas Date: Wed, 2 Apr 2025 21:25:38 +0300 Subject: [PATCH 6/6] Remove setuptools dependency --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6e5b6929..cdd62d56 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,5 +35,5 @@ tabulate = "tabulate:_main" # [tool.setuptools] # packages = ["tabulate"] -[tool.setuptools_scm] -write_to = "tabulate/version.py" +# [tool.setuptools_scm] +# write_to = "tabulate/version.py"