Goal
Render compiled regex patterns correctly in debug_repr output: escape the
pattern for HTML and restore the quoting that repr() provides.
Done when: debug_repr(re.compile(...)) renders the pattern as readable text
for any pattern content, and a test covers a pattern containing markup
characters and a bytes pattern.
Reproduction (reproduces on Python 3.9 through 3.14):
import re
from backlash.repr import debug_repr
print(debug_repr(re.compile('<img src=x>')))
print(debug_repr(re.compile(b'a&b')))
print(debug_repr(re.compile('\n')))
Current output:
re.compile(<span class="string regex">r'<img src=x>'</span>)
re.compile(<span class="string regex">r'b'a&b''</span>)
re.compile(<span class="string regex">r'
'</span>)
Three separate defects, all from the same expression:
- The pattern is not passed through
escape(), so <img src=x> is emitted as
raw markup and the browser consumes it as a tag instead of displaying it. The
user sees the pattern silently disappear from the console output.
- A bytes pattern renders as the nonsense
r'b'a&b'', because str() is
applied to the bytes object and then wrapped in another set of quotes.
- A pattern containing a newline emits a literal newline inside the quotes,
breaking the single-line rendering the <span> is styled for.
Cause: backlash/repr.py builds the markup with
're.compile(<span class="string regex">r\'%s\'</span>)' % obj.pattern, using
the raw pattern with neither escape() nor repr().
Suggested minimal fix: render escape(repr(obj.pattern)) instead, which
restores quoting and escapes the markup in one step, and matches how the
sibling methods in the same class already handle strings.
Why
debug_repr is what the interactive console prints, so a regex in scope is
displayed wrongly or not at all. A pattern is exactly the kind of value someone
inspects while debugging a matching problem, and silently dropping part of it
(or showing r'b'a&b'') actively misleads.
The other repr methods in the same class already escape their output, so this is
an inconsistency within one class rather than a design choice.
Reachability note: debug_repr is only called from backlash/console.py, so
this affects the interactive console rather than the plain traceback page.
Verified as pre-existing rather than a regression: the pre-modernization code
had separate Python 2 and Python 3 branches here, and only the Python 2 branch
applied repr(); the Python 3 branch never escaped either.
References
backlash/repr.py (DebugReprGenerator.regex_repr; py3_text_repr and
py3_binary_repr in the same class show the escaping pattern used elsewhere)
backlash/console.py (_ConsoleFrame/stream write path that calls debug_repr)
backlash/utils.py (escape)
tests/test_repr.py may be a natural home for a regression test
Goal
Render compiled regex patterns correctly in
debug_reproutput: escape thepattern for HTML and restore the quoting that
repr()provides.Done when:
debug_repr(re.compile(...))renders the pattern as readable textfor any pattern content, and a test covers a pattern containing markup
characters and a bytes pattern.
Reproduction (reproduces on Python 3.9 through 3.14):
Current output:
Three separate defects, all from the same expression:
escape(), so<img src=x>is emitted asraw markup and the browser consumes it as a tag instead of displaying it. The
user sees the pattern silently disappear from the console output.
r'b'a&b'', becausestr()isapplied to the bytes object and then wrapped in another set of quotes.
breaking the single-line rendering the
<span>is styled for.Cause:
backlash/repr.pybuilds the markup with're.compile(<span class="string regex">r\'%s\'</span>)' % obj.pattern, usingthe raw pattern with neither
escape()norrepr().Suggested minimal fix: render
escape(repr(obj.pattern))instead, whichrestores quoting and escapes the markup in one step, and matches how the
sibling methods in the same class already handle strings.
Why
debug_repris what the interactive console prints, so a regex in scope isdisplayed wrongly or not at all. A pattern is exactly the kind of value someone
inspects while debugging a matching problem, and silently dropping part of it
(or showing
r'b'a&b'') actively misleads.The other repr methods in the same class already escape their output, so this is
an inconsistency within one class rather than a design choice.
Reachability note:
debug_repris only called frombacklash/console.py, sothis affects the interactive console rather than the plain traceback page.
Verified as pre-existing rather than a regression: the pre-modernization code
had separate Python 2 and Python 3 branches here, and only the Python 2 branch
applied
repr(); the Python 3 branch never escaped either.References
backlash/repr.py(DebugReprGenerator.regex_repr;py3_text_reprandpy3_binary_reprin the same class show the escaping pattern used elsewhere)backlash/console.py(_ConsoleFrame/stream write path that callsdebug_repr)backlash/utils.py(escape)tests/test_repr.pymay be a natural home for a regression test