From e30870c2625cbd5ed549e65839e06295048ff2aa Mon Sep 17 00:00:00 2001 From: Yucheng Zhu Date: Sat, 11 Jul 2026 10:24:17 -0700 Subject: [PATCH] refactor: extract _resolve_logged_guardrail_mode to satisfy C901 strict budget --- litellm/integrations/custom_guardrail.py | 48 ++++++++++++++---------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/litellm/integrations/custom_guardrail.py b/litellm/integrations/custom_guardrail.py index e10679ae2f8..cf75fb38b75 100644 --- a/litellm/integrations/custom_guardrail.py +++ b/litellm/integrations/custom_guardrail.py @@ -41,6 +41,7 @@ except ImportError: if TYPE_CHECKING: from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj + from litellm.types.utils import GuardrailMode dc = DualCache() @@ -700,6 +701,33 @@ class CustomGuardrail(CustomLogger): return False return True + def _resolve_logged_guardrail_mode( + self, + event_type: Optional[GuardrailEventHooks], + ) -> Union[GuardrailEventHooks, "GuardrailMode", str]: + """ + Resolve the value logged as `guardrail_mode`. + + Use the resolved event_type (the concrete hook that actually fired + for *this* invocation) when available. Fall back to self.event_hook + only as a last resort — and normalise its various shapes so + downstream loggers always receive a JSON-serialisable scalar or + dict, never a raw List[str] that looks like a broken value. + """ + from litellm.types.utils import GuardrailMode + + if event_type is not None: + return event_type + if isinstance(self.event_hook, Mode): + return GuardrailMode(**dict(self.event_hook.model_dump())) # type: ignore[typeddict-item] + if isinstance(self.event_hook, list): + # Config lists like ["pre_call", "post_call"] are the *configured* + # modes, not the one that fired. Join into a comma-separated + # string so the logged value is unambiguously "raw config" rather + # than something that looks like a single resolved hook. + return ",".join(str(h) for h in self.event_hook) + return self.event_hook # type: ignore[return-value] + def add_standard_logging_guardrail_information_to_request_data( self, guardrail_json_response: Union[Exception, str, dict, List[dict]], @@ -723,26 +751,8 @@ class CustomGuardrail(CustomLogger): """ if isinstance(guardrail_json_response, Exception): guardrail_json_response = str(guardrail_json_response) - from litellm.types.utils import GuardrailMode - # Use the resolved event_type (the concrete hook that actually fired - # for *this* invocation) when available. Fall back to self.event_hook - # only as a last resort — and normalise its various shapes so - # downstream loggers always receive a JSON-serialisable scalar or - # dict, never a raw List[str] that looks like a broken value. - guardrail_mode: Union[GuardrailEventHooks, GuardrailMode, List[GuardrailEventHooks], str] - if event_type is not None: - guardrail_mode = event_type - elif isinstance(self.event_hook, Mode): - guardrail_mode = GuardrailMode(**dict(self.event_hook.model_dump())) # type: ignore[typeddict-item] - elif isinstance(self.event_hook, list): - # Config lists like ["pre_call", "post_call"] are the *configured* - # modes, not the one that fired. Join into a comma-separated - # string so the logged value is unambiguously "raw config" rather - # than something that looks like a single resolved hook. - guardrail_mode = ",".join(str(h) for h in self.event_hook) # type: ignore[assignment] - else: - guardrail_mode = self.event_hook # type: ignore[assignment] + guardrail_mode = self._resolve_logged_guardrail_mode(event_type) from litellm.litellm_core_utils.core_helpers import ( filter_exceptions_from_params,