FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

gh-145217: Add colour to `pprint` output by hugovk · Pull Request #145218 · python/cpython · GitHub

Repository navigation

gh-145217: Add colour to pprint output - #145218

Open
hugovk wants to merge 15 commits into
python:mainfrom
hugovk:3.15-pprint-colour
Open

hugovk wants to merge 15 commits into
python:mainfrom
hugovk:3.15-pprint-colour

Conversation

hugovk commented Feb 25, 2026 •
edited by github-actions Bot
Loading

Copy link
Copy Markdown
Member

Example:

import pprint

data = ["spam", "eggs", ("lumberjack", "knights"), "ni", 42, None]
data.insert(0, data)

pprint.pp(data)
pprint.pprint(data)
pprint.PrettyPrinter().pprint(data)

📚 Documentation preview 📚: https://cpython-previews--145218.org.readthedocs.build/

hugovk requested a review from AA-Turner as a code owner February 25, 2026 14:20
hugovk added type-feature A feature request or enhancement stdlib Standard Library Python modules in the Lib/ directory labels Feb 25, 2026

This comment was marked as resolved.

Comment thread Lib/pprint.py

This comment was marked as resolved.

This comment was marked as resolved.

johnslavik self-requested a review April 10, 2026 10:13
Comment thread Doc/whatsnew/3.15.rst
Comment thread Lib/pprint.py
self._expand = bool(expand)
self._sort_dicts = sort_dicts
self._underscore_numbers = underscore_numbers
self._color = color

sunmy2019 Apr 28, 2026 •
edited
Loading

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Shall we add a bool(color) conversion just as a few lines above?

        self._compact = bool(compact)
        self._expand = bool(expand)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Sure, can do, but not sure if it's necessary?

sunmy2019 left a comment •
edited
Loading

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Do we have explicit test for color=True and can_colorize=False? It's an end to end test.

something like

        obj = {"key": "value"}
        stream = io.StringIO()

        # color=True should not produce no ANSI codes for streams
        # that do not support color
        pprint.pprint(obj, stream=stream, color=True)
        result = stream.getvalue()
        self.assertNotIn("\x1b[", result)

Comment thread Lib/pprint.py Outdated
hugovk and others added 2 commits April 28, 2026 14:46
Co-authored-by: sunmy2019 <59365878+sunmy2019@users.noreply.github.com>
Comment thread Lib/test/test_pprint.py Outdated

Copy link
Copy Markdown
Member

If user's __repr__ contains color, it would break the color.

Code

import os
import pprint

os.environ["FORCE_COLOR"] = "1"
os.environ["NO_COLOR"] = ""


class Colorful:
    """something with a colorful repr"""

    def __repr__(self):
        return "\x1b[31mred\x1b[0m"

pprint.pprint({"a": Colorful(), "b": 42, "c": "hello"}, color=True)

What should we do for this case?

  1. Document and keep as is?
  2. Pre check escape sequence before colorize?
  3. Other techniques for this?

Co-authored-by: sunmy2019 <59365878+sunmy2019@users.noreply.github.com>

hugovk commented Apr 28, 2026

Copy link
Copy Markdown
Member Author
  1. Pre check escape sequence before colorize?

I think if there's any colour escapes, we bail and print it as-is without extra colour from us. So we get something like this:

And I expect colour is rare in users' __repr__s? If so, this won't happen often, and when it does, we don't override any of their own colour or need more complex handling. And they don't end up with just a green "a" like in your example.

read-the-docs-community Bot commented Apr 29, 2026 •
edited
Loading

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #32544585 | 📁 Comparing f6c4dd9 against main (4b33308)

  🔍 Preview build  

105 files changed · + 2 added · ± 103 modified

+ Added

± Modified

sunmy2019 commented Apr 30, 2026 •
edited
Loading

Copy link
Copy Markdown
Member

I think if there's any colour escapes, we bail and print it as-is without extra colour from us.

I agree with this.

But thinking further, our current highlighting logic relies on tokenize, yet pprint output has never made any guarantee that it must be valid Python source. __repr__ can return anything — it doesn't have to be tokenizer-friendly.

So, instead of special-casing \x1b[, how about

Probe the text with tokenize first,
-- if it can process the whole thing, highlight it;
-- if it chokes halfway through for any reason (ANSI escapes, illegal control chars, etc.), just print the raw text with no added colors.

No blacklist needed, no half-highlighted output.

What do you think?

 def _colorize_output(text):
     """Apply syntax highlighting."""
-    if "\x1b[" in text:
-        # If the text already contains ANSI escape sequences
-        # (for example, from a custom __repr__),
-        # return as-is to avoid breaking their color.
+    # Probe: if the text cannot be fully tokenized, fall back to plain text
+    # to avoid the "half-highlighted" problem.
+    try:
+        list(tokenize.generate_tokens(_StringIO(text).readline))
+    except (SyntaxError, tokenize.TokenError):
         return text
     colors = list(gen_colors(text))
     chars, _ = disp_str(text, colors=colors, force_color=True, escape=False)

hugovk commented May 3, 2026

Copy link
Copy Markdown
Member Author

Could do, although that'd mean we're potentially doing tokenize.generate_tokens() both here and in gen_colors(). Maybe that doesn't matter.

Copy link
Copy Markdown
Member

Maybe that doesn't matter.

If that matters, we could modify the latter to raise errors (rather than catch them)

hugovk commented May 4, 2026

Copy link
Copy Markdown
Member Author

I think I'll leave it like this, unless others also want to suggest something. We can always fix it later if needed. Thanks for the review!

encukou commented May 5, 2026

Copy link
Copy Markdown
Member

Should this tokenize reprs that start with <? In the following, highlighting the in and from doesn't make much sense.

hugovk commented May 5, 2026

Copy link
Copy Markdown
Member Author

Updated to skip those.

encukou commented May 5, 2026

Copy link
Copy Markdown
Member

That's inconsistent when nested:

Would it be possible to highlight as things are being formatted, while the structure is still available? I doubt post-processing can be done reliably.

hugovk commented May 6, 2026

Copy link
Copy Markdown
Member Author

Hmm, the root issue is that gen_colors tokenises as if it were Python source, so I think it would quite a big refactor to do that, at least to make it into 3.15.

I'm personally fine with the current version or the previous, but also fine in skipping this for 3.15 and doing it properly for 3.16 (or just closing :)

encukou commented May 6, 2026

Copy link
Copy Markdown
Member

Hmm, the root issue is that gen_colors tokenises as if it were Python source

Yeah. That guess might not be right; let's resist the temptation.
Colorization is much more helpful when you can trust it.

In 3.16 a pprint refactor might be needed anyway, for PEP-813.

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

This PR is stale because it has been open for 90 days with no activity.

github-actions Bot added the stale Stale PR or inactive for long period of time. label Aug 9, 2026
hugovk mentioned this pull request Oct 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting core review stale Stale PR or inactive for long period of time. stdlib Standard Library Python modules in the Lib/ directory type-feature A feature request or enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants


Back | FazBrowse Home | New Git URL