From 02606e770ebc6d967b9ab9da8263db5b242970eb Mon Sep 17 00:00:00 2001 From: thejedi433 Date: Sun, 18 Oct 2026 12:10:19 +0300 Subject: [PATCH] Fix BEL-terminated OSC 8 hyperlinks inflating column widths (#460) _st only recognized ESC \ as the OSC string terminator, so hyperlinks terminated with BEL (0x07, explicitly allowed by the OSC 8 spec) did not match the ANSI escape pattern and their full escape payload was counted as visible text when computing column widths. Accept both terminators: _st = (?:ESC \|BEL). Adds regression test test_alignment_of_bel_terminated_links; full suite: 324 passed. --- tabulate/__init__.py | 3 ++- test/test_regression.py | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/tabulate/__init__.py b/tabulate/__init__.py index 12a2950..60d19d9 100644 --- a/tabulate/__init__.py +++ b/tabulate/__init__.py @@ -783,7 +783,8 @@ def escape_empty(val): _esc = r"\x1b" _csi = rf"{_esc}\[" _osc = rf"{_esc}\]" -_st = rf"{_esc}\\" +# ST: ESC followed by '\' (0x5c), or BEL (0x07) - both are valid OSC terminators +_st = rf"(?:{_esc}\\|\x07)" _ansi_escape_pat = rf""" ( diff --git a/test/test_regression.py b/test/test_regression.py index 9555676..a1c0b7d 100644 --- a/test/test_regression.py +++ b/test/test_regression.py @@ -67,6 +67,29 @@ def test_alignment_of_link_cells(): assert_equal(expected, formatted) +def test_alignment_of_bel_terminated_links(): + "Regression: BEL-terminated OSC 8 hyperlinks should not inflate column widths." + bel_table = [ + ("test", "\x1b]8;;target\x07test\x1b]8;;\x07"), + ("test", "\x1b]8;;target\x07test\x1b]8;;\x07"), + ] + bel_headers = ("test", "\x1b]8;;target\x07test\x1b]8;;\x07") + formatted = tabulate(bel_table, bel_headers, "grid") + expected = "\n".join( + [ + "+--------+--------+", + "| test | \x1b]8;;target\x07test\x1b]8;;\x07 |", + "+========+========+", + "| test | \x1b]8;;target\x07test\x1b]8;;\x07 |", + "+--------+--------+", + "| test | \x1b]8;;target\x07test\x1b]8;;\x07 |", + "+--------+--------+", + ] + ) + print(f"expected: {expected!r}\n\ngot: {formatted!r}\n") + assert_equal(expected, formatted) + + def test_alignment_of_link_text_cells(): "Regression: Align links as if they were colorless." linktable = [