Source code for coinflip.randtests._pprint

"""Coloured ASCII art representations of binary sequences."""
from functools import lru_cache
from typing import Tuple

from colorama import Fore
from colorama import Style

from coinflip.randtests._decorators import infer_candidate
from coinflip.randtests._testutils import blocks

__all__ = ["determine_rep", "pretty_subseq", "pretty_seq", "dim", "bright"]


[docs]@lru_cache() def determine_rep(candidate, noncandidate) -> Tuple[str, str]: """Determine single-character representations of each binary value Parameters ---------- candidate : `Any` One of the two values in a sequence noncandidate : `Any` Value in a sequence which is not `candidate` Returns ------- c_rep : `str` Character representation of the `candidate` nc_rep : `str` Character representation of the `noncandidate` See Also -------- lru_cache : Method used for caching results """ c_rep = str(candidate)[0] nc_rep = str(noncandidate)[0] if c_rep.casefold() == nc_rep.casefold(): c_rep = "1" nc_rep = "0" return c_rep, nc_rep
[docs]def pretty_subseq(series, candidate, noncandidate) -> str: """Produce a one-line pretty representation of a subsequence Parameters ---------- series : `Series` Subsequence to represent candidate : `Any` One of the two values in `series` noncandidate : `Any` Value in a sequence which in `series` Returns ------- series_rep : `str` Pretty representation of `series` See Also -------- determine_rep : Method used to determine the `series` character representations """ c_rep, nc_rep = determine_rep(candidate, noncandidate) series = series.map({candidate: c_rep, noncandidate: nc_rep}) series_rep = "" for _, rep in series.iteritems(): if rep == c_rep: colour = Fore.CYAN else: colour = Fore.YELLOW series_rep += colour + rep series_rep += Fore.RESET return bright(series_rep)
[docs]def pretty_seq(series, cols) -> str: """Produce a multi-line representation of a sequence Parameters ---------- series : `Series` Sequence to represent cols : `int` Maximum number of characters to use per line Returns ------- series_rep : `str` Pretty represented of a sequence See Also -------- infer_candidate : Method used to infer the candidate value of the `series` pretty_subseq : Method wrapped to generate rows """ values = series.unique() candidate = infer_candidate(values) try: noncandidate = next(value for value in values if value != candidate) except StopIteration: noncandidate = None pad = 4 l_border = dim(" | ") l_arrow = dim(" < ") r_border = dim(" | ") r_arrow = dim(" > ") outer = cols - pad inner = outer - pad def pretty_row(series): return pretty_subseq(series, candidate, noncandidate) lines = [] n = len(series) if n <= inner: border = " " + hline(n + 4) + " " lines.append(border) f_series = l_border + pretty_row(series) + r_border lines.append(f_series) lines.append(border) else: border = " " + hline(outer) + " " rows = list(blocks(series, blocksize=cols - 8, truncate=False)) lines.append(border) f_row_first = l_border + pretty_row(rows[0]) + r_arrow lines.append(f_row_first) lines.append(border) def echo_row(row): frow = l_arrow + pretty_row(row) + r_arrow lines.append(frow) nrows = len(rows) if nrows > 10: for row in rows[1:5]: echo_row(row) lines.append(border) omit_msg = dim(f"..omitting {nrows - 10} rows..") omit_pad = "".join(" " for _ in range((cols // 2) - (len(omit_msg) // 2))) f_omit = omit_pad + omit_msg lines.append(f_omit) lines.append(border) for row in rows[-5:-1]: echo_row(row) lines.append(border) else: for row in rows[1:-1]: echo_row(row) lines.append(border) f_row_last = l_arrow + pretty_row(rows[-1]) + r_border lines.append(f_row_last) border_last = " " + hline(len(rows[-1]) + pad) lines.append(border_last + Style.RESET_ALL) return "\n".join(lines)
def hline(width) -> str: """Construct a horizontal line string""" return dim("+" + "".join("-" for _ in range(width - 2)) + "+")
[docs]def dim(string) -> str: """Wrap string in dim character codes Parameters ---------- string : `str` String to wrap Returns ------- `str` Wrapped string """ return Style.DIM + string + Style.RESET_ALL
[docs]def bright(string) -> str: """Wrap string in bright character codes Parameters ---------- string : `str` String to wrap Returns ------- `str` Wrapped string """ return Style.BRIGHT + string + Style.RESET_ALL