simnibs_analyze._logging

Logging utilities for the SimNIBS analysis pipeline.

Usage in every module: from _logging import get_logger logger = get_logger(__name__)

logger.info("message")
logger.warning("message")
logger.error("message")
logger.step("SECTION TITLE")   # rich rule across the terminal width
 1"""
 2Logging utilities for the SimNIBS analysis pipeline.
 3
 4Usage in every module:
 5    from _logging import get_logger
 6    logger = get_logger(__name__)
 7
 8    logger.info("message")
 9    logger.warning("message")
10    logger.error("message")
11    logger.step("SECTION TITLE")   # rich rule across the terminal width
12"""
13
14from __future__ import annotations
15
16import datetime
17import logging
18
19import rich.console
20import rich.theme
21
22_THEME = rich.theme.Theme(
23    {
24        "asctime": "green",
25        "name": "dim cyan",
26        "debug": "dim",
27        "info": "white",
28        "warning": "yellow",
29        "error": "bold red",
30        "step": "bold cyan",
31    }
32)
33
34# Shared console — lazy so pytest capture still works
35_console: rich.console.Console | None = None
36
37
38def _get_console() -> rich.console.Console:
39    global _console
40    if _console is None:
41        _console = rich.console.Console(soft_wrap=True, theme=_THEME)
42    return _console
43
44
45class _PipelineLogger:
46    """Lightweight rich-based logger."""
47
48    def __init__(self, name: str = "", level: int = logging.INFO) -> None:
49        self.name = name
50        self.level = level
51
52    def _emit(self, kind: str, msg: str) -> None:
53        if getattr(logging, kind.upper()) < self.level:
54            return
55        ts = datetime.datetime.now().strftime("%H:%M:%S")
56        name_part = f"[name]{self.name}[/]  " if self.name else ""
57        _get_console().print(f"[asctime]{ts}[/]  {name_part}[{kind}]{msg}[/]")
58
59    def debug(self, msg: str) -> None:
60        self._emit("debug", msg)
61
62    def info(self, msg: str) -> None:
63        self._emit("info", msg)
64
65    def warning(self, msg: str) -> None:
66        self._emit("warning", f"⚠  {msg}")
67
68    def error(self, msg: str) -> None:
69        self._emit("error", f"✗  {msg}")
70
71    def step(self, title: str) -> None:
72        """Print a full-width section banner (rich rule)."""
73        _get_console().rule(f"[step] {title} [/]", style="cyan")
74
75
76def get_logger(name: str = "", level: int = logging.INFO) -> _PipelineLogger:
77    """Return a pipeline logger bound to *name*."""
78    return _PipelineLogger(name=name, level=level)
def get_logger( name: str = '', level: int = 20) -> simnibs_analyze._logging._PipelineLogger:
77def get_logger(name: str = "", level: int = logging.INFO) -> _PipelineLogger:
78    """Return a pipeline logger bound to *name*."""
79    return _PipelineLogger(name=name, level=level)

Return a pipeline logger bound to name.