"""Using :pypi:`terminaltables` to draw ANSI tables."""
import sys
from operator import itemgetter
from typing import (
IO,
Any,
Callable,
Iterable,
List,
Mapping,
Optional,
Sequence,
Type,
cast,
)
from mode.utils import logging, text
from mode.utils.compat import isatty
from terminaltables import AsciiTable, SingleTable
from terminaltables.base_table import BaseTable as Table
__all__ = ["Table", "TableDataT", "table", "logtable"]
TableDataT = Sequence[Sequence[str]]
[docs]def table(
data: TableDataT,
*,
title: str,
target: IO = None,
tty: Optional[bool] = None,
**kwargs: Any,
) -> Table:
"""Create suitable :pypi:`terminaltables` table for target.
Arguments:
data (Sequence[Sequence[str]]): Table data.
target (IO): Target should be the destination output file
for your table, and defaults to :data:`sys.stdout`.
ANSI codes will be used if the target has a controlling
terminal, but not otherwise, which is why it's important
to pass the correct output file.
"""
if target is None:
target = sys.stdout
if tty is None:
tty = isatty(target)
if tty is None:
tty = False
return _get_best_table_type(tty)(data, title=title, **kwargs)
[docs]def logtable(
data: TableDataT,
*,
title: str,
target: IO = None,
tty: Optional[bool] = None,
headers: Optional[Sequence[str]] = None,
**kwargs: Any,
) -> str:
"""Prepare table for logging.
Will use ANSI escape codes if the log file is a tty.
"""
if tty is None:
tty = logging.LOG_ISATTY
if headers:
data = [headers] + list(data)
return table(data, title=title, target=target, tty=tty, **kwargs).table
def _get_best_table_type(tty: bool) -> Type[Table]:
return SingleTable if tty else AsciiTable
DEFAULT_SORT_KEY = itemgetter(0)
def dict_as_ansitable(
d: Mapping,
*,
key: str = "Key",
value: str = "Value",
sort: bool = False,
sortkey: Callable[[Any], Any] = DEFAULT_SORT_KEY,
target: IO = sys.stdout,
title: Optional[str] = None,
) -> str:
header = [text.title(key), text.title(value)]
data = cast(Iterable[List[str]], d.items())
data = sorted(data, key=sortkey) if sort else list(data)
if sort:
data = sorted(data, key=sortkey)
return table(
[header] + list(data),
title=text.title(title) if title is not None else "",
target=target,
).table