Skip to content

Compiled regex patterns are rendered incorrectly in debug_repr output #36

Description

@amol-

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions