From 54f757bde1e4b991d6d5fabdb4faca36c18790c0 Mon Sep 17 00:00:00 2001 From: apex-mochen <2756823972@qq.com> Date: Fri, 9 Oct 2026 13:28:15 +0000 Subject: [PATCH] fix(lint): make the rebased branch pass the delta-vs-base lint gates The rebase side failed CI at the first lint step, so the later gates had never run; running them locally surfaced three more. All four are mechanical: 1. ruff I001: the rebase resolution left the anthropic transformation import groups different from upstream's layout; restore upstream's own grouping (third-party block, then litellm). 2. ruff-strict B010: the usage change replaced one setattr with two, so the file counted one more B010 than the merge-base. 3. type-discipline LIT011 / basedpyright reportAttributeAccessIssue: writing `model_response.usage = ...` is an in-place store on a parameter; the two stores added 2 LIT011 and 2 attribute-access diagnostics over the merge-base ceilings. 4. basedpyright unknown-type rules: reading `completion_response.get("usage")` into a `Final` local added reportUnknownMemberType and reportUnknownVariableType. A Final name takes its inferred type, so an annotation cannot widen it away; the value has to stop flowing out of an unknown dict into a new local. Resolved as one shape rather than four patches: compute the value with a conditional expression and write it back through the single `setattr` upstream already used on that line, so the B010, LIT011, attribute-access and basedpyright rule counts all stay at their merge-base totals, with no suppression comment anywhere. No behavior change: a missing key and an explicit null both still mean "no usage reported" (asserted by test_transform_parsed_response_without_usage, both variants). Signed-off-by: apex-mochen <2756823972@qq.com> --- litellm/llms/anthropic/chat/transformation.py | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/litellm/llms/anthropic/chat/transformation.py b/litellm/llms/anthropic/chat/transformation.py index 21361946f37..82be738a782 100644 --- a/litellm/llms/anthropic/chat/transformation.py +++ b/litellm/llms/anthropic/chat/transformation.py @@ -6,6 +6,9 @@ from types import MappingProxyType from typing import TYPE_CHECKING, Any, ClassVar, Final, NoReturn, cast import httpx +from pydantic import BaseModel, ValidationError +from typing_extensions import ReadOnly, TypedDict + import litellm from litellm.constants import ( ANTHROPIC_MIN_THINKING_BUDGET_TOKENS, @@ -92,8 +95,6 @@ from litellm.utils import ( supports_reasoning, token_counter, ) -from pydantic import BaseModel, ValidationError -from typing_extensions import ReadOnly, TypedDict from ..common_utils import ( AnthropicError, @@ -2739,26 +2740,24 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig): map_finish_reason(completion_response["stop_reason"]), ) - usage_object: Final = completion_response.get("usage") - if usage_object is None: + usage: Final = ( + None + if "usage" not in completion_response or completion_response["usage"] is None + else self.calculate_usage( + usage_object=completion_response["usage"], + reasoning_content=reasoning_content, + completion_response=completion_response, + speed=speed, + ) + ) + if usage is None: # #44535: keep usage absent (None) instead of fabricating a 0/0 # usage object. Spend tracking and budgets must be able to tell # "no usage reported" apart from a genuine zero, otherwise a # response that omits usage would be recorded as free even though # the upstream consumed tokens. - setattr(model_response, "usage", None) _hidden_params["usage_missing"] = True - else: - setattr( - model_response, - "usage", - self.calculate_usage( - usage_object=usage_object, - reasoning_content=reasoning_content, - completion_response=completion_response, - speed=speed, - ), - ) + setattr(model_response, "usage", usage) model_response.created = int(time.time()) model_response.model = completion_response["model"]