Source code for gyoza.logging.logger
"""Logger singleton for gyoza operations."""
import logging
from typing import Final
[docs]
class GyozaLogger:
"""
Singleton logger for gyoza operations.
Provides specialized logging methods for gyoza operations with custom formatting.
"""
_instance: "GyozaLogger | None" = None
_initialized: bool = False
def __new__(cls) -> "GyozaLogger":
"""Create or return the singleton instance."""
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialized = False
return cls._instance
def __init__(self) -> None:
"""Initialize the logger if not already initialized."""
if hasattr(self, "_initialized") and self._initialized:
return
self._logger = logging.getLogger("gyoza")
self._logger.setLevel(logging.INFO)
# Only add handler if one doesn't exist
if not self._logger.handlers:
handler = logging.StreamHandler()
handler.setLevel(logging.INFO)
# Custom formatter for gyoza logs
formatter = logging.Formatter(
fmt="[GYOZA] %(message)s",
)
handler.setFormatter(formatter)
self._logger.addHandler(handler)
# Track current progress for relative increments
self._current_progress: float = 0.0
self._initialized = True
[docs]
def info(self, message: str) -> None:
"""
Log an info message.
Parameters
----------
message : str
The message to log
Examples
--------
>>> from gyoza import logger
>>> logger.info("Processing started")
"""
formatted_message = f"[INFO] {message}"
self._logger.info(formatted_message)
[docs]
def reset(self) -> None:
"""
Reset the progress counter to 0.
Useful for starting a new operation or resetting progress tracking.
Examples
--------
>>> from gyoza import logger
>>> logger.progress(50.0)
>>> logger.reset() # Reset to 0%
>>> logger.progress(25.0, relative=True) # Now at 25%
"""
self._current_progress = 0.0
[docs]
def progress(self, value: float, relative: bool = False) -> None:
"""
Log a progress value.
Parameters
----------
value : float
Progress value between 0 and 100, or increment if relative=True
relative : bool, default=False
If True, adds value to current progress instead of setting absolute value
Raises
------
ValueError
If value is not between 0 and 100 (when relative=False),
if value is negative (when relative=True),
or if absolute value would decrease progress.
"""
if relative:
# For relative increments, value must be positive
if value < 0:
error_msg = (
f"Relative progress increment must be non-negative, got {value}"
)
raise ValueError(error_msg)
# Add to current progress and cap at 100%
self._current_progress = min(100.0, self._current_progress + value)
final_value = self._current_progress
else:
# For absolute values, validate range
if not 0 <= value <= 100:
error_msg = f"Progress value must be between 0 and 100, got {value}"
raise ValueError(error_msg)
if value < self._current_progress:
error_msg = (
f"Progress cannot decrease from "
f"{self._current_progress:.2f}% to {value:.2f}%"
)
raise ValueError(error_msg)
self._current_progress = value
final_value = value
formatted_message = f"[PROGRESS] {final_value:.2f}%"
self._logger.info(formatted_message)
# Create singleton instance
logger: Final[GyozaLogger] = GyozaLogger()