Source code for afmformats.logging_setup
"""Package-wide logging configuration."""
import logging
import os
import pathlib
import sys
import tempfile
from typing import Optional
__all__ = [
"DEFAULT_LOG_PATH",
"configure_logging",
]
DEFAULT_LOG_PATH = os.path.join(tempfile.gettempdir(), "afmformats.log")
[docs]
def configure_logging(log_path: Optional[str] = DEFAULT_LOG_PATH,
console_logging_level: bool | int = 0) -> str:
"""Ensure afmformats writes debug logs to a file.
Returns the log path used so CI pipelines can publish it as an artifact.
"""
path = log_path
path = str(pathlib.Path(path))
logger = logging.getLogger("afmformats")
logger.setLevel(logging.DEBUG)
logger.propagate = False
handler_exists = any(
isinstance(h, logging.FileHandler)
and getattr(h, "baseFilename", None) == path
for h in logger.handlers
)
if not handler_exists:
pathlib.Path(path).parent.mkdir(parents=True, exist_ok=True)
fh = logging.FileHandler(path, encoding="utf-8")
fh.setLevel(logging.DEBUG)
formatter = logging.Formatter(
"%(asctime)s %(levelname)s %(name)s: %(message)s"
)
fh.setFormatter(formatter)
logger.addHandler(fh)
logger.debug("afmformats logging initialized at %s", path)
if console_logging_level:
configure_console_logging(console_logging_level)
return path
def configure_console_logging(level: int = logging.DEBUG) -> None:
"""Mirror afmformats log output to the terminal."""
logger = logging.getLogger("afmformats")
handler_exists = any(
isinstance(h, logging.StreamHandler)
and not isinstance(h, logging.FileHandler)
and getattr(h, "stream", None) is sys.stderr
for h in logger.handlers
)
if not handler_exists:
handler = logging.StreamHandler()
handler.setLevel(level)
handler.setFormatter(logging.Formatter(
"%(levelname)s:%(name)s:%(message)s"))
logger.addHandler(handler)