v0.156.1
 1from __future__ import annotations
 2
 3import logging
 4import threading
 5from typing import TYPE_CHECKING
 6
 7if TYPE_CHECKING:
 8    from types import TracebackType
 9
10
11class DebugMode:
12    """Context manager to temporarily set DEBUG level on a logger with reference counting."""
13
14    def __init__(self, logger: logging.Logger):
15        self.logger = logger
16        self.original_level = None
17        self._ref_count = 0
18        self._lock = threading.Lock()
19
20    def __enter__(self) -> DebugMode:
21        """Store original level and set to DEBUG."""
22        self.start()
23        return self
24
25    def __exit__(
26        self,
27        exc_type: type[BaseException] | None,
28        exc_val: BaseException | None,
29        exc_tb: TracebackType | None,
30    ) -> None:
31        """Restore original level."""
32        self.end()
33
34    def start(self) -> None:
35        """Enable DEBUG logging level."""
36        with self._lock:
37            if self._ref_count == 0:
38                self.original_level = self.logger.level
39                self.logger.setLevel(logging.DEBUG)
40            self._ref_count += 1
41
42    def end(self) -> None:
43        """Restore original logging level."""
44        with self._lock:
45            self._ref_count = max(0, self._ref_count - 1)
46            if self._ref_count == 0 and self.original_level is not None:
47                self.logger.setLevel(self.original_level)