# app/common/debug.py from __future__ import annotations import os import builtins as _bi from functools import lru_cache from typing import Callable # Chaves que aceitamos para ligar o debug (use APP_DEBUG como padrão) _DEBUG_ENV_KEYS = ("APP_DEBUG", "DEBUG", "NOVO_INQUILINO_DEBUG") _TRUE = {"1", "true", "yes", "on", "debug"} @lru_cache(maxsize=1) def debug_enabled() -> bool: """ Lê as variáveis de ambiente uma única vez (cache). Prioridade: APP_DEBUG > DEBUG > NOVO_INQUILINO_DEBUG. """ for key in _DEBUG_ENV_KEYS: val = os.getenv(key) if val is not None: return val.lower() in _TRUE return False def make_dbg(prefix: str) -> Callable[..., None]: """ Retorna uma função _dbg(msg, *args, **kwargs) que: - formata msg somente quando debug está ON - prefixa com [][DEBUG] - é NO-OP quando debug está OFF Uso: _dbg = make_dbg("MeuModulo") """ if debug_enabled(): def _dbg(msg: str = "", *args, **kwargs) -> None: if args or kwargs: try: msg = msg.format(*args, **kwargs) except Exception: # Não quebra log por erro de formatação pass _bi.print(f"[{prefix}][DEBUG] {msg}") return _dbg else: def _dbg(*args, **kwargs) -> None: return None return _dbg def make_dbg_lazy(prefix: str) -> Callable[[Callable[[], object]], None]: """ Versão “preguiçosa”: recebe um callable que só é executado quando o debug está ON. Uso: _dbg_lazy(lambda: f"payload grande: {json.dumps(obj)}") """ if debug_enabled(): def _dbg_lazy(builder) -> None: try: _bi.print(f"[{prefix}][DEBUG] {builder()}") except Exception as e: _bi.print(f"[{prefix}][DEBUG] [lazy-error] {e}") return _dbg_lazy else: def _dbg_lazy(*args, **kwargs) -> None: return None return _dbg_lazy