"""
Entry-side logging presentation helpers for simulate CLI.
This module configures the runtime logger (pyfcstm.simulate) with CLI-specific
presentation handlers. The entry layer and runtime share the same logger instance
to ensure consistent highlighting and formatting.
"""
import logging
import sys
from rich.console import Console
from rich.highlighter import Highlighter, ReprHighlighter, RegexHighlighter
from rich.logging import RichHandler
from rich.theme import Theme
[docs]
class SimulatePlainLogHandler(logging.StreamHandler):
"""
Plain stderr log handler for simulate CLI.
:param use_color: Whether colored terminal output is enabled.
:type use_color: bool
"""
[docs]
def __init__(self, use_color: bool = True):
super().__init__(sys.stderr)
self.use_color = use_color
class _SimulateRegexHighlighter(RegexHighlighter):
"""Regex-based highlighter for simulate log output."""
highlights = [
r"(?P<level_debug>\[DEBUG\])",
r"(?P<level_info>\[INFO\])",
r"(?P<level_warning>\[WARNING\])",
r"(?P<level_error>\[ERROR\])",
r"(?P<level_critical>\[CRITICAL\])",
r"(?P<cycle_complete>Cycle\s+\d+\s+completed\s+successfully)",
r"Execute\s+transition:\s+(?P<transition_path>[^\n]+?\s->\s[^\n]+?\(event=[^)]+\))",
]
base_style = "simulate."
[docs]
class SimulateLogHighlighter(Highlighter):
"""Combine Rich repr highlighting with simulate-specific regex highlighting."""
[docs]
def __init__(self):
self._repr = ReprHighlighter()
self._regex = _SimulateRegexHighlighter()
[docs]
def highlight(self, text) -> None:
self._repr.highlight(text)
self._regex.highlight(text)
[docs]
class SimulateRichLogHandler(RichHandler):
"""
Rich-based stderr log handler for simulate CLI.
:param use_color: Whether colored terminal output is enabled.
:type use_color: bool
"""
[docs]
def __init__(self, use_color: bool = True):
console = Console(
stderr=True,
no_color=not use_color,
soft_wrap=True,
theme=Theme({
'simulate.level_debug': 'dim cyan',
'simulate.level_info': 'green',
'simulate.level_warning': 'yellow',
'simulate.level_error': 'bold red',
'simulate.level_critical': 'bold white on red',
'simulate.cycle_complete': 'underline bold cyan',
'simulate.transition_path': 'underline green',
}),
)
super().__init__(
console=console,
show_time=False,
show_level=False,
show_path=False,
markup=False,
rich_tracebacks=False,
highlighter=SimulateLogHighlighter(),
)
self.use_color = use_color
[docs]
def create_simulate_log_handler(use_color: bool = True) -> logging.Handler:
"""
Create a CLI log handler for simulate output.
Uses Rich when colors are enabled. Falls back to a plain standard-library
handler otherwise.
:param use_color: Whether colored terminal output is enabled.
:type use_color: bool
:return: Configured logging handler.
:rtype: logging.Handler
"""
if use_color:
handler = SimulateRichLogHandler(use_color=use_color)
else:
handler = SimulatePlainLogHandler(use_color=use_color)
handler.setFormatter(SimulateCliFormatter())
return handler