diff options
author | Alexander Artemenko <svetlyak.40wt@gmail.com> | 2016-05-08 01:23:59 +0300 |
---|---|---|
committer | kxxoling <kxxoling@gmail.com> | 2016-07-13 13:36:41 +0800 |
commit | 3d29afd679c95238c8857a499b06179e752bbcc3 (patch) | |
tree | a74e18d7a40dc04cff89a69dc8e0937bf363fbcc | |
parent | d0fda1050c8ac8c9df8bfe91ce711d13839271d6 (diff) | |
download | python-prettytable-ptable-3d29afd679c95238c8857a499b06179e752bbcc3.tar.gz |
Now column scaling algorithm more strictly respects "max_table_width" setting.
-rw-r--r-- | CHANGELOG.md | 9 | ||||
-rw-r--r-- | prettytable/prettytable.py | 43 | ||||
-rw-r--r-- | tests/test_prettytable.py | 47 |
3 files changed, 96 insertions, 3 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index cf0b8d1..ad7af30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## 0.10 - Unreleased + +* Now column scaling algorithm more strictly respects "max_table_width" + setting. +* 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. + ## 0.9 - 2015-05-01 * Add command line tool `ptable`. Usage: `ptable --csv=filename`. diff --git a/prettytable/prettytable.py b/prettytable/prettytable.py index d2899a8..a9d28ff 100644 --- a/prettytable/prettytable.py +++ b/prettytable/prettytable.py @@ -469,7 +469,16 @@ class PrettyTable(object): Arguments: min_width - minimum width integer""" - return self._min_width + result = { + # minimum column width can't be lesser + # than header's length + name: max( + len(name), + self._min_width.get(name, 0) + ) + for name in self._field_names + } + return result @min_width.setter def min_width(self, val): @@ -1028,9 +1037,37 @@ class PrettyTable(object): if self._max_table_width: table_width = self._compute_table_width(options) if table_width > self._max_table_width: + # get dict with minimum widths for fields + min_width = self.min_width + + # first calculate width for paddings and vrules this + # space we can't shrink. + + # Space for vrules + nonshrinkable = 2 if options["vrules"] in (FRAME, ALL) else 0 + # Space for vrules between columns + nonshrinkable += len(self._field_names) - 1 + # Space for padding in each column + per_col_padding = sum(self._get_padding_widths(options)) + nonshrinkable += len(widths) * per_col_padding + # Min space for each column + nonshrinkable += sum(min_width.values()) + # Shrink widths in proportion - scale = 1.0 * self._max_table_width / table_width - widths = [int(math.floor(w * scale)) for w in widths] + scale = float(self._max_table_width - nonshrinkable) / (table_width - nonshrinkable) + + def calculate_new_width(field_name, old_width): + width = min_width[field_name] + # scale according to recalculated table width + scaled_part = int(math.floor((old_width - width) * scale)) + # enforce minimum column width as 1 symbol + return max(1, width + scaled_part) + + widths = list(map( + calculate_new_width, + self._field_names, + widths + )) self._widths = widths # Are we under min_table_width or title width? diff --git a/tests/test_prettytable.py b/tests/test_prettytable.py index b337088..09ea4b7 100644 --- a/tests/test_prettytable.py +++ b/tests/test_prettytable.py @@ -458,6 +458,53 @@ class BreakLineTests(unittest.TestCase): """.strip() +class MaxMaxWidthsTests(unittest.TestCase): + def testMaxTableWidthIsTheLaw(self): + max_width = 127 + t = PrettyTable(max_table_width=max_width) + t.field_names = ['tag', 'versions'] + + versions = [ + 'python/django-appconf:1.0.1', + 'python/django-braces:1.8.1', + 'python/django-compressor:2.0', + 'python/django-debug-toolbar:1.4', + 'python/django-extensions:1.6.1', + ] + t.add_row(['allmychanges.com', ', '.join(versions)]) + result = t.get_string(hrules=ALL) + lines = result.strip().split('\n') + + for line in lines: + line_length = len(line) + self.assertEqual(line_length, max_width) + + + def testMaxTableWidthIsTheLawWhenMinColumnWidthSetForSomeColumns(self): + max_width = 40 + t = PrettyTable(max_table_width=max_width) + t.field_names = ['tag', 'versions'] + versions = [ + 'python/django-appconf:1.0.1', + 'python/django-braces:1.8.1', + 'python/django-compressor:2.0', + 'python/django-debug-toolbar:1.4', + 'python/django-extensions:1.6.1', + ] + t.add_row(['allmychanges.com', ', '.join(versions)]) + + # Now, we'll set min width for first column + # to not wrap it's content + t._min_width['tag'] = len('allmychanges.com') + + result = t.get_string(hrules=ALL) + lines = result.strip().split('\n') + + for line in lines: + line_length = len(line) + self.assertEqual(line_length, max_width) + + class HtmlOutputTests(unittest.TestCase): def testHtmlOutput(self): t = PrettyTable(['Field 1', 'Field 2', 'Field 3']) |