diff --git a/README.md b/README.md index 0283a0c..d095596 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,8 @@ To suppress row indices for all types of data, pass `showindex="never"` or `showindex=False`. To add a custom row index column, pass `showindex=rowIDs`, where `rowIDs` is some iterable: +Custom indices apply to data rows; separating lines do not consume index values. + ```pycon >>> print(tabulate([["F",24],["M",19]], showindex="always")) - - -- diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 12a2950..4d80a3c 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -1401,12 +1401,12 @@ def _prepend_row_index(rows, index): """Add a left-most index column.""" if index is None or index is False: return rows - if isinstance(index, Sized) and len(index) != len(rows): + sans_rows, separating_lines = _remove_separating_lines(rows) + if isinstance(index, Sized) and len(index) != len(sans_rows): raise ValueError( "index must be as long as the number of data rows: " - f"len(index)={len(index)} len(rows)={len(rows)}" + f"len(index)={len(index)} len(rows)={len(sans_rows)}" ) - sans_rows, separating_lines = _remove_separating_lines(rows) new_rows = [] index_iter = iter(index) for row in sans_rows: @@ -1599,7 +1599,7 @@ def _normalize_tabular_data(tabular_data, headers, showindex="default"): rows = _prepend_row_index(rows, showindex) elif showindex == "always" or (_bool(showindex) and not showindex_is_a_str): if index is None: - index = list(range(len(rows))) + index = list(range(sum(not _is_separating_line(row) for row in rows))) rows = _prepend_row_index(rows, index) elif showindex == "never" or (not _bool(showindex) and not showindex_is_a_str): pass diff --git a/test/test_separator_index.py b/test/test_separator_index.py new file mode 100644 index 0000000..f7489b5 --- /dev/null +++ b/test/test_separator_index.py @@ -0,0 +1,20 @@ +import pytest + +from tabulate import SEPARATING_LINE, tabulate + + +@pytest.mark.parametrize("indices", [["A", "B"], ("A", "B"), iter(["A", "B"])]) +def test_custom_index_skips_separator_rows(indices): + table = [["apple"], SEPARATING_LINE, ["pear"]] + assert tabulate(table, showindex=indices, tablefmt="plain") == "A apple\n\nB pear" + + +def test_automatic_index_skips_separator_rows(): + table = [["apple"], SEPARATING_LINE, ["pear"]] + assert tabulate(table, showindex=True, tablefmt="plain") == "0 apple\n\n1 pear" + + +def test_custom_index_length_counts_only_data_rows(): + table = [["apple"], SEPARATING_LINE, ["pear"]] + with pytest.raises(ValueError, match="len\\(rows\\)=2"): + tabulate(table, showindex=["A"], tablefmt="plain")