diff options
Diffstat (limited to 'tests/tabular_output/test_output_formatter.py')
-rw-r--r-- | tests/tabular_output/test_output_formatter.py | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/tests/tabular_output/test_output_formatter.py b/tests/tabular_output/test_output_formatter.py new file mode 100644 index 0000000..8e1fa92 --- /dev/null +++ b/tests/tabular_output/test_output_formatter.py @@ -0,0 +1,271 @@ +# -*- coding: utf-8 -*- +"""Test the generic output formatter interface.""" + +from __future__ import unicode_literals +from decimal import Decimal +from textwrap import dedent + +import pytest + +from cli_helpers.tabular_output import format_output, TabularOutputFormatter +from cli_helpers.compat import binary_type, text_type +from cli_helpers.utils import strip_ansi + + +def test_tabular_output_formatter(): + """Test the TabularOutputFormatter class.""" + headers = ["text", "numeric"] + data = [ + ["abc", Decimal(1)], + ["defg", Decimal("11.1")], + ["hi", Decimal("1.1")], + ["Pablo\rß\n", 0], + ] + expected = dedent( + """\ + +-------+---------+ + | text | numeric | + +-------+---------+ + | abc | 1 | + | defg | 11.1 | + | hi | 1.1 | + | Pablo | 0 | + | ß | | + +-------+---------+""" + ) + + print(expected) + print( + "\n".join( + TabularOutputFormatter().format_output( + iter(data), headers, format_name="ascii" + ) + ) + ) + assert expected == "\n".join( + TabularOutputFormatter().format_output(iter(data), headers, format_name="ascii") + ) + + +def test_tabular_output_escaped(): + """Test the ascii_escaped output format.""" + headers = ["text", "numeric"] + data = [ + ["abc", Decimal(1)], + ["defg", Decimal("11.1")], + ["hi", Decimal("1.1")], + ["Pablo\rß\n", 0], + ] + expected = dedent( + """\ + +------------+---------+ + | text | numeric | + +------------+---------+ + | abc | 1 | + | defg | 11.1 | + | hi | 1.1 | + | Pablo\\rß\\n | 0 | + +------------+---------+""" + ) + + print(expected) + print( + "\n".join( + TabularOutputFormatter().format_output( + iter(data), headers, format_name="ascii_escaped" + ) + ) + ) + assert expected == "\n".join( + TabularOutputFormatter().format_output( + iter(data), headers, format_name="ascii_escaped" + ) + ) + + +def test_tabular_format_output_wrapper(): + """Test the format_output wrapper.""" + data = [["1", None], ["2", "Sam"], ["3", "Joe"]] + headers = ["id", "name"] + expected = dedent( + """\ + +----+------+ + | id | name | + +----+------+ + | 1 | N/A | + | 2 | Sam | + | 3 | Joe | + +----+------+""" + ) + + assert expected == "\n".join( + format_output(iter(data), headers, format_name="ascii", missing_value="N/A") + ) + + +def test_additional_preprocessors(): + """Test that additional preprocessors are run.""" + + def hello_world(data, headers, **_): + def hello_world_data(data): + for row in data: + for i, value in enumerate(row): + if value == "hello": + row[i] = "{}, world".format(value) + yield row + + return hello_world_data(data), headers + + data = [["foo", None], ["hello!", "hello"]] + headers = "ab" + + expected = dedent( + """\ + +--------+--------------+ + | a | b | + +--------+--------------+ + | foo | hello | + | hello! | hello, world | + +--------+--------------+""" + ) + + assert expected == "\n".join( + TabularOutputFormatter().format_output( + iter(data), + headers, + format_name="ascii", + preprocessors=(hello_world,), + missing_value="hello", + ) + ) + + +def test_format_name_attribute(): + """Test the the format_name attribute be set and retrieved.""" + formatter = TabularOutputFormatter(format_name="plain") + assert formatter.format_name == "plain" + formatter.format_name = "simple" + assert formatter.format_name == "simple" + + with pytest.raises(ValueError): + formatter.format_name = "foobar" + + +def test_headless_tabulate_format(): + """Test that a headless formatter doesn't display headers""" + formatter = TabularOutputFormatter(format_name="minimal") + headers = ["text", "numeric"] + data = [["a"], ["b"], ["c"]] + expected = "a\nb\nc" + assert expected == "\n".join( + TabularOutputFormatter().format_output( + iter(data), + headers, + format_name="minimal", + ) + ) + + +def test_unsupported_format(): + """Test that TabularOutputFormatter rejects unknown formats.""" + formatter = TabularOutputFormatter() + + with pytest.raises(ValueError): + formatter.format_name = "foobar" + + with pytest.raises(ValueError): + formatter.format_output((), (), format_name="foobar") + + +def test_tabulate_ansi_escape_in_default_value(): + """Test that ANSI escape codes work with tabulate.""" + + data = [["1", None], ["2", "Sam"], ["3", "Joe"]] + headers = ["id", "name"] + + styled = format_output( + iter(data), + headers, + format_name="psql", + missing_value="\x1b[38;5;10mNULL\x1b[39m", + ) + unstyled = format_output( + iter(data), headers, format_name="psql", missing_value="NULL" + ) + + stripped_styled = [strip_ansi(s) for s in styled] + + assert list(unstyled) == stripped_styled + + +def test_get_type(): + """Test that _get_type returns the expected type.""" + formatter = TabularOutputFormatter() + + tests = ( + (1, int), + (2.0, float), + (b"binary", binary_type), + ("text", text_type), + (None, type(None)), + ((), text_type), + ) + + for value, data_type in tests: + assert data_type is formatter._get_type(value) + + +def test_provide_column_types(): + """Test that provided column types are passed to preprocessors.""" + expected_column_types = (bool, float) + data = ((1, 1.0), (0, 2)) + headers = ("a", "b") + + def preprocessor(data, headers, column_types=(), **_): + assert expected_column_types == column_types + return data, headers + + format_output( + data, + headers, + "csv", + column_types=expected_column_types, + preprocessors=(preprocessor,), + ) + + +def test_enforce_iterable(): + """Test that all output formatters accept iterable""" + formatter = TabularOutputFormatter() + loremipsum = ( + "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod".split( + " " + ) + ) + + for format_name in formatter.supported_formats: + formatter.format_name = format_name + try: + formatted = next(formatter.format_output(zip(loremipsum), ["lorem"])) + except TypeError: + assert False, "{0} doesn't return iterable".format(format_name) + + +@pytest.mark.parametrize( + "extra_kwargs", + [ + {}, + {"style": "default"}, + {"style": "colorful"}, + ], +) +def test_all_text_type(extra_kwargs): + """Test the TabularOutputFormatter class.""" + data = [[1, "", None, Decimal(2)]] + headers = ["col1", "col2", "col3", "col4"] + output_formatter = TabularOutputFormatter() + for format_name in output_formatter.supported_formats: + for row in output_formatter.format_output( + iter(data), headers, format_name=format_name, **extra_kwargs + ): + assert isinstance(row, text_type), "not unicode for {}".format(format_name) |