Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 35.2k
gh-145217: Add colour to pprint output#145218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base:main
Are you sure you want to change the base?
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
0906a8d71739fe1aac260e11465b7208828fede2553597fbd0df1f64c3392e6028ca36fccaa12e95aab21d05505d907d38f6c4dd9File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -38,6 +38,11 @@ | ||
| import sys as _sys | ||
| import types as _types | ||
| from io import StringIO as _StringIO | ||
| lazy import _colorize | ||
| lazy import re | ||
| lazy from _pyrepl.utils import disp_str, gen_colors | ||
zooba marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| lazy from dataclasses import fields as dataclass_fields | ||
| lazy from dataclasses import is_dataclass | ||
| __all__ = ["pprint","pformat","isreadable","isrecursive","saferepr", | ||
| "PrettyPrinter", "pp"] | ||
| @@ -50,15 +55,22 @@ def pprint( | ||
| width=88, | ||
| depth=None, | ||
| *, | ||
| color=True, | ||
| compact=False, | ||
| sort_dicts=True, | ||
| underscore_numbers=False, | ||
| ): | ||
| """Pretty-print a Python object to a stream [default is sys.stdout].""" | ||
| printer = PrettyPrinter( | ||
| stream=stream, indent=indent, width=width, depth=depth, | ||
| compact=compact, sort_dicts=sort_dicts, | ||
| underscore_numbers=underscore_numbers) | ||
| stream=stream, | ||
| indent=indent, | ||
| width=width, | ||
| depth=depth, | ||
| color=color, | ||
| compact=compact, | ||
| sort_dicts=sort_dicts, | ||
| underscore_numbers=underscore_numbers, | ||
| ) | ||
| printer.pprint(object) | ||
| @@ -126,6 +138,24 @@ def _safe_tuple(t): | ||
| return _safe_key(t[0]), _safe_key(t[1]) | ||
| 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. | ||
| return text | ||
| # Skip coloring inside <...> reprs (for example, <built-in function print>), | ||
| # they're placeholders, not Python source. | ||
| skip = [m.span() for m in re.finditer(r"<[^<>\n]*>", text)] | ||
| colors = [ | ||
| c for c in gen_colors(text) | ||
| if not any(start <= c.span.start < end for start, end in skip) | ||
| ] | ||
| chars, _ = disp_str(text, colors=colors, force_color=True, escape=False) | ||
| return "".join(chars) | ||
| class PrettyPrinter: | ||
| def __init__( | ||
| self, | ||
| @@ -134,6 +164,7 @@ def __init__( | ||
| depth=None, | ||
| stream=None, | ||
| *, | ||
| color=True, | ||
| compact=False, | ||
| sort_dicts=True, | ||
| underscore_numbers=False, | ||
| @@ -154,6 +185,11 @@ def __init__( | ||
| The desired output stream. If omitted (or false), the standard | ||
| output stream available at construction will be used. | ||
| color | ||
| If true (the default), syntax highlighting is enabled for pprint | ||
| when the stream and environment variables permit. | ||
| If false, colored output is always disabled. | ||
| compact | ||
| If true, several items will be combined in one line. | ||
| @@ -182,11 +218,30 @@ def __init__( | ||
| self._compact = bool(compact) | ||
| self._sort_dicts = sort_dicts | ||
| self._underscore_numbers = underscore_numbers | ||
| self._color = color | ||
| ||
| def pprint(self, object): | ||
| if self._stream is not None: | ||
| if self._stream is None: | ||
| return | ||
| use_color = False | ||
| if self._color: | ||
| try: | ||
| if _colorize.can_colorize(file=self._stream): | ||
| # Attempt to reify lazy imports, or ImportError | ||
| gen_colors, disp_str | ||
| use_color = True | ||
| except ImportError: | ||
| pass | ||
| if use_color: | ||
| sio = _StringIO() | ||
| self._format(object, sio, 0, 0, {}, 0) | ||
| self._stream.write(_colorize_output(sio.getvalue())) | ||
| else: | ||
| self._format(object, self._stream, 0, 0, {}, 0) | ||
| self._stream.write("\n") | ||
| self._stream.write("\n") | ||
| def pformat(self, object): | ||
| sio = _StringIO() | ||
| @@ -211,9 +266,6 @@ def _format(self, object, stream, indent, allowance, context, level): | ||
| max_width = self._width - indent - allowance | ||
| if len(rep) > max_width: | ||
| p = self._dispatch.get(type(object).__repr__, None) | ||
| # Lazy import to improve module import time | ||
| from dataclasses import is_dataclass | ||
| if p is not None: | ||
| context[objid] = 1 | ||
| p(self, object, stream, indent, allowance, context, level + 1) | ||
| @@ -254,9 +306,6 @@ def _write_indent_padding(self, write): | ||
| write(self._indent_per_level * " ") | ||
| def _pprint_dataclass(self, object, stream, indent, allowance, context, level): | ||
| # Lazy import to improve module import time | ||
| from dataclasses import fields as dataclass_fields | ||
| cls_name = object.__class__.__name__ | ||
| if self._compact: | ||
| indent += len(cls_name) + 1 | ||
| @@ -436,9 +485,6 @@ def _pprint_str(self, object, stream, indent, allowance, context, level): | ||
| if len(rep) <= max_width1: | ||
| chunks.append(rep) | ||
| else: | ||
| # Lazy import to improve module import time | ||
| import re | ||
| # A list of alternating (non-space, space) strings | ||
| parts = re.findall(r'\S*\s*', line) | ||
| assert parts | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.