GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-145217: Add colour to `pprint` output by hugovk · Pull Request #145218 · python/cpython

Conversation

@hugovk

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

Uh oh!

There was an error while loading. Please reload this page.

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)
image
  • Issue: Add colour to pprint output #145217

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

shiningmatcha and edvilme reacted with thumbs up emoji ZeroIntensity, johnslavik, and edvilme reacted with rocket emoji
All reactions
  • 👍 2 reactions
  • 🚀 3 reactions
hugovk added 2 commits February 25, 2026 16:07
@hugovk
Add colour to pprint output
0906a8d
@hugovk
Add blurb
71739fe
@hugovk
hugovk requested a review from AA-Turner as a code owner February 25, 2026 14:20
@hugovk hugovk added type-feature A feature request or enhancement stdlib Standard Library Python modules in the Lib/ directory labels Feb 25, 2026
@bedevere-app bedevere-app Bot added the awaiting core review label Feb 25, 2026
@bedevere-app bedevere-app Bot mentioned this pull request Feb 25, 2026
Add colour to pprint output #145217
Open
@StanFromIreland

This comment was marked as resolved.

Sign in to view
@hugovk
Merge remote-tracking branch 'upstream/main' into 3.15-pprint-colour
1aac260
StanFromIreland
StanFromIreland reviewed Apr 9, 2026
View reviewed changes
Comment thread Lib/pprint.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@StanFromIreland

This comment was marked as resolved.

Sign in to view
@hugovk
Pass escape=False for pprint to keep real control chars
e11465b
@hugovk
hugovk requested review from ambv, lysnikolaou and pablogsal as code owners April 9, 2026 13:49
@hugovk

This comment was marked as resolved.

Sign in to view
@johnslavik
johnslavik self-requested a review April 10, 2026 10:13
@hugovk
Merge branch 'main' into 3.15-pprint-colour
7208828
StanFromIreland
StanFromIreland reviewed Apr 18, 2026
View reviewed changes
Comment thread Doc/whatsnew/3.15.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

@hugovk
Change back line endings to LF
fede255
@hugovk hugovk mentioned this pull request Apr 18, 2026
Prevent GitHub's web conflict editor from converting LF to CRLF #148739
Merged
@hugovk
Fall back to monochrome if _colorize/_pyrepl.utils don't reify (import)
3597fbd
@hugovk hugovk mentioned this pull request Apr 26, 2026
Add colour to pickletools CLI output #149026
Closed
@sunmy2019
sunmy2019 self-requested a review April 27, 2026 00:39
sunmy2019
sunmy2019 reviewed Apr 28, 2026
View reviewed changes
Comment thread Lib/pprint.py
self._expand = bool(expand)
self._sort_dicts = sort_dicts
self._underscore_numbers = underscore_numbers
self._color = color

@sunmy2019 sunmy2019 Apr 28, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

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

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@hugovk hugovk Apr 28, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
sunmy2019
sunmy2019 reviewed Apr 28, 2026
View reviewed changes

@sunmy2019 sunmy2019 left a comment •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

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)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

hugovk reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
sunmy2019
sunmy2019 reviewed Apr 28, 2026
View reviewed changes
Comment thread Misc/NEWS.d/next/Library/2026-02-25-16-19-21.gh-issue-145217.QQBY0-.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

sunmy2019
sunmy2019 reviewed Apr 28, 2026
View reviewed changes
Comment thread Lib/pprint.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

hugovk and others added 2 commits April 28, 2026 14:46
@hugovk @sunmy2019
Update NEWS
0df1f64
Co-authored-by: sunmy2019 <[email protected]>
@hugovk
Avoid calling _format twice
c3392e6
@hugovk
Add test
028ca36
sunmy2019
sunmy2019 reviewed Apr 28, 2026
View reviewed changes
Comment thread Lib/test/test_pprint.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@sunmy2019

sunmy2019 commented Apr 28, 2026

Copy link
Copy Markdown
Member

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

image
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?
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@hugovk @sunmy2019
Update test
fccaa12
Co-authored-by: sunmy2019 <[email protected]>
@hugovk

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:

image

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.

sunmy2019 reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

hugovk added 2 commits April 29, 2026 17:56
@hugovk
Don't add colour if there's already colour
e95aab2
@hugovk
Refactor other lazy imports with keyword
1d05505
@read-the-docs-community

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

Uh oh!

There was an error while loading. Please reload this page.

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

  • c-api/sentinel.html
  • c-api/slots.html

± Modified

  • glossary.html
  • c-api/buffer.html
  • c-api/code.html
  • c-api/concrete.html
  • c-api/descriptor.html
  • c-api/exceptions.html
  • c-api/extension-modules.html
  • c-api/gen.html
  • c-api/index.html
  • c-api/intro.html
  • and 93 more...
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@sunmy2019

sunmy2019 commented Apr 30, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

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)
encukou reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@StanFromIreland StanFromIreland mentioned this pull request May 3, 2026
gh-145378: Generate consistent colors for pdb commands #149305
Merged
@hugovk

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.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@sunmy2019

sunmy2019 commented May 3, 2026

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)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@hugovk

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!

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@hugovk
Merge remote-tracking branch 'upstream/main' into 3.15-pprint-colour
d907d38
@encukou

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.

image
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@hugovk
Skip colour for non-Python <repr>
f6c4dd9
@hugovk

hugovk commented May 5, 2026

Copy link
Copy Markdown
Member Author

Updated to skip those.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@encukou

encukou commented May 5, 2026

Copy link
Copy Markdown
Member

That's inconsistent when nested:
image

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.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@hugovk

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 :)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@encukou

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.

hugovk, sunmy2019, and StanFromIreland reacted with thumbs up emoji
All reactions
  • 👍 3 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@github-actions

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.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@github-actions github-actions Bot added the stale Stale PR or inactive for long period of time. label Aug 9, 2026
@hugovk hugovk mentioned this pull request Oct 23, 2026
Colorful pprint #160466
Open
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@zooba zooba zooba left review comments
@sunmy2019 sunmy2019 sunmy2019 left review comments
@StanFromIreland StanFromIreland StanFromIreland left review comments
@AA-Turner AA-Turner Awaiting requested review from AA-Turner AA-Turner is a code owner
@pablogsal pablogsal Awaiting requested review from pablogsal pablogsal is a code owner
@lysnikolaou lysnikolaou Awaiting requested review from lysnikolaou lysnikolaou is a code owner
@ambv ambv Awaiting requested review from ambv ambv is a code owner
@johnslavik johnslavik Awaiting requested review from johnslavik

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

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

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

5 participants

@hugovk @StanFromIreland @sunmy2019 @encukou @zooba
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.