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