Hello community, here is the log from the commit of package python-texttable for openSUSE:Factory checked in at 2017-12-08 13:02:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-texttable (Old) and /work/SRC/openSUSE:Factory/.python-texttable.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-texttable" Fri Dec 8 13:02:38 2017 rev:2 rq:555176 version:1.1.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-texttable/python-texttable.changes 2015-08-26 10:01:06.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python-texttable.new/python-texttable.changes 2017-12-08 13:03:31.980369415 +0100 @@ -1,0 +2,5 @@ +Thu Dec 7 13:10:46 UTC 2017 - [email protected] + +- update to 1.1.1, no upstream changelog available + +------------------------------------------------------------------- Old: ---- texttable-0.8.3.tar.gz New: ---- texttable-1.1.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-texttable.spec ++++++ --- /var/tmp/diff_new_pack.HnkuZZ/_old 2017-12-08 13:03:33.356319722 +0100 +++ /var/tmp/diff_new_pack.HnkuZZ/_new 2017-12-08 13:03:33.360319577 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-texttable # -# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,40 +16,49 @@ # -%define upstream_name texttable +%{?!python_module:%define python_module() python-%{**} python3-%{**}} +%bcond_with test Name: python-texttable -Version: 0.8.3 +Version: 1.1.1 Release: 0 Summary: Module for creating simple ASCII tables -License: LGPL-3.0+ +License: LGPL-3.0 Group: Development/Languages/Python -Url: http://foutaise.org/code -Source0: %{upstream_name}-%{version}.tar.gz -BuildRequires: python-setuptools -BuildRoot: %{_tmppath}/%{name}-%{version}-build - -%if 0%{?suse_version} && 0%{?suse_version} <= 1110 -%{!?python_sitelib: %global python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} -%else -BuildArch: noarch +Url: https://github.com/foutaise/texttable/ +Source: https://files.pythonhosted.org/packages/source/t/texttable/texttable-%{version}.tar.gz +BuildRequires: %{python_module devel} +BuildRequires: %{python_module setuptools} +%if %{with test} +BuildRequires: python3-testsuite %endif +BuildRequires: fdupes +BuildRequires: python-rpm-macros +BuildArch: noarch + +%python_subpackages %description -Texttable is a module to generate a formatted text table, using ASCII +texttable is a module to generate a formatted text table, using ASCII characters. %prep -%setup -q -n %{upstream_name}-%{version} +%setup -q -n texttable-%{version} %build -python setup.py build +%python_build %install -python setup.py install --prefix=%{_prefix} --root=%{buildroot} +%python_install +%python_expand %fdupes %{buildroot}%{$python_sitelib} + +%if %{with test} +%check +%python_exec setup.py test +%endif -%files -%defattr(-,root,root,-) -%{python_sitelib}/%{upstream_name}.py* -%{python_sitelib}/%{upstream_name}-%{version}*egg-info +%files %{python_files} +%license LICENSE +%doc README.md +%{python_sitelib}/* %changelog ++++++ texttable-0.8.3.tar.gz -> texttable-1.1.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/texttable-0.8.3/.gitignore new/texttable-1.1.1/.gitignore --- old/texttable-0.8.3/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/texttable-1.1.1/.gitignore 2017-10-26 14:23:51.000000000 +0200 @@ -0,0 +1,7 @@ +/.cache/ +/.coverage +/.tox/ +/MANIFEST +/__pycache__/ +*.egg-info/ +*.pyc diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/texttable-0.8.3/PKG-INFO new/texttable-1.1.1/PKG-INFO --- old/texttable-0.8.3/PKG-INFO 2015-03-11 20:28:47.000000000 +0100 +++ new/texttable-1.1.1/PKG-INFO 2017-10-26 14:23:51.000000000 +0200 @@ -1,12 +1,12 @@ Metadata-Version: 1.0 Name: texttable -Version: 0.8.3 +Version: 1.1.1 Summary: module for creating simple ASCII tables -Home-page: http://foutaise.org/code/ +Home-page: https://github.com/foutaise/texttable/ Author: Gerome Fournier -Author-email: jef(at)foutaise.org +Author-email: [email protected] License: LGPL -Download-URL: http://foutaise.org/code/texttable/texttable-0.8.3.tar.gz +Download-URL: https://github.com/foutaise/texttable/archive/v1.1.1.tar.gz Description: texttable is a module to generate a formatted text table, using ASCII characters. Platform: any diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/texttable-0.8.3/README.md new/texttable-1.1.1/README.md --- old/texttable-0.8.3/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/texttable-1.1.1/README.md 2017-10-26 14:23:51.000000000 +0200 @@ -0,0 +1,233 @@ +# texttable + +Python module for creating simple ASCII tables + +## Availability + +This module is available on [PypI](https://pypi.python.org/pypi/texttable/1.1.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...). + +## Documentation + +``` +NAME + texttable - module for creating simple ASCII tables + +FILE + /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"], + ["Mr\nXavier\nHuon", 32, "Xav'"], + ["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 + '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]]) + print table.draw() + + Result: + + +----------+-----+----------+ + | Name | Age | Nickname | + +==========+=====+==========+ + | Mr | | | + | Xavier | 32 | | + | Huon | | Xav' | + +----------+-----+----------+ + | Mr | | | + | Baptiste | 1 | | + | Clement | | Baby | + +----------+-----+----------+ + | Mme | | Lou | + | Louise | 28 | | + | Bourgeau | | Loue | + +----------+-----+----------+ + + 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 + +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 callable or any of + | "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 + | * a callable: should return formatted string for any value given + | + | - 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 ...at... + __license__ = 'LGPL' + __version__ = '1.1.1' + +VERSION + 1.1.1 + +AUTHOR + Gerome Fournier <jef(at)foutaise.org> + +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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/texttable-0.8.3/setup.py new/texttable-1.1.1/setup.py --- old/texttable-0.8.3/setup.py 2015-03-11 20:29:06.000000000 +0100 +++ new/texttable-1.1.1/setup.py 2017-10-26 14:23:51.000000000 +0200 @@ -1,7 +1,7 @@ #!/usr/bin/env python # # texttable - module for creating simple ASCII tables -# Copyright (C) 2003-2011 Gerome Fournier <jef(at)foutaise.org> +# Copyright (C) 2003-2015 Gerome Fournier <jef(at)foutaise.org> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -33,11 +33,11 @@ setup( name = "texttable", - version = "0.8.3", - author = "Gerome Fournier", - author_email = "jef(at)foutaise.org", - url = "http://foutaise.org/code/", - download_url = "http://foutaise.org/code/texttable/texttable-0.8.3.tar.gz", + version = "1.1.1", + author = "Gerome Fournier", + author_email = "[email protected]", + url = "https://github.com/foutaise/texttable/", + download_url = "https://github.com/foutaise/texttable/archive/v1.1.1.tar.gz", license = "LGPL", py_modules = ["texttable"], description = DESCRIPTION, @@ -55,5 +55,11 @@ '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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/texttable-0.8.3/tests.py new/texttable-1.1.1/tests.py --- old/texttable-0.8.3/tests.py 1970-01-01 01:00:00.000000000 +0100 +++ new/texttable-1.1.1/tests.py 2017-10-26 14:23:51.000000000 +0200 @@ -0,0 +1,198 @@ +#coding: utf-8 + +import re +import sys +from textwrap import dedent +from texttable import Texttable + +if sys.version >= '3': + u_dedent = dedent +else: + def u_dedent(b): + return unicode(dedent(b), 'utf-8') + +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(): + 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 | + +-----+------------+---------+ + ''') + +def test_combining_char2(): + table = Texttable() + table.add_rows([ + ["a", "b", "c"], + ["诶诶诶", "bbb", "西西西"], + ], False) + assert clean(table.draw()) == u_dedent('''\ + +--------+-----+--------+ + | a | b | c | + +--------+-----+--------+ + | 诶诶诶 | bbb | 西西西 | + +--------+-----+--------+ + ''') + + +def test_user_dtype(): + table = Texttable() + + table.set_cols_align(["l", "r", "r"]) + table.set_cols_dtype([ + 'a', # automatic + lambda s:str(s)+"s", # user-def + lambda s:('%s'%s) if s>=0 else '[%s]'%(-s), # user-def + ]) + table.add_rows([ + ["str", "code-point\nlength", "display\nwidth"], + ["a", 2, 1], + ["a", 1,-3], + ]) + assert clean(table.draw()) == u_dedent('''\ + +-----+------------+---------+ + | str | code-point | display | + | | length | width | + +=====+============+=========+ + | a | 2s | 1 | + +-----+------------+---------+ + | a | 1s | [3] | + +-----+------------+---------+ + ''') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/texttable-0.8.3/texttable.py new/texttable-1.1.1/texttable.py --- old/texttable-0.8.3/texttable.py 2015-03-11 20:34:27.000000000 +0100 +++ new/texttable-1.1.1/texttable.py 2017-10-26 14:23:51.000000000 +0200 @@ -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 @@ 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 @@ | Baptiste | 1 | | | Clement | | Baby | +----------+-----+----------+ + | Mme | | Lou | + | Louise | 28 | | + | Bourgeau | | Loue | + +----------+-----+----------+ text float exp int auto =========================================== @@ -67,11 +70,13 @@ 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.3' +__version__ = '1.1.1' __credits__ = """\ Jeff Kowalczyk: - textwrap improved import @@ -94,15 +99,19 @@ 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': + if sys.version_info >= (2, 3): import textwrap - elif sys.version >= '2.2': + elif sys.version_info >= (2, 2): from optparse import textwrap else: from optik import textwrap @@ -110,21 +119,43 @@ sys.stderr.write("Can't import textwrap module!\n") raise -if sys.version >= '2.7': +if sys.version_info >= (2, 7): from functools import reduce +if sys.version_info >= (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__() @@ -140,6 +171,11 @@ return self.msg +class FallbackToText(Exception): + """Used for failed conversion to float""" + pass + + class Texttable: BORDER = 1 @@ -241,13 +277,15 @@ def 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": + - the elements of the array should be either a callable or any of + "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 + * a callable: should return formatted string for any value given - by default, automatic datatyping is used for each column """ @@ -291,7 +329,7 @@ """ 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 +341,7 @@ 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 +356,7 @@ 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'): @@ -356,39 +394,88 @@ out += self._hline() return out[:-1] + @classmethod + def _to_float(cls, x): + if x is None: + raise FallbackToText() + try: + return float(x) + except (TypeError, ValueError): + raise FallbackToText() + + @classmethod + def _fmt_int(cls, x, **kw): + """Integer formatting class-method. + + - x will be float-converted and then used. + """ + return str(int(round(cls._to_float(x)))) + + @classmethod + def _fmt_float(cls, x, **kw): + """Float formatting class-method. + + - x parameter is ignored. Instead kw-argument f being x float-converted + will be used. + + - precision will be taken from `n` kw-argument. + """ + n = kw.get('n') + return '%.*f' % (n, cls._to_float(x)) + + @classmethod + def _fmt_exp(cls, x, **kw): + """Exponential formatting class-method. + + - x parameter is ignored. Instead kw-argument f being x float-converted + will be used. + + - precision will be taken from `n` kw-argument. + """ + n = kw.get('n') + return '%.*e' % (n, cls._to_float(x)) + + @classmethod + def _fmt_text(cls, x, **kw): + """String formatting class-method.""" + return obj2unicode(x) + + @classmethod + def _fmt_auto(cls, x, **kw): + """auto formatting class-method.""" + f = cls._to_float(x) + if abs(f) > 1e8: + fn = cls._fmt_exp + else: + if f - round(f) == 0: + fn = cls._fmt_int + else: + fn = cls._fmt_float + return fn(x, **kw) + 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) + FMT = { + 'a':self._fmt_auto, + 'i':self._fmt_int, + 'f':self._fmt_float, + 'e':self._fmt_exp, + 't':self._fmt_text, + } n = self._precision dtype = self._dtype[i] - - if dtype == 'i': - return str(int(round(f))) - elif dtype == 'f': - return '%.*f' % (n, f) - elif dtype == 'e': - return '%.*e' % (n, f) - elif dtype == 't': - return str(x) - else: - if f - round(f) == 0: - if abs(f) > 1e8: - return '%.*e' % (n, f) - else: - return str(int(round(f))) + try: + if callable(dtype): + return dtype(x) else: - if abs(f) > 1e8: - return '%.*e' % (n, f) - else: - return '%.*f' % (n, f) + return FMT[dtype](x, n=n) + except FallbackToText: + return self._fmt_text(x) def _check_row_size(self, array): """Check that the specified array fits the previous rows size @@ -496,11 +583,25 @@ 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 +633,15 @@ 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 +655,10 @@ 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 +681,13 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/texttable-0.8.3/tox.ini new/texttable-1.1.1/tox.ini --- old/texttable-0.8.3/tox.ini 1970-01-01 01:00:00.000000000 +0100 +++ new/texttable-1.1.1/tox.ini 2017-10-26 14:23:51.000000000 +0200 @@ -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
