Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ corresponds to the `pipe` format with the same alignment colons:
```pycon
>>> print(tabulate(table, headers, tablefmt="github"))
| item | qty |
|:-------|------:|
| :----- | ----: |
| spam | 42 |
| eggs | 451 |
| bacon | 0 |
Expand Down Expand Up @@ -487,7 +487,7 @@ indicate column alignment:
```pycon
>>> print(tabulate(table, headers, tablefmt="pipe"))
| item | qty |
|:-------|------:|
| :----- | ----: |
| spam | 42 |
| eggs | 451 |
| bacon | 0 |
Expand Down Expand Up @@ -931,7 +931,7 @@ spam
>>> print(tabulate(table, headers, tablefmt="pipe"))
| item | qty |
| name | |
|:-------|------:|
| :----- | ----: |
| eggs | 451 |
| more | 42 |
| spam | |
Expand Down
57 changes: 34 additions & 23 deletions tabulate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,26 +131,37 @@ def _is_separating_line(row):
)


def _pipe_segment_with_colons(align, colwidth):
def _pipe_segment_with_colons(align, colwidth, padding=0):
"""Return a segment of a horizontal line with optional colons which
indicate column's alignment (as in `pipe` output format)."""
indicate column's alignment (as in `pipe` output format).

When ``padding`` is non-zero, the segment respects the format's padding by
placing spaces at the padding positions instead of filling the entire width
with dashes. This makes separator rows consistent with data rows, which
already honour padding via ``_pad_row``.
"""
w = colwidth
pad = " " * padding
# Width available for dashes and alignment colons.
dw = w - 2 * padding
if align in ["right", "decimal"]:
return ("-" * (w - 1)) + ":"
return pad + ("-" * (dw - 1)) + ":" + pad
elif align == "center":
return ":" + ("-" * (w - 2)) + ":"
return pad + ":" + ("-" * (dw - 2)) + ":" + pad
elif align == "left":
return ":" + ("-" * (w - 1))
return pad + ":" + ("-" * (dw - 1)) + pad
else:
return "-" * w
return pad + ("-" * dw) + pad


def _pipe_line_with_colons(colwidths, colaligns):
def _pipe_line_with_colons(colwidths, colaligns, padding=0):
"""Return a horizontal line with optional colons to indicate column's
alignment (as in `pipe` output format)."""
if not colaligns: # e.g. printing an empty data frame (github issue #15)
colaligns = [""] * len(colwidths)
segments = "|".join(_pipe_segment_with_colons(a, w) for a, w in zip(colaligns, colwidths))
segments = "|".join(
_pipe_segment_with_colons(a, w, padding) for a, w in zip(colaligns, colwidths)
)
return f"|{segments}|"


Expand All @@ -168,7 +179,7 @@ def _grid_segment_with_colons(colwidth, align):
return "=" * width


def _grid_line_with_colons(colwidths, colaligns):
def _grid_line_with_colons(colwidths, colaligns, **kwargs):
"""Return a horizontal line with optional colons to indicate column's alignment
in a grid table."""
if not colaligns:
Expand Down Expand Up @@ -200,7 +211,7 @@ def _textile_row_with_attrs(cell_values, colwidths, colaligns):
return f"|{values}|"


def _html_begin_table_without_header(colwidths_ignore, colaligns_ignore):
def _html_begin_table_without_header(colwidths_ignore, colaligns_ignore, **kwargs):
# this table header will be suppressed if there is a header row
return "<table>\n<tbody>"

Expand Down Expand Up @@ -242,7 +253,7 @@ def _moin_row_with_attrs(celltag, cell_values, colwidths, colaligns, header=""):
return "".join(values_with_attrs) + "||"


def _latex_line_begin_tabular(colwidths, colaligns, booktabs=False, longtable=False):
def _latex_line_begin_tabular(colwidths, colaligns, booktabs=False, longtable=False, **kwargs):
alignment = {"left": "l", "right": "r", "center": "c", "decimal": "r"}
tabular_columns_fmt = "".join([alignment.get(a, "l") for a in colaligns])
return "\n".join(
Expand All @@ -255,7 +266,7 @@ def _latex_line_begin_tabular(colwidths, colaligns, booktabs=False, longtable=Fa
)


def _asciidoc_row(is_header, *args):
def _asciidoc_row(is_header, *args, **kwargs):
"""handle header and data rows for asciidoc format"""

def make_header_line(is_header, colwidths, colaligns):
Expand Down Expand Up @@ -2063,7 +2074,7 @@ def tabulate(
>>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]],
... ["strings", "numbers"], "pipe"))
| strings | numbers |
|:----------|----------:|
| :-------- | --------: |
| spam | 41.9999 |
| eggs | 451 |

Expand All @@ -2077,7 +2088,7 @@ def tabulate(
eggs | 451

>>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tablefmt="pipe"))
|:-----|---------:|
| :--- | -------: |
| spam | 41.9999 |
| eggs | 451 |

Expand Down Expand Up @@ -2578,21 +2589,21 @@ def _append_multiline_row(
return lines


def _build_line(colwidths, colaligns, linefmt):
def _build_line(colwidths, colaligns, linefmt, padding=0):
"Return a string which represents a horizontal line."
if not linefmt:
return None
if callable(linefmt):
return linefmt(colwidths, colaligns)
return linefmt(colwidths, colaligns, padding=padding)
else:
begin, fill, sep, end = linefmt
cells = [fill * w for w in colwidths]
rowfmt = DataRow(begin, sep, end)
return _build_simple_row(cells, rowfmt)


def _append_line(lines, colwidths, colaligns, linefmt):
lines.append(_build_line(colwidths, colaligns, linefmt))
def _append_line(lines, colwidths, colaligns, linefmt, padding=0):
lines.append(_build_line(colwidths, colaligns, linefmt, padding=padding))
return lines


Expand Down Expand Up @@ -2629,12 +2640,12 @@ def _format_table(
padded_headers = pad_row(headers, pad)

if fmt.lineabove and "lineabove" not in hidden:
_append_line(lines, padded_widths, colaligns, fmt.lineabove)
_append_line(lines, padded_widths, colaligns, fmt.lineabove, padding=pad)

if padded_headers:
append_row(lines, padded_headers, padded_widths, headersaligns, headerrow)
if fmt.linebelowheader and "linebelowheader" not in hidden:
_append_line(lines, padded_widths, colaligns, fmt.linebelowheader)
_append_line(lines, padded_widths, colaligns, fmt.linebelowheader, padding=pad)

if rows and fmt.linebetweenrows and "linebetweenrows" not in hidden:
# initial rows with a line below
Expand All @@ -2648,7 +2659,7 @@ def _format_table(
fmt.datarow,
rowalign=ralign,
)
_append_line(lines, padded_widths, colaligns, fmt.linebetweenrows)
_append_line(lines, padded_widths, colaligns, fmt.linebetweenrows, padding=pad)
# the last row without a line below
append_row(
lines,
Expand All @@ -2670,12 +2681,12 @@ def _format_table(
# test to see if either the 1st column or the 2nd column (account for showindex) has
# the SEPARATING_LINE flag
if _is_separating_line(row):
_append_line(lines, padded_widths, colaligns, separating_line)
_append_line(lines, padded_widths, colaligns, separating_line, padding=pad)
else:
append_row(lines, pad_row(row, pad), padded_widths, colaligns, fmt.datarow)

if fmt.linebelow and "linebelow" not in hidden:
_append_line(lines, padded_widths, colaligns, fmt.linebelow)
_append_line(lines, padded_widths, colaligns, fmt.linebelow, padding=pad)

if headers or rows:
output = "\n".join(lines)
Expand Down
17 changes: 9 additions & 8 deletions test/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,9 @@ def test_simple_headerless_with_sep_line_with_padding_in_tablefmt():
"Output: simple without headers with sep line with padding in tablefmt"
expected = "\n".join(
[
"|:-----|---------:|",
"| :--- | -------: |",
"| spam | 41.9999 |",
"|:-----|---------:|",
"| :--- | -------: |",
"| eggs | 451 |",
]
)
Expand Down Expand Up @@ -489,12 +489,13 @@ def test_github():
expected = "\n".join(
[
"| strings | numbers |",
"|:----------|----------:|",
"| :-------- | --------: |",
"| spam | 41.9999 |",
"| eggs | 451 |",
]
)
result = tabulate(_test_table, _test_table_headers, tablefmt="github")

assert_equal(expected, result)


Expand All @@ -506,7 +507,7 @@ def test_github_multiline():
[
"| more | more spam |",
"| spam eggs | & eggs |",
"|------------:|:------------|",
"| ----------: | :---------- |",
"| 2 | foo |",
"| | bar |",
]
Expand All @@ -520,7 +521,7 @@ def test_github_with_colalign():
expected = "\n".join(
[
"| Name | Age |",
"|:-------|------:|",
"| :----- | ----: |",
"| Alice | 24 |",
"| Bob | 19 |",
]
Expand All @@ -539,7 +540,7 @@ def test_github_no_alignment():
expected = "\n".join(
[
"| strings | numbers |",
"|-----------|-----------|",
"| --------- | --------- |",
"| spam | 41.9999 |",
"| eggs | 451 |",
]
Expand Down Expand Up @@ -1995,7 +1996,7 @@ def test_pipe():
expected = "\n".join(
[
"| strings | numbers |",
"|:----------|----------:|",
"| :-------- | --------: |",
"| spam | 41.9999 |",
"| eggs | 451 |",
]
Expand All @@ -2006,7 +2007,7 @@ def test_pipe():

def test_pipe_headerless():
"Output: pipe without headers"
expected = "\n".join(["|:-----|---------:|", "| spam | 41.9999 |", "| eggs | 451 |"])
expected = "\n".join(["| :--- | -------: |", "| spam | 41.9999 |", "| eggs | 451 |"])
result = tabulate(_test_table, tablefmt="pipe")
assert_equal(expected, result)

Expand Down
10 changes: 5 additions & 5 deletions test/test_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def test_ansi_color_in_table_cells():
expected = "\n".join(
[
"| test | test | test |",
"|:-------|:-------|:-------|",
"| :----- | :----- | :----- |",
"| test | \x1b[31mtest\x1b[0m | \x1b[32mtest\x1b[0m |",
]
)
Expand Down Expand Up @@ -195,7 +195,7 @@ def test_88_256_ANSI_color_codes():
expected = "\n".join(
[
"| background | foreground |",
"|:-------------|:-------------|",
"| :----------- | :----------- |",
"| \x1b[48;5;196mred\x1b[49m | \x1b[38;5;196mred\x1b[39m |",
]
)
Expand Down Expand Up @@ -424,7 +424,7 @@ def test_empty_pipe_table_with_columns():
"Regression: allow empty pipe tables with columns, like empty dataframes (github issue #15)"
table = []
headers = ["Col1", "Col2"]
expected = "\n".join(["| Col1 | Col2 |", "|--------|--------|"])
expected = "\n".join(["| Col1 | Col2 |", "| ------ | ------ |"])
result = tabulate(table, headers, tablefmt="pipe")
assert_equal(expected, result)

Expand Down Expand Up @@ -542,7 +542,7 @@ def test_numpy_int64_as_integer():
expected = "\n".join(
[
"| int | float |",
"|------:|--------:|",
"| ----: | ------: |",
"| 1 | 3.14 |",
]
)
Expand Down Expand Up @@ -596,5 +596,5 @@ def test_asciidoc_without_trailing_whitespace():
def test_github_escape_pipe_character():
"Regression: github format must escape pipe character with a backslash (issue #241)"
result = tabulate([["foo|bar"]], headers=("spam|eggs",), tablefmt="github")
expected = "| spam\\|eggs |\n|:------------|\n| foo\\|bar |"
expected = "| spam\\|eggs |\n| :---------- |\n| foo\\|bar |"
assert_equal(expected, result)
Loading