1
0
Fork 0
cli-helpers/cli_helpers/utils.py

115 lines
3 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
"""Various utility functions and helpers."""
import binascii
import re
from functools import lru_cache
from typing import Dict
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from pygments.style import StyleMeta
from cli_helpers.compat import binary_type, text_type, Terminal256Formatter, StringIO
def bytes_to_string(b):
"""Convert bytes *b* to a string.
Hexlify bytes that can't be decoded.
"""
if isinstance(b, binary_type):
needs_hex = False
try:
result = b.decode("utf8")
needs_hex = not result.isprintable()
except UnicodeDecodeError:
needs_hex = True
if needs_hex:
return "0x" + binascii.hexlify(b).decode("ascii")
else:
return result
return b
def to_string(value):
"""Convert *value* to a string."""
if isinstance(value, binary_type):
return bytes_to_string(value)
else:
return text_type(value)
def truncate_string(value, max_width=None, skip_multiline_string=True):
"""Truncate string values."""
if skip_multiline_string and isinstance(value, text_type) and "\n" in value:
return value
elif (
isinstance(value, text_type)
and max_width is not None
and len(value) > max_width
):
return value[: max_width - 3] + "..."
return value
def intlen(n):
"""Find the length of the integer part of a number *n*."""
pos = n.find(".")
return len(n) if pos < 0 else pos
def filter_dict_by_key(d, keys):
"""Filter the dict *d* to remove keys not in *keys*."""
return {k: v for k, v in d.items() if k in keys}
def unique_items(seq):
"""Return the unique items from iterable *seq* (in order)."""
seen = set()
return [x for x in seq if not (x in seen or seen.add(x))]
_ansi_re = re.compile("\033\\[((?:\\d|;)*)([a-zA-Z])")
def strip_ansi(value):
"""Strip the ANSI escape sequences from a string."""
return _ansi_re.sub("", value)
def replace(s, replace):
"""Replace multiple values in a string"""
for r in replace:
s = s.replace(*r)
return s
@lru_cache()
def _get_formatter(style) -> Terminal256Formatter:
return Terminal256Formatter(style=style)
def style_field(token, field, style):
"""Get the styled text for a *field* using *token* type."""
formatter = _get_formatter(style)
s = StringIO()
formatter.format(((token, field),), s)
return s.getvalue()
def filter_style_table(style: "StyleMeta", *relevant_styles: str) -> Dict:
"""
get a dictionary of styles for given tokens. Typical usage:
filter_style_table(style, Token.Output.EvenRow, Token.Output.OddRow) == {
Token.Output.EvenRow: "",
Token.Output.OddRow: "",
}
"""
_styles_iter = ((key, val) for key, val in getattr(style, "styles", {}).items())
_relevant_styles_iter = filter(lambda tpl: tpl[0] in relevant_styles, _styles_iter)
return {key: val for key, val in _relevant_styles_iter}