pytermgui.pretty

This module calls install() on import, and defines print as pprint.

It allows setting up pretty print functionality in only one line.

Usage
>>> from pytermgui.pretty import print
  1"""This module calls `install()` on import, and defines `print` as `pprint`.
  2
  3It allows setting up pretty print functionality in only one line.
  4
  5Usage:
  6    ```python3
  7    >>> from pytermgui.pretty import print
  8    ```
  9"""
 10
 11# isort: skip_file
 12
 13from __future__ import annotations
 14
 15import builtins
 16import os
 17import sys
 18from typing import Any
 19
 20from .markup import tim
 21from .prettifiers import prettify
 22from .terminal import get_terminal
 23
 24try:
 25    # Try to get IPython instance. This function is provided by the
 26    # IPython runtime, so if running outside of that context a NameError
 27    # is raised.
 28    IPYTHON = get_ipython()  # type: ignore
 29    from IPython.core.formatters import (  # type: ignore # pylint: disable=import-error
 30        BaseFormatter,
 31    )
 32
 33except NameError:
 34    IPYTHON = None
 35    BaseFormatter = object
 36
 37
 38NO_WELCOME = (
 39    os.getenv("PTG_SILENCE_PRETTY") is not None or not get_terminal().is_interactive()
 40)
 41
 42__all__ = ["pprint", "install"]
 43
 44
 45def pprint(
 46    *items: Any,
 47    indent: int = 2,
 48    expand_all: bool = False,
 49    force_markup: bool = False,
 50    parse: bool = True,
 51    **print_args: Any,
 52) -> None:
 53    r"""A wrapper to pretty-print any object.
 54
 55    This essentially just calls `prettify` on each given object, and passes the
 56    `**print_args` right through to print. Note that when the `sep` print argument is
 57    ommitted it is manually set to ", \n".
 58
 59    To customize any of the styles, see `MarkupLanguage.prettify`.
 60
 61    Args:
 62        *items: The items to print. These are passed in the same way they would be into
 63            builtin print.
 64        indent: The indentation value used for multi-line objects. This is ignored when
 65            the given object has a `len() < 2`, and `expand_all is not set.`
 66        force_tim: Turn all ANSI-sequences into tim before pretty printing.
 67        expand_all: Force-expand containers, even when they would normally be collapsed.
 68        **print_args: All arguments passed to builtin print.
 69    """
 70
 71    if "sep" not in print_args:
 72        print_args["sep"] = ", \n"
 73
 74    pretty = []
 75    for item in items:
 76        pretty.append(
 77            prettify(
 78                item,
 79                force_markup=force_markup,
 80                indent=indent,
 81                expand_all=expand_all,
 82                parse=parse,
 83            )
 84        )
 85
 86    get_terminal().print(*pretty, **print_args)
 87
 88
 89def install(
 90    indent: int = 2, force_markup: bool = False, expand_all: bool = False
 91) -> None:
 92    """Sets up `pprint` to print all REPL output. IPython is also supported.
 93
 94    This functions sets up a hook that will call `pprint` after every interactive
 95    return. The given arguments are passed directly to `pprint`, so for more information
 96    you can check out that function.
 97
 98    Usage is pretty simple:
 99
100    ```python3
101    >>> from pytermgui import pretty
102    >>> tim.setup_displayhook()
103    >>> # Any function output will now be prettified
104    ```
105
106    ...or alternatively, you can import `print` from `pytermgui.pretty`,
107    and have it automatically set up, and replace your namespace's `print`
108    function with `tim.pprint`:
109
110    ```python3
111    >>> from pytermgui.pretty import print
112    ... # Under the hood, the above is called and `tim.pprint` is set
113    ... # for the `print` name
114    >>> # Any function output will now be prettified
115    ```
116
117    Args:
118        indent: The indentation value used for multi-line objects. This is ignored when
119            the given object has a `len() < 2`, and `expand_all is not set.`
120        force_tim: Turn all ANSI-sequences into tim before pretty printing.
121        expand_all: Force-expand containers, even when they would normally be collapsed.
122    """
123
124    def _hook(value: Any) -> None:
125        if value is None:
126            return
127
128        pprint(value, force_markup=force_markup, indent=indent, expand_all=expand_all)
129
130        # Sets up "_" as a way to access return value,
131        # inkeeping with sys.displayhook
132        builtins._ = value  # type: ignore
133
134    if IPYTHON is not None:
135        IPYTHON.display_formatter.formatters["text/plain"] = PTGFormatter(
136            force_markup=force_markup, indent=indent, expand_all=expand_all
137        )
138
139    else:
140        sys.displayhook = _hook
141
142    if not NO_WELCOME:
143        with get_terminal().no_record():
144            builtins.print()
145            tim.print("[113 bold]Successfully set up prettification!")
146            tim.print("[245 italic]> All function returns will now be pretty-printed,")
147            builtins.print()
148            pprint("[245 italic]Including [/italic 210]Markup!")
149            builtins.print()
150
151    get_terminal().displayhook_installed = True
152
153
154class PTGFormatter(BaseFormatter):  # pylint: disable=too-few-public-methods
155    """An IPython formatter for PTG pretty printing."""
156
157    def __init__(self, **kwargs: Any) -> None:
158        """Initializes PTGFormatter, storing **kwargs."""
159
160        super().__init__()
161
162        self.kwargs = kwargs
163
164    def __call__(self, value: Any) -> None:
165        """Pretty prints the given value, as well as a leading newline.
166
167        The newline is needed since IPython output is prepended with
168        "Out[i]:", and it might mess alignments up.
169        """
170
171        builtins.print("\n")
172        pprint(value, **self.kwargs)
173
174        # Sets up "_" as a way to access return value,
175        # inkeeping with sys.displayhook
176        builtins._ = value  # type: ignore
177
178
179# I am normally violently against shadowing builtins, but this is an optional,
180# (hopefully always) REPL-only name, only provided for convenience.
181print = pprint  # pylint: disable=redefined-builtin
182
183install()
def pprint( *items: Any, indent: int = 2, expand_all: bool = False, force_markup: bool = False, parse: bool = True, **print_args: Any) -> None:
46def pprint(
47    *items: Any,
48    indent: int = 2,
49    expand_all: bool = False,
50    force_markup: bool = False,
51    parse: bool = True,
52    **print_args: Any,
53) -> None:
54    r"""A wrapper to pretty-print any object.
55
56    This essentially just calls `prettify` on each given object, and passes the
57    `**print_args` right through to print. Note that when the `sep` print argument is
58    ommitted it is manually set to ", \n".
59
60    To customize any of the styles, see `MarkupLanguage.prettify`.
61
62    Args:
63        *items: The items to print. These are passed in the same way they would be into
64            builtin print.
65        indent: The indentation value used for multi-line objects. This is ignored when
66            the given object has a `len() < 2`, and `expand_all is not set.`
67        force_tim: Turn all ANSI-sequences into tim before pretty printing.
68        expand_all: Force-expand containers, even when they would normally be collapsed.
69        **print_args: All arguments passed to builtin print.
70    """
71
72    if "sep" not in print_args:
73        print_args["sep"] = ", \n"
74
75    pretty = []
76    for item in items:
77        pretty.append(
78            prettify(
79                item,
80                force_markup=force_markup,
81                indent=indent,
82                expand_all=expand_all,
83                parse=parse,
84            )
85        )
86
87    get_terminal().print(*pretty, **print_args)

A wrapper to pretty-print any object.

This essentially just calls prettify on each given object, and passes the **print_args right through to print. Note that when the sep print argument is ommitted it is manually set to ", \n".

To customize any of the styles, see MarkupLanguage.prettify.

Args
  • *items: The items to print. These are passed in the same way they would be into builtin print.
  • indent: The indentation value used for multi-line objects. This is ignored when the given object has a len() < 2, and expand_all is not set.
  • force_tim: Turn all ANSI-sequences into tim before pretty printing.
  • expand_all: Force-expand containers, even when they would normally be collapsed.
  • **print_args: All arguments passed to builtin print.
def install( indent: int = 2, force_markup: bool = False, expand_all: bool = False) -> None:
 90def install(
 91    indent: int = 2, force_markup: bool = False, expand_all: bool = False
 92) -> None:
 93    """Sets up `pprint` to print all REPL output. IPython is also supported.
 94
 95    This functions sets up a hook that will call `pprint` after every interactive
 96    return. The given arguments are passed directly to `pprint`, so for more information
 97    you can check out that function.
 98
 99    Usage is pretty simple:
100
101    ```python3
102    >>> from pytermgui import pretty
103    >>> tim.setup_displayhook()
104    >>> # Any function output will now be prettified
105    ```
106
107    ...or alternatively, you can import `print` from `pytermgui.pretty`,
108    and have it automatically set up, and replace your namespace's `print`
109    function with `tim.pprint`:
110
111    ```python3
112    >>> from pytermgui.pretty import print
113    ... # Under the hood, the above is called and `tim.pprint` is set
114    ... # for the `print` name
115    >>> # Any function output will now be prettified
116    ```
117
118    Args:
119        indent: The indentation value used for multi-line objects. This is ignored when
120            the given object has a `len() < 2`, and `expand_all is not set.`
121        force_tim: Turn all ANSI-sequences into tim before pretty printing.
122        expand_all: Force-expand containers, even when they would normally be collapsed.
123    """
124
125    def _hook(value: Any) -> None:
126        if value is None:
127            return
128
129        pprint(value, force_markup=force_markup, indent=indent, expand_all=expand_all)
130
131        # Sets up "_" as a way to access return value,
132        # inkeeping with sys.displayhook
133        builtins._ = value  # type: ignore
134
135    if IPYTHON is not None:
136        IPYTHON.display_formatter.formatters["text/plain"] = PTGFormatter(
137            force_markup=force_markup, indent=indent, expand_all=expand_all
138        )
139
140    else:
141        sys.displayhook = _hook
142
143    if not NO_WELCOME:
144        with get_terminal().no_record():
145            builtins.print()
146            tim.print("[113 bold]Successfully set up prettification!")
147            tim.print("[245 italic]> All function returns will now be pretty-printed,")
148            builtins.print()
149            pprint("[245 italic]Including [/italic 210]Markup!")
150            builtins.print()
151
152    get_terminal().displayhook_installed = True

Sets up pprint to print all REPL output. IPython is also supported.

This functions sets up a hook that will call pprint after every interactive return. The given arguments are passed directly to pprint, so for more information you can check out that function.

Usage is pretty simple:

>>> from pytermgui import pretty
>>> tim.setup_displayhook()
>>> # Any function output will now be prettified

...or alternatively, you can import print from pytermgui.pretty, and have it automatically set up, and replace your namespace's print function with tim.pprint:

>>> from pytermgui.pretty import print
... # Under the hood, the above is called and `tim.pprint` is set
... # for the `print` name
>>> # Any function output will now be prettified
Args
  • indent: The indentation value used for multi-line objects. This is ignored when the given object has a len() < 2, and expand_all is not set.
  • force_tim: Turn all ANSI-sequences into tim before pretty printing.
  • expand_all: Force-expand containers, even when they would normally be collapsed.