fix: escape filename in markdown report #2141#2142
Conversation
…2141 Both underscore and pipe characters are valid in filenames and meaningful in markdown tables. Underscores were already escaped by the markdown report, using a simple string replacement, but pipe characters were not.
c7162e4 to
b014e0e
Compare
|
|
|
Thanks! I think we need to escape more than just underscore and pipe. I'm surprised this hasn't come up already: don't we need to escape backslashes? If a file name starts with pipe, on Windows, it would be Since Commonmark says all ASCII punctuation can be escaped, we can do all of |
|
If the whole of string.punctuation is needed, then a chain of s.replace() becomes super unwieldy. Instead, how about str.maketrans + str.translate? edit: 4 tests are affected. But since diff --git a/coverage/report.py b/coverage/report.py
index 544106f3..bf6a7982 100644
--- a/coverage/report.py
+++ b/coverage/report.py
@@ -7,6 +7,7 @@
import sys
from collections.abc import Iterable
+from string import punctuation
from typing import IO, TYPE_CHECKING, Any
from coverage.exceptions import ConfigError, NoDataError
@@ -19,6 +20,13 @@
if TYPE_CHECKING:
from coverage import Coverage
+ESCAPE_PUNCTUATION_TABLE = "".maketrans(
+ {char: f"\\{char}" for char in punctuation if char not in ".,/-"}
+)
+
+
+def escape_markdown(input_value: str) -> str:
+ """Prefix all characters meaningful in markdown tables with backslashes."""
+ return input_value.translate(ESCAPE_PUNCTUATION_TABLE)
+
class SummaryReporter:
"""A reporter for writing the summary report."""
@@ -127,10 +135,6 @@ def report_markdown(
"""
- def escape_markdown(input_value: str) -> str:
- """Crudely replace characters meaningful in markdown tables."""
- return input_value.replace("_", "\\_").replace("|", "\\|")
-
# Prepare the formatting strings, header, and column sorting.
max_name = max((len(escape_markdown(line[0])) for line in lines_values), default=0)
max_name = max(max_name, len("**TOTAL**")) + 1 |
|
TBH, this comment (not yours!) kind of horrified me: That slipped past me in a previous pull request. It seems like a hacky way to deal with the windows backslashes. I would amend the - cov.report(file=repout, **kwargs)
- report = repout.getvalue().replace("\\", "/")
+ if output_format == "markdown":
+ report = report.replace("\\\\", r"\/")
+ else:
+ report = report.replace("\\", "/") |
|
Is |
…mat argument No longer produce forward slash escaped underscore in test helper
|
I added a parametrized test I think this is ready to review. There's several separate commits for various pieces of feedback. Do you want to squash (some of) them? |
|
Thanks, this looks good. I'll squash the commits and update the changelog. |
|
This is now released as part of coverage 7.13.5. |
Both underscore and pipe characters are valid in filenames and meaningful in markdown tables. Underscores were already escaped by the markdown report, using a simple string replacement, but pipe characters were not.
aka