diff -pruN 0.8.7-0.2/benchmark.py 0.8.9-1/benchmark.py
--- 0.8.7-0.2/benchmark.py	2020-03-22 12:08:26.000000000 +0000
+++ 0.8.9-1/benchmark.py	2021-02-20 11:11:30.000000000 +0000
@@ -96,8 +96,6 @@ def benchmark(n):
     global methods
     if "--onlyself" in sys.argv[1:]:
         methods = [m for m in methods if m[0].startswith("tabulate")]
-    else:
-        methods = methods
 
     results = [
         (desc, timeit(code, setup_code, number=n) / n * 1e6) for desc, code in methods
@@ -110,9 +108,9 @@ def benchmark(n):
         results, ["Table formatter", "time, μs", "rel. time"], "rst", floatfmt=".1f"
     )
 
-    import platform
+    from platform import platform
 
-    if platform.platform().startswith("Windows"):
+    if platform().startswith("Windows"):
         print(table)
     elif python_version_tuple()[0] < "3":
         print(codecs.encode(table, "utf-8"))
diff -pruN 0.8.7-0.2/CHANGELOG 0.8.9-1/CHANGELOG
--- 0.8.7-0.2/CHANGELOG	2020-03-22 16:49:34.000000000 +0000
+++ 0.8.9-1/CHANGELOG	2021-02-22 07:19:44.000000000 +0000
@@ -1,3 +1,11 @@
+- 0.8.9: Bug fix. Revert support of decimal separators.
+- 0.8.8: Python 3.9 support, 3.10 ready.
+  New formats: ``unsafehtml``, ``latex_longtable``, ``fancy_outline``.
+  Support lists of UserDicts as input.
+  Support hyperlinks in terminal output.
+  Improve testing on systems with proxies.
+  Migrate to pytest.
+  Various bug fixes and improvements.
 - 0.8.7: Bug fixes. New format: `pretty`. HTML escaping.
 - 0.8.6: Bug fixes. Stop supporting Python 3.3, 3.4.
 - 0.8.5: Fix broken Windows package. Minor documentation updates.
diff -pruN 0.8.7-0.2/debian/changelog 0.8.9-1/debian/changelog
--- 0.8.7-0.2/debian/changelog	2021-12-04 16:25:24.000000000 +0000
+++ 0.8.9-1/debian/changelog	2021-12-08 18:12:11.000000000 +0000
@@ -1,3 +1,31 @@
+python-tabulate (0.8.9-1) unstable; urgency=medium
+
+  [ Yago González ]
+  * New upstream release.
+  * Remove git-dpm in favour of gbp.
+  * Set debian/master as the Debianized branch, following DPT's Policy.
+  * Remove unused python3-nose dependency.
+  * Remove patch for FTBFS issue with Python 3.10 (solved upstream).
+  * Update references of upstream repo.
+  * Set Vcs-* to new DPT repo.
+  * Add myself to d/copyright for debian/*.
+  * Upgrade debian/watch to v4.
+  * Upgrade debian/control to Standards Version 4.6.0.
+  * Upgrade debhelper-compat to v13.
+  * Update upstream copyright.
+  * Set the Debian Python Team as the maintainer.
+
+  [ Ondřej Nový ]
+  * Use https protocol in Format field.
+  * Use https protocol in watch URL.
+
+  [ Gordon Ball ]
+  * Update Standards-Version to 4.3.0.
+  * Declare Testsuite: autopkgtest-pkg-python so importability is tested.
+  * Re-enable build time tests.
+
+ -- Yago González <yagogonzalezg@gmail.com>  Wed, 08 Dec 2021 18:12:11 +0000
+
 python-tabulate (0.8.7-0.2) unstable; urgency=medium
 
   * Non-maintainer upload.
diff -pruN 0.8.7-0.2/debian/compat 0.8.9-1/debian/compat
--- 0.8.7-0.2/debian/compat	2021-12-04 16:14:37.000000000 +0000
+++ 0.8.9-1/debian/compat	1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-10
diff -pruN 0.8.7-0.2/debian/control 0.8.9-1/debian/control
--- 0.8.7-0.2/debian/control	2021-12-04 16:14:37.000000000 +0000
+++ 0.8.9-1/debian/control	2021-12-08 18:12:11.000000000 +0000
@@ -1,16 +1,19 @@
 Source: python-tabulate
 Priority: optional
-Maintainer: Yago González <yagogonzalezg@gmail.com>
-Uploaders: ChangZhuo Chen (陳昌倬) <czchen@debian.org>,
-Build-Depends: debhelper (>= 10),
+Maintainer: Debian Python Team <team+python@tracker.debian.org>
+Uploaders: Yago González <yagogonzalezg@gmail.com>,
+ ChangZhuo Chen (陳昌倬) <czchen@debian.org>
+Build-Depends: debhelper-compat (= 13),
                dh-python,
                python3-all,
-               python3-nose,
                python3-setuptools,
                python3-wcwidth,
-Standards-Version: 3.9.8
+Standards-Version: 4.6.0
 Section: python
-Homepage: https://bitbucket.org/astanin/python-tabulate/
+Homepage: https://github.com/astanin/python-tabulate/
+Vcs-Git: https://salsa.debian.org/python-team/packages/python-tabulate.git
+Vcs-Browser: https://salsa.debian.org/python-team/packages/python-tabulate
+Testsuite: autopkgtest-pkg-python
 
 Package: python3-tabulate
 Architecture: all
diff -pruN 0.8.7-0.2/debian/copyright 0.8.9-1/debian/copyright
--- 0.8.7-0.2/debian/copyright	2021-12-04 16:14:37.000000000 +0000
+++ 0.8.9-1/debian/copyright	2021-12-08 18:12:11.000000000 +0000
@@ -1,14 +1,16 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
 Upstream-Name: python-tabulate
-Source: https://bitbucket.org/astanin/python-tabulate
+Source: https://github.com/astanin/python-tabulate
 
 Files: *
-Copyright: Copyright (c) 2011-2016 Sergey Astanin <s.astanin@gmail.com>
+Copyright: Copyright (c) 2011-2020 Sergey Astanin <s.astanin@gmail.com> and
+ contributors
 License: Expat
 
 Files: debian/*
 Copyright: 2015 ChangZhuo Chen (陳昌倬) <czchen@debian.org>
  2016 Sandro Tosi <morph@debian.org>
+ 2018-2021 Yago González <yagogonzalezg@gmail.com>
 License: Expat
 
 License: Expat
diff -pruN 0.8.7-0.2/debian/gbp.conf 0.8.9-1/debian/gbp.conf
--- 0.8.7-0.2/debian/gbp.conf	2021-12-04 16:14:37.000000000 +0000
+++ 0.8.9-1/debian/gbp.conf	2021-12-08 18:12:11.000000000 +0000
@@ -1,2 +1,3 @@
 [DEFAULT]
+debian-branch = debian/master
 pristine-tar = True
diff -pruN 0.8.7-0.2/debian/.git-dpm 0.8.9-1/debian/.git-dpm
--- 0.8.7-0.2/debian/.git-dpm	2021-12-04 16:14:37.000000000 +0000
+++ 0.8.9-1/debian/.git-dpm	1970-01-01 00:00:00.000000000 +0000
@@ -1,11 +0,0 @@
-# see git-dpm(1) from git-dpm package
-3aa23bd9f6b7172b47447c192a6f09137fd6d8e8
-3aa23bd9f6b7172b47447c192a6f09137fd6d8e8
-3aa23bd9f6b7172b47447c192a6f09137fd6d8e8
-3aa23bd9f6b7172b47447c192a6f09137fd6d8e8
-python-tabulate_0.7.7.orig.tar.gz
-9021b475eefb357deb12f7b0e59a12457411472c
-39140
-debianTag="debian/%e%v"
-patchedTag="patched/%e%v"
-upstreamTag="upstream/%e%u"
diff -pruN 0.8.7-0.2/debian/patches/fix-3.10-FTBFS.patch 0.8.9-1/debian/patches/fix-3.10-FTBFS.patch
--- 0.8.7-0.2/debian/patches/fix-3.10-FTBFS.patch	2021-12-04 16:24:44.000000000 +0000
+++ 0.8.9-1/debian/patches/fix-3.10-FTBFS.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,17 +0,0 @@
-Description: Rather than comparing python tuple which is rather sloppy, use try-except block to get Iterable
-Author: Nilesh Patra <nilesh@debian.org>
-Last-Update: 2021-12-04
---- a/tabulate.py
-+++ b/tabulate.py
-@@ -10,9 +10,9 @@
- import math
- 
- 
--if python_version_tuple() >= ("3", "3", "0"):
-+try:
-     from collections.abc import Iterable
--else:
-+except ImportError:
-     from collections import Iterable
- 
- if python_version_tuple()[0] < "3":
diff -pruN 0.8.7-0.2/debian/patches/series 0.8.9-1/debian/patches/series
--- 0.8.7-0.2/debian/patches/series	2021-12-04 16:22:29.000000000 +0000
+++ 0.8.9-1/debian/patches/series	1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-fix-3.10-FTBFS.patch
diff -pruN 0.8.7-0.2/debian/rules 0.8.9-1/debian/rules
--- 0.8.7-0.2/debian/rules	2021-12-04 16:14:37.000000000 +0000
+++ 0.8.9-1/debian/rules	2021-12-08 18:12:11.000000000 +0000
@@ -4,6 +4,3 @@ export PYBUILD_NAME = tabulate
 
 %:
 	dh $@ --with python3 --buildsystem=pybuild
-
-override_dh_auto_test:
-	echo "https://bitbucket.org/astanin/python-tabulate/issues/106/test-commonpy-not-release-in-pypi-tarball"
diff -pruN 0.8.7-0.2/debian/tabulate.1 0.8.9-1/debian/tabulate.1
--- 0.8.7-0.2/debian/tabulate.1	2021-12-04 16:14:37.000000000 +0000
+++ 0.8.9-1/debian/tabulate.1	2021-12-08 18:12:11.000000000 +0000
@@ -7,7 +7,7 @@ tabulate \- Pretty-print tabulate data.
 [\fI\,options\/\fR]
 [\fI\,FILE ...\/\fR]
 .SH DESCRIPTION
-See also <https://bitbucket.org/astanin/python-tabulate>.
+See also <https://github.com/astanin/python-tabulate>.
 
 .SH OPTIONS
 .TP
diff -pruN 0.8.7-0.2/debian/watch 0.8.9-1/debian/watch
--- 0.8.7-0.2/debian/watch	2021-12-04 16:14:37.000000000 +0000
+++ 0.8.9-1/debian/watch	2021-12-08 18:12:11.000000000 +0000
@@ -1,3 +1,3 @@
-version=3
+version=4
 opts=uversionmangle=s/(rc|a|b|c)/~$1/ \
-http://pypi.debian.net/tabulate/tabulate-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz)))
+https://pypi.debian.net/tabulate/tabulate-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz)))
\ No newline at end of file
diff -pruN 0.8.7-0.2/PKG-INFO 0.8.9-1/PKG-INFO
--- 0.8.7-0.2/PKG-INFO	2020-03-22 16:53:35.577126000 +0000
+++ 0.8.9-1/PKG-INFO	2021-02-22 07:31:54.646124400 +0000
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: tabulate
-Version: 0.8.7
+Version: 0.8.9
 Summary: Pretty-print tabular data
 Home-page: https://github.com/astanin/python-tabulate
 Author: Sergey Astanin
@@ -149,10 +149,13 @@ Description: python-tabulate
         -   "moinmoin"
         -   "youtrack"
         -   "html"
+        -   "unsafehtml"
         -   "latex"
         -   "latex\_raw"
         -   "latex\_booktabs"
+        -   "latex\_longtable"
         -   "textile"
+        -   "tsv"
         
         `plain` tables do not use any pseudo-graphics to draw lines:
         
@@ -175,7 +178,7 @@ Description: python-tabulate
             eggs      451
             bacon       0
         
-        `github` follows the conventions of Github flavored Markdown. It
+        `github` follows the conventions of GitHub flavored Markdown. It
         corresponds to the `pipe` format without alignment colons:
         
             >>> print(tabulate(table, headers, tablefmt="github"))
@@ -334,7 +337,8 @@ Description: python-tabulate
         
         `html` produces standard HTML markup as an html.escape'd str
         with a ._repr_html_ method so that Jupyter Lab and Notebook display the HTML
-        and a .str property so that the raw HTML remains accessible:
+        and a .str property so that the raw HTML remains accessible.
+        `unsafehtml` table format can be used if an unescaped HTML is required:
         
             >>> print(tabulate(table, headers, tablefmt="html"))
             <table>
@@ -367,6 +371,9 @@ Description: python-tabulate
         `latex_booktabs` creates a `tabular` environment for LaTeX markup using
         spacing and style from the `booktabs` package.
         
+        `latex_longtable` creates a table that can stretch along multiple pages,
+        using the `longtable` package.
+        
         ### Column alignment
         
         `tabulate` is smart about column alignment. It detects columns which
@@ -649,7 +656,7 @@ Description: python-tabulate
             -f FMT, --format FMT      set output table format; supported formats:
                                       plain, simple, github, grid, fancy_grid, pipe,
                                       orgtbl, rst, mediawiki, html, latex, latex_raw,
-                                      latex_booktabs, tsv
+                                      latex_booktabs, latex_longtable, tsv
                                       (default: simple)
         
         Performance considerations
@@ -666,24 +673,25 @@ Description: python-tabulate
         It may not be suitable for serializing really big tables (but who's
         going to do that, anyway?) or printing tables in performance sensitive
         applications. `tabulate` is about two orders of magnitude slower than
-        simply joining lists of values with a tab, coma or other separator.
+        simply joining lists of values with a tab, comma, or other separator.
         
-        In the same time `tabulate` is comparable to other table
+        At the same time, `tabulate` is comparable to other table
         pretty-printers. Given a 10x10 table (a list of lists) of mixed text and
         numeric data, `tabulate` appears to be slower than `asciitable`, and
         faster than `PrettyTable` and `texttable` The following mini-benchmark
-        was run in Python 3.8.1 in Windows 10 x64:
+        was run in Python 3.8.3 in Windows 10 x64:
         
-            ===========================  ==========  ===========
-            Table formatter                time, μs    rel. time
-            ===========================  ==========  ===========
-            csv to StringIO                    12.4          1.0
-            join with tabs and newlines        15.7          1.3
-            asciitable (0.8.0)                208.3         16.7
-            tabulate (0.8.7)                  492.1         39.5
-            PrettyTable (0.7.2)               945.5         76.0
-            texttable (1.6.2)                1239.5         99.6
-            ===========================  ==========  ===========
+            =================================  ==========  ===========
+            Table formatter                      time, μs    rel. time
+            =================================  ==========  ===========
+            csv to StringIO                          12.5          1.0
+            join with tabs and newlines              15.6          1.3
+            asciitable (0.8.0)                      191.4         15.4
+            tabulate (0.8.9)                        472.8         38.0
+            tabulate (0.8.9, WIDE_CHARS_MODE)       789.6         63.4
+            PrettyTable (0.7.2)                     879.1         70.6
+            texttable (1.6.2)                      1352.2        108.6
+            =================================  ==========  ===========
         
         
         Version history
@@ -698,13 +706,13 @@ Description: python-tabulate
         they propose. Documentation (examples, docstrings, README.md) should be
         updated accordingly.
         
-        This project uses [nose](https://nose.readthedocs.org/) testing
+        This project uses [pytest](https://docs.pytest.org/) testing
         framework and [tox](https://tox.readthedocs.io/) to automate testing in
         different environments. Add tests to one of the files in the `test/`
         folder.
         
         To run tests on all supported Python versions, make sure all Python
-        interpreters, `nose` and `tox` are installed, then run `tox` in the root
+        interpreters, `pytest` and `tox` are installed, then run `tox` in the root
         of the project source tree.
         
         On Linux `tox` expects to find executables like `python2.6`,
@@ -712,21 +720,25 @@ Description: python-tabulate
         `C:\Python26\python.exe`, `C:\Python27\python.exe` and
         `C:\Python34\python.exe` respectively.
         
-        To test only some Python environements, use `-e` option. For example, to
-        test only against Python 2.7 and Python 3.6, run:
+        To test only some Python environments, use `-e` option. For example, to
+        test only against Python 2.7 and Python 3.8, run:
         
-            tox -e py27,py36
+            tox -e py27,py38
         
         in the root of the project source tree.
         
         To enable NumPy and Pandas tests, run:
         
-            tox -e py27-extra,py36-extra
+            tox -e py27-extra,py38-extra
         
         (this may take a long time the first time, because NumPy and Pandas will
         have to be installed in the new virtual environments)
         
-        See `tox.ini` file to learn how to use `nosetests` directly to test
+        To fix code formatting:
+        
+            tox -e lint
+        
+        See `tox.ini` file to learn how to use to test
         individual Python versions.
         
         Contributors
@@ -742,8 +754,11 @@ Description: python-tabulate
         Nick Satterly, Daniel Robbins, Dmitry B, Lars Butler, Andreas Maier,
         Dick Marinus, Sébastien Celles, Yago González, Andrew Gaul, Wim Glenn,
         Jean Michel Rouly, Tim Gates, John Vandenberg, Sorin Sbarnea,
-        Wes Turner, Andrew Tija, Marco Gorelli, Sean McGinnis.
-        
+        Wes Turner, Andrew Tija, Marco Gorelli, Sean McGinnis, danja100,
+        endolith, Dominic Davis-Foster, pavlocat, Daniel Aslau, paulc,
+        Felix Yan, Shane Loretz, Frank Busse, Harsh Singh, Derek Weitzel,
+        Vladimir Vrzić, 서승우 (chrd5273), Georgy Frolov, Christian Cwienk,
+        Bart Broere, Vilhelm Prytz.
         
 Platform: UNKNOWN
 Classifier: Development Status :: 4 - Beta
@@ -756,6 +771,7 @@ Classifier: Programming Language :: Pyth
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
 Classifier: Topic :: Software Development :: Libraries
 Description-Content-Type: text/markdown
 Provides-Extra: widechars
diff -pruN 0.8.7-0.2/README.md 0.8.9-1/README.md
--- 0.8.7-0.2/README.md	2020-03-22 16:46:52.000000000 +0000
+++ 0.8.9-1/README.md	2021-02-22 07:31:03.000000000 +0000
@@ -149,10 +149,13 @@ Supported table formats are:
 -   "moinmoin"
 -   "youtrack"
 -   "html"
+-   "unsafehtml"
 -   "latex"
 -   "latex\_raw"
 -   "latex\_booktabs"
+-   "latex\_longtable"
 -   "textile"
+-   "tsv"
 
 `plain` tables do not use any pseudo-graphics to draw lines:
 
@@ -175,7 +178,7 @@ extensions](http://johnmacfarlane.net/pa
     eggs      451
     bacon       0
 
-`github` follows the conventions of Github flavored Markdown. It
+`github` follows the conventions of GitHub flavored Markdown. It
 corresponds to the `pipe` format without alignment colons:
 
     >>> print(tabulate(table, headers, tablefmt="github"))
@@ -334,7 +337,8 @@ MediaWiki-based sites:
 
 `html` produces standard HTML markup as an html.escape'd str
 with a ._repr_html_ method so that Jupyter Lab and Notebook display the HTML
-and a .str property so that the raw HTML remains accessible:
+and a .str property so that the raw HTML remains accessible.
+`unsafehtml` table format can be used if an unescaped HTML is required:
 
     >>> print(tabulate(table, headers, tablefmt="html"))
     <table>
@@ -367,6 +371,9 @@ special characters.
 `latex_booktabs` creates a `tabular` environment for LaTeX markup using
 spacing and style from the `booktabs` package.
 
+`latex_longtable` creates a table that can stretch along multiple pages,
+using the `longtable` package.
+
 ### Column alignment
 
 `tabulate` is smart about column alignment. It detects columns which
@@ -649,7 +656,7 @@ Usage of the command line utility
     -f FMT, --format FMT      set output table format; supported formats:
                               plain, simple, github, grid, fancy_grid, pipe,
                               orgtbl, rst, mediawiki, html, latex, latex_raw,
-                              latex_booktabs, tsv
+                              latex_booktabs, latex_longtable, tsv
                               (default: simple)
 
 Performance considerations
@@ -666,24 +673,25 @@ as a number imply that `tabulate`:
 It may not be suitable for serializing really big tables (but who's
 going to do that, anyway?) or printing tables in performance sensitive
 applications. `tabulate` is about two orders of magnitude slower than
-simply joining lists of values with a tab, coma or other separator.
+simply joining lists of values with a tab, comma, or other separator.
 
-In the same time `tabulate` is comparable to other table
+At the same time, `tabulate` is comparable to other table
 pretty-printers. Given a 10x10 table (a list of lists) of mixed text and
 numeric data, `tabulate` appears to be slower than `asciitable`, and
 faster than `PrettyTable` and `texttable` The following mini-benchmark
-was run in Python 3.8.1 in Windows 10 x64:
+was run in Python 3.8.3 in Windows 10 x64:
 
-    ===========================  ==========  ===========
-    Table formatter                time, μs    rel. time
-    ===========================  ==========  ===========
-    csv to StringIO                    12.4          1.0
-    join with tabs and newlines        15.7          1.3
-    asciitable (0.8.0)                208.3         16.7
-    tabulate (0.8.7)                  492.1         39.5
-    PrettyTable (0.7.2)               945.5         76.0
-    texttable (1.6.2)                1239.5         99.6
-    ===========================  ==========  ===========
+    =================================  ==========  ===========
+    Table formatter                      time, μs    rel. time
+    =================================  ==========  ===========
+    csv to StringIO                          12.5          1.0
+    join with tabs and newlines              15.6          1.3
+    asciitable (0.8.0)                      191.4         15.4
+    tabulate (0.8.9)                        472.8         38.0
+    tabulate (0.8.9, WIDE_CHARS_MODE)       789.6         63.4
+    PrettyTable (0.7.2)                     879.1         70.6
+    texttable (1.6.2)                      1352.2        108.6
+    =================================  ==========  ===========
 
 
 Version history
@@ -698,13 +706,13 @@ Contributions should include tests and a
 they propose. Documentation (examples, docstrings, README.md) should be
 updated accordingly.
 
-This project uses [nose](https://nose.readthedocs.org/) testing
+This project uses [pytest](https://docs.pytest.org/) testing
 framework and [tox](https://tox.readthedocs.io/) to automate testing in
 different environments. Add tests to one of the files in the `test/`
 folder.
 
 To run tests on all supported Python versions, make sure all Python
-interpreters, `nose` and `tox` are installed, then run `tox` in the root
+interpreters, `pytest` and `tox` are installed, then run `tox` in the root
 of the project source tree.
 
 On Linux `tox` expects to find executables like `python2.6`,
@@ -712,21 +720,25 @@ On Linux `tox` expects to find executabl
 `C:\Python26\python.exe`, `C:\Python27\python.exe` and
 `C:\Python34\python.exe` respectively.
 
-To test only some Python environements, use `-e` option. For example, to
-test only against Python 2.7 and Python 3.6, run:
+To test only some Python environments, use `-e` option. For example, to
+test only against Python 2.7 and Python 3.8, run:
 
-    tox -e py27,py36
+    tox -e py27,py38
 
 in the root of the project source tree.
 
 To enable NumPy and Pandas tests, run:
 
-    tox -e py27-extra,py36-extra
+    tox -e py27-extra,py38-extra
 
 (this may take a long time the first time, because NumPy and Pandas will
 have to be installed in the new virtual environments)
 
-See `tox.ini` file to learn how to use `nosetests` directly to test
+To fix code formatting:
+
+    tox -e lint
+
+See `tox.ini` file to learn how to use to test
 individual Python versions.
 
 Contributors
@@ -742,5 +754,8 @@ Maier, Andy MacKinlay, Thomas Roten, Jue
 Nick Satterly, Daniel Robbins, Dmitry B, Lars Butler, Andreas Maier,
 Dick Marinus, Sébastien Celles, Yago González, Andrew Gaul, Wim Glenn,
 Jean Michel Rouly, Tim Gates, John Vandenberg, Sorin Sbarnea,
-Wes Turner, Andrew Tija, Marco Gorelli, Sean McGinnis.
-
+Wes Turner, Andrew Tija, Marco Gorelli, Sean McGinnis, danja100,
+endolith, Dominic Davis-Foster, pavlocat, Daniel Aslau, paulc,
+Felix Yan, Shane Loretz, Frank Busse, Harsh Singh, Derek Weitzel,
+Vladimir Vrzić, 서승우 (chrd5273), Georgy Frolov, Christian Cwienk,
+Bart Broere, Vilhelm Prytz.
diff -pruN 0.8.7-0.2/setup.py 0.8.9-1/setup.py
--- 0.8.7-0.2/setup.py	2020-03-22 12:08:26.000000000 +0000
+++ 0.8.9-1/setup.py	2021-02-18 00:37:08.000000000 +0000
@@ -38,7 +38,7 @@ else:
 
 setup(
     name="tabulate",
-    version="0.8.7",
+    version="0.8.9",
     description="Pretty-print tabular data",
     long_description=LONG_DESCRIPTION,
     long_description_content_type="text/markdown",
@@ -57,10 +57,10 @@ setup(
         "Programming Language :: Python :: 3.6",
         "Programming Language :: Python :: 3.7",
         "Programming Language :: Python :: 3.8",
+        "Programming Language :: Python :: 3.9",
         "Topic :: Software Development :: Libraries",
     ],
     py_modules=["tabulate"],
     entry_points={"console_scripts": console_scripts},
     extras_require={"widechars": ["wcwidth"]},
-    test_suite="nose.collector",
 )
diff -pruN 0.8.7-0.2/tabulate.egg-info/PKG-INFO 0.8.9-1/tabulate.egg-info/PKG-INFO
--- 0.8.7-0.2/tabulate.egg-info/PKG-INFO	2020-03-22 16:53:35.000000000 +0000
+++ 0.8.9-1/tabulate.egg-info/PKG-INFO	2021-02-22 07:31:54.000000000 +0000
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: tabulate
-Version: 0.8.7
+Version: 0.8.9
 Summary: Pretty-print tabular data
 Home-page: https://github.com/astanin/python-tabulate
 Author: Sergey Astanin
@@ -149,10 +149,13 @@ Description: python-tabulate
         -   "moinmoin"
         -   "youtrack"
         -   "html"
+        -   "unsafehtml"
         -   "latex"
         -   "latex\_raw"
         -   "latex\_booktabs"
+        -   "latex\_longtable"
         -   "textile"
+        -   "tsv"
         
         `plain` tables do not use any pseudo-graphics to draw lines:
         
@@ -175,7 +178,7 @@ Description: python-tabulate
             eggs      451
             bacon       0
         
-        `github` follows the conventions of Github flavored Markdown. It
+        `github` follows the conventions of GitHub flavored Markdown. It
         corresponds to the `pipe` format without alignment colons:
         
             >>> print(tabulate(table, headers, tablefmt="github"))
@@ -334,7 +337,8 @@ Description: python-tabulate
         
         `html` produces standard HTML markup as an html.escape'd str
         with a ._repr_html_ method so that Jupyter Lab and Notebook display the HTML
-        and a .str property so that the raw HTML remains accessible:
+        and a .str property so that the raw HTML remains accessible.
+        `unsafehtml` table format can be used if an unescaped HTML is required:
         
             >>> print(tabulate(table, headers, tablefmt="html"))
             <table>
@@ -367,6 +371,9 @@ Description: python-tabulate
         `latex_booktabs` creates a `tabular` environment for LaTeX markup using
         spacing and style from the `booktabs` package.
         
+        `latex_longtable` creates a table that can stretch along multiple pages,
+        using the `longtable` package.
+        
         ### Column alignment
         
         `tabulate` is smart about column alignment. It detects columns which
@@ -649,7 +656,7 @@ Description: python-tabulate
             -f FMT, --format FMT      set output table format; supported formats:
                                       plain, simple, github, grid, fancy_grid, pipe,
                                       orgtbl, rst, mediawiki, html, latex, latex_raw,
-                                      latex_booktabs, tsv
+                                      latex_booktabs, latex_longtable, tsv
                                       (default: simple)
         
         Performance considerations
@@ -666,24 +673,25 @@ Description: python-tabulate
         It may not be suitable for serializing really big tables (but who's
         going to do that, anyway?) or printing tables in performance sensitive
         applications. `tabulate` is about two orders of magnitude slower than
-        simply joining lists of values with a tab, coma or other separator.
+        simply joining lists of values with a tab, comma, or other separator.
         
-        In the same time `tabulate` is comparable to other table
+        At the same time, `tabulate` is comparable to other table
         pretty-printers. Given a 10x10 table (a list of lists) of mixed text and
         numeric data, `tabulate` appears to be slower than `asciitable`, and
         faster than `PrettyTable` and `texttable` The following mini-benchmark
-        was run in Python 3.8.1 in Windows 10 x64:
+        was run in Python 3.8.3 in Windows 10 x64:
         
-            ===========================  ==========  ===========
-            Table formatter                time, μs    rel. time
-            ===========================  ==========  ===========
-            csv to StringIO                    12.4          1.0
-            join with tabs and newlines        15.7          1.3
-            asciitable (0.8.0)                208.3         16.7
-            tabulate (0.8.7)                  492.1         39.5
-            PrettyTable (0.7.2)               945.5         76.0
-            texttable (1.6.2)                1239.5         99.6
-            ===========================  ==========  ===========
+            =================================  ==========  ===========
+            Table formatter                      time, μs    rel. time
+            =================================  ==========  ===========
+            csv to StringIO                          12.5          1.0
+            join with tabs and newlines              15.6          1.3
+            asciitable (0.8.0)                      191.4         15.4
+            tabulate (0.8.9)                        472.8         38.0
+            tabulate (0.8.9, WIDE_CHARS_MODE)       789.6         63.4
+            PrettyTable (0.7.2)                     879.1         70.6
+            texttable (1.6.2)                      1352.2        108.6
+            =================================  ==========  ===========
         
         
         Version history
@@ -698,13 +706,13 @@ Description: python-tabulate
         they propose. Documentation (examples, docstrings, README.md) should be
         updated accordingly.
         
-        This project uses [nose](https://nose.readthedocs.org/) testing
+        This project uses [pytest](https://docs.pytest.org/) testing
         framework and [tox](https://tox.readthedocs.io/) to automate testing in
         different environments. Add tests to one of the files in the `test/`
         folder.
         
         To run tests on all supported Python versions, make sure all Python
-        interpreters, `nose` and `tox` are installed, then run `tox` in the root
+        interpreters, `pytest` and `tox` are installed, then run `tox` in the root
         of the project source tree.
         
         On Linux `tox` expects to find executables like `python2.6`,
@@ -712,21 +720,25 @@ Description: python-tabulate
         `C:\Python26\python.exe`, `C:\Python27\python.exe` and
         `C:\Python34\python.exe` respectively.
         
-        To test only some Python environements, use `-e` option. For example, to
-        test only against Python 2.7 and Python 3.6, run:
+        To test only some Python environments, use `-e` option. For example, to
+        test only against Python 2.7 and Python 3.8, run:
         
-            tox -e py27,py36
+            tox -e py27,py38
         
         in the root of the project source tree.
         
         To enable NumPy and Pandas tests, run:
         
-            tox -e py27-extra,py36-extra
+            tox -e py27-extra,py38-extra
         
         (this may take a long time the first time, because NumPy and Pandas will
         have to be installed in the new virtual environments)
         
-        See `tox.ini` file to learn how to use `nosetests` directly to test
+        To fix code formatting:
+        
+            tox -e lint
+        
+        See `tox.ini` file to learn how to use to test
         individual Python versions.
         
         Contributors
@@ -742,8 +754,11 @@ Description: python-tabulate
         Nick Satterly, Daniel Robbins, Dmitry B, Lars Butler, Andreas Maier,
         Dick Marinus, Sébastien Celles, Yago González, Andrew Gaul, Wim Glenn,
         Jean Michel Rouly, Tim Gates, John Vandenberg, Sorin Sbarnea,
-        Wes Turner, Andrew Tija, Marco Gorelli, Sean McGinnis.
-        
+        Wes Turner, Andrew Tija, Marco Gorelli, Sean McGinnis, danja100,
+        endolith, Dominic Davis-Foster, pavlocat, Daniel Aslau, paulc,
+        Felix Yan, Shane Loretz, Frank Busse, Harsh Singh, Derek Weitzel,
+        Vladimir Vrzić, 서승우 (chrd5273), Georgy Frolov, Christian Cwienk,
+        Bart Broere, Vilhelm Prytz.
         
 Platform: UNKNOWN
 Classifier: Development Status :: 4 - Beta
@@ -756,6 +771,7 @@ Classifier: Programming Language :: Pyth
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
 Classifier: Topic :: Software Development :: Libraries
 Description-Content-Type: text/markdown
 Provides-Extra: widechars
diff -pruN 0.8.7-0.2/tabulate.py 0.8.9-1/tabulate.py
--- 0.8.7-0.2/tabulate.py	2020-03-22 12:08:26.000000000 +0000
+++ 0.8.9-1/tabulate.py	2021-02-20 11:11:30.000000000 +0000
@@ -5,17 +5,17 @@
 from __future__ import print_function
 from __future__ import unicode_literals
 from collections import namedtuple
-from platform import python_version_tuple
+import sys
 import re
 import math
 
 
-if python_version_tuple() >= ("3", "3", "0"):
+if sys.version_info >= (3, 3):
     from collections.abc import Iterable
 else:
     from collections import Iterable
 
-if python_version_tuple()[0] < "3":
+if sys.version_info[0] < 3:
     from itertools import izip_longest
     from functools import partial
 
@@ -62,7 +62,7 @@ except ImportError:
 
 
 __all__ = ["tabulate", "tabulate_formats", "simple_separated_format"]
-__version__ = "0.8.7"
+__version__ = "0.8.9"
 
 
 # minimum extra space in headers
@@ -73,6 +73,9 @@ PRESERVE_WHITESPACE = False
 
 _DEFAULT_FLOATFMT = "g"
 _DEFAULT_MISSINGVAL = ""
+# default align will be overwritten by "left", "center" or "decimal"
+# depending on the formatter
+_DEFAULT_ALIGN = "default"
 
 
 # if True, enable wide-character (CJK) support
@@ -91,9 +94,9 @@ DataRow = namedtuple("DataRow", ["begin"
 #         headerrow
 #     --- linebelowheader ---
 #         datarow
-#     --- linebewteenrows ---
+#     --- linebetweenrows ---
 #     ... (more datarows) ...
-#     --- linebewteenrows ---
+#     --- linebetweenrows ---
 #         last datarow
 #     --- linebelow ---------
 #
@@ -182,17 +185,23 @@ def _html_begin_table_without_header(col
     return "<table>\n<tbody>"
 
 
-def _html_row_with_attrs(celltag, cell_values, colwidths, colaligns):
+def _html_row_with_attrs(celltag, unsafe, cell_values, colwidths, colaligns):
     alignment = {
         "left": "",
         "right": ' style="text-align: right;"',
         "center": ' style="text-align: center;"',
         "decimal": ' style="text-align: right;"',
     }
-    values_with_attrs = [
-        "<{0}{1}>{2}</{0}>".format(celltag, alignment.get(a, ""), htmlescape(c))
-        for c, a in zip(cell_values, colaligns)
-    ]
+    if unsafe:
+        values_with_attrs = [
+            "<{0}{1}>{2}</{0}>".format(celltag, alignment.get(a, ""), c)
+            for c, a in zip(cell_values, colaligns)
+        ]
+    else:
+        values_with_attrs = [
+            "<{0}{1}>{2}</{0}>".format(celltag, alignment.get(a, ""), htmlescape(c))
+            for c, a in zip(cell_values, colaligns)
+        ]
     rowhtml = "<tr>{}</tr>".format("".join(values_with_attrs).rstrip())
     if celltag == "th":  # it's a header row, create a new table header
         rowhtml = "<table>\n<thead>\n{}\n</thead>\n<tbody>".format(rowhtml)
@@ -213,12 +222,14 @@ def _moin_row_with_attrs(celltag, cell_v
     return "".join(values_with_attrs) + "||"
 
 
-def _latex_line_begin_tabular(colwidths, colaligns, booktabs=False):
+def _latex_line_begin_tabular(colwidths, colaligns, booktabs=False, longtable=False):
     alignment = {"left": "l", "right": "r", "center": "c", "decimal": "r"}
     tabular_columns_fmt = "".join([alignment.get(a, "l") for a in colaligns])
     return "\n".join(
         [
-            "\\begin{tabular}{" + tabular_columns_fmt + "}",
+            ("\\begin{tabular}{" if not longtable else "\\begin{longtable}{")
+            + tabular_columns_fmt
+            + "}",
             "\\toprule" if booktabs else "\\hline",
         ]
     )
@@ -309,6 +320,16 @@ _table_formats = {
         padding=1,
         with_header_hide=None,
     ),
+    "fancy_outline": TableFormat(
+        lineabove=Line("╒", "═", "╤", "╕"),
+        linebelowheader=Line("╞", "═", "╪", "╡"),
+        linebetweenrows=None,
+        linebelow=Line("╘", "═", "╧", "╛"),
+        headerrow=DataRow("│", "│", "│"),
+        datarow=DataRow("│", "│", "│"),
+        padding=1,
+        with_header_hide=None,
+    ),
     "github": TableFormat(
         lineabove=Line("|", "-", "|", "|"),
         linebelowheader=Line("|", "-", "|", "|"),
@@ -429,8 +450,18 @@ _table_formats = {
         linebelowheader="",
         linebetweenrows=None,
         linebelow=Line("</tbody>\n</table>", "", "", ""),
-        headerrow=partial(_html_row_with_attrs, "th"),
-        datarow=partial(_html_row_with_attrs, "td"),
+        headerrow=partial(_html_row_with_attrs, "th", False),
+        datarow=partial(_html_row_with_attrs, "td", False),
+        padding=0,
+        with_header_hide=["lineabove"],
+    ),
+    "unsafehtml": TableFormat(
+        lineabove=_html_begin_table_without_header,
+        linebelowheader="",
+        linebetweenrows=None,
+        linebelow=Line("</tbody>\n</table>", "", "", ""),
+        headerrow=partial(_html_row_with_attrs, "th", True),
+        datarow=partial(_html_row_with_attrs, "td", True),
         padding=0,
         with_header_hide=["lineabove"],
     ),
@@ -464,6 +495,16 @@ _table_formats = {
         padding=1,
         with_header_hide=None,
     ),
+    "latex_longtable": TableFormat(
+        lineabove=partial(_latex_line_begin_tabular, longtable=True),
+        linebelowheader=Line("\\hline\n\\endhead", "", "", ""),
+        linebetweenrows=None,
+        linebelow=Line("\\hline\n\\end{longtable}", "", "", ""),
+        headerrow=_latex_row,
+        datarow=_latex_row,
+        padding=1,
+        with_header_hide=None,
+    ),
     "tsv": TableFormat(
         lineabove=None,
         linebelowheader=None,
@@ -519,11 +560,14 @@ multiline_formats = {
 _multiline_codes = re.compile(r"\r|\n|\r\n")
 _multiline_codes_bytes = re.compile(b"\r|\n|\r\n")
 _invisible_codes = re.compile(
-    r"\x1b\[\d+[;\d]*m|\x1b\[\d*\;\d*\;\d*m"
+    r"\x1b\[\d+[;\d]*m|\x1b\[\d*\;\d*\;\d*m|\x1b\]8;;(.*?)\x1b\\"
 )  # ANSI color codes
 _invisible_codes_bytes = re.compile(
-    b"\x1b\\[\\d+\\[;\\d]*m|\x1b\\[\\d*;\\d*;\\d*m"
+    b"\x1b\\[\\d+\\[;\\d]*m|\x1b\\[\\d*;\\d*;\\d*m|\\x1b\\]8;;(.*?)\\x1b\\\\"
 )  # ANSI color codes
+_invisible_codes_link = re.compile(
+    r"\x1B]8;[a-zA-Z0-9:]*;[^\x1B]+\x1B\\([^\x1b]+)\x1B]8;;\x1B\\"
+)  # Terminal hyperlinks
 
 
 def simple_separated_format(separator):
@@ -708,9 +752,15 @@ def _padnone(ignore_width, s):
 
 
 def _strip_invisible(s):
-    "Remove invisible ANSI color codes."
+    r"""Remove invisible ANSI color codes.
+
+    >>> str(_strip_invisible('\x1B]8;;https://example.com\x1B\\This is a link\x1B]8;;\x1B\\'))
+    'This is a link'
+
+    """
     if isinstance(s, _text_type):
-        return re.sub(_invisible_codes, "", s)
+        links_removed = re.sub(_invisible_codes_link, "\\1", s)
+        return re.sub(_invisible_codes, "", links_removed)
     else:  # a bytestring
         return re.sub(_invisible_codes_bytes, "", s)
 
@@ -786,6 +836,36 @@ def _align_column_choose_padfn(strings,
     return strings, padfn
 
 
+def _align_column_choose_width_fn(has_invisible, enable_widechars, is_multiline):
+    if has_invisible:
+        line_width_fn = _visible_width
+    elif enable_widechars:  # optional wide-character support if available
+        line_width_fn = wcwidth.wcswidth
+    else:
+        line_width_fn = len
+    if is_multiline:
+        width_fn = lambda s: _align_column_multiline_width(s, line_width_fn)  # noqa
+    else:
+        width_fn = line_width_fn
+    return width_fn
+
+
+def _align_column_multiline_width(multiline_s, line_width_fn=len):
+    """Visible width of a potentially multiline content."""
+    return list(map(line_width_fn, re.split("[\r\n]", multiline_s)))
+
+
+def _flat_list(nested_list):
+    ret = []
+    for item in nested_list:
+        if isinstance(item, list):
+            for subitem in item:
+                ret.append(subitem)
+        else:
+            ret.append(item)
+    return ret
+
+
 def _align_column(
     strings,
     alignment,
@@ -796,10 +876,12 @@ def _align_column(
 ):
     """[string] -> [padded_string]"""
     strings, padfn = _align_column_choose_padfn(strings, alignment, has_invisible)
-    width_fn = _choose_width_fn(has_invisible, enable_widechars, is_multiline)
+    width_fn = _align_column_choose_width_fn(
+        has_invisible, enable_widechars, is_multiline
+    )
 
     s_widths = list(map(width_fn, strings))
-    maxwidth = max(max(s_widths), minwidth)
+    maxwidth = max(max(_flat_list(s_widths)), minwidth)
     # TODO: refactor column alignment in single-line and multiline modes
     if is_multiline:
         if not enable_widechars and not has_invisible:
@@ -809,13 +891,16 @@ def _align_column(
             ]
         else:
             # enable wide-character width corrections
-            s_lens = [max((len(s) for s in re.split("[\r\n]", ms))) for ms in strings]
-            visible_widths = [maxwidth - (w - l) for w, l in zip(s_widths, s_lens)]
+            s_lens = [[len(s) for s in re.split("[\r\n]", ms)] for ms in strings]
+            visible_widths = [
+                [maxwidth - (w - l) for w, l in zip(mw, ml)]
+                for mw, ml in zip(s_widths, s_lens)
+            ]
             # wcswidth and _visible_width don't count invisible characters;
             # padfn doesn't need to apply another correction
             padded_strings = [
-                "\n".join([padfn(w, s) for s in (ms.splitlines() or ms)])
-                for ms, w in zip(strings, visible_widths)
+                "\n".join([padfn(w, s) for s, w in zip((ms.splitlines() or ms), mw)])
+                for ms, mw in zip(strings, visible_widths)
             ]
     else:  # single-line cell values
         if not enable_widechars and not has_invisible:
@@ -878,7 +963,7 @@ def _column_type(strings, has_invisible=
 
 
 def _format(val, valtype, floatfmt, missingval="", has_invisible=True):
-    """Format a value accoding to its type.
+    """Format a value according to its type.
 
     Unicode is supported:
 
@@ -1006,7 +1091,10 @@ def _normalize_tabular_data(tabular_data
         elif hasattr(tabular_data, "index"):
             # values is a property, has .index => it's likely a pandas.DataFrame (pandas 0.11.0)
             keys = list(tabular_data)
-            if tabular_data.index.name is not None:
+            if (
+                showindex in ["default", "always", True]
+                and tabular_data.index.name is not None
+            ):
                 if isinstance(tabular_data.index.name, list):
                     keys[:0] = tabular_data.index.name
                 else:
@@ -1042,8 +1130,8 @@ def _normalize_tabular_data(tabular_data
         ):
             # namedtuple
             headers = list(map(_text_type, rows[0]._fields))
-        elif len(rows) > 0 and isinstance(rows[0], dict):
-            # dict or OrderedDict
+        elif len(rows) > 0 and hasattr(rows[0], "keys") and hasattr(rows[0], "values"):
+            # dict-like object
             uniq_keys = set()  # implements hashed lookup
             keys = []  # storage for set
             if headers == "firstrow":
@@ -1130,8 +1218,8 @@ def tabulate(
     headers=(),
     tablefmt="simple",
     floatfmt=_DEFAULT_FLOATFMT,
-    numalign="decimal",
-    stralign="left",
+    numalign=_DEFAULT_ALIGN,
+    stralign=_DEFAULT_ALIGN,
     missingval=_DEFAULT_MISSINGVAL,
     showindex="default",
     disable_numparse=False,
@@ -1221,8 +1309,8 @@ def tabulate(
 
     Various plain-text table formats (`tablefmt`) are supported:
     'plain', 'simple', 'grid', 'pipe', 'orgtbl', 'rst', 'mediawiki',
-    'latex', 'latex_raw' and 'latex_booktabs'. Variable `tabulate_formats`
-    contains the list of currently supported formats.
+    'latex', 'latex_raw', 'latex_booktabs', 'latex_longtable' and tsv.
+    Variable `tabulate_formats`contains the list of currently supported formats.
 
     "plain" format doesn't use any pseudographics to draw tables,
     it separates columns with a double space:
@@ -1360,7 +1448,8 @@ def tabulate(
 
     "html" produces HTML markup as an html.escape'd str
     with a ._repr_html_ method so that Jupyter Lab and Notebook display the HTML
-    and a .str property so that the raw HTML remains accessible:
+    and a .str property so that the raw HTML remains accessible
+    the unsafehtml table format can be used if an unescaped HTML format is required:
 
     >>> print(tabulate([["strings", "numbers"], ["spam", 41.9999], ["eggs", "451.0"]],
     ...                headers="firstrow", tablefmt="html"))
@@ -1407,6 +1496,18 @@ def tabulate(
     \\bottomrule
     \\end{tabular}
 
+    "latex_longtable" produces a tabular environment that can stretch along
+    multiple pages, using the longtable package for LaTeX.
+
+    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tablefmt="latex_longtable"))
+    \\begin{longtable}{lr}
+    \\hline
+     spam &  41.9999 \\\\
+     eggs & 451      \\\\
+    \\hline
+    \\end{longtable}
+
+
     Number parsing
     --------------
     By default, anything which can be parsed as a number is a number.
@@ -1421,6 +1522,7 @@ def tabulate(
     e.g. `disable_numparse=[0, 2]` would disable number parsing only on the
     first and third columns.
     """
+
     if tabular_data is None:
         tabular_data = []
     list_of_lists, headers = _normalize_tabular_data(
@@ -1440,8 +1542,11 @@ def tabulate(
     if tablefmt == "pretty":
         min_padding = 0
         disable_numparse = True
-        numalign = "center"
-        stralign = "center"
+        numalign = "center" if numalign == _DEFAULT_ALIGN else numalign
+        stralign = "center" if stralign == _DEFAULT_ALIGN else stralign
+    else:
+        numalign = "decimal" if numalign == _DEFAULT_ALIGN else numalign
+        stralign = "left" if stralign == _DEFAULT_ALIGN else stralign
 
     # optimization: look for ANSI control codes once,
     # enable smart width functions only if a control code is found
@@ -1451,6 +1556,8 @@ def tabulate(
     )
 
     has_invisible = re.search(_invisible_codes, plain_text)
+    if not has_invisible:
+        has_invisible = re.search(_invisible_codes_link, plain_text)
     enable_widechars = wcwidth is not None and WIDE_CHARS_MODE
     if (
         not isinstance(tablefmt, TableFormat)
@@ -1687,7 +1794,7 @@ def _main():
     -f FMT, --format FMT      set output table format; supported formats:
                               plain, simple, grid, fancy_grid, pipe, orgtbl,
                               rst, mediawiki, html, latex, latex_raw,
-                              latex_booktabs, tsv
+                              latex_booktabs, latex_longtable, tsv
                               (default: simple)
     """
     import getopt
diff -pruN 0.8.7-0.2/test/common.py 0.8.9-1/test/common.py
--- 0.8.7-0.2/test/common.py	2020-03-22 12:08:26.000000000 +0000
+++ 0.8.9-1/test/common.py	2020-03-23 21:00:04.000000000 +0000
@@ -1,49 +1,16 @@
-try:
-    from nose.plugins.skip import SkipTest
-except ImportError:
-    try:
-        from unittest.case import SkipTest  # Python >= 2.7
-    except ImportError:
-        try:
-            from unittest2.case import SkipTest  # Python < 2.7
-        except ImportError:
+import pytest  # noqa
+from pytest import skip, raises  # noqa
 
-            class SkipTest(Exception):
-                """Raise this exception to mark a test as skipped.
-                """
 
-                pass
-
-
-try:
-    from nose.tools import assert_equal, assert_in, assert_raises
-
-
-except ImportError:
-
-    def assert_equal(expected, result):
-        print("Expected:\n%s\n" % expected)
-        print("Got:\n%s\n" % result)
-        assert expected == result
-
-    def assert_in(result, expected_set):
-        nums = range(1, len(expected_set) + 1)
-        for i, expected in zip(nums, expected_set):
-            print("Expected %d:\n%s\n" % (i, expected))
-        print("Got:\n%s\n" % result)
-        assert result in expected_set
-
-    class assert_raises(object):
-        def __init__(self, exception_type):
-            self.watch_exception_type = exception_type
-
-        def __enter__(self):
-            pass
-
-        def __exit__(self, exception_type, exception_value, traceback):
-            if isinstance(exception_value, self.watch_exception_type):
-                return True  # suppress exception
-            elif exception_type is None:
-                msg = "%s not raised" % self.watch_exception_type.__name__
-                raise AssertionError(msg)
-            # otherwise propagate whatever other exception is raised
+def assert_equal(expected, result):
+    print("Expected:\n%s\n" % expected)
+    print("Got:\n%s\n" % result)
+    assert expected == result
+
+
+def assert_in(result, expected_set):
+    nums = range(1, len(expected_set) + 1)
+    for i, expected in zip(nums, expected_set):
+        print("Expected %d:\n%s\n" % (i, expected))
+    print("Got:\n%s\n" % result)
+    assert result in expected_set
diff -pruN 0.8.7-0.2/test/test_api.py 0.8.9-1/test/test_api.py
--- 0.8.7-0.2/test/test_api.py	2020-03-22 12:08:26.000000000 +0000
+++ 0.8.9-1/test/test_api.py	2021-02-17 23:27:40.000000000 +0000
@@ -6,7 +6,7 @@ from __future__ import print_function
 from __future__ import unicode_literals
 from tabulate import tabulate, tabulate_formats, simple_separated_format
 from platform import python_version_tuple
-from common import SkipTest
+from common import skip
 
 
 try:
@@ -31,7 +31,7 @@ def test_tabulate_formats():
 
 def _check_signature(function, expected_sig):
     if not signature:
-        raise SkipTest()
+        skip("")
     actual_sig = signature(function)
     print("expected: %s\nactual: %s\n" % (expected_sig, str(actual_sig)))
     for (e, ev), (a, av) in zip(expected_sig, actual_sig.parameters.items()):
@@ -46,8 +46,8 @@ def test_tabulate_signature():
         ("headers", ()),
         ("tablefmt", "simple"),
         ("floatfmt", "g"),
-        ("numalign", "decimal"),
-        ("stralign", "left"),
+        ("numalign", "default"),
+        ("stralign", "default"),
         ("missingval", ""),
     ]
     _check_signature(tabulate, expected_sig)
diff -pruN 0.8.7-0.2/test/test_input.py 0.8.9-1/test/test_input.py
--- 0.8.7-0.2/test/test_input.py	2020-03-22 12:08:26.000000000 +0000
+++ 0.8.9-1/test/test_input.py	2021-02-20 11:11:30.000000000 +0000
@@ -5,7 +5,13 @@
 from __future__ import print_function
 from __future__ import unicode_literals
 from tabulate import tabulate
-from common import assert_equal, assert_in, assert_raises, SkipTest
+from common import assert_equal, assert_in, raises, skip
+
+try:
+    from collections import UserDict
+except ImportError:
+    # Python2
+    from UserDict import UserDict
 
 
 def test_iterable_of_iterables():
@@ -123,8 +129,7 @@ def test_numpy_2d():
         result = tabulate(na, ["a", "b", "c"])
         assert_equal(expected, result)
     except ImportError:
-        print("test_numpy_2d is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_numpy_2d is skipped")
 
 
 def test_numpy_2d_firstrow():
@@ -139,8 +144,7 @@ def test_numpy_2d_firstrow():
         result = tabulate(na, headers="firstrow")
         assert_equal(expected, result)
     except ImportError:
-        print("test_numpy_2d_firstrow is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_numpy_2d_firstrow is skipped")
 
 
 def test_numpy_2d_keys():
@@ -161,8 +165,7 @@ def test_numpy_2d_keys():
         result = tabulate(na, headers="keys")
         assert_equal(expected, result)
     except ImportError:
-        print("test_numpy_2d_keys is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_numpy_2d_keys is skipped")
 
 
 def test_numpy_record_array():
@@ -188,8 +191,7 @@ def test_numpy_record_array():
         result = tabulate(na)
         assert_equal(expected, result)
     except ImportError:
-        print("test_numpy_2d_keys is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_numpy_2d_keys is skipped")
 
 
 def test_numpy_record_array_keys():
@@ -215,8 +217,7 @@ def test_numpy_record_array_keys():
         result = tabulate(na, headers="keys")
         assert_equal(expected, result)
     except ImportError:
-        print("test_numpy_2d_keys is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_numpy_2d_keys is skipped")
 
 
 def test_numpy_record_array_headers():
@@ -242,8 +243,7 @@ def test_numpy_record_array_headers():
         result = tabulate(na, headers=["person", "years", "cm"])
         assert_equal(expected, result)
     except ImportError:
-        print("test_numpy_2d_keys is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_numpy_2d_keys is skipped")
 
 
 def test_pandas():
@@ -263,8 +263,7 @@ def test_pandas():
         result = tabulate(df, headers=["string", "number"])
         assert_equal(expected, result)
     except ImportError:
-        print("test_pandas is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_pandas is skipped")
 
 
 def test_pandas_firstrow():
@@ -281,8 +280,7 @@ def test_pandas_firstrow():
         result = tabulate(df, headers="firstrow")
         assert_equal(expected, result)
     except ImportError:
-        print("test_pandas_firstrow is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_pandas_firstrow is skipped")
 
 
 def test_pandas_keys():
@@ -304,8 +302,7 @@ def test_pandas_keys():
         result = tabulate(df, headers="keys")
         assert_equal(expected, result)
     except ImportError:
-        print("test_pandas_keys is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_pandas_keys is skipped")
 
 
 def test_sqlite3():
@@ -327,8 +324,7 @@ Alice          23       169.5
 Bob            27       175"""
         assert_equal(expected, result)
     except ImportError:
-        print("test_sqlite3 is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_sqlite3 is skipped")
 
 
 def test_sqlite3_keys():
@@ -352,8 +348,7 @@ Alice          23       169.5
 Bob            27       175"""
         assert_equal(expected, result)
     except ImportError:
-        print("test_sqlite3_keys is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_sqlite3_keys is skipped")
 
 
 def test_list_of_namedtuples():
@@ -389,6 +384,15 @@ def test_list_of_dicts():
     assert_in(result, [expected1, expected2])
 
 
+def test_list_of_userdicts():
+    "Input: a list of UserDicts."
+    lod = [UserDict(foo=1, bar=2), UserDict(foo=3, bar=4)]
+    expected1 = "\n".join(["-  -", "1  2", "3  4", "-  -"])
+    expected2 = "\n".join(["-  -", "2  1", "4  3", "-  -"])
+    result = tabulate(lod)
+    assert_in(result, [expected1, expected2])
+
+
 def test_list_of_dicts_keys():
     "Input: a list of dictionaries, with keys as headers."
     lod = [{"foo": 1, "bar": 2}, {"foo": 3, "bar": 4}]
@@ -402,6 +406,19 @@ def test_list_of_dicts_keys():
     assert_in(result, [expected1, expected2])
 
 
+def test_list_of_userdicts_keys():
+    "Input: a list of UserDicts."
+    lod = [UserDict(foo=1, bar=2), UserDict(foo=3, bar=4)]
+    expected1 = "\n".join(
+        ["  foo    bar", "-----  -----", "    1      2", "    3      4"]
+    )
+    expected2 = "\n".join(
+        ["  bar    foo", "-----  -----", "    2      1", "    4      3"]
+    )
+    result = tabulate(lod, headers="keys")
+    assert_in(result, [expected1, expected2])
+
+
 def test_list_of_dicts_with_missing_keys():
     "Input: a list of dictionaries, with missing keys."
     lod = [{"foo": 1}, {"bar": 2}, {"foo": 4, "baz": 3}]
@@ -450,7 +467,7 @@ def test_list_of_dicts_with_list_of_head
     "Input: ValueError on a list of headers with a list of dicts (issue #23)"
     table = [{"letters": "ABCDE", "digits": 12345}]
     headers = ["DIGITS", "LETTERS"]
-    with assert_raises(ValueError):
+    with raises(ValueError):
         tabulate(table, headers=headers)
 
 
diff -pruN 0.8.7-0.2/test/test_output.py 0.8.9-1/test/test_output.py
--- 0.8.7-0.2/test/test_output.py	2020-03-22 12:08:26.000000000 +0000
+++ 0.8.9-1/test/test_output.py	2021-02-17 21:22:24.000000000 +0000
@@ -6,7 +6,7 @@ from __future__ import print_function
 from __future__ import unicode_literals
 import tabulate as tabulate_module
 from tabulate import tabulate, simple_separated_format
-from common import assert_equal, assert_raises, SkipTest
+from common import assert_equal, raises, skip
 
 
 # _test_table shows
@@ -59,6 +59,22 @@ def test_plain_multiline():
     assert_equal(expected, result)
 
 
+def test_plain_multiline_with_links():
+    "Output: plain with multiline cells with links and headers"
+    table = [[2, "foo\nbar"]]
+    headers = ("more\nspam \x1b]8;;target\x1b\\eggs\x1b]8;;\x1b\\", "more spam\n& eggs")
+    expected = "\n".join(
+        [
+            "       more  more spam",
+            "  spam \x1b]8;;target\x1b\\eggs\x1b]8;;\x1b\\  & eggs",
+            "          2  foo",
+            "             bar",
+        ]
+    )
+    result = tabulate(table, headers, tablefmt="plain")
+    assert_equal(expected, result)
+
+
 def test_plain_multiline_with_empty_cells():
     "Output: plain with multiline cells and empty cells with headers"
     table = [
@@ -162,6 +178,23 @@ def test_simple_multiline():
     assert_equal(expected, result)
 
 
+def test_simple_multiline_with_links():
+    "Output: simple with multiline cells with links and headers"
+    table = [[2, "foo\nbar"]]
+    headers = ("more\nspam \x1b]8;;target\x1b\\eggs\x1b]8;;\x1b\\", "more spam\n& eggs")
+    expected = "\n".join(
+        [
+            "       more  more spam",
+            "  spam \x1b]8;;target\x1b\\eggs\x1b]8;;\x1b\\  & eggs",
+            "-----------  -----------",
+            "          2  foo",
+            "             bar",
+        ]
+    )
+    result = tabulate(table, headers, tablefmt="simple")
+    assert_equal(expected, result)
+
+
 def test_simple_multiline_with_empty_cells():
     "Output: simple with multiline cells and empty cells with headers"
     table = [
@@ -235,8 +268,7 @@ def test_grid_wide_characters():
     try:
         import wcwidth  # noqa
     except ImportError:
-        print("test_grid_wide_characters is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_grid_wide_characters is skipped")
     headers = list(_test_table_headers)
     headers[1] = "配列"
     expected = "\n".join(
@@ -767,6 +799,25 @@ def test_pretty_multiline():
     assert_equal(expected, result)
 
 
+def test_pretty_multiline_with_links():
+    "Output: pretty with multiline cells with headers"
+    table = [[2, "foo\nbar"]]
+    headers = ("more\nspam \x1b]8;;target\x1b\\eggs\x1b]8;;\x1b\\", "more spam\n& eggs")
+    expected = "\n".join(
+        [
+            "+-----------+-----------+",
+            "|   more    | more spam |",
+            "| spam \x1b]8;;target\x1b\\eggs\x1b]8;;\x1b\\ |  & eggs   |",
+            "+-----------+-----------+",
+            "|     2     |    foo    |",
+            "|           |    bar    |",
+            "+-----------+-----------+",
+        ]
+    )
+    result = tabulate(table, headers, tablefmt="pretty")
+    assert_equal(expected, result)
+
+
 def test_pretty_multiline_with_empty_cells():
     "Output: pretty with multiline cells and empty cells with headers"
     table = [
@@ -890,6 +941,25 @@ def test_rst_multiline():
     assert_equal(expected, result)
 
 
+def test_rst_multiline_with_links():
+    "Output: rst with multiline cells with headers"
+    table = [[2, "foo\nbar"]]
+    headers = ("more\nspam \x1b]8;;target\x1b\\eggs\x1b]8;;\x1b\\", "more spam\n& eggs")
+    expected = "\n".join(
+        [
+            "===========  ===========",
+            "       more  more spam",
+            "  spam \x1b]8;;target\x1b\\eggs\x1b]8;;\x1b\\  & eggs",
+            "===========  ===========",
+            "          2  foo",
+            "             bar",
+            "===========  ===========",
+        ]
+    )
+    result = tabulate(table, headers, tablefmt="rst")
+    assert_equal(expected, result)
+
+
 def test_rst_multiline_with_empty_cells():
     "Output: rst with multiline cells and empty cells with headers"
     table = [
@@ -1005,7 +1075,11 @@ def test_moinmoin_headerless():
 
 _test_table_html_headers = ["<strings>", "<&numbers&>"]
 _test_table_html = [["spam >", 41.9999], ["eggs &", 451.0]]
-assert_equal.__self__.maxDiff = None
+_test_table_unsafehtml_headers = ["strings", "numbers"]
+_test_table_unsafehtml = [
+    ["spam", '<font color="red">41.9999</font>'],
+    ["eggs", '<font color="red">451.0</font>'],
+]
 
 
 def test_html():
@@ -1029,6 +1103,29 @@ def test_html():
     assert result._repr_html_() == result.str
 
 
+def test_unsafehtml():
+    "Output: unsafe html with headers"
+    expected = "\n".join(
+        [
+            "<table>",
+            "<thead>",
+            "<tr><th>strings  </th><th>numbers                         </th></tr>",  # noqa
+            "</thead>",
+            "<tbody>",
+            '<tr><td>spam     </td><td><font color="red">41.9999</font></td></tr>',
+            '<tr><td>eggs     </td><td><font color="red">451.0</font>  </td></tr>',
+            "</tbody>",
+            "</table>",
+        ]
+    )
+    result = tabulate(
+        _test_table_unsafehtml, _test_table_unsafehtml_headers, tablefmt="unsafehtml"
+    )
+    assert_equal(expected, result)
+    assert hasattr(result, "_repr_html_")
+    assert result._repr_html_() == result.str
+
+
 def test_html_headerless():
     "Output: html without headers"
     expected = "\n".join(
@@ -1047,6 +1144,24 @@ def test_html_headerless():
     assert result._repr_html_() == result.str
 
 
+def test_unsafehtml_headerless():
+    "Output: unsafe html without headers"
+    expected = "\n".join(
+        [
+            "<table>",
+            "<tbody>",
+            '<tr><td>spam</td><td><font color="red">41.9999</font></td></tr>',
+            '<tr><td>eggs</td><td><font color="red">451.0</font>  </td></tr>',
+            "</tbody>",
+            "</table>",
+        ]
+    )
+    result = tabulate(_test_table_unsafehtml, tablefmt="unsafehtml")
+    assert_equal(expected, result)
+    assert hasattr(result, "_repr_html_")
+    assert result._repr_html_() == result.str
+
+
 def test_latex():
     "Output: latex with headers and replaced characters"
     raw_test_table_headers = list(_test_table_headers)
@@ -1310,8 +1425,7 @@ def test_pandas_with_index():
         result = tabulate(df, headers="keys")
         assert_equal(expected, result)
     except ImportError:
-        print("test_pandas_with_index is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_pandas_with_index is skipped")
 
 
 def test_pandas_without_index():
@@ -1320,7 +1434,9 @@ def test_pandas_without_index():
         import pandas
 
         df = pandas.DataFrame(
-            [["one", 1], ["two", None]], columns=["string", "number"], index=["a", "b"]
+            [["one", 1], ["two", None]],
+            columns=["string", "number"],
+            index=pandas.Index(["a", "b"], name="index"),
         )
         expected = "\n".join(
             [
@@ -1333,8 +1449,7 @@ def test_pandas_without_index():
         result = tabulate(df, headers="keys", showindex=False)
         assert_equal(expected, result)
     except ImportError:
-        print("test_pandas_without_index is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_pandas_without_index is skipped")
 
 
 def test_pandas_rst_with_index():
@@ -1358,8 +1473,7 @@ def test_pandas_rst_with_index():
         result = tabulate(df, tablefmt="rst", headers="keys")
         assert_equal(expected, result)
     except ImportError:
-        print("test_pandas_rst_with_index is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_pandas_rst_with_index is skipped")
 
 
 def test_pandas_rst_with_named_index():
@@ -1384,8 +1498,7 @@ def test_pandas_rst_with_named_index():
         result = tabulate(df, tablefmt="rst", headers="keys")
         assert_equal(expected, result)
     except ImportError:
-        print("test_pandas_rst_with_index is skipped")
-        raise SkipTest()  # this test is optional
+        skip("test_pandas_rst_with_index is skipped")
 
 
 def test_dict_like_with_index():
@@ -1418,9 +1531,8 @@ def test_list_of_lists_with_supplied_ind
     assert_equal(result, expected)
     # TODO: make it a separate test case
     # the index must be as long as the number of rows
-    assert_raises(
-        ValueError, lambda: tabulate(dd, headers=["a", "b"], showindex=[1, 2])
-    )
+    with raises(ValueError):
+        tabulate(dd, headers=["a", "b"], showindex=[1, 2])
 
 
 def test_list_of_lists_with_index_firstrow():
@@ -1433,9 +1545,8 @@ def test_list_of_lists_with_index_firstr
     assert_equal(result, expected)
     # TODO: make it a separate test case
     # the index must be as long as the number of rows
-    assert_raises(
-        ValueError, lambda: tabulate(dd, headers="firstrow", showindex=[1, 2])
-    )
+    with raises(ValueError):
+        tabulate(dd, headers="firstrow", showindex=[1, 2])
 
 
 def test_disable_numparse_default():
diff -pruN 0.8.7-0.2/test/test_regression.py 0.8.9-1/test/test_regression.py
--- 0.8.7-0.2/test/test_regression.py	2020-03-22 12:08:26.000000000 +0000
+++ 0.8.9-1/test/test_regression.py	2021-02-20 11:11:30.000000000 +0000
@@ -5,7 +5,7 @@
 from __future__ import print_function
 from __future__ import unicode_literals
 from tabulate import tabulate, _text_type, _long_type, TableFormat, Line, DataRow
-from common import assert_equal, assert_in, SkipTest
+from common import assert_equal, assert_in, skip
 
 
 def test_ansi_color_in_table_cells():
@@ -47,6 +47,52 @@ def test_alignment_of_colored_cells():
     assert_equal(expected, formatted)
 
 
+def test_alignment_of_link_cells():
+    "Regression: Align links as if they were colorless."
+    linktable = [
+        ("test", 42, "\x1b]8;;target\x1b\\test\x1b]8;;\x1b\\"),
+        ("test", 101, "\x1b]8;;target\x1b\\test\x1b]8;;\x1b\\"),
+    ]
+    linkheaders = ("test", "\x1b]8;;target\x1b\\test\x1b]8;;\x1b\\", "test")
+    formatted = tabulate(linktable, linkheaders, "grid")
+    expected = "\n".join(
+        [
+            "+--------+--------+--------+",
+            "| test   |   \x1b]8;;target\x1b\\test\x1b]8;;\x1b\\ | test   |",
+            "+========+========+========+",
+            "| test   |     42 | \x1b]8;;target\x1b\\test\x1b]8;;\x1b\\   |",
+            "+--------+--------+--------+",
+            "| test   |    101 | \x1b]8;;target\x1b\\test\x1b]8;;\x1b\\   |",
+            "+--------+--------+--------+",
+        ]
+    )
+    print("expected: %r\n\ngot:      %r\n" % (expected, formatted))
+    assert_equal(expected, formatted)
+
+
+def test_alignment_of_link_text_cells():
+    "Regression: Align links as if they were colorless."
+    linktable = [
+        ("test", 42, "1\x1b]8;;target\x1b\\test\x1b]8;;\x1b\\2"),
+        ("test", 101, "3\x1b]8;;target\x1b\\test\x1b]8;;\x1b\\4"),
+    ]
+    linkheaders = ("test", "5\x1b]8;;target\x1b\\test\x1b]8;;\x1b\\6", "test")
+    formatted = tabulate(linktable, linkheaders, "grid")
+    expected = "\n".join(
+        [
+            "+--------+----------+--------+",
+            "| test   |   5\x1b]8;;target\x1b\\test\x1b]8;;\x1b\\6 | test   |",
+            "+========+==========+========+",
+            "| test   |       42 | 1\x1b]8;;target\x1b\\test\x1b]8;;\x1b\\2 |",
+            "+--------+----------+--------+",
+            "| test   |      101 | 3\x1b]8;;target\x1b\\test\x1b]8;;\x1b\\4 |",
+            "+--------+----------+--------+",
+        ]
+    )
+    print("expected: %r\n\ngot:      %r\n" % (expected, formatted))
+    assert_equal(expected, formatted)
+
+
 def test_iter_of_iters_with_headers():
     "Regression: Generator of generators with a gen. of headers (issue #9)."
 
@@ -226,6 +272,19 @@ def test_alignment_of_decimal_numbers_wi
     assert_equal(result, expected)
 
 
+def test_alignment_of_decimal_numbers_with_commas():
+    "Regression: alignment for decimal numbers with comma separators"
+    skip("test is temporarily disable until the feature is reimplemented")
+    # table = [["c1r1", "14502.05"], ["c1r2", 105]]
+    # result = tabulate(table, tablefmt="grid", floatfmt=',.2f')
+    # expected = "\n".join(
+    #    ['+------+-----------+', '| c1r1 | 14,502.05 |',
+    #    '+------+-----------+', '| c1r2 |    105.00 |',
+    #    '+------+-----------+']
+    # )
+    # assert_equal(result, expected)
+
+
 def test_long_integers():
     "Regression: long integers should be printed as integers (issue #48)"
     table = [[18446744073709551614]]
@@ -273,8 +332,27 @@ def test_mix_normal_and_wide_characters(
         )
         assert_equal(result, expected)
     except ImportError:
-        print("test_mix_normal_and_wide_characters is skipped (requires wcwidth lib)")
-        raise SkipTest()
+        skip("test_mix_normal_and_wide_characters is skipped (requires wcwidth lib)")
+
+
+def test_multiline_with_wide_characters():
+    "Regression: multiline tables with varying number of wide characters (github issue #28)"
+    try:
+        import wcwidth  # noqa
+
+        table = [["가나\n가ab", "가나", "가나"]]
+        result = tabulate(table, tablefmt="fancy_grid")
+        expected = "\n".join(
+            [
+                "╒══════╤══════╤══════╕",
+                "│ 가나 │ 가나 │ 가나 │",
+                "│ 가ab │      │      │",
+                "╘══════╧══════╧══════╛",
+            ]
+        )
+        assert_equal(result, expected)
+    except ImportError:
+        skip("test_multiline_with_wide_characters is skipped (requires wcwidth lib)")
 
 
 def test_align_long_integers():
@@ -295,7 +373,7 @@ def test_numpy_array_as_headers():
         expected = "foo    bar"
         assert_equal(result, expected)
     except ImportError:
-        raise SkipTest()
+        raise skip("")
 
 
 def test_boolean_columns():
@@ -383,3 +461,11 @@ def test_custom_tablefmt():
     expected = "\n".join(["A    B", "---  ---", "foo  bar", "baz  qux"])
     result = tabulate(rows, headers=["A", "B"], tablefmt=tablefmt)
     assert_equal(result, expected)
+
+
+def test_string_with_comma_between_digits_without_floatfmt_grouping_option():
+    "Regression: accept commas in numbers-as-text when grouping is not defined (github issue #110)"
+    table = [["126,000"]]
+    expected = "126,000"
+    result = tabulate(table, tablefmt="plain")
+    assert_equal(result, expected)  # no exception
