From 9ed3724789d14e3342a89fcd46f88ed5bd620aca Mon Sep 17 00:00:00 2001 From: Daniel Cherubini Date: Mon, 14 Sep 2026 18:48:24 +0200 Subject: [PATCH] fix: clear strict-rule gate breaches (C901 +1, RUF100 +1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit C901: the rewritten delta emitter crossed the 15-complexity ceiling. Extract the per-choice payload accumulation into Accumulate streaming chunk payloads (and drop a redundant isinstance+hasattr+truthy+len chain — both choice types share the same Delta, whose optional fields simply default to None), leaving a small delta-type selector in the original method. RUF100: the # noqa: PLR0915 on the sync stream method was stale: PLR0915 is not selected in either config (ruff tom, ruff strict toml), so the directive itself was the violation. Verified with the ruff strict gate comparison against the merge base: every strict rule back within its ceiling. --- .../adapters/streaming_iterator.py | 2 +- .../adapters/transformation.py | 54 +++++++++++-------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py b/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py index 04b9834ca1f..2efa9157575 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/streaming_iterator.py @@ -527,7 +527,7 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper): cache_read_input_tokens=0, ) - def __next__(self): # noqa: PLR0915 + def __next__(self): from .transformation import LiteLLMAnthropicMessagesAdapter try: diff --git a/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py b/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py index a170282c95e..546ae55ec29 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py @@ -1738,6 +1738,34 @@ class LiteLLMAnthropicMessagesAdapter: StreamingContentBlockDeltaType, ContentTextBlockDelta | ContentJsonBlockDelta | ContentThinkingBlockDelta | ContentThinkingSignatureBlockDelta, ]: + text, reasoning_content, reasoning_signature, partial_json = self._accumulate_streaming_chunk_payloads( + choices, thinking_disabled=thinking_disabled + ) + if partial_json is not None: + return "input_json_delta", ContentJsonBlockDelta(type="input_json_delta", partial_json=partial_json) + elif reasoning_signature: + return "signature_delta", ContentThinkingSignatureBlockDelta( + type="signature_delta", signature=reasoning_signature + ) + elif reasoning_content: + return "thinking_delta", ContentThinkingBlockDelta(type="thinking_delta", thinking=reasoning_content) + else: + refusal_text: Final = "".join( + refusal for choice in choices if (refusal := openai_chat_refusal_text(choice.delta)) is not None + ) + return "text_delta", ContentTextBlockDelta(type="text_delta", text=text + refusal_text) + + def _accumulate_streaming_chunk_payloads( + self, + choices: list[OpenAIStreamingChoice | StreamingChoices], + thinking_disabled: bool = False, + ) -> tuple[str, str, str, str | None]: + """Fold a chunk's choices into (text, reasoning_content, reasoning_signature, partial_json). + + ``partial_json`` is ``None`` when the chunk carries no tool calls — the + caller uses that to decide the delta type's precedence (tool JSON beats + thinking/thinking-signature text). + """ text: str = "" reasoning_content: str = "" reasoning_signature: str = "" @@ -1749,17 +1777,13 @@ class LiteLLMAnthropicMessagesAdapter: continue if block_type == "thinking": - if ( - isinstance(choice, StreamingChoices) - and hasattr(choice.delta, "thinking_blocks") - and choice.delta.thinking_blocks - and len(choice.delta.thinking_blocks) > 0 - ): - for thinking_block in choice.delta.thinking_blocks: + thinking_blocks = getattr(choice.delta, "thinking_blocks", None) + if isinstance(choice, StreamingChoices) and thinking_blocks: + for thinking_block in thinking_blocks: if thinking_block.get("type") in ("thinking", "redacted_thinking"): reasoning_content += str(thinking_block.get("thinking") or "") reasoning_signature += str(thinking_block.get("signature") or "") - elif isinstance(choice, StreamingChoices) and getattr(choice.delta, "reasoning_content", None): + elif getattr(choice.delta, "reasoning_content", None): reasoning_content += str(choice.delta.reasoning_content) elif block_type == "redacted_thinking": @@ -1778,19 +1802,7 @@ class LiteLLMAnthropicMessagesAdapter: if choice.delta.content is not None and len(choice.delta.content) > 0: text += choice.delta.content - if partial_json is not None: - return "input_json_delta", ContentJsonBlockDelta(type="input_json_delta", partial_json=partial_json) - elif reasoning_signature: - return "signature_delta", ContentThinkingSignatureBlockDelta( - type="signature_delta", signature=reasoning_signature - ) - elif reasoning_content: - return "thinking_delta", ContentThinkingBlockDelta(type="thinking_delta", thinking=reasoning_content) - else: - refusal_text: Final = "".join( - refusal for choice in choices if (refusal := openai_chat_refusal_text(choice.delta)) is not None - ) - return "text_delta", ContentTextBlockDelta(type="text_delta", text=text + refusal_text) + return text, reasoning_content, reasoning_signature, partial_json def translate_streaming_openai_response_to_anthropic( self,