From 3fb37a1d0237869e8e37864d06c0dfd94bb43189 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 6 Sep 2021 06:12:56 +0200 Subject: Merging upstream version 2.2.0. Signed-off-by: Daniel Baumann --- .../test_delimited_output_adapter.py | 39 ++-- tests/tabular_output/test_output_formatter.py | 147 ++++++++---- tests/tabular_output/test_preprocessors.py | 256 +++++++++++---------- tests/tabular_output/test_tabulate_adapter.py | 127 +++++----- .../tabular_output/test_terminaltables_adapter.py | 69 ------ tests/tabular_output/test_tsv_output_adapter.py | 23 +- .../tabular_output/test_vertical_table_adapter.py | 31 ++- 7 files changed, 365 insertions(+), 327 deletions(-) delete mode 100644 tests/tabular_output/test_terminaltables_adapter.py (limited to 'tests/tabular_output') diff --git a/tests/tabular_output/test_delimited_output_adapter.py b/tests/tabular_output/test_delimited_output_adapter.py index 3627b84..86a622e 100644 --- a/tests/tabular_output/test_delimited_output_adapter.py +++ b/tests/tabular_output/test_delimited_output_adapter.py @@ -12,37 +12,44 @@ from cli_helpers.tabular_output import delimited_output_adapter def test_csv_wrapper(): """Test the delimited output adapter.""" # Test comma-delimited output. - data = [['abc', '1'], ['d', '456']] - headers = ['letters', 'number'] - output = delimited_output_adapter.adapter(iter(data), headers, dialect='unix') - assert "\n".join(output) == dedent('''\ + data = [["abc", "1"], ["d", "456"]] + headers = ["letters", "number"] + output = delimited_output_adapter.adapter(iter(data), headers, dialect="unix") + assert "\n".join(output) == dedent( + '''\ "letters","number"\n\ "abc","1"\n\ - "d","456"''') + "d","456"''' + ) # Test tab-delimited output. - data = [['abc', '1'], ['d', '456']] - headers = ['letters', 'number'] + data = [["abc", "1"], ["d", "456"]] + headers = ["letters", "number"] output = delimited_output_adapter.adapter( - iter(data), headers, table_format='csv-tab', dialect='unix') - assert "\n".join(output) == dedent('''\ + iter(data), headers, table_format="csv-tab", dialect="unix" + ) + assert "\n".join(output) == dedent( + '''\ "letters"\t"number"\n\ "abc"\t"1"\n\ - "d"\t"456"''') + "d"\t"456"''' + ) with pytest.raises(ValueError): output = delimited_output_adapter.adapter( - iter(data), headers, table_format='foobar') + iter(data), headers, table_format="foobar" + ) list(output) def test_unicode_with_csv(): """Test that the csv wrapper can handle non-ascii characters.""" - data = [['观音', '1'], ['Ποσειδῶν', '456']] - headers = ['letters', 'number'] + data = [["观音", "1"], ["Ποσειδῶν", "456"]] + headers = ["letters", "number"] output = delimited_output_adapter.adapter(data, headers) - assert "\n".join(output) == dedent('''\ + assert "\n".join(output) == dedent( + """\ letters,number\n\ 观音,1\n\ - Ποσειδῶν,456''') - + Ποσειδῶν,456""" + ) diff --git a/tests/tabular_output/test_output_formatter.py b/tests/tabular_output/test_output_formatter.py index 0509cb6..d064427 100644 --- a/tests/tabular_output/test_output_formatter.py +++ b/tests/tabular_output/test_output_formatter.py @@ -14,14 +14,15 @@ from cli_helpers.utils import strip_ansi def test_tabular_output_formatter(): """Test the TabularOutputFormatter class.""" - headers = ['text', 'numeric'] + headers = ["text", "numeric"] data = [ ["abc", Decimal(1)], ["defg", Decimal("11.1")], ["hi", Decimal("1.1")], ["Pablo\rß\n", 0], ] - expected = dedent("""\ + expected = dedent( + """\ +------------+---------+ | text | numeric | +------------+---------+ @@ -33,66 +34,99 @@ def test_tabular_output_formatter(): ) 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')) + 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_format_output_wrapper(): """Test the format_output wrapper.""" - data = [['1', None], ['2', 'Sam'], - ['3', 'Joe']] - headers = ['id', 'name'] - expected = dedent('''\ + 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')) + 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': + if value == "hello": row[i] = "{}, world".format(value) yield row + return hello_world_data(data), headers - data = [['foo', None], ['hello!', 'hello']] - headers = 'ab' + data = [["foo", None], ["hello!", "hello"]] + headers = "ab" - expected = dedent('''\ + 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')) + 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' + 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' + 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(): @@ -100,23 +134,27 @@ def test_unsupported_format(): formatter = TabularOutputFormatter() with pytest.raises(ValueError): - formatter.format_name = 'foobar' + formatter.format_name = "foobar" with pytest.raises(ValueError): - formatter.format_output((), (), format_name='foobar') + 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'] + 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') + 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] @@ -127,8 +165,14 @@ 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)) + 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) @@ -138,36 +182,45 @@ 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') + 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,)) + 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(' ') + 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'])) + formatted = next(formatter.format_output(zip(loremipsum), ["lorem"])) except TypeError: assert False, "{0} doesn't return iterable".format(format_name) def test_all_text_type(): """Test the TabularOutputFormatter class.""" - data = [[1, u"", None, Decimal(2)]] - headers = ['col1', 'col2', 'col3', 'col4'] + 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): + for row in output_formatter.format_output( + iter(data), headers, format_name=format_name + ): assert isinstance(row, text_type), "not unicode for {}".format(format_name) diff --git a/tests/tabular_output/test_preprocessors.py b/tests/tabular_output/test_preprocessors.py index e579bbe..efc1b54 100644 --- a/tests/tabular_output/test_preprocessors.py +++ b/tests/tabular_output/test_preprocessors.py @@ -8,8 +8,15 @@ import pytest from cli_helpers.compat import HAS_PYGMENTS from cli_helpers.tabular_output.preprocessors import ( - align_decimals, bytes_to_string, convert_to_string, quote_whitespaces, - override_missing_value, override_tab_value, style_output, format_numbers) + align_decimals, + bytes_to_string, + convert_to_string, + quote_whitespaces, + override_missing_value, + override_tab_value, + style_output, + format_numbers, +) if HAS_PYGMENTS: from pygments.style import Style @@ -22,9 +29,9 @@ import types def test_convert_to_string(): """Test the convert_to_string() function.""" - data = [[1, 'John'], [2, 'Jill']] - headers = [0, 'name'] - expected = ([['1', 'John'], ['2', 'Jill']], ['0', 'name']) + data = [[1, "John"], [2, "Jill"]] + headers = [0, "name"] + expected = ([["1", "John"], ["2", "Jill"]], ["0", "name"]) results = convert_to_string(data, headers) assert expected == (list(results[0]), results[1]) @@ -32,42 +39,41 @@ def test_convert_to_string(): def test_override_missing_values(): """Test the override_missing_values() function.""" - data = [[1, None], [2, 'Jill']] - headers = [0, 'name'] - expected = ([[1, ''], [2, 'Jill']], [0, 'name']) - results = override_missing_value(data, headers, missing_value='') + data = [[1, None], [2, "Jill"]] + headers = [0, "name"] + expected = ([[1, ""], [2, "Jill"]], [0, "name"]) + results = override_missing_value(data, headers, missing_value="") assert expected == (list(results[0]), results[1]) -@pytest.mark.skipif(not HAS_PYGMENTS, reason='requires the Pygments library') +@pytest.mark.skipif(not HAS_PYGMENTS, reason="requires the Pygments library") def test_override_missing_value_with_style(): """Test that *override_missing_value()* styles output.""" class NullStyle(Style): - styles = { - Token.Output.Null: '#0f0' - } + styles = {Token.Output.Null: "#0f0"} - headers = ['h1', 'h2'] - data = [[None, '2'], ['abc', None]] + headers = ["h1", "h2"] + data = [[None, "2"], ["abc", None]] - expected_headers = ['h1', 'h2'] + expected_headers = ["h1", "h2"] expected_data = [ - ['\x1b[38;5;10m\x1b[39m', '2'], - ['abc', '\x1b[38;5;10m\x1b[39m'] + ["\x1b[38;5;10m\x1b[39m", "2"], + ["abc", "\x1b[38;5;10m\x1b[39m"], ] - results = override_missing_value(data, headers, - style=NullStyle, missing_value="") + results = override_missing_value( + data, headers, style=NullStyle, missing_value="" + ) assert (expected_data, expected_headers) == (list(results[0]), results[1]) def test_override_tab_value(): """Test the override_tab_value() function.""" - data = [[1, '\tJohn'], [2, 'Jill']] - headers = ['id', 'name'] - expected = ([[1, ' John'], [2, 'Jill']], ['id', 'name']) + data = [[1, "\tJohn"], [2, "Jill"]] + headers = ["id", "name"] + expected = ([[1, " John"], [2, "Jill"]], ["id", "name"]) results = override_tab_value(data, headers) assert expected == (list(results[0]), results[1]) @@ -75,9 +81,9 @@ def test_override_tab_value(): def test_bytes_to_string(): """Test the bytes_to_string() function.""" - data = [[1, 'John'], [2, b'Jill']] - headers = [0, 'name'] - expected = ([[1, 'John'], [2, 'Jill']], [0, 'name']) + data = [[1, "John"], [2, b"Jill"]] + headers = [0, "name"] + expected = ([[1, "John"], [2, "Jill"]], [0, "name"]) results = bytes_to_string(data, headers) assert expected == (list(results[0]), results[1]) @@ -85,11 +91,10 @@ def test_bytes_to_string(): def test_align_decimals(): """Test the align_decimals() function.""" - data = [[Decimal('200'), Decimal('1')], [ - Decimal('1.00002'), Decimal('1.0')]] - headers = ['num1', 'num2'] + data = [[Decimal("200"), Decimal("1")], [Decimal("1.00002"), Decimal("1.0")]] + headers = ["num1", "num2"] column_types = (float, float) - expected = ([['200', '1'], [' 1.00002', '1.0']], ['num1', 'num2']) + expected = ([["200", "1"], [" 1.00002", "1.0"]], ["num1", "num2"]) results = align_decimals(data, headers, column_types=column_types) assert expected == (list(results[0]), results[1]) @@ -98,9 +103,9 @@ def test_align_decimals(): def test_align_decimals_empty_result(): """Test align_decimals() with no results.""" data = [] - headers = ['num1', 'num2'] + headers = ["num1", "num2"] column_types = () - expected = ([], ['num1', 'num2']) + expected = ([], ["num1", "num2"]) results = align_decimals(data, headers, column_types=column_types) assert expected == (list(results[0]), results[1]) @@ -108,10 +113,10 @@ def test_align_decimals_empty_result(): def test_align_decimals_non_decimals(): """Test align_decimals() with non-decimals.""" - data = [[Decimal('200.000'), Decimal('1.000')], [None, None]] - headers = ['num1', 'num2'] + data = [[Decimal("200.000"), Decimal("1.000")], [None, None]] + headers = ["num1", "num2"] column_types = (float, float) - expected = ([['200.000', '1.000'], [None, None]], ['num1', 'num2']) + expected = ([["200.000", "1.000"], [None, None]], ["num1", "num2"]) results = align_decimals(data, headers, column_types=column_types) assert expected == (list(results[0]), results[1]) @@ -120,9 +125,8 @@ def test_align_decimals_non_decimals(): def test_quote_whitespaces(): """Test the quote_whitespaces() function.""" data = [[" before", "after "], [" both ", "none"]] - headers = ['h1', 'h2'] - expected = ([["' before'", "'after '"], ["' both '", "'none'"]], - ['h1', 'h2']) + headers = ["h1", "h2"] + expected = ([["' before'", "'after '"], ["' both '", "'none'"]], ["h1", "h2"]) results = quote_whitespaces(data, headers) assert expected == (list(results[0]), results[1]) @@ -131,8 +135,8 @@ def test_quote_whitespaces(): def test_quote_whitespaces_empty_result(): """Test the quote_whitespaces() function with no results.""" data = [] - headers = ['h1', 'h2'] - expected = ([], ['h1', 'h2']) + headers = ["h1", "h2"] + expected = ([], ["h1", "h2"]) results = quote_whitespaces(data, headers) assert expected == (list(results[0]), results[1]) @@ -141,106 +145,115 @@ def test_quote_whitespaces_empty_result(): def test_quote_whitespaces_non_spaces(): """Test the quote_whitespaces() function with non-spaces.""" data = [["\tbefore", "after \r"], ["\n both ", "none"]] - headers = ['h1', 'h2'] - expected = ([["'\tbefore'", "'after \r'"], ["'\n both '", "'none'"]], - ['h1', 'h2']) + headers = ["h1", "h2"] + expected = ([["'\tbefore'", "'after \r'"], ["'\n both '", "'none'"]], ["h1", "h2"]) results = quote_whitespaces(data, headers) assert expected == (list(results[0]), results[1]) -@pytest.mark.skipif(not HAS_PYGMENTS, reason='requires the Pygments library') +@pytest.mark.skipif(not HAS_PYGMENTS, reason="requires the Pygments library") def test_style_output_no_styles(): """Test that *style_output()* does not style without styles.""" - headers = ['h1', 'h2'] - data = [['1', '2'], ['a', 'b']] + headers = ["h1", "h2"] + data = [["1", "2"], ["a", "b"]] results = style_output(data, headers) assert (data, headers) == (list(results[0]), results[1]) -@pytest.mark.skipif(HAS_PYGMENTS, - reason='requires the Pygments library be missing') +@pytest.mark.skipif(HAS_PYGMENTS, reason="requires the Pygments library be missing") def test_style_output_no_pygments(): """Test that *style_output()* does not try to style without Pygments.""" - headers = ['h1', 'h2'] - data = [['1', '2'], ['a', 'b']] + headers = ["h1", "h2"] + data = [["1", "2"], ["a", "b"]] results = style_output(data, headers) assert (data, headers) == (list(results[0]), results[1]) -@pytest.mark.skipif(not HAS_PYGMENTS, reason='requires the Pygments library') +@pytest.mark.skipif(not HAS_PYGMENTS, reason="requires the Pygments library") def test_style_output(): """Test that *style_output()* styles output.""" class CliStyle(Style): default_style = "" styles = { - Token.Output.Header: 'bold ansibrightred', - Token.Output.OddRow: 'bg:#eee #111', - Token.Output.EvenRow: '#0f0' + Token.Output.Header: "bold ansibrightred", + Token.Output.OddRow: "bg:#eee #111", + Token.Output.EvenRow: "#0f0", } - headers = ['h1', 'h2'] - data = [['观音', '2'], ['Ποσειδῶν', 'b']] - expected_headers = ['\x1b[91;01mh1\x1b[39;00m', '\x1b[91;01mh2\x1b[39;00m'] - expected_data = [['\x1b[38;5;233;48;5;7m观音\x1b[39;49m', - '\x1b[38;5;233;48;5;7m2\x1b[39;49m'], - ['\x1b[38;5;10mΠοσειδῶν\x1b[39m', '\x1b[38;5;10mb\x1b[39m']] + headers = ["h1", "h2"] + data = [["观音", "2"], ["Ποσειδῶν", "b"]] + + expected_headers = ["\x1b[91;01mh1\x1b[39;00m", "\x1b[91;01mh2\x1b[39;00m"] + expected_data = [ + ["\x1b[38;5;233;48;5;7m观音\x1b[39;49m", "\x1b[38;5;233;48;5;7m2\x1b[39;49m"], + ["\x1b[38;5;10mΠοσειδῶν\x1b[39m", "\x1b[38;5;10mb\x1b[39m"], + ] results = style_output(data, headers, style=CliStyle) assert (expected_data, expected_headers) == (list(results[0]), results[1]) -@pytest.mark.skipif(not HAS_PYGMENTS, reason='requires the Pygments library') +@pytest.mark.skipif(not HAS_PYGMENTS, reason="requires the Pygments library") def test_style_output_with_newlines(): """Test that *style_output()* styles output with newlines in it.""" class CliStyle(Style): default_style = "" styles = { - Token.Output.Header: 'bold ansibrightred', - Token.Output.OddRow: 'bg:#eee #111', - Token.Output.EvenRow: '#0f0' + Token.Output.Header: "bold ansibrightred", + Token.Output.OddRow: "bg:#eee #111", + Token.Output.EvenRow: "#0f0", } - headers = ['h1', 'h2'] - data = [['观音\nLine2', 'Ποσειδῶν']] - expected_headers = ['\x1b[91;01mh1\x1b[39;00m', '\x1b[91;01mh2\x1b[39;00m'] + headers = ["h1", "h2"] + data = [["观音\nLine2", "Ποσειδῶν"]] + + expected_headers = ["\x1b[91;01mh1\x1b[39;00m", "\x1b[91;01mh2\x1b[39;00m"] expected_data = [ - ['\x1b[38;5;233;48;5;7m观音\x1b[39;49m\n\x1b[38;5;233;48;5;7m' - 'Line2\x1b[39;49m', - '\x1b[38;5;233;48;5;7mΠοσειδῶν\x1b[39;49m']] + [ + "\x1b[38;5;233;48;5;7m观音\x1b[39;49m\n\x1b[38;5;233;48;5;7m" + "Line2\x1b[39;49m", + "\x1b[38;5;233;48;5;7mΠοσειδῶν\x1b[39;49m", + ] + ] results = style_output(data, headers, style=CliStyle) - assert (expected_data, expected_headers) == (list(results[0]), results[1]) -@pytest.mark.skipif(not HAS_PYGMENTS, reason='requires the Pygments library') + +@pytest.mark.skipif(not HAS_PYGMENTS, reason="requires the Pygments library") def test_style_output_custom_tokens(): """Test that *style_output()* styles output with custom token names.""" class CliStyle(Style): default_style = "" styles = { - Token.Results.Headers: 'bold ansibrightred', - Token.Results.OddRows: 'bg:#eee #111', - Token.Results.EvenRows: '#0f0' + Token.Results.Headers: "bold ansibrightred", + Token.Results.OddRows: "bg:#eee #111", + Token.Results.EvenRows: "#0f0", } - headers = ['h1', 'h2'] - data = [['1', '2'], ['a', 'b']] - expected_headers = ['\x1b[91;01mh1\x1b[39;00m', '\x1b[91;01mh2\x1b[39;00m'] - expected_data = [['\x1b[38;5;233;48;5;7m1\x1b[39;49m', - '\x1b[38;5;233;48;5;7m2\x1b[39;49m'], - ['\x1b[38;5;10ma\x1b[39m', '\x1b[38;5;10mb\x1b[39m']] + headers = ["h1", "h2"] + data = [["1", "2"], ["a", "b"]] + + expected_headers = ["\x1b[91;01mh1\x1b[39;00m", "\x1b[91;01mh2\x1b[39;00m"] + expected_data = [ + ["\x1b[38;5;233;48;5;7m1\x1b[39;49m", "\x1b[38;5;233;48;5;7m2\x1b[39;49m"], + ["\x1b[38;5;10ma\x1b[39m", "\x1b[38;5;10mb\x1b[39m"], + ] output = style_output( - data, headers, style=CliStyle, - header_token='Token.Results.Headers', - odd_row_token='Token.Results.OddRows', - even_row_token='Token.Results.EvenRows') + data, + headers, + style=CliStyle, + header_token="Token.Results.Headers", + odd_row_token="Token.Results.OddRows", + even_row_token="Token.Results.EvenRows", + ) assert (expected_data, expected_headers) == (list(output[0]), output[1]) @@ -248,29 +261,25 @@ def test_style_output_custom_tokens(): def test_format_integer(): """Test formatting for an INTEGER datatype.""" data = [[1], [1000], [1000000]] - headers = ['h1'] - result_data, result_headers = format_numbers(data, - headers, - column_types=(int,), - integer_format=',', - float_format=',') - - expected = [['1'], ['1,000'], ['1,000,000']] + headers = ["h1"] + result_data, result_headers = format_numbers( + data, headers, column_types=(int,), integer_format=",", float_format="," + ) + + expected = [["1"], ["1,000"], ["1,000,000"]] assert expected == list(result_data) assert headers == result_headers def test_format_decimal(): """Test formatting for a DECIMAL(12, 4) datatype.""" - data = [[Decimal('1.0000')], [Decimal('1000.0000')], [Decimal('1000000.0000')]] - headers = ['h1'] - result_data, result_headers = format_numbers(data, - headers, - column_types=(float,), - integer_format=',', - float_format=',') - - expected = [['1.0000'], ['1,000.0000'], ['1,000,000.0000']] + data = [[Decimal("1.0000")], [Decimal("1000.0000")], [Decimal("1000000.0000")]] + headers = ["h1"] + result_data, result_headers = format_numbers( + data, headers, column_types=(float,), integer_format=",", float_format="," + ) + + expected = [["1.0000"], ["1,000.0000"], ["1,000,000.0000"]] assert expected == list(result_data) assert headers == result_headers @@ -278,13 +287,11 @@ def test_format_decimal(): def test_format_float(): """Test formatting for a REAL datatype.""" data = [[1.0], [1000.0], [1000000.0]] - headers = ['h1'] - result_data, result_headers = format_numbers(data, - headers, - column_types=(float,), - integer_format=',', - float_format=',') - expected = [['1.0'], ['1,000.0'], ['1,000,000.0']] + headers = ["h1"] + result_data, result_headers = format_numbers( + data, headers, column_types=(float,), integer_format=",", float_format="," + ) + expected = [["1.0"], ["1,000.0"], ["1,000,000.0"]] assert expected == list(result_data) assert headers == result_headers @@ -292,11 +299,12 @@ def test_format_float(): def test_format_integer_only(): """Test that providing one format string works.""" data = [[1, 1.0], [1000, 1000.0], [1000000, 1000000.0]] - headers = ['h1', 'h2'] - result_data, result_headers = format_numbers(data, headers, column_types=(int, float), - integer_format=',') + headers = ["h1", "h2"] + result_data, result_headers = format_numbers( + data, headers, column_types=(int, float), integer_format="," + ) - expected = [['1', 1.0], ['1,000', 1000.0], ['1,000,000', 1000000.0]] + expected = [["1", 1.0], ["1,000", 1000.0], ["1,000,000", 1000000.0]] assert expected == list(result_data) assert headers == result_headers @@ -304,7 +312,7 @@ def test_format_integer_only(): def test_format_numbers_no_format_strings(): """Test that numbers aren't formatted without format strings.""" data = ((1), (1000), (1000000)) - headers = ('h1',) + headers = ("h1",) result_data, result_headers = format_numbers(data, headers, column_types=(int,)) assert list(data) == list(result_data) assert headers == result_headers @@ -313,17 +321,25 @@ def test_format_numbers_no_format_strings(): def test_format_numbers_no_column_types(): """Test that numbers aren't formatted without column types.""" data = ((1), (1000), (1000000)) - headers = ('h1',) - result_data, result_headers = format_numbers(data, headers, integer_format=',', - float_format=',') + headers = ("h1",) + result_data, result_headers = format_numbers( + data, headers, integer_format=",", float_format="," + ) assert list(data) == list(result_data) assert headers == result_headers + def test_enforce_iterable(): - preprocessors = inspect.getmembers(cli_helpers.tabular_output.preprocessors, inspect.isfunction) - loremipsum = 'lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod'.split(' ') + preprocessors = inspect.getmembers( + cli_helpers.tabular_output.preprocessors, inspect.isfunction + ) + loremipsum = ( + "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod".split( + " " + ) + ) for name, preprocessor in preprocessors: - preprocessed = preprocessor(zip(loremipsum), ['lorem'], column_types=(str,)) + preprocessed = preprocessor(zip(loremipsum), ["lorem"], column_types=(str,)) try: first = next(preprocessed[0]) except StopIteration: diff --git a/tests/tabular_output/test_tabulate_adapter.py b/tests/tabular_output/test_tabulate_adapter.py index e0dd5a8..6e7c7db 100644 --- a/tests/tabular_output/test_tabulate_adapter.py +++ b/tests/tabular_output/test_tabulate_adapter.py @@ -16,35 +16,53 @@ if HAS_PYGMENTS: def test_tabulate_wrapper(): """Test the *output_formatter.tabulate_wrapper()* function.""" - data = [['abc', 1], ['d', 456]] - headers = ['letters', 'number'] - output = tabulate_adapter.adapter(iter(data), headers, table_format='psql') - assert "\n".join(output) == dedent('''\ - +-----------+----------+ - | letters | number | - |-----------+----------| - | abc | 1 | - | d | 456 | - +-----------+----------+''') - - data = [['{1,2,3}', '{{1,2},{3,4}}', '{å,魚,текст}'], ['{}', '', '{}']] - headers = ['bigint_array', 'nested_numeric_array', '配列'] - output = tabulate_adapter.adapter(iter(data), headers, table_format='psql') - assert "\n".join(output) == dedent('''\ - +----------------+------------------------+--------------+ - | bigint_array | nested_numeric_array | 配列 | - |----------------+------------------------+--------------| - | {1,2,3} | {{1,2},{3,4}} | {å,魚,текст} | - | {} | | {} | - +----------------+------------------------+--------------+''') + data = [["abc", 1], ["d", 456]] + headers = ["letters", "number"] + output = tabulate_adapter.adapter(iter(data), headers, table_format="psql") + assert "\n".join(output) == dedent( + """\ + +---------+--------+ + | letters | number | + |---------+--------| + | abc | 1 | + | d | 456 | + +---------+--------+""" + ) + + data = [["abc", 1], ["d", 456]] + headers = ["letters", "number"] + output = tabulate_adapter.adapter(iter(data), headers, table_format="psql_unicode") + assert "\n".join(output) == dedent( + """\ + ┌─────────┬────────┐ + │ letters │ number │ + ├─────────┼────────┤ + │ abc │ 1 │ + │ d │ 456 │ + └─────────┴────────┘""" + ) + + data = [["{1,2,3}", "{{1,2},{3,4}}", "{å,魚,текст}"], ["{}", "", "{}"]] + headers = ["bigint_array", "nested_numeric_array", "配列"] + output = tabulate_adapter.adapter(iter(data), headers, table_format="psql") + assert "\n".join(output) == dedent( + """\ + +--------------+----------------------+--------------+ + | bigint_array | nested_numeric_array | 配列 | + |--------------+----------------------+--------------| + | {1,2,3} | {{1,2},{3,4}} | {å,魚,текст} | + | {} | | {} | + +--------------+----------------------+--------------+""" + ) def test_markup_format(): """Test that markup formats do not have number align or string align.""" - data = [['abc', 1], ['d', 456]] - headers = ['letters', 'number'] - output = tabulate_adapter.adapter(iter(data), headers, table_format='mediawiki') - assert "\n".join(output) == dedent('''\ + data = [["abc", 1], ["d", 456]] + headers = ["letters", "number"] + output = tabulate_adapter.adapter(iter(data), headers, table_format="mediawiki") + assert "\n".join(output) == dedent( + """\ {| class="wikitable" style="text-align: left;" |+ |- @@ -53,44 +71,43 @@ def test_markup_format(): | abc || 1 |- | d || 456 - |}''') + |}""" + ) -@pytest.mark.skipif(not HAS_PYGMENTS, reason='requires the Pygments library') +@pytest.mark.skipif(not HAS_PYGMENTS, reason="requires the Pygments library") def test_style_output_table(): """Test that *style_output_table()* styles the output table.""" class CliStyle(Style): default_style = "" styles = { - Token.Output.TableSeparator: 'ansibrightred', + Token.Output.TableSeparator: "ansibrightred", } - headers = ['h1', 'h2'] - data = [['观音', '2'], ['Ποσειδῶν', 'b']] - style_output_table = tabulate_adapter.style_output_table('psql') + + headers = ["h1", "h2"] + data = [["观音", "2"], ["Ποσειδῶν", "b"]] + style_output_table = tabulate_adapter.style_output_table("psql") style_output_table(data, headers, style=CliStyle) - output = tabulate_adapter.adapter(iter(data), headers, table_format='psql') - - assert "\n".join(output) == dedent('''\ - \x1b[91m+\x1b[39m''' + ( - ('\x1b[91m-\x1b[39m' * 10) + - '\x1b[91m+\x1b[39m' + - ('\x1b[91m-\x1b[39m' * 6)) + - '''\x1b[91m+\x1b[39m - \x1b[91m|\x1b[39m h1 \x1b[91m|\x1b[39m''' + - ''' h2 \x1b[91m|\x1b[39m - ''' + '\x1b[91m|\x1b[39m' + ( - ('\x1b[91m-\x1b[39m' * 10) + - '\x1b[91m+\x1b[39m' + - ('\x1b[91m-\x1b[39m' * 6)) + - '''\x1b[91m|\x1b[39m - \x1b[91m|\x1b[39m 观音 \x1b[91m|\x1b[39m''' + - ''' 2 \x1b[91m|\x1b[39m - \x1b[91m|\x1b[39m Ποσειδῶν \x1b[91m|\x1b[39m''' + - ''' b \x1b[91m|\x1b[39m - ''' + '\x1b[91m+\x1b[39m' + ( - ('\x1b[91m-\x1b[39m' * 10) + - '\x1b[91m+\x1b[39m' + - ('\x1b[91m-\x1b[39m' * 6)) + - '\x1b[91m+\x1b[39m') + output = tabulate_adapter.adapter(iter(data), headers, table_format="psql") + PLUS = "\x1b[91m+\x1b[39m" + MINUS = "\x1b[91m-\x1b[39m" + PIPE = "\x1b[91m|\x1b[39m" + + expected = ( + dedent( + """\ + +----------+----+ + | h1 | h2 | + |----------+----| + | 观音 | 2 | + | Ποσειδῶν | b | + +----------+----+""" + ) + .replace("+", PLUS) + .replace("-", MINUS) + .replace("|", PIPE) + ) + + assert "\n".join(output) == expected diff --git a/tests/tabular_output/test_terminaltables_adapter.py b/tests/tabular_output/test_terminaltables_adapter.py deleted file mode 100644 index f756327..0000000 --- a/tests/tabular_output/test_terminaltables_adapter.py +++ /dev/null @@ -1,69 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test the terminaltables output adapter.""" - -from __future__ import unicode_literals -from textwrap import dedent - -import pytest - -from cli_helpers.compat import HAS_PYGMENTS -from cli_helpers.tabular_output import terminaltables_adapter - -if HAS_PYGMENTS: - from pygments.style import Style - from pygments.token import Token - - -def test_terminal_tables_adapter(): - """Test the terminaltables output adapter.""" - data = [['abc', 1], ['d', 456]] - headers = ['letters', 'number'] - output = terminaltables_adapter.adapter( - iter(data), headers, table_format='ascii') - assert "\n".join(output) == dedent('''\ - +---------+--------+ - | letters | number | - +---------+--------+ - | abc | 1 | - | d | 456 | - +---------+--------+''') - - -@pytest.mark.skipif(not HAS_PYGMENTS, reason='requires the Pygments library') -def test_style_output_table(): - """Test that *style_output_table()* styles the output table.""" - - class CliStyle(Style): - default_style = "" - styles = { - Token.Output.TableSeparator: 'ansibrightred', - } - headers = ['h1', 'h2'] - data = [['观音', '2'], ['Ποσειδῶν', 'b']] - style_output_table = terminaltables_adapter.style_output_table('ascii') - - style_output_table(data, headers, style=CliStyle) - output = terminaltables_adapter.adapter(iter(data), headers, table_format='ascii') - - assert "\n".join(output) == dedent('''\ - \x1b[91m+\x1b[39m''' + ( - ('\x1b[91m-\x1b[39m' * 10) + - '\x1b[91m+\x1b[39m' + - ('\x1b[91m-\x1b[39m' * 4)) + - '''\x1b[91m+\x1b[39m - \x1b[91m|\x1b[39m h1 \x1b[91m|\x1b[39m''' + - ''' h2 \x1b[91m|\x1b[39m - ''' + '\x1b[91m+\x1b[39m' + ( - ('\x1b[91m-\x1b[39m' * 10) + - '\x1b[91m+\x1b[39m' + - ('\x1b[91m-\x1b[39m' * 4)) + - '''\x1b[91m+\x1b[39m - \x1b[91m|\x1b[39m 观音 \x1b[91m|\x1b[39m''' + - ''' 2 \x1b[91m|\x1b[39m - \x1b[91m|\x1b[39m Ποσειδῶν \x1b[91m|\x1b[39m''' + - ''' b \x1b[91m|\x1b[39m - ''' + '\x1b[91m+\x1b[39m' + ( - ('\x1b[91m-\x1b[39m' * 10) + - '\x1b[91m+\x1b[39m' + - ('\x1b[91m-\x1b[39m' * 4)) + - '\x1b[91m+\x1b[39m') diff --git a/tests/tabular_output/test_tsv_output_adapter.py b/tests/tabular_output/test_tsv_output_adapter.py index 707d757..9249d87 100644 --- a/tests/tabular_output/test_tsv_output_adapter.py +++ b/tests/tabular_output/test_tsv_output_adapter.py @@ -12,22 +12,25 @@ from cli_helpers.tabular_output import tsv_output_adapter def test_tsv_wrapper(): """Test the tsv output adapter.""" # Test tab-delimited output. - data = [['ab\r\nc', '1'], ['d', '456']] - headers = ['letters', 'number'] - output = tsv_output_adapter.adapter( - iter(data), headers, table_format='tsv') - assert "\n".join(output) == dedent('''\ + data = [["ab\r\nc", "1"], ["d", "456"]] + headers = ["letters", "number"] + output = tsv_output_adapter.adapter(iter(data), headers, table_format="tsv") + assert "\n".join(output) == dedent( + """\ letters\tnumber\n\ ab\r\\nc\t1\n\ - d\t456''') + d\t456""" + ) def test_unicode_with_tsv(): """Test that the tsv wrapper can handle non-ascii characters.""" - data = [['观音', '1'], ['Ποσειδῶν', '456']] - headers = ['letters', 'number'] + data = [["观音", "1"], ["Ποσειδῶν", "456"]] + headers = ["letters", "number"] output = tsv_output_adapter.adapter(data, headers) - assert "\n".join(output) == dedent('''\ + assert "\n".join(output) == dedent( + """\ letters\tnumber\n\ 观音\t1\n\ - Ποσειδῶν\t456''') + Ποσειδῶν\t456""" + ) diff --git a/tests/tabular_output/test_vertical_table_adapter.py b/tests/tabular_output/test_vertical_table_adapter.py index 8b5e18c..359d9d9 100644 --- a/tests/tabular_output/test_vertical_table_adapter.py +++ b/tests/tabular_output/test_vertical_table_adapter.py @@ -9,30 +9,41 @@ from cli_helpers.tabular_output import vertical_table_adapter def test_vertical_table(): """Test the default settings for vertical_table().""" - results = [('hello', text_type(123)), ('world', text_type(456))] + results = [("hello", text_type(123)), ("world", text_type(456))] - expected = dedent("""\ + expected = dedent( + """\ ***************************[ 1. row ]*************************** name | hello age | 123 ***************************[ 2. row ]*************************** name | world - age | 456""") + age | 456""" + ) assert expected == "\n".join( - vertical_table_adapter.adapter(results, ('name', 'age'))) + vertical_table_adapter.adapter(results, ("name", "age")) + ) def test_vertical_table_customized(): """Test customized settings for vertical_table().""" - results = [('john', text_type(47)), ('jill', text_type(50))] + results = [("john", text_type(47)), ("jill", text_type(50))] - expected = dedent("""\ + expected = dedent( + """\ -[ PERSON 1 ]----- name | john age | 47 -[ PERSON 2 ]----- name | jill - age | 50""") - assert expected == "\n".join(vertical_table_adapter.adapter( - results, ('name', 'age'), sep_title='PERSON {n}', - sep_character='-', sep_length=(1, 5))) + age | 50""" + ) + assert expected == "\n".join( + vertical_table_adapter.adapter( + results, + ("name", "age"), + sep_title="PERSON {n}", + sep_character="-", + sep_length=(1, 5), + ) + ) -- cgit v1.2.3