diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 12a2950..7bbd2bb 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -193,10 +193,16 @@ def _mediawiki_row_with_attrs(separator, cell_values, colwidths, colaligns): return (separator + colsep.join(values_with_attrs)).rstrip() +def _escape_pipe(value): + return value.replace("|", "|") + + def _textile_row_with_attrs(cell_values, colwidths, colaligns): cell_values[0] += " " alignment = {"left": "<.", "right": ">.", "center": "=.", "decimal": ">."} - values = "|".join(alignment.get(a, "") + v for a, v in zip(colaligns, cell_values)) + values = "|".join( + alignment.get(a, "") + _escape_pipe(v) for a, v in zip(colaligns, cell_values) + ) return f"|{values}|" @@ -236,7 +242,11 @@ def _moin_row_with_attrs(celltag, cell_values, colwidths, colaligns, header=""): "decimal": '', } values_with_attrs = [ - "{}{} {} ".format(celltag, alignment.get(a, ""), header + c + header) + "{}{} {} ".format( + celltag, + alignment.get(a, ""), + header + _escape_pipe(c) + header, + ) for c, a in zip(cell_values, colaligns) ] return "".join(values_with_attrs) + "||" @@ -690,7 +700,7 @@ def escape_empty(val): linebelowheader=None, linebetweenrows=None, linebelow=None, - headerrow=DataRow("|_. ", "|_.", "|"), + headerrow=DataRow("|_. ", "|_.", "|", {r"|": r"|"}), datarow=_textile_row_with_attrs, padding=1, with_header_hide=None, diff --git a/test/test_output.py b/test/test_output.py index ea3da87..58659f2 100644 --- a/test/test_output.py +++ b/test/test_output.py @@ -2584,6 +2584,34 @@ def test_moinmoin_headerless(): assert_equal(expected, result) +def test_moinmoin_escapes_pipes(): + "Output: moinmoin with literal pipes in cell and header content" + # https://github.com/astanin/python-tabulate/issues/501 + expected = "\n".join( + [ + '|| \'\'\' h | 1 \'\'\' ' + '|| \'\'\' h2 \'\'\' ||', + '|| x | y ' + '|| a || b ||', + ] + ) + result = tabulate([["x | y", "a || b"]], headers=["h | 1", "h2"], tablefmt="moinmoin") + assert_equal(expected, result) + + +def test_textile_escapes_pipes(): + "Output: textile with literal pipes in cell and header content" + # https://github.com/astanin/python-tabulate/issues/501 + expected = "\n".join( + [ + "|_. h | 1 |_. h2 |", + "|<. x | y |<. a || b |", + ] + ) + result = tabulate([["x | y", "a || b"]], headers=["h | 1", "h2"], tablefmt="textile") + assert_equal(expected, result) + + _test_table_html_headers = ["", "<&numbers&>"] _test_table_html = [["spam >", 41.9999], ["eggs &", 451.0]] _test_table_unsafehtml_headers = ["strings", "numbers"]