fix(mavvrik): lazy import Service in mavvrik_endpoints to avoid polars at startup

Importing 'from litellm.integrations.mavvrik import Service' at module level
caused the entire mavvrik package to load at proxy startup, which could
transitively import polars (optional [proxy] dep) for SDK-only users.

Fix: lazy import via _get_service() helper — Service (and the polars dep chain)
is only loaded when a Mavvrik endpoint is actually called, not at import time.

Note: cloudzero_endpoints.py and vantage_endpoints.py use the same
unconditional pattern; we've proactively fixed ours to be stricter.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Praveen Ghuge 2026-04-26 21:36:36 +05:30
parent 04dd7c345f
commit cff49b8a01

View file

@ -17,7 +17,6 @@ from typing import AsyncIterator
from fastapi import APIRouter, Depends, HTTPException
from litellm.integrations.mavvrik import Service
from litellm.proxy._types import CommonProxyErrors, LitellmUserRoles, UserAPIKeyAuth
from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
from litellm.types.proxy.mavvrik_endpoints import (
@ -33,6 +32,14 @@ from litellm.types.proxy.mavvrik_endpoints import (
router = APIRouter()
def _get_service():
"""Lazy import of Service — keeps polars (optional [proxy] dep) out of startup."""
from litellm.integrations.mavvrik import Service # noqa: PLC0415
return Service()
# ---------------------------------------------------------------------------
# Shared helpers
# ---------------------------------------------------------------------------
@ -88,7 +95,7 @@ async def init_mavvrik_settings(
"""Initialize Mavvrik settings and register the background export job."""
_require_admin(user_api_key_dict)
async with _mavvrik_errors():
result = await Service().initialize(
result = await _get_service().initialize(
api_key=request.api_key,
api_endpoint=request.api_endpoint,
connection_id=request.connection_id,
@ -113,7 +120,7 @@ async def get_mavvrik_settings(
"""View current Mavvrik settings. The API key is masked in the response."""
_require_admin(user_api_key_dict)
async with _mavvrik_errors():
result = await Service().get_settings()
result = await _get_service().get_settings()
return MavvrikSettingsView(**result)
@ -145,7 +152,7 @@ async def update_mavvrik_settings(
)
async with _mavvrik_errors():
result = await Service().update_settings(
result = await _get_service().update_settings(
api_key=request.api_key,
api_endpoint=request.api_endpoint,
connection_id=request.connection_id,
@ -170,7 +177,7 @@ async def delete_mavvrik_settings(
"""Remove all Mavvrik settings and deregister the background job."""
_require_admin(user_api_key_dict)
async with _mavvrik_errors():
result = await Service().delete()
result = await _get_service().delete()
return MavvrikDeleteResponse(**result)
@ -192,7 +199,7 @@ async def dry_run_mavvrik_export(
"""Preview the CSV records that would be uploaded for a given date without sending data."""
_require_admin(user_api_key_dict)
async with _mavvrik_errors():
result = await Service().dry_run(
result = await _get_service().dry_run(
date_str=request.date_str,
limit=request.limit,
)
@ -217,7 +224,7 @@ async def export_mavvrik_data(
"""Manually trigger a Mavvrik export for a specific date."""
_require_admin(user_api_key_dict)
async with _mavvrik_errors():
result = await Service().export(
result = await _get_service().export(
date_str=request.date_str,
limit=request.limit,
)