X-Git-Url: https://wannabe.guru.org/gitweb/?a=blobdiff_plain;f=ansi.py;h=1633fddbcb31714d3ae7342daca37c1c4034b4c6;hb=d2357ff35e7752ae3eb6caa2813c35c17fea778b;hp=950a0c4a3c809587bb7c8324a884c62d83b553ab;hpb=f33ea8b6b0f7dd862ae24f49a7e834c2bbb3d4dd;p=python_utils.git diff --git a/ansi.py b/ansi.py index 950a0c4..1633fdd 100755 --- a/ansi.py +++ b/ansi.py @@ -1,11 +1,11 @@ #!/usr/bin/env python3 -from abc import abstractmethod import difflib import io import logging import re import sys +from abc import abstractmethod from typing import Any, Callable, Dict, Iterable, Optional, Tuple from overrides import overrides @@ -1731,13 +1731,15 @@ def _find_color_by_name(name: str) -> Tuple[int, int, int]: @logging_utils.squelch_repeated_log_messages(1) -def fg(name: Optional[str] = "", - red: Optional[int] = None, - green: Optional[int] = None, - blue: Optional[int] = None, - *, - force_16color: bool = False, - force_216color: bool = False) -> str: +def fg( + name: Optional[str] = "", + red: Optional[int] = None, + green: Optional[int] = None, + blue: Optional[int] = None, + *, + force_16color: bool = False, + force_216color: bool = False, +) -> str: """Return the ANSI escape sequence to change the foreground color being printed. Target colors may be indicated by name or R/G/B. Result will use the 16 or 216 color scheme if force_16color or @@ -1762,7 +1764,7 @@ def fg(name: Optional[str] = "", rgb[1], rgb[2], force_16color=force_16color, - force_216color=force_216color + force_216color=force_216color, ) if red is None: @@ -1771,14 +1773,10 @@ def fg(name: Optional[str] = "", green = 0 if blue is None: blue = 0 - if ( - is_16color(red) and is_16color(green) and is_16color(blue) - ) or force_16color: + if (is_16color(red) and is_16color(green) and is_16color(blue)) or force_16color: logger.debug("Using 16-color strategy") return fg_16color(red, green, blue) - if ( - is_216color(red) and is_216color(green) and is_216color(blue) - ) or force_216color: + if (is_216color(red) and is_216color(green) and is_216color(blue)) or force_216color: logger.debug("Using 216-color strategy") return fg_216color(red, green, blue) logger.debug("Using 24-bit color strategy") @@ -1791,14 +1789,16 @@ def _rgb_to_yiq(rgb: Tuple[int, int, int]) -> int: def _contrast(rgb: Tuple[int, int, int]) -> Tuple[int, int, int]: if _rgb_to_yiq(rgb) < 128: - return (0xff, 0xff, 0xff) + return (0xFF, 0xFF, 0xFF) return (0, 0, 0) -def pick_contrasting_color(name: Optional[str] = "", - red: Optional[int] = None, - green: Optional[int] = None, - blue: Optional[int] = None) -> Tuple[int, int, int]: +def pick_contrasting_color( + name: Optional[str] = "", + red: Optional[int] = None, + green: Optional[int] = None, + blue: Optional[int] = None, +) -> Tuple[int, int, int]: """This method will return a red, green, blue tuple representing a contrasting color given the red, green, blue of a background color or a color name of the background color. @@ -1827,11 +1827,7 @@ def guess_name(name: str) -> str: best_guess = None max_ratio = None for possibility in COLOR_NAMES_TO_RGB: - r = difflib.SequenceMatcher( - None, - name, - possibility - ).ratio() + r = difflib.SequenceMatcher(None, name, possibility).ratio() if max_ratio is None or r > max_ratio: max_ratio = r best_guess = possibility @@ -1840,13 +1836,16 @@ def guess_name(name: str) -> str: return best_guess -def bg(name: Optional[str] = "", - red: Optional[int] = None, - green: Optional[int] = None, - blue: Optional[int] = None, - *, - force_16color: bool = False, - force_216color: bool = False) -> str: +@logging_utils.squelch_repeated_log_messages(1) +def bg( + name: Optional[str] = "", + red: Optional[int] = None, + green: Optional[int] = None, + blue: Optional[int] = None, + *, + force_16color: bool = False, + force_216color: bool = False, +) -> str: """Returns an ANSI color code for changing the current background color. @@ -1868,7 +1867,7 @@ def bg(name: Optional[str] = "", rgb[1], rgb[2], force_16color=force_16color, - force_216color=force_216color + force_216color=force_216color, ) if red is None: red = 0 @@ -1876,14 +1875,10 @@ def bg(name: Optional[str] = "", green = 0 if blue is None: blue = 0 - if ( - is_16color(red) and is_16color(green) and is_16color(blue) - ) or force_16color: + if (is_16color(red) and is_16color(green) and is_16color(blue)) or force_16color: logger.debug("Using 16-color strategy") return bg_16color(red, green, blue) - if ( - is_216color(red) and is_216color(green) and is_216color(blue) - ) or force_216color: + if (is_216color(red) and is_216color(green) and is_216color(blue)) or force_216color: logger.debug("Using 216-color strategy") return bg_216color(red, green, blue) logger.debug("Using 24-bit color strategy") @@ -1892,19 +1887,19 @@ def bg(name: Optional[str] = "", class StdoutInterceptor(io.TextIOBase): def __init__(self): - self.saved_stdout: Optional[io.TextIOBase] = None + self.saved_stdout: io.TextIO = None self.buf = '' @abstractmethod def write(self, s: str): pass - def __enter__(self) -> None: + def __enter__(self): self.saved_stdout = sys.stdout sys.stdout = self - return None + return self - def __exit__(self, *args) -> bool: + def __exit__(self, *args) -> Optional[bool]: sys.stdout = self.saved_stdout print(self.buf) return None @@ -1912,8 +1907,8 @@ class StdoutInterceptor(io.TextIOBase): class ProgrammableColorizer(StdoutInterceptor): def __init__( - self, - patterns: Iterable[Tuple[re.Pattern, Callable[[Any, re.Pattern], str]]] + self, + patterns: Iterable[Tuple[re.Pattern, Callable[[Any, re.Pattern], str]]], ): super().__init__() self.patterns = [_ for _ in patterns] @@ -1926,8 +1921,10 @@ class ProgrammableColorizer(StdoutInterceptor): if __name__ == '__main__': + def main() -> None: import doctest + doctest.testmod() name = " ".join(sys.argv[1:]) @@ -1938,6 +1935,6 @@ if __name__ == '__main__': _ = pick_contrasting_color(possibility) xf = fg(None, _[0], _[1], _[2]) xb = bg(None, _[0], _[1], _[2]) - print(f'{f}{xb}{possibility}{reset()}\t\t\t' - f'{b}{xf}{possibility}{reset()}') + print(f'{f}{xb}{possibility}{reset()}\t\t\t' f'{b}{xf}{possibility}{reset()}') + main()