Python: fix: use getattr for non-OpenAI provider response compatibility (#6270)

* fix: use getattr for non-OpenAI provider response compatibility

Fixes #6234
Fixes #6235

Use getattr with None fallback for system_fingerprint and output
attributes to prevent AttributeError when non-OpenAI providers
return response objects without these fields.

* fix: use typed variable for response output to satisfy pyright

Fixes #6235

Use getattr with None fallback for the output attribute, and assign
to a typed list variable before the match statement to help pyright
narrow the response item types correctly.

* fix: rename response_outputs to avoid name collision with case-block variable

Fixes #6235

Rename outputs to response_outputs on line 1974 to avoid mypy error
about conflicting variable names in the match statement's case blocks.
Also use list[Any] for explicit generic type annotation.

* fix: use cast(list[Any]) for response output to satisfy pyright

Fixes #6235

The getattr() call returns Unknown type which pyright cannot narrow
in the match statement. Use an explicit cast to list[Any].

* fix: use hasattr guard instead of getattr for response.output

Fixes #6235

Using hasattr(response, 'output') and then accessing response.output
directly gives pyright enough type information to verify the match
statement exhaustiveness. This avoids the cast(list[Any]) approach
which pyright still flagged as partially unknown.

* fix: use ternary operator for response_outputs assignment

Replace if-else block with ternary expression to satisfy ruff SIM108 lint rule.
This fixes the Package Checks (3.11) CI failure.

* fix: use ternary with cast for ruff SIM108 and pyright type safety

Replace if-else block with ternary expression using cast(list[Any], ...)
to satisfy:
- ruff SIM108 (use ternary instead of if-else)
- ruff E501 (line length < 120)
- pyright type narrowing (cast preserves type info lost in ternary)

All local checks pass: ruff check, ruff format, pyright, 298 tests.

* fix: replace hasattr+cast with try/except to preserve pyright types

---------

Co-authored-by: Tao Chen <taochen@microsoft.com>
This commit is contained in:
Willow Lopez
2026-06-09 23:17:39 +08:00
committed by GitHub
Unverified
parent 96d242fa7f
commit 29cec0d27b
2 changed files with 7 additions and 3 deletions
@@ -1997,7 +1997,11 @@ class RawOpenAIChatClient( # type: ignore[misc]
metadata: dict[str, Any] = response.metadata or {}
contents: list[Content] = []
local_shell_tool_name = self._get_local_shell_tool_name(options.get("tools"))
for item in response.output: # type: ignore[reportUnknownMemberType]
try:
response_outputs = response.output # type: ignore[reportUnknownMemberType]
except AttributeError:
response_outputs = []
for item in response_outputs: # type: ignore[reportUnknownVariableType]
match item.type:
# types:
# ParsedResponseOutputMessage[Unknown] |
@@ -788,13 +788,13 @@ class RawOpenAIChatCompletionClient( # type: ignore[misc]
def _get_metadata_from_chat_response(self, response: ChatCompletion) -> dict[str, Any]:
"""Get metadata from a chat response."""
return {
"system_fingerprint": response.system_fingerprint,
"system_fingerprint": getattr(response, "system_fingerprint", None),
}
def _get_metadata_from_streaming_chat_response(self, response: ChatCompletionChunk) -> dict[str, Any]:
"""Get metadata from a streaming chat response."""
return {
"system_fingerprint": response.system_fingerprint,
"system_fingerprint": getattr(response, "system_fingerprint", None),
}
def _get_metadata_from_chat_choice(self, choice: Choice | ChunkChoice) -> dict[str, Any]: