Source code for mdacli.logger

#!/usr/bin/env python3
#
# Copyright (c) 2021 Authors and contributors
#
# Released under the GNU Public Licence, v2 or any higher version
# SPDX-License-Identifier: GPL-2.0-or-later
"""Logging."""

import contextlib
import logging
import sys
import warnings
from pathlib import Path

from .colors import Emphasise


[docs] def check_suffix(filename: str | Path, suffix: str) -> str | Path: """Check the suffix of a file name and adds if it not existing. If ``filename`` does not end with ``suffix`` the ``suffix`` is added and a warning will be issued. Parameters ---------- filename : Name of the file to be checked. suffix : Expected file suffix i.e. ``.txt``. Returns ------- Checked and probably extended file name. """ path_filename = Path(filename) if path_filename.suffix != suffix: warnings.warn( f"The file name should have a '{suffix}' extension. The user " f"requested the file with name '{filename}', but it will be saved " f"as '{filename}{suffix}'.", stacklevel=1, ) path_filename = path_filename.parent / (path_filename.name + suffix) if type(filename) is str: return str(path_filename) return path_filename
[docs] @contextlib.contextmanager def setup_logging( logobj: logging.Logger, logfile: str | Path | None = None, level: int = logging.WARNING, ): """Create a logging environment for a given ``log_obj``. Parameters ---------- logobj : ``logging.Logger`` A logging instance logfile : str Name of the log file level : int Set the root logger level to the specified level. If for example set to :py:obj:`logging.DEBUG` detailed debug logs inludcing filename and function name are displayed. For :py:obj:`logging.INFO` only the message logged from errors, warnings and infos will be displayed. """ try: format = "" if level == logging.DEBUG: format += "[{levelname}]:{filename}:{funcName}:{lineno} - " format += "{message}" formatter = logging.Formatter(format, style="{") handlers: list[logging.StreamHandler | logging.FileHandler] = [] stream_handler = logging.StreamHandler(sys.stdout) stream_handler.setFormatter(formatter) handlers.append(stream_handler) if logfile: logfile = check_suffix(filename=logfile, suffix=".log") file_handler = logging.FileHandler(filename=str(logfile), encoding="utf-8") file_handler.setFormatter(formatter) handlers.append(file_handler) else: logging.addLevelName(logging.INFO, Emphasise.info("INFO")) logging.addLevelName(logging.DEBUG, Emphasise.debug("DEBUG")) logging.addLevelName(logging.WARNING, Emphasise.warning("WARNING")) logging.addLevelName(logging.ERROR, Emphasise.error("ERROR")) logging.basicConfig(format=format, handlers=handlers, level=level, style="{") logging.captureWarnings(True) if logfile: abs_path = str(Path(logfile).absolute().resolve()) logobj.info(f"This log is also available at '{abs_path}'.") else: logobj.debug("Logging to file is disabled.") for handler in handlers: logobj.addHandler(handler) yield finally: for handler in handlers: handler.flush() handler.close() logobj.removeHandler(handler)