import logging
import math
from typing import Optional, Any
from bukka.config import LOG_LEVEL
# Define constants for better maintainability and readability
DEFAULT_FORMAT_LEVEL: str = 'p'
H2_MAX_WIDTH: int = 76
H4_SEPARATOR: str = "=" * 50
H3_SEPARATOR: str = "=" * 50
H2_BORDER_CHAR: str = "+"
H2_BORDER_LENGTH: int = H2_MAX_WIDTH + 4 # 76 + 4 = 80
[docs]
class BukkaLogger:
"""
A custom wrapper around Python's standard logging logger
that adds custom message formatting capabilities based on a
specified format level.
The formatting levels mimic typical Markdown or HTML heading structures
(p, h4, h3, h2, h1) for visual distinction in logs.
Attributes
----------
logger : logging.Logger
The underlying standard library logger instance.
"""
[docs]
def __init__(self, name: str, log_level: int = LOG_LEVEL) -> None:
"""
Initializes the BukkaLogger.
Parameters
----------
name : str
The name to use for the underlying logging.Logger instance.
Typically the module name (__name__).
"""
# Get a specific logger instance with the given name
self.logger: logging.Logger = logging.getLogger(name)
self.logger.setLevel(log_level)
# Add console handler if not already present
if not self.logger.handlers:
console_handler = logging.StreamHandler()
console_handler.setLevel(log_level)
# Create a simple formatter
formatter = logging.Formatter('%(levelname)s - %(name)s - %(message)s')
console_handler.setFormatter(formatter)
self.logger.addHandler(console_handler)
[docs]
def debug(self, msg: Any, format_level: str = DEFAULT_FORMAT_LEVEL) -> None:
"""
Logs a message with level DEBUG, after formatting.
Parameters
----------
msg : Any
The message to be logged. It will be converted to a string
by the logging system.
format_level : str, optional
The formatting level to apply ('p', 'h4', 'h3', 'h2', 'h1').
Defaults to 'p' (paragraph/plain).
"""
# Format the message string based on the provided format_level
formatted_msg: str = self.format_message(str(msg), format_level)
# Log the formatted message using the standard debug method
self.logger.debug(formatted_msg)
[docs]
def info(self, msg: Any, format_level: str = DEFAULT_FORMAT_LEVEL) -> None:
"""
Logs a message with level INFO, after formatting.
Parameters
----------
msg : Any
The message to be logged.
format_level : str, optional
The formatting level to apply. Defaults to 'p'.
"""
formatted_msg: str = self.format_message(str(msg), format_level)
self.logger.info(formatted_msg)
[docs]
def warn(self, msg: Any, format_level: str = DEFAULT_FORMAT_LEVEL) -> None:
"""
Logs a message with level WARNING, after formatting.
Parameters
----------
msg : Any
The message to be logged.
format_level : str, optional
The formatting level to apply. Defaults to 'p'.
"""
# Note: The logging module recommends using .warning() instead of .warn(),
# but .warn() is kept for backward compatibility with the original code.
formatted_msg: str = self.format_message(str(msg), format_level)
self.logger.warning(formatted_msg) # Using standard .warning() as per best practice
[docs]
def error(self, msg: Any, format_level: str = DEFAULT_FORMAT_LEVEL) -> None:
"""
Logs a message with level ERROR, after formatting.
Parameters
----------
msg : Any
The message to be logged.
format_level : str, optional
The formatting level to apply. Defaults to 'p'.
"""
formatted_msg: str = self.format_message(str(msg), format_level)
self.logger.error(formatted_msg)
[docs]
def critical(self, msg: Any, format_level: str = DEFAULT_FORMAT_LEVEL) -> None:
"""
Logs a message with level CRITICAL, after formatting.
Parameters
----------
msg : Any
The message to be logged.
format_level : str, optional
The formatting level to apply. Defaults to 'p'.
"""
formatted_msg: str = self.format_message(str(msg), format_level)
self.logger.critical(formatted_msg)