pytermgui.prettifiers

This module provides some methods to prettify things.

The main export here is prettify. It uses pytermgui.parser.tim, and all of its markup magic to create prettier representations of whatever is given.

View Source
  0"""This module provides some methods to prettify things.
  1
  2The main export here is `prettify`. It uses `pytermgui.parser.tim`, and all of its
  3markup magic to create prettier representations of whatever is given.
  4"""
  5
  6from typing import Any
  7from collections import UserDict, UserList
  8
  9from .parser import RE_MARKUP, tim
 10from .highlighters import highlight_python
 11
 12
 13__all__ = ["prettify"]
 14
 15CONTAINER_TYPES = (list, dict, set, tuple, UserDict, UserList)
 16
 17
 18# Note: This function can be optimized in a lot of ways, primarily the way containers
 19#       are treated.
 20def prettify(  # pylint: disable=too-many-branches
 21    target: Any,
 22    indent: int = 2,
 23    force_markup: bool = False,
 24    expand_all: bool = False,
 25    parse: bool = True,
 26) -> str:
 27    """Prettifies any Python object.
 28
 29    This uses a set of pre-defined aliases for the styling, and as such is fully
 30    customizable.
 31
 32    The aliases are:
 33    - `str`: Applied to all strings, so long as they do not contain TIM code.
 34    - `int`: Applied to all integers and booleans. The latter are included as they
 35        subclass int.
 36    - `type`: Applied to all types.
 37    - `none`: Applied to NoneType. Note that when using `pytermgui.pretty`, a
 38        single `None` return value will not be printed, only when part of a more
 39        complex structure.
 40
 41    Args:
 42        target: The object to prettify. Can be any type.
 43        indent: The indentation used for multi-line objects, like containers. When
 44            set to 0, these will be collapsed. By default, container types with
 45            `len() == 1` are always collapsed, regardless of this value. See
 46            `expand_all` to overwrite that behaviour.
 47        force_markup: When this is set every ANSI-sequence string will be turned
 48            into markup and syntax highlighted.
 49        expand_all: When set, objects that would normally be force-collapsed are
 50            also going to be expanded.
 51        parse: If not set, the return value will be a plain markup string, not yet
 52            parsed.
 53
 54    Returns:
 55        A pretty string of the given target.
 56    """
 57
 58    if isinstance(target, str):
 59        if RE_MARKUP.match(target) is not None:
 60            if parse:
 61                return f'"{tim.prettify_markup(target)}"'
 62
 63            return target + "[/]"
 64
 65        target = repr(target)
 66
 67    if isinstance(target, CONTAINER_TYPES):
 68        if len(target) < 2 and not expand_all:
 69            indent = 0
 70
 71        indent_str = ("\n" if indent > 0 else "") + indent * " "
 72
 73        chars = str(target)[0], str(target)[-1]
 74        buff = chars[0]
 75
 76        if isinstance(target, (dict, UserDict)):
 77            for i, (key, value) in enumerate(target.items()):
 78                if i > 0:
 79                    buff += ", "
 80
 81                buff += indent_str + highlight_python(f"{key!r}: ")
 82
 83                pretty = prettify(
 84                    value,
 85                    indent=indent,
 86                    expand_all=expand_all,
 87                    force_markup=force_markup,
 88                    parse=False,
 89                )
 90
 91                lines = pretty.splitlines()
 92                buff += lines[0]
 93
 94                for line in lines[1:]:
 95                    buff += indent_str + line
 96
 97        else:
 98            for i, value in enumerate(target):
 99                if i > 0:
100                    buff += ", "
101
102                pretty = prettify(
103                    value,
104                    indent=indent,
105                    expand_all=expand_all,
106                    force_markup=force_markup,
107                    parse=False,
108                )
109
110                lines = pretty.splitlines()
111
112                for line in lines:
113                    buff += indent_str + line
114
115        if indent > 0:
116            buff += "\n"
117
118        buff += chars[1]
119
120        if force_markup:
121            return buff
122
123        return tim.parse(buff)
124
125    buff = highlight_python(str(target))
126
127    return tim.parse(buff) if parse else buff
#   def prettify( target: Any, indent: int = 2, force_markup: bool = False, expand_all: bool = False, parse: bool = True ) -> str:
View Source
 21def prettify(  # pylint: disable=too-many-branches
 22    target: Any,
 23    indent: int = 2,
 24    force_markup: bool = False,
 25    expand_all: bool = False,
 26    parse: bool = True,
 27) -> str:
 28    """Prettifies any Python object.
 29
 30    This uses a set of pre-defined aliases for the styling, and as such is fully
 31    customizable.
 32
 33    The aliases are:
 34    - `str`: Applied to all strings, so long as they do not contain TIM code.
 35    - `int`: Applied to all integers and booleans. The latter are included as they
 36        subclass int.
 37    - `type`: Applied to all types.
 38    - `none`: Applied to NoneType. Note that when using `pytermgui.pretty`, a
 39        single `None` return value will not be printed, only when part of a more
 40        complex structure.
 41
 42    Args:
 43        target: The object to prettify. Can be any type.
 44        indent: The indentation used for multi-line objects, like containers. When
 45            set to 0, these will be collapsed. By default, container types with
 46            `len() == 1` are always collapsed, regardless of this value. See
 47            `expand_all` to overwrite that behaviour.
 48        force_markup: When this is set every ANSI-sequence string will be turned
 49            into markup and syntax highlighted.
 50        expand_all: When set, objects that would normally be force-collapsed are
 51            also going to be expanded.
 52        parse: If not set, the return value will be a plain markup string, not yet
 53            parsed.
 54
 55    Returns:
 56        A pretty string of the given target.
 57    """
 58
 59    if isinstance(target, str):
 60        if RE_MARKUP.match(target) is not None:
 61            if parse:
 62                return f'"{tim.prettify_markup(target)}"'
 63
 64            return target + "[/]"
 65
 66        target = repr(target)
 67
 68    if isinstance(target, CONTAINER_TYPES):
 69        if len(target) < 2 and not expand_all:
 70            indent = 0
 71
 72        indent_str = ("\n" if indent > 0 else "") + indent * " "
 73
 74        chars = str(target)[0], str(target)[-1]
 75        buff = chars[0]
 76
 77        if isinstance(target, (dict, UserDict)):
 78            for i, (key, value) in enumerate(target.items()):
 79                if i > 0:
 80                    buff += ", "
 81
 82                buff += indent_str + highlight_python(f"{key!r}: ")
 83
 84                pretty = prettify(
 85                    value,
 86                    indent=indent,
 87                    expand_all=expand_all,
 88                    force_markup=force_markup,
 89                    parse=False,
 90                )
 91
 92                lines = pretty.splitlines()
 93                buff += lines[0]
 94
 95                for line in lines[1:]:
 96                    buff += indent_str + line
 97
 98        else:
 99            for i, value in enumerate(target):
100                if i > 0:
101                    buff += ", "
102
103                pretty = prettify(
104                    value,
105                    indent=indent,
106                    expand_all=expand_all,
107                    force_markup=force_markup,
108                    parse=False,
109                )
110
111                lines = pretty.splitlines()
112
113                for line in lines:
114                    buff += indent_str + line
115
116        if indent > 0:
117            buff += "\n"
118
119        buff += chars[1]
120
121        if force_markup:
122            return buff
123
124        return tim.parse(buff)
125
126    buff = highlight_python(str(target))
127
128    return tim.parse(buff) if parse else buff

Prettifies any Python object.

This uses a set of pre-defined aliases for the styling, and as such is fully customizable.

The aliases are:

  • str: Applied to all strings, so long as they do not contain TIM code.
  • int: Applied to all integers and booleans. The latter are included as they subclass int.
  • type: Applied to all types.
  • none: Applied to NoneType. Note that when using pytermgui.pretty, a single None return value will not be printed, only when part of a more complex structure.
Args
  • target: The object to prettify. Can be any type.
  • indent: The indentation used for multi-line objects, like containers. When set to 0, these will be collapsed. By default, container types with len() == 1 are always collapsed, regardless of this value. See expand_all to overwrite that behaviour.
  • force_markup: When this is set every ANSI-sequence string will be turned into markup and syntax highlighted.
  • expand_all: When set, objects that would normally be force-collapsed are also going to be expanded.
  • parse: If not set, the return value will be a plain markup string, not yet parsed.
Returns

A pretty string of the given target.