Skip to content

Commit a16c979

Browse files
committed
Respect padding in pipe/github separator rows
Follow up on #410; Refs #260 and #261.
1 parent 268615a commit a16c979

2 files changed

Lines changed: 36 additions & 24 deletions

File tree

tabulate/__init__.py

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -131,26 +131,38 @@ def _is_separating_line(row):
131131
)
132132

133133

134-
def _pipe_segment_with_colons(align, colwidth):
134+
def _pipe_segment_with_colons(align, colwidth, padding=0):
135135
"""Return a segment of a horizontal line with optional colons which
136-
indicate column's alignment (as in `pipe` output format)."""
136+
indicate column's alignment (as in `pipe` output format).
137+
138+
When ``padding`` is non-zero, the segment respects the format's padding by
139+
placing spaces at the padding positions instead of filling the entire width
140+
with dashes. This makes separator rows consistent with data rows, which
141+
already honour padding via ``_pad_row``.
142+
"""
137143
w = colwidth
144+
pad = " " * padding
145+
# Width available for dashes and alignment colons.
146+
dw = w - 2 * padding
138147
if align in ["right", "decimal"]:
139-
return ("-" * (w - 1)) + ":"
148+
return pad + ("-" * (dw - 1)) + ":" + pad
140149
elif align == "center":
141-
return ":" + ("-" * (w - 2)) + ":"
150+
return pad + ":" + ("-" * (dw - 2)) + ":" + pad
142151
elif align == "left":
143-
return ":" + ("-" * (w - 1))
152+
return pad + ":" + ("-" * (dw - 1)) + pad
144153
else:
145-
return "-" * w
154+
return pad + ("-" * dw) + pad
146155

147156

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

156168

@@ -168,7 +180,7 @@ def _grid_segment_with_colons(colwidth, align):
168180
return "=" * width
169181

170182

171-
def _grid_line_with_colons(colwidths, colaligns):
183+
def _grid_line_with_colons(colwidths, colaligns, **kwargs):
172184
"""Return a horizontal line with optional colons to indicate column's alignment
173185
in a grid table."""
174186
if not colaligns:
@@ -200,7 +212,7 @@ def _textile_row_with_attrs(cell_values, colwidths, colaligns):
200212
return f"|{values}|"
201213

202214

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

@@ -242,7 +254,7 @@ def _moin_row_with_attrs(celltag, cell_values, colwidths, colaligns, header=""):
242254
return "".join(values_with_attrs) + "||"
243255

244256

245-
def _latex_line_begin_tabular(colwidths, colaligns, booktabs=False, longtable=False):
257+
def _latex_line_begin_tabular(colwidths, colaligns, booktabs=False, longtable=False, **kwargs):
246258
alignment = {"left": "l", "right": "r", "center": "c", "decimal": "r"}
247259
tabular_columns_fmt = "".join([alignment.get(a, "l") for a in colaligns])
248260
return "\n".join(
@@ -255,7 +267,7 @@ def _latex_line_begin_tabular(colwidths, colaligns, booktabs=False, longtable=Fa
255267
)
256268

257269

258-
def _asciidoc_row(is_header, *args):
270+
def _asciidoc_row(is_header, *args, **kwargs):
259271
"""handle header and data rows for asciidoc format"""
260272

261273
def make_header_line(is_header, colwidths, colaligns):
@@ -2578,21 +2590,21 @@ def _append_multiline_row(
25782590
return lines
25792591

25802592

2581-
def _build_line(colwidths, colaligns, linefmt):
2593+
def _build_line(colwidths, colaligns, linefmt, padding=0):
25822594
"Return a string which represents a horizontal line."
25832595
if not linefmt:
25842596
return None
25852597
if callable(linefmt):
2586-
return linefmt(colwidths, colaligns)
2598+
return linefmt(colwidths, colaligns, padding=padding)
25872599
else:
25882600
begin, fill, sep, end = linefmt
25892601
cells = [fill * w for w in colwidths]
25902602
rowfmt = DataRow(begin, sep, end)
25912603
return _build_simple_row(cells, rowfmt)
25922604

25932605

2594-
def _append_line(lines, colwidths, colaligns, linefmt):
2595-
lines.append(_build_line(colwidths, colaligns, linefmt))
2606+
def _append_line(lines, colwidths, colaligns, linefmt, padding=0):
2607+
lines.append(_build_line(colwidths, colaligns, linefmt, padding=padding))
25962608
return lines
25972609

25982610

@@ -2629,12 +2641,12 @@ def _format_table(
26292641
padded_headers = pad_row(headers, pad)
26302642

26312643
if fmt.lineabove and "lineabove" not in hidden:
2632-
_append_line(lines, padded_widths, colaligns, fmt.lineabove)
2644+
_append_line(lines, padded_widths, colaligns, fmt.lineabove, padding=pad)
26332645

26342646
if padded_headers:
26352647
append_row(lines, padded_headers, padded_widths, headersaligns, headerrow)
26362648
if fmt.linebelowheader and "linebelowheader" not in hidden:
2637-
_append_line(lines, padded_widths, colaligns, fmt.linebelowheader)
2649+
_append_line(lines, padded_widths, colaligns, fmt.linebelowheader, padding=pad)
26382650

26392651
if rows and fmt.linebetweenrows and "linebetweenrows" not in hidden:
26402652
# initial rows with a line below
@@ -2648,7 +2660,7 @@ def _format_table(
26482660
fmt.datarow,
26492661
rowalign=ralign,
26502662
)
2651-
_append_line(lines, padded_widths, colaligns, fmt.linebetweenrows)
2663+
_append_line(lines, padded_widths, colaligns, fmt.linebetweenrows, padding=pad)
26522664
# the last row without a line below
26532665
append_row(
26542666
lines,
@@ -2670,12 +2682,12 @@ def _format_table(
26702682
# test to see if either the 1st column or the 2nd column (account for showindex) has
26712683
# the SEPARATING_LINE flag
26722684
if _is_separating_line(row):
2673-
_append_line(lines, padded_widths, colaligns, separating_line)
2685+
_append_line(lines, padded_widths, colaligns, separating_line, padding=pad)
26742686
else:
26752687
append_row(lines, pad_row(row, pad), padded_widths, colaligns, fmt.datarow)
26762688

26772689
if fmt.linebelow and "linebelow" not in hidden:
2678-
_append_line(lines, padded_widths, colaligns, fmt.linebelow)
2690+
_append_line(lines, padded_widths, colaligns, fmt.linebelow, padding=pad)
26792691

26802692
if headers or rows:
26812693
output = "\n".join(lines)

test/test_output.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,9 +369,9 @@ def test_simple_headerless_with_sep_line_with_padding_in_tablefmt():
369369
"Output: simple without headers with sep line with padding in tablefmt"
370370
expected = "\n".join(
371371
[
372-
"|:-----|---------:|",
372+
"| :--- | -------: |",
373373
"| spam | 41.9999 |",
374-
"|:-----|---------:|",
374+
"| :--- | -------: |",
375375
"| eggs | 451 |",
376376
]
377377
)
@@ -2006,7 +2006,7 @@ def test_pipe():
20062006

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

0 commit comments

Comments
 (0)