Getting Started: Terminal Colors and Protocol Safety¶
The base module provides the base.TerminalColorMixin, which allows any class to
print colorized output while ensuring structural integrity through protocols.
Using the TerminalColorMixin Class¶
The TerminalColorMixin class provides standardized CLI color capabilities.
It encapsulates ANSI escape sequences and ensures a safe fallback
(plain text) for environments where colors are disabled or not supported.
Global Controls¶
Unlike some other tools, TerminalColorMixin does not perform “magic”
terminal detection via isatty(). This ensures consistent behavior
across different environments and pipes.
The mixin features a global toggle to enable or disable colorized output entirely. This is particularly useful when piping output to logs, files, or other scripts that cannot process ANSI codes.
>>> from fitzzftw.patch.ftw_patch import TerminalColorMixin
By default, colors are enabled. To disable them globally:
>>> TerminalColorMixin.use_colors = False
The colors defined are the following. There is a special color called terminal, this is the color of the terminal it is run from.
>>> TerminalColorMixin._ANSI.defined_colors
['red', 'green', 'yellow', 'cyan', 'terminal']
>>> TerminalColorMixin._ANSI.defined_keys
['red', 'green', 'yellow', 'cyan', 'reset', 'bold', 'terminal']
Method Signature¶
The colorize() method is the primary interface for styling text.
It accepts a color_key (red, green, yellow, terminal, or cyan) and an optional bold flag.
Testing and Validation¶
In automated testing environments like doctests, raw ANSI escape codes are
invisible and difficult to assert. To solve this, the internal
_ANSI
mapping can be overridden with human-readable placeholders.
Mocking colors for readable test assertions.
>>> TerminalColorMixin._ANSI.switch_to_testmode()
>>> TerminalColorMixin._ANSI.mode
'TEST'
>>> m = TerminalColorMixin()
>>> m._ANSI.mode
'TEST'
If use_colors is False,
the text remains plain:
>>> TerminalColorMixin.use_colors = False
>>> m.colorize(text="Error", color_key="red", bold=True)
Error
If use_colors is set to True,
the mocked style is applied:
>>> TerminalColorMixin.use_colors = True
>>> m.colorize("Error", "red", True)
bold.red>Error<reset
Diagnostic Tool: color_terminal_check¶
Beyond the mixin, the module provides a diagnostic function to verify terminal compatibility. This function prints a visual test pattern to the console.
Standalone Usage:¶
If the package is installed, this diagnostic can be invoked directly from the command line:
$ ftw-terminal-color-check
Programmatic Usage:¶
>>> from fitzzftw.patch.ftw_patch import color_terminal_check
>>> color_terminal_check()
=================================================
========== Visual Terminal Color Check ==========
Enabled : grn>GRN<reset|bold.grn>GRN-B<reset|red>RED<reset|bold.red>RED-B<reset|cyn>CYN<reset|bold.cyn>CYN-B<reset|ylw>YLW<reset|bold.ylw>YLW-B<reset
Disabled: GRN|GRN-B|RED|RED-B|CYN|CYN-B|YLW|YLW-B
=================================================
Basic Integration¶
To equip a class with color capabilities, inherit from
TerminalColorMixin.
The colorize() method then
becomes available to handle styled output.
>>> class PatchReporter(TerminalColorMixin):
... def info(self, message: str):
... self.colorize(message, "cyan", bold=True)
>>> reporter = PatchReporter()
>>> reporter.info("Starting patch process...")
bold.cyn>Starting patch process...<reset
The print() method is more advanced: it requires the object to be
protocol.LineLike
(it must have a _color_map, prefix and orig_line attribute).
If we try to print an object that does not follow this protocol, the framework
raises a detailed FtwProtocolError. Doctest allows us to verify
this behavior by looking for the specific error message:
>>> reporter.print()
Traceback (most recent call last):
...
fitzzftw.patch.exceptions.FtwProtocolError:
Error: TerminalColorMixin.print for PatchReporter
Please implement:
LineLike:
Args:
_color_map: dict
orig_line: str
prefix: str | None
or
overwrite TerminalColorMixin.print(self, **kwargs) -> None.
Let’s create a class which fullfils the lines.LineLike` protocols.
>>> class PatchLineReporter(TerminalColorMixin):
... _color_map = {"?": "green", "": "yellow"}
... def __init__(self):
... self.prefix: str = "?"
... self.orig_line:str = "Hallo world."
>>> line = PatchLineReporter()
>>> from fitzzftw.patch.base import LineLike
>>> isinstance(line, LineLike)
True
>>> line.print()
grn>Hallo world.<reset
>>> line.prefix=""
>>> line.orig_line="Have a nice day."
>>> line.print()
ylw>Have a nice day.<reset
>>> line.prefix="&"
>>> line.orig_line="Have a nice day."
>>> line.print()
trm>Have a nice day.<reset