Skip to content

Commit 4cb9524

Browse files
authored
Add tests and better user warnings
• Better warnings using (built-in)[https://docs.python.org/3/library/warnings.html] `warnings` module when `colalign` or `headersalign` is a `string`. Warnings are now directed to `stderr`. • Added `check_warning` tool to `test/common.py`. • Added following tests: - `test_column_global_and_specific_alignment` - `test_headers_global_and_specific_alignment` - `test_colalign_or_headersalign_too_long` - `test_warning_when_colalign_or_headersalign_is_string`
1 parent 051cac7 commit 4cb9524

File tree

3 files changed

+74
-6
lines changed

3 files changed

+74
-6
lines changed

tabulate/__init__.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Pretty-print tabular data."""
22

3+
import warnings
34
from collections import namedtuple
45
from collections.abc import Iterable, Sized
56
from html import escape as htmlescape
@@ -2209,8 +2210,7 @@ def tabulate(
22092210
if colalign is not None:
22102211
assert isinstance(colalign, Iterable)
22112212
if isinstance(colalign, str):
2212-
print(
2213-
f"Warning in `tabulate`: As a string, `colalign` is interpreted as {[c for c in colalign]}. Did you mean `colglobalalign = \"{colalign}\"` or `colalign = (\"{colalign}\",)`?")
2213+
warnings.warn(f"As a string, `colalign` is interpreted as {[c for c in colalign]}. Did you mean `colglobalalign = \"{colalign}\"` or `colalign = (\"{colalign}\",)`?", stacklevel=2)
22142214
for idx, align in enumerate(colalign):
22152215
if not idx < len(aligns):
22162216
break
@@ -2237,8 +2237,7 @@ def tabulate(
22372237
if headersalign is not None:
22382238
assert isinstance(headersalign, Iterable)
22392239
if isinstance(headersalign, str):
2240-
print(
2241-
f"Warning in `tabulate`: As a string, `headersalign` is interpreted as {[c for c in headersalign]}. Did you mean `headersglobalalign = \"{headersalign}\"` or `headersalign = (\"{headersalign}\",)`?")
2240+
warnings.warn(f"As a string, `headersalign` is interpreted as {[c for c in headersalign]}. Did you mean `headersglobalalign = \"{headersalign}\"` or `headersalign = (\"{headersalign}\",)`?", stacklevel=2)
22422241
for idx, align in enumerate(headersalign):
22432242
hidx = headers_pad + idx
22442243
if not hidx < len(aligns_headers):

test/common.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import pytest # noqa
22
from pytest import skip, raises # noqa
3-
3+
import warnings
44

55
def assert_equal(expected, result):
66
print("Expected:\n%s\n" % expected)
@@ -27,3 +27,18 @@ def rows_to_pipe_table_str(rows):
2727
lines.append(line)
2828

2929
return "\n".join(lines)
30+
31+
def check_warnings(func_args_kwargs, *, num=None, category=None, contain=None):
32+
func, args, kwargs = func_args_kwargs
33+
with warnings.catch_warnings(record=True) as W:
34+
# Causes all warnings to always be triggered inside here.
35+
warnings.simplefilter("always")
36+
func(*args, **kwargs)
37+
# Checks
38+
if num is not None:
39+
assert len(W) == num
40+
if category is not None:
41+
assert all([issubclass(w.category, category) for w in W])
42+
if contain is not None:
43+
assert all([contain in str(w.message) for w in W])
44+

test/test_output.py

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Test output of the various forms of tabular data."""
22

33
import tabulate as tabulate_module
4-
from common import assert_equal, raises, skip
4+
from common import assert_equal, raises, skip, check_warnings
55
from tabulate import tabulate, simple_separated_format, SEPARATING_LINE
66

77
# _test_table shows
@@ -2680,6 +2680,60 @@ def test_colalign_multi_with_sep_line():
26802680
expected = " one two\n\nthree four"
26812681
assert_equal(expected, result)
26822682

2683+
def test_column_global_and_specific_alignment():
2684+
""" Test `colglobalalign` and `"global"` parameter for `colalign`. """
2685+
table = [[1,2,3,4],[111,222,333,444]]
2686+
colglobalalign = 'center'
2687+
colalign = ('global','left', 'right')
2688+
result = tabulate(table, colglobalalign=colglobalalign, colalign=colalign)
2689+
expected = '\n'.join([
2690+
"--- --- --- ---",
2691+
" 1 2 3 4",
2692+
"111 222 333 444",
2693+
"--- --- --- ---"])
2694+
assert_equal(expected, result)
2695+
2696+
def test_headers_global_and_specific_alignment():
2697+
""" Test `headersglobalalign` and `headersalign`. """
2698+
table = [[1,2,3,4,5,6],[111,222,333,444,555,666]]
2699+
colglobalalign = 'center'
2700+
colalign = ('left',)
2701+
headers = ['h', 'e', 'a', 'd', 'e', 'r']
2702+
headersglobalalign = 'right'
2703+
headersalign = ('same', 'same', 'left', 'global', 'center')
2704+
result = tabulate(table, headers=headers, colglobalalign=colglobalalign, colalign=colalign, headersglobalalign=headersglobalalign, headersalign=headersalign)
2705+
expected = '\n'.join([
2706+
"h e a d e r",
2707+
"--- --- --- --- --- ---",
2708+
"1 2 3 4 5 6",
2709+
"111 222 333 444 555 666"])
2710+
assert_equal(expected, result)
2711+
2712+
def test_colalign_or_headersalign_too_long():
2713+
""" Test `colalign` and `headersalign` too long. """
2714+
table = [[1,2],[111,222]]
2715+
colalign = ('global', 'left', 'center')
2716+
headers = ['h']
2717+
headersalign = ('center', 'right', 'same')
2718+
result = tabulate(table, headers=headers, colalign=colalign, headersalign=headersalign)
2719+
expected = '\n'.join([
2720+
" h",
2721+
"--- ---",
2722+
" 1 2",
2723+
"111 222"])
2724+
assert_equal(expected, result)
2725+
2726+
def test_warning_when_colalign_or_headersalign_is_string():
2727+
""" Test user warnings when `colalign` or `headersalign` is a string. """
2728+
table = [[1,"bar"]]
2729+
opt = {
2730+
'colalign': "center",
2731+
'headers': ['foo', '2'],
2732+
'headersalign': "center"}
2733+
check_warnings((tabulate, [table], opt),
2734+
num = 2,
2735+
category = UserWarning,
2736+
contain = "As a string")
26832737

26842738
def test_float_conversions():
26852739
"Output: float format parsed"

0 commit comments

Comments
 (0)