feat: add reactor control persistence and tests

This commit is contained in:
Andrii Prokhorov
2025-11-21 17:11:00 +02:00
commit cc7fba4e7a
43 changed files with 1435 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
"""Logging helpers for the reactor simulation package."""
from __future__ import annotations
import logging
from typing import Optional
def configure_logging(level: int | str = "INFO", logfile: Optional[str] = None) -> logging.Logger:
"""Configure a package-scoped logger emitting to stdout and optional file."""
resolved_level = logging.getLevelName(level) if isinstance(level, str) else level
logger = logging.getLogger("reactor_sim")
logger.setLevel(resolved_level)
if not logger.handlers:
stream_handler = logging.StreamHandler()
formatter = logging.Formatter(
fmt="%(asctime)s | %(levelname)s | %(name)s | %(message)s", datefmt="%H:%M:%S"
)
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
if logfile:
file_handler = logging.FileHandler(logfile)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
else:
for handler in logger.handlers:
handler.setLevel(resolved_level)
if logfile and not any(isinstance(handler, logging.FileHandler) for handler in logger.handlers):
file_handler = logging.FileHandler(logfile)
formatter = logging.Formatter(
fmt="%(asctime)s | %(levelname)s | %(name)s | %(message)s", datefmt="%H:%M:%S"
)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
# Keep package loggers self-contained so host apps can opt-in to propagation.
logger.propagate = False
logging.getLogger().setLevel(resolved_level)
return logger