"""This module contains the logging module.""" from typing import Union from pathlib import Path from datetime import datetime import sys class Logger: """A logger class that logs, ya get the point.""" LOG_LEVELS = [ "debug", "info", "warning", "error", "critical", ] """The log levels' names. When used as arguments, the counting starts at 1 instead of 0. """ def __init__( self, log_file: Union[Path, str] = None, append: bool = True, stdout: bool = True, log_level: int = 3, ): """Initialize a new Logger object. Args: log_file: path to a log file. If any of the folders within the log file's path don't exist, they will get created. If no value is specified, no log file is created. append: wether or not to append to the existing file or overwrite it. If False, the original file gets deleted during init. stdout: wether or not to log to stdout as well log_level: the minimum level to log """ self.log_file = Path(log_file) if log_file else None self.stdout = stdout self.log_level = log_level # Remove the original log file if not append: self.log_file.unlink(missing_ok=True) def custom(self, message: str, header: str = None): """Log a message given a header and a message. If a header is provided (aka truthy), the final form of the messsage wil be: `[YYYY-MM-DD HH:MM:SS][header] message` Otherwise, it's just: `[YYYY-MM-DD HH:MM:SS] message` Args: message: the message to display header: the header to add to the message """ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_message = f"[{timestamp}] {message}\n" if header: log_message = f"[{timestamp}][{header}] {message}\n" if self.log_file: self.log_file.write_text(log_message) if self.stdout: sys.stdout.write(log_message) def log(self, level: int, message: str): """Log a message with a specific level. Args: level: log level (index in the LOG_LEVELS variable) message: the message to log """ if level < self.log_level: return level_name = self.LOG_LEVELS[level - 1].upper() self.custom(level_name, message) def debug(self, message: str): """Log a debug message.""" self.log(1, message) def info(self, message: str): """Log an info message.""" self.log(2, message) def warning(self, message: str): """Log a warning message.""" self.log(3, message) def error(self, message: str): """Log an error message.""" self.log(4, message) def critical(self, message: str): """Log a critical message.""" self.log(5, message)