fix: correct SlackAlerting lazy mapping and keep eager encoding path importable

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
yassin 2026-09-01 15:43:15 +00:00
parent 973d3acdef
commit 40347d4874
3 changed files with 14 additions and 12 deletions

View file

@ -2151,16 +2151,6 @@ if TYPE_CHECKING:
# Track if async client cleanup has been registered (for lazy loading)
_async_client_cleanup_registered = False
# Eager loading for backwards compatibility with VCR and other HTTP recording tools
# When LITELLM_DISABLE_LAZY_LOADING is set, lazy-loaded attributes are loaded at import time
# For now, this only affects encoding (tiktoken) as it was the only reported issue
# See: https://github.com/BerriAI/litellm/issues/18659
# This ensures encoding is initialized before VCR starts recording HTTP requests
if os.getenv("LITELLM_DISABLE_LAZY_LOADING", "").lower() in ("1", "true", "yes", "on"):
# Load encoding at import time (pre-#18070 behavior)
# This ensures encoding is initialized before VCR starts recording
from .main import encoding
def __getattr__(name: str) -> Any:
"""Lazy import handler with cached registry for improved performance."""
@ -2377,3 +2367,12 @@ __all__ = list(STAR_IMPORT_PUBLIC_NAMES) # mutable-ok: star imports require __a
# ALL_LITELLM_RESPONSE_TYPES is lazy-loaded via __getattr__ to avoid loading utils at import time
# Eager loading for backwards compatibility with VCR and other HTTP recording tools
# When LITELLM_DISABLE_LAZY_LOADING is set, lazy-loaded attributes are loaded at import time
# For now, this only affects encoding (tiktoken) as it was the only reported issue
# See: https://github.com/BerriAI/litellm/issues/18659
# This ensures encoding is initialized before VCR starts recording HTTP requests
# This block stays at the bottom so __getattr__ can resolve attributes main.py needs during its import
if os.getenv("LITELLM_DISABLE_LAZY_LOADING", "").lower() in ("1", "true", "yes", "on"):
from .main import encoding

View file

@ -81,7 +81,10 @@ def _get_utils_globals() -> dict[str, object]:
This is where we cache imported attributes so we don't import them twice.
When you do `litellm.utils.some_function`, it gets stored in this dictionary.
"""
return sys.modules["litellm.utils"].__dict__
cached: Final = sys.modules.get("litellm.utils")
if cached is not None:
return cached.__dict__
return importlib.import_module("litellm.utils").__dict__
def _get_module_level_client_timeout(litellm_globals: Mapping[str, Any]) -> "float | httpx.Timeout | None":

View file

@ -2030,7 +2030,7 @@ _SDK_SYMBOLS_IMPORT_MAP: Final[Mapping[str, tuple[str, str]]] = MappingProxyType
"SerializerFunctionWrapHandler": ("litellm.assistants.main", "SerializerFunctionWrapHandler"),
"ServiceUnavailableError": ("litellm.exceptions", "ServiceUnavailableError"),
"ShellToolParam": ("litellm.types.llms.openai", "ShellToolParam"),
"SlackAlerting": ("litellm.integrations", "SlackAlerting"),
"SlackAlerting": ("litellm.integrations.SlackAlerting.slack_alerting", "SlackAlerting"),
"StandardLoggingRoutingDecision": ("litellm.types.utils", "StandardLoggingRoutingDecision"),
"StreamingChoices": ("litellm.types.utils", "StreamingChoices"),
"SyncCursorPage": ("litellm.assistants.main", "SyncCursorPage"),