From 6ea172bca8d2c9c456696ecfa06018fae5ba2b9f Mon Sep 17 00:00:00 2001 From: Daniel Aslau Date: Wed, 16 Nov 2022 10:59:14 +0100 Subject: [PATCH 1/3] configure break long words and on hyphen for maxcolwidths --- tabulate/__init__.py | 6 +++++- test/test_output.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 3b1a1e1..1da1150 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -33,6 +33,10 @@ def _is_file(f): # Whether or not to preserve leading/trailing whitespace in data. PRESERVE_WHITESPACE = False +# TextWrapper breaks words longer than 'width'. +BREAK_LONG_WORDS = True +# TextWrapper is breaking hyphenated words. +BREAK_ON_HYPHENS = True _DEFAULT_FLOATFMT = "g" _DEFAULT_INTFMT = "" @@ -1524,7 +1528,7 @@ def _wrap_text_to_colwidths(list_of_lists, colwidths, numparses=True): continue if width is not None: - wrapper = _CustomTextWrap(width=width) + wrapper = _CustomTextWrap(width=width, break_long_words=BREAK_LONG_WORDS, break_on_hyphens=BREAK_ON_HYPHENS) # 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 diff --git a/test/test_output.py b/test/test_output.py index 9043aed..61ec869 100644 --- a/test/test_output.py +++ b/test/test_output.py @@ -2973,3 +2973,36 @@ def test_preserve_whitespace(): expected = "\n".join(["h1 h2 h3", "---- ---- ----", "foo bar foo"]) result = tabulate(test_table, table_headers) assert_equal(expected, result) + +def test_break_long_words(): + "Output: Default table output, with breakwords true." + table_headers = ["h1", "h2", "h3"] + test_table = [[" foo1", " bar2 ", "foo3"]] + + # Table is not wrapped + tabulate_module.BREAK_LONG_WORDS = False + expected = "h1 h2 h3\n---- ---- ----\nfoo1 bar2 foo3" + result = tabulate(test_table, table_headers, maxcolwidths=3) + assert_equal(expected, result) + + # Table is wrapped on 2 letters + tabulate_module.BREAK_LONG_WORDS = True + expected = "h1 h2 h3\n---- ---- ----\nf ba foo\noo1 r2 3" + result = tabulate(test_table, table_headers, maxcolwidths=3) + assert_equal(expected, result) + +def test_break_on_hyphens(): + "Output: Default table output, with break on hyphens true." + tabulate_module.BREAK_ON_HYPHENS = False + table_headers = ["h1", "h2", "h3"] + test_table = [[" foo-bar", " bar-bar ", "foo-foo"]] + # Table is wrapped on 2 letters + expected = "h1 h2 h3\n---- ---- -----\nfoo bar- foo-f\n-bar bar oo" + result = tabulate(test_table, table_headers, maxcolwidths=5) + assert_equal(expected, result) + + # Table is no longer wrapped + tabulate_module.BREAK_ON_HYPHENS = True + expected = "h1 h2 h3\n---- ---- ----\nfoo- bar- foo-\nbar bar foo" + result = tabulate(test_table, table_headers, maxcolwidths=5) + assert_equal(expected, result) From 95eb24e598076f20a6a48622086e8b24bc9f2e92 Mon Sep 17 00:00:00 2001 From: Daniel Aslau Date: Wed, 16 Nov 2022 16:02:53 +0100 Subject: [PATCH 2/3] break long words and on hyphen for maxcolwidths --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index d64b99a..05c7a26 100644 --- a/README.md +++ b/README.md @@ -927,6 +927,14 @@ and thus no automate multiline wrapping will take place. The wrapping uses the python standard [textwrap.wrap](https://docs.python.org/3/library/textwrap.html#textwrap.wrap) function with default parameters - aside from width. +BREAK_LONG_WORDS and BREAK_LONG_WORDS can be used to turn off the TextWrapper break_long_words and break_on_hyphens options. + +```python +import tabulate +tabulate.BREAK_LONG_WORDS = False +tabulate.BREAK_ON_HYPHENS = False +``` + This example demonstrates usage of automatic multiline wrapping, though typically the lines being wrapped would probably be significantly longer than this. From ecbd67ce44cb0a47079f081326276dd153d11799 Mon Sep 17 00:00:00 2001 From: Daniel Aslau Date: Wed, 16 Nov 2022 16:37:36 +0100 Subject: [PATCH 3/3] break_long_words and break_on_hyphens as named arguments --- README.md | 33 +++++++++++++++++++++++++-------- tabulate/__init__.py | 15 +++++++++------ test/test_api.py | 2 ++ test/test_output.py | 20 ++++++++------------ 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 05c7a26..069cb3e 100644 --- a/README.md +++ b/README.md @@ -927,14 +927,6 @@ and thus no automate multiline wrapping will take place. The wrapping uses the python standard [textwrap.wrap](https://docs.python.org/3/library/textwrap.html#textwrap.wrap) function with default parameters - aside from width. -BREAK_LONG_WORDS and BREAK_LONG_WORDS can be used to turn off the TextWrapper break_long_words and break_on_hyphens options. - -```python -import tabulate -tabulate.BREAK_LONG_WORDS = False -tabulate.BREAK_ON_HYPHENS = False -``` - This example demonstrates usage of automatic multiline wrapping, though typically the lines being wrapped would probably be significantly longer than this. @@ -948,6 +940,31 @@ the lines being wrapped would probably be significantly longer than this. +------------+---------+ ``` +Text is preferably wrapped on whitespaces and right after the hyphens in hyphenated words. + +break_long_words (default: True) If true, then words longer than width will be broken in order to ensure that no lines are longer than width. +If it is false, long words will not be broken, and some lines may be longer than width. +(Long words will be put on a line by themselves, in order to minimize the amount by which width is exceeded.) + +break_on_hyphens (default: True) If true, wrapping will occur preferably on whitespaces and right after hyphens in compound words, as it is customary in English. +If false, only whitespaces will be considered as potentially good places for line breaks. + +```pycon +>>> print(tabulate([["John Smith", "Middle-Manager"]], headers=["Name", "Title"], tablefmt="grid", maxcolwidths=[None, 5], break_long_words=False)) ++------------+---------+ +| Name | Title | ++============+=========+ +| John Smith | Middle- | +| | Manager | ++------------+---------+ +>>> print(tabulate([["John Smith", "Middle-Manager"]], headers=["Name", "Title"], tablefmt="grid", maxcolwidths=[None, 5], break_long_words=False, break_on_hyphens=False)) ++------------+----------------+ +| Name | Title | ++============+================+ +| John Smith | Middle-Manager | ++------------+----------------+ +``` + ### Adding Separating lines One might want to add one or more separating lines to highlight different sections in a table. diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 1da1150..294e3b2 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -33,10 +33,11 @@ def _is_file(f): # Whether or not to preserve leading/trailing whitespace in data. PRESERVE_WHITESPACE = False + # TextWrapper breaks words longer than 'width'. -BREAK_LONG_WORDS = True +_BREAK_LONG_WORDS = True # TextWrapper is breaking hyphenated words. -BREAK_ON_HYPHENS = True +_BREAK_ON_HYPHENS = True _DEFAULT_FLOATFMT = "g" _DEFAULT_INTFMT = "" @@ -1511,7 +1512,7 @@ def _normalize_tabular_data(tabular_data, headers, showindex="default"): return rows, headers -def _wrap_text_to_colwidths(list_of_lists, colwidths, numparses=True): +def _wrap_text_to_colwidths(list_of_lists, colwidths, numparses=True, 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: @@ -1528,7 +1529,7 @@ def _wrap_text_to_colwidths(list_of_lists, colwidths, numparses=True): continue if width is not None: - wrapper = _CustomTextWrap(width=width, break_long_words=BREAK_LONG_WORDS, break_on_hyphens=BREAK_ON_HYPHENS) + wrapper = _CustomTextWrap(width=width, break_long_words=break_long_words, break_on_hyphens=break_on_hyphens) # 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 @@ -1588,6 +1589,8 @@ def tabulate( maxcolwidths=None, rowalign=None, maxheadercolwidths=None, + break_long_words=_BREAK_LONG_WORDS, + break_on_hyphens=_BREAK_ON_HYPHENS, ): """Format a fixed width table for pretty printing. @@ -2086,7 +2089,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, break_long_words=break_long_words, break_on_hyphens=break_on_hyphens ) if maxheadercolwidths is not None: @@ -2100,7 +2103,7 @@ def tabulate( numparses = _expand_numparse(disable_numparse, num_cols) headers = _wrap_text_to_colwidths( - [headers], maxheadercolwidths, numparses=numparses + [headers], maxheadercolwidths, numparses=numparses, 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) diff --git a/test/test_api.py b/test/test_api.py index 046d752..b70f2e0 100644 --- a/test/test_api.py +++ b/test/test_api.py @@ -52,6 +52,8 @@ def test_tabulate_signature(): ("maxcolwidths", None), ("rowalign", None), ("maxheadercolwidths", None), + ("break_long_words", True), + ("break_on_hyphens", True), ] _check_signature(tabulate, expected_sig) diff --git a/test/test_output.py b/test/test_output.py index 61ec869..932b6a5 100644 --- a/test/test_output.py +++ b/test/test_output.py @@ -2979,30 +2979,26 @@ def test_break_long_words(): table_headers = ["h1", "h2", "h3"] test_table = [[" foo1", " bar2 ", "foo3"]] - # Table is not wrapped - tabulate_module.BREAK_LONG_WORDS = False + # Table is not wrapped on 3 letters due to long word expected = "h1 h2 h3\n---- ---- ----\nfoo1 bar2 foo3" - result = tabulate(test_table, table_headers, maxcolwidths=3) + result = tabulate(test_table, table_headers, maxcolwidths=3, break_long_words=False) assert_equal(expected, result) - # Table is wrapped on 2 letters - tabulate_module.BREAK_LONG_WORDS = True + # Table max width is 3 letters expected = "h1 h2 h3\n---- ---- ----\nf ba foo\noo1 r2 3" - result = tabulate(test_table, table_headers, maxcolwidths=3) + result = tabulate(test_table, table_headers, maxcolwidths=3, break_long_words=True) assert_equal(expected, result) def test_break_on_hyphens(): "Output: Default table output, with break on hyphens true." - tabulate_module.BREAK_ON_HYPHENS = False table_headers = ["h1", "h2", "h3"] test_table = [[" foo-bar", " bar-bar ", "foo-foo"]] - # Table is wrapped on 2 letters + # Table max width is 5, long lines breaks on hyphens expected = "h1 h2 h3\n---- ---- -----\nfoo bar- foo-f\n-bar bar oo" - result = tabulate(test_table, table_headers, maxcolwidths=5) + result = tabulate(test_table, table_headers, maxcolwidths=5, break_on_hyphens=False) assert_equal(expected, result) - # Table is no longer wrapped - tabulate_module.BREAK_ON_HYPHENS = True + # Table data is no longer breaks on hyphens expected = "h1 h2 h3\n---- ---- ----\nfoo- bar- foo-\nbar bar foo" - result = tabulate(test_table, table_headers, maxcolwidths=5) + result = tabulate(test_table, table_headers, maxcolwidths=5, break_on_hyphens=True) assert_equal(expected, result)