[Python-modules-commits] [texttable] 01/05: New upstream version 0.9.1
Sergio Durigan Junior
sergiodj-guest at moszumanska.debian.org
Tue Aug 8 22:48:47 UTC 2017
This is an automated email from the git hooks/post-receive script.
sergiodj-guest pushed a commit to branch master
in repository texttable.
commit d8cd8b850aa211e94a129dbd44e182cba79fbfb6
Author: Sergio Durigan Junior <sergiodj at sergiodj.net>
Date: Tue Aug 8 18:41:53 2017 -0400
New upstream version 0.9.1
---
.gitignore | 7 +++
PKG-INFO | 4 +-
README.md | 134 ++++++++++++++++++++++++++------------------------
setup.py | 12 +++--
tests.py | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
texttable.py | 126 ++++++++++++++++++++++++++++++-----------------
tox.ini | 8 +++
7 files changed, 336 insertions(+), 112 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..21c7895
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+/.cache/
+/.coverage
+/.tox/
+/MANIFEST
+/__pycache__/
+*.egg-info/
+*.pyc
diff --git a/PKG-INFO b/PKG-INFO
index a3079ad..5167919 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,12 +1,12 @@
Metadata-Version: 1.0
Name: texttable
-Version: 0.8.4
+Version: 0.9.1
Summary: module for creating simple ASCII tables
Home-page: https://github.com/foutaise/texttable/
Author: Gerome Fournier
Author-email: jef(at)foutaise.org
License: LGPL
-Download-URL: https://github.com/foutaise/texttable/archive/v0.8.4.tar.gz
+Download-URL: https://github.com/foutaise/texttable/archive/v0.9.1.tar.gz
Description: texttable is a module to generate a formatted text table, using ASCII
characters.
Platform: any
diff --git a/README.md b/README.md
index 0d9895e..49f4b27 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ Python module for creating simple ASCII tables
## Availability
-This module is available on [PypI](https://pypi.python.org/pypi/texttable/0.8.4), and has been packaged for several Linux/Unix platforms
+This module is available on [PypI](https://pypi.python.org/pypi/texttable/0.9.1), and has been packaged for several Linux/Unix platforms
([Debian](https://packages.debian.org/search?&searchon=names&keywords=python-texttable+),
[FreeBSD](https://www.freebsd.org/cgi/ports.cgi?query=texttable&stype=all), Fedora, Suse...).
@@ -15,23 +15,24 @@ NAME
texttable - module for creating simple ASCII tables
FILE
- /usr/lib/python2.3/site-packages/texttable.py
+ /usr/local/lib/python2.7/dist-packages/texttable.py
DESCRIPTION
-
+
Example:
-
+
table = Texttable()
table.set_cols_align(["l", "r", "c"])
table.set_cols_valign(["t", "m", "b"])
- table.add_rows([["Name", "Age", "Nickname"],
+ table.add_rows([["Name", "Age", "Nickname"],
["Mr\nXavier\nHuon", 32, "Xav'"],
- ["Mr\nBaptiste\nClement", 1, "Baby"]])
+ ["Mr\nBaptiste\nClement", 1, "Baby"],
+ ["Mme\nLouise\nBourgeau", 28, "Lou\n\nLoue"]])
print table.draw() + "\n"
-
+
table = Texttable()
table.set_deco(Texttable.HEADER)
- table.set_cols_dtype(['t', # text
+ table.set_cols_dtype(['t', # text
'f', # float (decimal)
'e', # float (exponent)
'i', # integer
@@ -43,9 +44,9 @@ DESCRIPTION
["lmn", 5e-78, 5e-78, 89.4, .000000000000128],
["opqrstu", .023, 5e+78, 92., 12800000000000000000000]])
print table.draw()
-
+
Result:
-
+
+----------+-----+----------+
| Name | Age | Nickname |
+==========+=====+==========+
@@ -57,7 +58,11 @@ DESCRIPTION
| Baptiste | 1 | |
| Clement | | Baby |
+----------+-----+----------+
-
+ | Mme | | Lou |
+ | Louise | 28 | |
+ | Bourgeau | | Loue |
+ +----------+-----+----------+
+
text float exp int auto
===========================================
abcd 67.000 6.540e+02 89 128.001
@@ -68,132 +73,132 @@ DESCRIPTION
CLASSES
class Texttable
| Methods defined here:
- |
+ |
| __init__(self, max_width=80)
| Constructor
- |
+ |
| - max_width is an integer, specifying the maximum width of the table
| - if set to 0, size is unlimited, therefore cells won't be wrapped
- |
+ |
| add_row(self, array)
| Add a row in the rows stack
- |
+ |
| - cells can contain newlines and tabs
- |
+ |
| add_rows(self, rows, header=True)
| Add several rows in the rows stack
- |
+ |
| - The 'rows' argument can be either an iterator returning arrays,
| or a by-dimensional array
| - 'header' specifies if the first row should be used as the header
| of the table
- |
+ |
| draw(self)
| Draw the table
- |
+ |
| - the table is returned as a whole string
- |
+ |
| header(self, array)
| Specify the header of the table
- |
+ |
| reset(self)
| Reset the instance
- |
+ |
| - reset rows and header
- |
+ |
| set_chars(self, array)
| Set the characters used to draw lines between rows and columns
- |
+ |
| - the array should contain 4 fields:
- |
+ |
| [horizontal, vertical, corner, header]
- |
+ |
| - default is set to:
- |
+ |
| ['-', '|', '+', '=']
- |
+ |
| set_cols_align(self, array)
| Set the desired columns alignment
- |
+ |
| - the elements of the array should be either "l", "c" or "r":
- |
+ |
| * "l": column flushed left
| * "c": column centered
| * "r": column flushed right
- |
+ |
| set_cols_dtype(self, array)
| Set the desired columns datatype for the cols.
- |
+ |
| - the elements of the array should be either "a", "t", "f", "e" or "i":
- |
+ |
| * "a": automatic (try to use the most appropriate datatype)
| * "t": treat as text
| * "f": treat as float in decimal format
| * "e": treat as float in exponential format
| * "i": treat as int
- |
+ |
| - by default, automatic datatyping is used for each column
- |
+ |
| set_cols_valign(self, array)
| Set the desired columns vertical alignment
- |
+ |
| - the elements of the array should be either "t", "m" or "b":
- |
+ |
| * "t": column aligned on the top of the cell
| * "m": column aligned on the middle of the cell
| * "b": column aligned on the bottom of the cell
- |
+ |
| set_cols_width(self, array)
| Set the desired columns width
- |
+ |
| - the elements of the array should be integers, specifying the
| width of each column. For example:
- |
+ |
| [10, 20, 5]
- |
+ |
| set_deco(self, deco)
| Set the table decoration
- |
+ |
| - 'deco' can be a combinaison of:
- |
+ |
| Texttable.BORDER: Border around the table
| Texttable.HEADER: Horizontal line below the header
| Texttable.HLINES: Horizontal lines between rows
| Texttable.VLINES: Vertical lines between columns
- |
+ |
| All of them are enabled by default
- |
+ |
| - example:
- |
+ |
| Texttable.BORDER | Texttable.HEADER
- |
+ |
| set_precision(self, width)
| Set the desired precision for float/exponential formats
- |
+ |
| - width must be an integer >= 0
- |
+ |
| - default value is set to 3
- |
+ |
| ----------------------------------------------------------------------
| Data and other attributes defined here:
- |
+ |
| BORDER = 1
- |
+ |
| HEADER = 2
- |
+ |
| HLINES = 4
- |
+ |
| VLINES = 8
DATA
__all__ = ['Texttable', 'ArraySizeError']
__author__ = 'Gerome Fournier <jef(at)foutaise.org>'
- __credits__ = 'Jeff Kowalczyk:\n - textwrap improved import\n ...:\...
+ __credits__ = 'Jeff Kowalczyk:\n - textwrap improved import\n ...at...
__license__ = 'LGPL'
- __version__ = '0.8.4'
+ __version__ = '0.9.1'
VERSION
- 0.8.4
+ 0.9.1
AUTHOR
Gerome Fournier <jef(at)foutaise.org>
@@ -202,22 +207,25 @@ CREDITS
Jeff Kowalczyk:
- textwrap improved import
- comment concerning header output
-
+
Anonymous:
- add_rows method, for adding rows in one go
-
+
Sergey Simonenko:
- redefined len() function to deal with non-ASCII characters
-
+
Roger Lew:
- columns datatype specifications
-
+
Brian Peterson:
- better handling of unicode errors
-
+
Frank Sachsenheim:
- add Python 2/3-compatibility
-
+
Maximilian Hils:
- fix minor bug for Python 3 compatibility
+
+ frinkelpi:
+ - preserve empty lines
```
diff --git a/setup.py b/setup.py
index eb8c9e3..8ee4948 100644
--- a/setup.py
+++ b/setup.py
@@ -33,11 +33,11 @@ if sys.version < '2.2.3':
setup(
name = "texttable",
- version = "0.8.4",
- author = "Gerome Fournier",
+ version = "0.9.1",
+ author = "Gerome Fournier",
author_email = "jef(at)foutaise.org",
url = "https://github.com/foutaise/texttable/",
- download_url = "https://github.com/foutaise/texttable/archive/v0.8.4.tar.gz",
+ download_url = "https://github.com/foutaise/texttable/archive/v0.9.1.tar.gz",
license = "LGPL",
py_modules = ["texttable"],
description = DESCRIPTION,
@@ -55,5 +55,11 @@ setup(
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Text Processing',
'Topic :: Utilities',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
]
)
diff --git a/tests.py b/tests.py
new file mode 100644
index 0000000..b287bb1
--- /dev/null
+++ b/tests.py
@@ -0,0 +1,157 @@
+#coding: utf-8
+
+import re
+import sys
+from textwrap import dedent
+from texttable import Texttable
+
+def clean(text):
+ return re.sub(r'( +)$', '', text, flags=re.MULTILINE) + '\n'
+
+def test_texttable():
+ table = Texttable()
+ table.set_cols_align(["l", "r", "c"])
+ table.set_cols_valign(["t", "m", "b"])
+ table.add_rows([
+ ["Name", "Age", "Nickname"],
+ ["Mr\nXavier\nHuon", 32, "Xav'"],
+ ["Mr\nBaptiste\nClement", 1, "Baby"],
+ ["Mme\nLouise\nBourgeau", 28, "Lou\n \nLoue"],
+ ])
+ assert clean(table.draw()) == dedent('''\
+ +----------+-----+----------+
+ | Name | Age | Nickname |
+ +==========+=====+==========+
+ | Mr | | |
+ | Xavier | 32 | |
+ | Huon | | Xav' |
+ +----------+-----+----------+
+ | Mr | | |
+ | Baptiste | 1 | |
+ | Clement | | Baby |
+ +----------+-----+----------+
+ | Mme | | Lou |
+ | Louise | 28 | |
+ | Bourgeau | | Loue |
+ +----------+-----+----------+
+ ''')
+
+def test_texttable_header():
+ table = Texttable()
+ table.set_deco(Texttable.HEADER)
+ table.set_cols_dtype([
+ 't', # text
+ 'f', # float (decimal)
+ 'e', # float (exponent)
+ 'i', # integer
+ 'a', # automatic
+ ])
+ table.set_cols_align(["l", "r", "r", "r", "l"])
+ table.add_rows([
+ ["text", "float", "exp", "int", "auto"],
+ ["abcd", "67", 654, 89, 128.001],
+ ["efghijk", 67.5434, .654, 89.6, 12800000000000000000000.00023],
+ ["lmn", 5e-78, 5e-78, 89.4, .000000000000128],
+ ["opqrstu", .023, 5e+78, 92., 12800000000000000000000],
+ ])
+ assert clean(table.draw()) == dedent('''\
+ text float exp int auto
+ ==============================================
+ abcd 67.000 6.540e+02 89 128.001
+ efghijk 67.543 6.540e-01 90 1.280e+22
+ lmn 0.000 5.000e-78 89 0.000
+ opqrstu 0.023 5.000e+78 92 1.280e+22
+ ''')
+
+def test_set_cols_width():
+ table = Texttable()
+ table.set_deco(Texttable.HEADER)
+ table.set_cols_width([10, 10])
+ table.add_rows([
+ ["key", "value"],
+ [1, "a"],
+ [2, "b"],
+ ])
+ assert clean(table.draw()) == dedent('''\
+ key value
+ =======================
+ 1 a
+ 2 b
+ ''')
+
+def test_exceeding_max_width():
+ table = Texttable(max_width=35)
+ table.set_deco(Texttable.HEADER)
+ table.add_rows([
+ ["key", "value"],
+ [1, "a"],
+ [2, "b"],
+ [3, "very long, very long, very long"],
+ ])
+ assert clean(table.draw()) == dedent('''\
+ key value
+ ===================================
+ 1 a
+ 2 b
+ 3 very long, very long, very
+ long
+ ''')
+
+def test_exceeding_max_width2():
+ table = Texttable(max_width=14)
+ table.add_rows([
+ ["a", "b"],
+ [1, "+"],
+ [22, "++++++++"],
+ ])
+ assert clean(table.draw()) == dedent('''\
+ +----+-------+
+ | a | b |
+ +====+=======+
+ | 1 | + |
+ +----+-------+
+ | 22 | +++++ |
+ | | +++ |
+ +----+-------+
+ ''')
+
+def test_obj2unicode():
+ table = Texttable()
+ table.set_deco(Texttable.HEADER)
+ table.add_rows([
+ ["key", "value"],
+ [1, "a"],
+ [2, 1],
+ [3, None],
+ ])
+ assert clean(table.draw()) == dedent('''\
+ key value
+ ===========
+ 1 a
+ 2 1
+ 3 None
+ ''')
+
+def test_combining_char():
+ if sys.version >= '3':
+ u_dedent = dedent
+ else:
+ def u_dedent(b):
+ return unicode(dedent(b), 'utf-8')
+ table = Texttable()
+ table.set_cols_align(["l", "r", "r"])
+ table.add_rows([
+ ["str", "code-point\nlength", "display\nwidth"],
+ ["ā", 2, 1],
+ ["a", 1, 1],
+ ])
+ assert clean(table.draw()) == u_dedent('''\
+ +-----+------------+---------+
+ | str | code-point | display |
+ | | length | width |
+ +=====+============+=========+
+ | ā | 2 | 1 |
+ +-----+------------+---------+
+ | a | 1 | 1 |
+ +-----+------------+---------+
+ ''')
diff --git a/texttable.py b/texttable.py
index 775a43e..f294cd1 100644
--- a/texttable.py
+++ b/texttable.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-#
# texttable - module for creating simple ASCII tables
# Copyright (C) 2003-2015 Gerome Fournier <jef(at)foutaise.org>
#
@@ -25,14 +23,15 @@ Example:
table = Texttable()
table.set_cols_align(["l", "r", "c"])
table.set_cols_valign(["t", "m", "b"])
- table.add_rows([["Name", "Age", "Nickname"],
+ table.add_rows([["Name", "Age", "Nickname"],
["Mr\\nXavier\\nHuon", 32, "Xav'"],
- ["Mr\\nBaptiste\\nClement", 1, "Baby"]])
+ ["Mr\\nBaptiste\\nClement", 1, "Baby"],
+ ["Mme\\nLouise\\nBourgeau", 28, "Lou\\n\\nLoue"]])
print table.draw() + "\\n"
table = Texttable()
table.set_deco(Texttable.HEADER)
- table.set_cols_dtype(['t', # text
+ table.set_cols_dtype(['t', # text
'f', # float (decimal)
'e', # float (exponent)
'i', # integer
@@ -58,6 +57,10 @@ Result:
| Baptiste | 1 | |
| Clement | | Baby |
+----------+-----+----------+
+ | Mme | | Lou |
+ | Louise | 28 | |
+ | Bourgeau | | Loue |
+ +----------+-----+----------+
text float exp int auto
===========================================
@@ -67,11 +70,13 @@ Result:
mnop 0.023 5.000e+78 92 1.280e+22
"""
+from __future__ import division
+
__all__ = ["Texttable", "ArraySizeError"]
__author__ = 'Gerome Fournier <jef(at)foutaise.org>'
__license__ = 'LGPL'
-__version__ = '0.8.4'
+__version__ = '0.8.8'
__credits__ = """\
Jeff Kowalczyk:
- textwrap improved import
@@ -94,10 +99,14 @@ Frank Sachsenheim:
Maximilian Hils:
- fix minor bug for Python 3 compatibility
+
+frinkelpi:
+ - preserve empty lines
"""
import sys
import string
+import unicodedata
try:
if sys.version >= '2.3':
@@ -113,18 +122,40 @@ except ImportError:
if sys.version >= '2.7':
from functools import reduce
+if sys.version >= '3.0':
+ unicode_type = str
+ bytes_type = bytes
+else:
+ unicode_type = unicode
+ bytes_type = str
+
+
+def obj2unicode(obj):
+ """Return a unicode representation of a python object
+ """
+ if isinstance(obj, unicode_type):
+ return obj
+ elif isinstance(obj, bytes_type):
+ try:
+ return unicode_type(obj, 'utf-8')
+ except UnicodeDecodeError as strerror:
+ sys.stderr.write("UnicodeDecodeError exception for string '%s': %s\n" % (obj, strerror))
+ return unicode_type(obj, 'utf-8', 'replace')
+ else:
+ return unicode_type(obj)
+
+
def len(iterable):
"""Redefining len here so it will be able to work with non-ASCII characters
"""
- if not isinstance(iterable, str):
- return iterable.__len__()
-
- try:
- if sys.version >= '3.0':
- return len(str)
+ if isinstance(iterable, bytes_type) or isinstance(iterable, unicode_type):
+ unicode_data = obj2unicode(iterable)
+ if hasattr(unicodedata, 'east_asian_width'):
+ w = unicodedata.east_asian_width
+ return sum([w(c) in 'WF' and 2 or 0 if unicodedata.combining(c) else 1 for c in unicode_data])
else:
- return len(unicode(iterable, 'utf'))
- except:
+ return unicode_data.__len__()
+ else:
return iterable.__len__()
@@ -291,7 +322,7 @@ class Texttable:
"""
self._check_row_size(array)
- self._header = list(map(str, array))
+ self._header = list(map(obj2unicode, array))
def add_row(self, array):
"""Add a row in the rows stack
@@ -303,7 +334,7 @@ class Texttable:
if not hasattr(self, "_dtype"):
self._dtype = ["a"] * self._row_size
-
+
cells = []
for i, x in enumerate(array):
cells.append(self._str(i, x))
@@ -318,7 +349,7 @@ class Texttable:
of the table
"""
- # nb: don't use 'iter' on by-dimensional arrays, to get a
+ # nb: don't use 'iter' on by-dimensional arrays, to get a
# usable code for python 2.1
if header:
if hasattr(rows, '__iter__') and hasattr(rows, 'next'):
@@ -359,13 +390,13 @@ class Texttable:
def _str(self, i, x):
"""Handles string formatting of cell data
- i - index of the cell datatype in self._dtype
+ i - index of the cell datatype in self._dtype
x - cell data to format
"""
try:
f = float(x)
except:
- return str(x)
+ return obj2unicode(x)
n = self._precision
dtype = self._dtype[i]
@@ -377,7 +408,7 @@ class Texttable:
elif dtype == 'e':
return '%.*e' % (n, f)
elif dtype == 't':
- return str(x)
+ return obj2unicode(x)
else:
if f - round(f) == 0:
if abs(f) > 1e8:
@@ -496,11 +527,25 @@ class Texttable:
maxi[i] = max(maxi[i], self._len_cell(cell))
except (TypeError, IndexError):
maxi.append(self._len_cell(cell))
- items = len(maxi)
- length = reduce(lambda x, y: x+y, maxi)
- if self._max_width and length + items * 3 + 1 > self._max_width:
- maxi = [(self._max_width - items * 3 -1) // items \
- for n in range(items)]
+
+ ncols = len(maxi)
+ content_width = sum(maxi)
+ deco_width = 3*(ncols-1) + [0,4][self._has_border()]
+ if self._max_width and (content_width + deco_width) > self._max_width:
+ """ content too wide to fit the expected max_width
+ let's recompute maximum cell width for each cell
+ """
+ if self._max_width < (ncols + deco_width):
+ raise ValueError('max_width too low to render data')
+ available_width = self._max_width - deco_width
+ newmaxi = [0] * ncols
+ i = 0
+ while available_width > 0:
+ if newmaxi[i] < maxi[i]:
+ newmaxi[i] += 1
+ available_width -= 1
+ i = (i + 1) % ncols
+ maxi = newmaxi
self._width = maxi
def _check_align(self):
@@ -532,15 +577,15 @@ class Texttable:
if isheader:
align = "c"
if align == "r":
- out += "%s " % (fill * space + cell_line)
+ out += fill * space + cell_line
elif align == "c":
- out += "%s " % (int(fill/2) * space + cell_line \
+ out += (int(fill/2) * space + cell_line \
+ int(fill/2 + fill%2) * space)
else:
- out += "%s " % (cell_line + fill * space)
+ out += cell_line + fill * space
if length < len(line):
- out += "%s " % [space, self._char_vert][self._has_vlines()]
- out += "%s\n" % ['', self._char_vert][self._has_border()]
+ out += " %s " % [space, self._char_vert][self._has_vlines()]
+ out += "%s\n" % ['', space + self._char_vert][self._has_border()]
return out
def _splitit(self, line, isheader):
@@ -554,18 +599,10 @@ class Texttable:
for cell, width in zip(line, self._width):
array = []
for c in cell.split('\n'):
- try:
- if sys.version >= '3.0':
- c = str(c)
- else:
- c = unicode(c, 'utf')
- except UnicodeDecodeError as strerror:
- sys.stderr.write("UnicodeDecodeError exception for string '%s': %s\n" % (c, strerror))
- if sys.version >= '3.0':
- c = str(c, 'utf', 'replace')
- else:
- c = unicode(c, 'utf', 'replace')
- array.extend(textwrap.wrap(c, width))
+ if c.strip() == "":
+ array.append("")
+ else:
+ array.extend(textwrap.wrap(c, width))
line_wrapped.append(array)
max_cell_lines = reduce(max, list(map(len, line_wrapped)))
for cell, valign in zip(line_wrapped, self._valign):
@@ -588,12 +625,13 @@ if __name__ == '__main__':
table.set_cols_valign(["t", "m", "b"])
table.add_rows([["Name", "Age", "Nickname"],
["Mr\nXavier\nHuon", 32, "Xav'"],
- ["Mr\nBaptiste\nClement", 1, "Baby"]])
+ ["Mr\nBaptiste\nClement", 1, "Baby"],
+ ["Mme\nLouise\nBourgeau", 28, "Lou\n \nLoue"]])
print(table.draw() + "\n")
table = Texttable()
table.set_deco(Texttable.HEADER)
- table.set_cols_dtype(['t', # text
+ table.set_cols_dtype(['t', # text
'f', # float (decimal)
'e', # float (exponent)
'i', # integer
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..afa52d4
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,8 @@
+[tox]
+envlist = py27,py35,py36
+
+[testenv]
+deps =
+ pytest
+ pytest-cov
+commands = py.test --cov-report=term-missing --cov=texttable tests.py
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/texttable.git
More information about the Python-modules-commits
mailing list