diff options
author | Alexander Artemenko <svetlyak.40wt@gmail.com> | 2016-05-08 02:24:48 +0300 |
---|---|---|
committer | kxxoling <kxxoling@gmail.com> | 2016-07-13 16:06:22 +0800 |
commit | 29ed171ffdf8c5e69e4dacff7027372ac48d073c (patch) | |
tree | c206ec68e3a430076f891cf4e8ddebd63eeb8050 | |
parent | 052f0c85f466e6cff1f383fcdb1e985d68929166 (diff) | |
download | python-prettytable-ptable-feature/support-wrapping-options.tar.gz |
New option `wrap_opts` was added.feature/support-wrapping-options
It's value is passed as keyword arguments to `textwrap.fill` function.
-rw-r--r-- | CHANGELOG.md | 9 | ||||
-rw-r--r-- | prettytable/prettytable.py | 34 | ||||
-rw-r--r-- | tests/test_prettytable.py | 58 |
3 files changed, 95 insertions, 6 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index ad7af30..8f483c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,13 @@ ## 0.10 - Unreleased -* Now column scaling algorithm more strictly respects "max_table_width" +* New option `wrap_opts` was added. It's value is passed + as keyword arguments to `textwrap.fill` function. + Read `textwrap's` [documentation](https://docs.python.org/2/library/textwrap.html#textwrap.TextWrapper) + to figure out which options are available. + +* Now column scaling algorithm more strictly respects ``max_table_width`` setting. -* Also, header's width was fixed in case when "max_table_width" was +* Also, header's width was fixed in case when ``max_table_width`` was given and calculated column's width lesser than this field name's length. Now pretty table just sets minimum column width to the width of it's name. diff --git a/prettytable/prettytable.py b/prettytable/prettytable.py index 290038a..8a5747b 100644 --- a/prettytable/prettytable.py +++ b/prettytable/prettytable.py @@ -75,6 +75,10 @@ class PrettyTable(object): self.valign = {} self.max_width = {} self.min_width = {} + # this dict contains options for textwrap's fill function + # for each field, ie: + # name -> {opts} + self.wrap_opts = {} self.int_format = {} self.float_format = {} if field_names: @@ -259,6 +263,8 @@ class PrettyTable(object): self._validate_single_char(option, val) elif option == "attributes": self._validate_attributes(option, val) + elif option == "wrap_opts": + self._validate_dict_format(option, val) def _validate_field_names(self, val): # Check for appropriate length @@ -310,6 +316,10 @@ class PrettyTable(object): except AssertionError: raise Exception("Invalid value for %s! Must be True or False." % name) + def _validate_dict_format(self, name, val): + if not isinstance(val, dict): + raise Exception("Invalid value for %s! Must be a dict." % name) + def _validate_int_format(self, name, val): if val == "": return @@ -515,6 +525,24 @@ class PrettyTable(object): self._max_table_width = val @property + def wrap_opts(self): + """Additional options for wrapping text in cells. + + These options are passed as keyword arguments to the + textwrap.fill function. + """ + return self._wrap_opts + + @wrap_opts.setter + def wrap_opts(self, val): + if not val: + self._wrap_opts = {} + else: + self._validate_option('wrap_opts', val) + for field in self._field_names: + self._wrap_opts[field] = val + + @property def fields(self): """List or tuple of field names to include in displays""" return self._fields @@ -1312,7 +1340,11 @@ class PrettyTable(object): new_lines = [] for line in lines: if _str_block_width(line) > width: - line = textwrap.fill(line, width) + line = textwrap.fill( + line, + width, + **self.wrap_opts.get(field, {}) + ) new_lines.append(line) lines = new_lines value = "\n".join(lines) diff --git a/tests/test_prettytable.py b/tests/test_prettytable.py index 8d353a7..2a34429 100644 --- a/tests/test_prettytable.py +++ b/tests/test_prettytable.py @@ -435,12 +435,64 @@ class BreakLineTests(unittest.TestCase): +------------+-------------+ """.strip() - def testHtmlBreakLine(self): + def testLongLineBreak(self): + t = PrettyTable(['F1', 'Field 2']) + t.add_row(['value 1', 'this is a really long-value2 in first row']) + t.add_row(['value 3', 'value4']) + t.max_table_width = 22 + result = t.get_string(hrules=ALL) + expected = """ ++----+--------------+ +| F1 | Field 2 | ++----+--------------+ +| va | this is a | +| lu | really long- | +| e | value2 in | +| 1 | first row | ++----+--------------+ +| va | value4 | +| lu | | +| e | | +| 3 | | ++----+--------------+ +""" + + import logging + logging.error(result.strip()) + logging.error('expected.strip(): ') + logging.error(expected.strip()) + self.assertEqual(result.strip(), expected.strip()) + + def testLongLineBreakReactsOnOptions(self): + t = PrettyTable(['F1', 'Field 2']) + t.add_row(['value 1', 'this is a really long-value2 in first row']) + t.add_row(['value 3', 'value4']) + t.max_table_width = 22 + t.wrap_opts = {'break_on_hyphens': False} + result = t.get_string(hrules=ALL) + expected = """ ++----+--------------+ +| F1 | Field 2 | ++----+--------------+ +| va | this is a | +| lu | really | +| e | long-value2 | +| 1 | in first row | ++----+--------------+ +| va | value4 | +| lu | | +| e | | +| 3 | | ++----+--------------+ +""" + self.assertEqual(result.strip(), expected.strip()) + + def testHTMLBreakLine(self): t = PrettyTable(['Field 1', 'Field 2']) t.add_row(['value 1', 'value2\nsecond line']) t.add_row(['value 3', 'value4']) result = t.get_html_string(hrules=ALL) - assert result.strip() == """ + self.assertEqual(result.strip(), """ <table> <tr> <th>Field 1</th> @@ -455,7 +507,7 @@ class BreakLineTests(unittest.TestCase): <td>value4</td> </tr> </table> -""".strip() +""".strip()) class MaxMaxWidthsTests(unittest.TestCase): |