"""Logging helpers for applications embedding ``librevna_driver``. The library uses standard ``logging`` module loggers under the ``librevna_driver`` namespace and never configures global logging implicitly. Use :func:`configure_logging` in scripts/services when you want a convenient default console setup. """ from __future__ import annotations import logging _LOGGER_NAMESPACE = "librevna_driver" _DEFAULT_FORMAT = ( "%(asctime)s | %(levelname)-8s | %(name)s | %(message)s" ) DEFAULT_LOG_LEVEL = "INFO" def configure_logging( level: int | str | None = None, *, fmt: str = _DEFAULT_FORMAT, datefmt: str | None = "%Y-%m-%d %H:%M:%S", ) -> None: """Configure package logger with one stream handler. This helper affects only the ``librevna_driver`` logger tree and is safe to call repeatedly (previous handlers attached by this function are replaced). When ``level`` is ``None``, :data:`DEFAULT_LOG_LEVEL` is used. """ effective_level = level if level is not None else DEFAULT_LOG_LEVEL logger = logging.getLogger(_LOGGER_NAMESPACE) logger.handlers.clear() handler = logging.StreamHandler() handler.setFormatter(logging.Formatter(fmt=fmt, datefmt=datefmt)) logger.addHandler(handler) logger.setLevel(_parse_level(effective_level)) logger.propagate = False def _parse_level(level: int | str) -> int: """Parse numeric or textual log level into logging constant.""" if isinstance(level, int): return level normalized = level.strip().upper() if normalized in logging.getLevelNamesMapping(): return logging.getLevelNamesMapping()[normalized] raise ValueError(f"Unknown logging level: {level!r}")