summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Artemenko <svetlyak.40wt@gmail.com>2016-05-08 01:23:59 +0300
committerkxxoling <kxxoling@gmail.com>2016-07-13 13:36:41 +0800
commit3d29afd679c95238c8857a499b06179e752bbcc3 (patch)
treea74e18d7a40dc04cff89a69dc8e0937bf363fbcc
parentd0fda1050c8ac8c9df8bfe91ce711d13839271d6 (diff)
downloadpython-prettytable-ptable-3d29afd679c95238c8857a499b06179e752bbcc3.tar.gz
Now column scaling algorithm more strictly respects "max_table_width" setting.
-rw-r--r--CHANGELOG.md9
-rw-r--r--prettytable/prettytable.py43
-rw-r--r--tests/test_prettytable.py47
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'])