Source code for pain001.context.context

# Copyright (C) 2023-2026 Sebastien Rousseau.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
from typing import Optional


[docs] class Context: """A class that can be used to manage logging. Methods: __init__(self): Initializes the class and creates a logger. get_instance(): Returns the singleton instance of the class. get_logger(self): Returns the logger. init_logger(self): Initializes the logger. set_log_level(self, log_level): Sets the log level of the logger. set_name(self, name): Sets the name of the logger. """ instance: Optional["Context"] = None
[docs] @staticmethod def get_instance() -> "Context": """Returns the singleton instance of the class. Returns: A Context instance. """ if Context.instance is None: Context() if Context.instance is None: # pragma: no cover # Defensive check: unreachable because Context() always sets instance raise RuntimeError("Failed to initialize Context singleton") return Context.instance
[docs] def __init__(self) -> None: """Initializes the class and creates a logger. Raises: RuntimeError: If the class is already initialized. """ if Context.instance is not None: raise RuntimeError("This class is a singleton!") else: Context.instance = self self.name: str = "" self.log_level: int = logging.INFO self.logger: logging.Logger = logging.getLogger(self.name) self.logger.setLevel(self.log_level) self.logger.info("Context initialized")
[docs] def set_name(self, name: str) -> None: """Sets the name of the logger. Args: name: The name of the logger. """ self.name = name
[docs] def set_log_level(self, log_level: int) -> None: """Sets the log level of the logger. Args: log_level: The log level of the logger. Raises: ValueError: If the log level is invalid. """ valid_log_levels = { "DEBUG": logging.DEBUG, "INFO": logging.INFO, "WARNING": logging.WARNING, "ERROR": logging.ERROR, "CRITICAL": logging.CRITICAL, } if isinstance(log_level, int): # Check if log_level is an integer if log_level in valid_log_levels.values(): self.log_level = log_level else: raise ValueError("Invalid log level") else: log_level = ( log_level.strip().upper() ) # Strip and convert to uppercase if log_level in valid_log_levels: self.log_level = valid_log_levels[log_level] else: raise ValueError("Invalid log level") if self.logger: self.logger.setLevel(self.log_level)
[docs] def init_logger(self) -> None: """Initializes the logger. Raises: RuntimeError: If the logger has already been initialized. """ if self.logger is not None: raise RuntimeError("Logger has already been initialized") self.logger = logging.getLogger(self.name) console_handler = logging.StreamHandler() self.logger.setLevel(self.log_level) log_format = logging.Formatter( "%(asctime)s - %(name)s - %(levelname)s - %(message)s" ) console_handler.setFormatter(log_format) if not self.logger.handlers: self.logger.addHandler(console_handler) self.logger.info("Logging initialized")
[docs] def get_logger(self) -> logging.Logger: """Returns the logger. Returns: A Logger instance. """ if self.logger is None: self.init_logger() return self.logger