diff --git a/python/packages/ag-ui/agent_framework_ag_ui/_client.py b/python/packages/ag-ui/agent_framework_ag_ui/_client.py index d04550f9c9..c30e4e5926 100644 --- a/python/packages/ag-ui/agent_framework_ag_ui/_client.py +++ b/python/packages/ag-ui/agent_framework_ag_ui/_client.py @@ -59,17 +59,17 @@ def _unwrap_server_function_call_contents(contents: MutableSequence[Content | di contents[idx] = content.function_call # type: ignore[assignment, union-attr] -TBaseChatClient = TypeVar("TBaseChatClient", bound=type[BaseChatClient[Any]]) +BaseChatClientT = TypeVar("BaseChatClientT", bound=type[BaseChatClient[Any]]) -TAGUIChatOptions = TypeVar( - "TAGUIChatOptions", +AGUIChatOptionsT = TypeVar( + "AGUIChatOptionsT", bound=TypedDict, # type: ignore[valid-type] default="AGUIChatOptions", covariant=True, ) -def _apply_server_function_call_unwrap(chat_client: TBaseChatClient) -> TBaseChatClient: +def _apply_server_function_call_unwrap(chat_client: BaseChatClientT) -> BaseChatClientT: """Class decorator that unwraps server-side function calls after tool handling.""" original_get_response = chat_client.get_response @@ -111,11 +111,11 @@ def _map_update(update: ChatResponseUpdate) -> ChatResponseUpdate: @_apply_server_function_call_unwrap class AGUIChatClient( - ChatMiddlewareLayer[TAGUIChatOptions], - FunctionInvocationLayer[TAGUIChatOptions], - ChatTelemetryLayer[TAGUIChatOptions], - BaseChatClient[TAGUIChatOptions], - Generic[TAGUIChatOptions], + ChatMiddlewareLayer[AGUIChatOptionsT], + FunctionInvocationLayer[AGUIChatOptionsT], + ChatTelemetryLayer[AGUIChatOptionsT], + BaseChatClient[AGUIChatOptionsT], + Generic[AGUIChatOptionsT], ): """Chat client for communicating with AG-UI compliant servers. diff --git a/python/packages/ag-ui/agent_framework_ag_ui/_types.py b/python/packages/ag-ui/agent_framework_ag_ui/_types.py index 928a755b31..383bf78b5a 100644 --- a/python/packages/ag-ui/agent_framework_ag_ui/_types.py +++ b/python/packages/ag-ui/agent_framework_ag_ui/_types.py @@ -18,8 +18,8 @@ from typing_extensions import TypedDict # type: ignore # pragma: no cover -TAGUIChatOptions = TypeVar("TAGUIChatOptions", bound=TypedDict, default="AGUIChatOptions", covariant=True) # type: ignore[valid-type] -TResponseModel = TypeVar("TResponseModel", bound=BaseModel | None, default=None) +AGUIChatOptionsT = TypeVar("AGUIChatOptionsT", bound=TypedDict, default="AGUIChatOptions", covariant=True) # type: ignore[valid-type] +ResponseModelT = TypeVar("ResponseModelT", bound=BaseModel | None, default=None) class PredictStateConfig(TypedDict): @@ -84,7 +84,7 @@ class AGUIRequest(BaseModel): # region AG-UI Chat Options TypedDict -class AGUIChatOptions(ChatOptions[TResponseModel], Generic[TResponseModel], total=False): +class AGUIChatOptions(ChatOptions[ResponseModelT], Generic[ResponseModelT], total=False): """AG-UI protocol-specific chat options dict. Extends base ChatOptions for the AG-UI (Agent-UI) protocol. diff --git a/python/packages/ag-ui/agent_framework_ag_ui_examples/agents/ui_generator_agent.py b/python/packages/ag-ui/agent_framework_ag_ui_examples/agents/ui_generator_agent.py index 33848c379c..3f50fc9c07 100644 --- a/python/packages/ag-ui/agent_framework_ag_ui_examples/agents/ui_generator_agent.py +++ b/python/packages/ag-ui/agent_framework_ag_ui_examples/agents/ui_generator_agent.py @@ -165,10 +165,10 @@ For other requests, use the appropriate tool (create_chart, display_timeline, show_comparison_table). """ -TOptions = TypeVar("TOptions", bound=TypedDict, default="ChatOptions") # type: ignore[valid-type] +OptionsT = TypeVar("OptionsT", bound=TypedDict, default="ChatOptions") # type: ignore[valid-type] -def ui_generator_agent(chat_client: ChatClientProtocol[TOptions]) -> AgentFrameworkAgent: +def ui_generator_agent(chat_client: ChatClientProtocol[OptionsT]) -> AgentFrameworkAgent: """Create a UI generator agent with custom React component rendering. Args: diff --git a/python/packages/ag-ui/tests/ag_ui/conftest.py b/python/packages/ag-ui/tests/ag_ui/conftest.py index 176f4c031d..4612750f5f 100644 --- a/python/packages/ag-ui/tests/ag_ui/conftest.py +++ b/python/packages/ag-ui/tests/ag_ui/conftest.py @@ -21,7 +21,7 @@ Content, SupportsAgentRun, ) -from agent_framework._clients import TOptions_co +from agent_framework._clients import OptionsCoT from agent_framework._middleware import ChatMiddlewareLayer from agent_framework._tools import FunctionInvocationLayer from agent_framework._types import ResponseStream @@ -37,11 +37,11 @@ class StreamingChatClientStub( - ChatMiddlewareLayer[TOptions_co], - FunctionInvocationLayer[TOptions_co], - ChatTelemetryLayer[TOptions_co], - BaseChatClient[TOptions_co], - Generic[TOptions_co], + ChatMiddlewareLayer[OptionsCoT], + FunctionInvocationLayer[OptionsCoT], + ChatTelemetryLayer[OptionsCoT], + BaseChatClient[OptionsCoT], + Generic[OptionsCoT], ): """Typed streaming stub that satisfies ChatClientProtocol.""" @@ -68,7 +68,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[False] = ..., - options: TOptions_co | ChatOptions[None] | None = ..., + options: OptionsCoT | ChatOptions[None] | None = ..., **kwargs: Any, ) -> Awaitable[ChatResponse[Any]]: ... @@ -78,7 +78,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[True], - options: TOptions_co | ChatOptions[Any] | None = ..., + options: OptionsCoT | ChatOptions[Any] | None = ..., **kwargs: Any, ) -> ResponseStream[ChatResponseUpdate, ChatResponse[Any]]: ... @@ -87,7 +87,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: bool = False, - options: TOptions_co | ChatOptions[Any] | None = None, + options: OptionsCoT | ChatOptions[Any] | None = None, **kwargs: Any, ) -> Awaitable[ChatResponse[Any]] | ResponseStream[ChatResponseUpdate, ChatResponse[Any]]: self.last_thread = kwargs.get("thread") diff --git a/python/packages/anthropic/agent_framework_anthropic/_chat_client.py b/python/packages/anthropic/agent_framework_anthropic/_chat_client.py index 641eb52444..1a000ebd69 100644 --- a/python/packages/anthropic/agent_framework_anthropic/_chat_client.py +++ b/python/packages/anthropic/agent_framework_anthropic/_chat_client.py @@ -78,7 +78,7 @@ BETA_FLAGS: Final[list[str]] = ["mcp-client-2025-04-04", "code-execution-2025-08-25"] STRUCTURED_OUTPUTS_BETA_FLAG: Final[str] = "structured-outputs-2025-11-13" -TResponseModel = TypeVar("TResponseModel", bound=BaseModel | None, default=None) +ResponseModelT = TypeVar("ResponseModelT", bound=BaseModel | None, default=None) # region Anthropic Chat Options TypedDict @@ -102,7 +102,7 @@ class ThinkingConfig(TypedDict, total=False): budget_tokens: int -class AnthropicChatOptions(ChatOptions[TResponseModel], Generic[TResponseModel], total=False): +class AnthropicChatOptions(ChatOptions[ResponseModelT], Generic[ResponseModelT], total=False): """Anthropic-specific chat options. Extends ChatOptions with options specific to Anthropic's Messages API. @@ -160,8 +160,8 @@ class AnthropicChatOptions(ChatOptions[TResponseModel], Generic[TResponseModel], conversation_id: None # type: ignore[misc] -TAnthropicOptions = TypeVar( - "TAnthropicOptions", +AnthropicOptionsT = TypeVar( + "AnthropicOptionsT", bound=TypedDict, # type: ignore[valid-type] default="AnthropicChatOptions", covariant=True, @@ -232,11 +232,11 @@ class AnthropicSettings(AFBaseSettings): class AnthropicClient( - ChatMiddlewareLayer[TAnthropicOptions], - FunctionInvocationLayer[TAnthropicOptions], - ChatTelemetryLayer[TAnthropicOptions], - BaseChatClient[TAnthropicOptions], - Generic[TAnthropicOptions], + ChatMiddlewareLayer[AnthropicOptionsT], + FunctionInvocationLayer[AnthropicOptionsT], + ChatTelemetryLayer[AnthropicOptionsT], + BaseChatClient[AnthropicOptionsT], + Generic[AnthropicOptionsT], ): """Anthropic Chat client with middleware, telemetry, and function invocation support.""" diff --git a/python/packages/azure-ai/agent_framework_azure_ai/_agent_provider.py b/python/packages/azure-ai/agent_framework_azure_ai/_agent_provider.py index afeb85ec86..dcc0e9db29 100644 --- a/python/packages/azure-ai/agent_framework_azure_ai/_agent_provider.py +++ b/python/packages/azure-ai/agent_framework_azure_ai/_agent_provider.py @@ -38,17 +38,17 @@ from typing_extensions import TypedDict # type: ignore # pragma: no cover -# Type variable for options - allows typed ChatAgent[TOptions] returns +# Type variable for options - allows typed ChatAgent[OptionsCoT] returns # Default matches AzureAIAgentClient's default options type -TOptions_co = TypeVar( - "TOptions_co", +OptionsCoT = TypeVar( + "OptionsCoT", bound=TypedDict, # type: ignore[valid-type] default="AzureAIAgentOptions", covariant=True, ) -class AzureAIAgentsProvider(Generic[TOptions_co]): +class AzureAIAgentsProvider(Generic[OptionsCoT]): """Provider for Azure AI Agent Service V1 (Persistent Agents API). This provider enables creating, retrieving, and wrapping Azure AI agents as ChatAgent @@ -176,10 +176,10 @@ async def create_agent( | MutableMapping[str, Any] | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, middleware: Sequence[MiddlewareTypes] | None = None, context_provider: ContextProvider | None = None, - ) -> ChatAgent[TOptions_co]: + ) -> ChatAgent[OptionsCoT]: """Create a new agent on the Azure AI service and return a ChatAgent. This method creates a persistent agent on the Azure AI service with the specified @@ -273,10 +273,10 @@ async def get_agent( | MutableMapping[str, Any] | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, middleware: Sequence[MiddlewareTypes] | None = None, context_provider: ContextProvider | None = None, - ) -> ChatAgent[TOptions_co]: + ) -> ChatAgent[OptionsCoT]: """Retrieve an existing agent from the service and return a ChatAgent. This method fetches an agent by ID from the Azure AI service @@ -329,10 +329,10 @@ def as_agent( | MutableMapping[str, Any] | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, middleware: Sequence[MiddlewareTypes] | None = None, context_provider: ContextProvider | None = None, - ) -> ChatAgent[TOptions_co]: + ) -> ChatAgent[OptionsCoT]: """Wrap an existing Agent SDK object as a ChatAgent without making HTTP calls. Use this method when you already have an Agent object from a previous @@ -382,10 +382,10 @@ def _to_chat_agent_from_agent( self, agent: Agent, provided_tools: Sequence[ToolProtocol | MutableMapping[str, Any]] | None = None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, middleware: Sequence[MiddlewareTypes] | None = None, context_provider: ContextProvider | None = None, - ) -> ChatAgent[TOptions_co]: + ) -> ChatAgent[OptionsCoT]: """Create a ChatAgent from an Agent SDK object. Args: diff --git a/python/packages/azure-ai/agent_framework_azure_ai/_chat_client.py b/python/packages/azure-ai/agent_framework_azure_ai/_chat_client.py index dc013e30d7..504f615a0a 100644 --- a/python/packages/azure-ai/agent_framework_azure_ai/_chat_client.py +++ b/python/packages/azure-ai/agent_framework_azure_ai/_chat_client.py @@ -193,8 +193,8 @@ class AzureAIAgentOptions(ChatOptions, total=False): } """Maps ChatOptions keys to Azure AI Agents API parameter names.""" -TAzureAIAgentOptions = TypeVar( - "TAzureAIAgentOptions", +AzureAIAgentOptionsT = TypeVar( + "AzureAIAgentOptionsT", bound=TypedDict, # type: ignore[valid-type] default="AzureAIAgentOptions", covariant=True, @@ -205,11 +205,11 @@ class AzureAIAgentOptions(ChatOptions, total=False): class AzureAIAgentClient( - ChatMiddlewareLayer[TAzureAIAgentOptions], - FunctionInvocationLayer[TAzureAIAgentOptions], - ChatTelemetryLayer[TAzureAIAgentOptions], - BaseChatClient[TAzureAIAgentOptions], - Generic[TAzureAIAgentOptions], + ChatMiddlewareLayer[AzureAIAgentOptionsT], + FunctionInvocationLayer[AzureAIAgentOptionsT], + ChatTelemetryLayer[AzureAIAgentOptionsT], + BaseChatClient[AzureAIAgentOptionsT], + Generic[AzureAIAgentOptionsT], ): """Azure AI Agent Chat client with middleware, telemetry, and function invocation support.""" @@ -1296,12 +1296,12 @@ def as_agent( | MutableMapping[str, Any] | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - default_options: TAzureAIAgentOptions | Mapping[str, Any] | None = None, + default_options: AzureAIAgentOptionsT | Mapping[str, Any] | None = None, chat_message_store_factory: Callable[[], ChatMessageStoreProtocol] | None = None, context_provider: ContextProvider | None = None, middleware: Sequence[MiddlewareTypes] | None = None, **kwargs: Any, - ) -> ChatAgent[TAzureAIAgentOptions]: + ) -> ChatAgent[AzureAIAgentOptionsT]: """Convert this chat client to a ChatAgent. This method creates a ChatAgent instance with this client pre-configured. diff --git a/python/packages/azure-ai/agent_framework_azure_ai/_client.py b/python/packages/azure-ai/agent_framework_azure_ai/_client.py index 2dd3e8cc8b..8d262b9b13 100644 --- a/python/packages/azure-ai/agent_framework_azure_ai/_client.py +++ b/python/packages/azure-ai/agent_framework_azure_ai/_client.py @@ -60,15 +60,15 @@ class AzureAIProjectAgentOptions(OpenAIResponsesOptions, total=False): """Configuration for enabling reasoning capabilities (requires azure.ai.projects.models.Reasoning).""" -TAzureAIClientOptions = TypeVar( - "TAzureAIClientOptions", +AzureAIClientOptionsT = TypeVar( + "AzureAIClientOptionsT", bound=TypedDict, # type: ignore[valid-type] default="AzureAIProjectAgentOptions", covariant=True, ) -class RawAzureAIClient(RawOpenAIResponsesClient[TAzureAIClientOptions], Generic[TAzureAIClientOptions]): +class RawAzureAIClient(RawOpenAIResponsesClient[AzureAIClientOptionsT], Generic[AzureAIClientOptionsT]): """Raw Azure AI client without middleware, telemetry, or function invocation layers. Warning: @@ -570,12 +570,12 @@ def as_agent( | MutableMapping[str, Any] | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - default_options: TAzureAIClientOptions | Mapping[str, Any] | None = None, + default_options: AzureAIClientOptionsT | Mapping[str, Any] | None = None, chat_message_store_factory: Callable[[], ChatMessageStoreProtocol] | None = None, context_provider: ContextProvider | None = None, middleware: Sequence[MiddlewareTypes] | None = None, **kwargs: Any, - ) -> ChatAgent[TAzureAIClientOptions]: + ) -> ChatAgent[AzureAIClientOptionsT]: """Convert this chat client to a ChatAgent. This method creates a ChatAgent instance with this client pre-configured. @@ -615,11 +615,11 @@ def as_agent( class AzureAIClient( - ChatMiddlewareLayer[TAzureAIClientOptions], - FunctionInvocationLayer[TAzureAIClientOptions], - ChatTelemetryLayer[TAzureAIClientOptions], - RawAzureAIClient[TAzureAIClientOptions], - Generic[TAzureAIClientOptions], + ChatMiddlewareLayer[AzureAIClientOptionsT], + FunctionInvocationLayer[AzureAIClientOptionsT], + ChatTelemetryLayer[AzureAIClientOptionsT], + RawAzureAIClient[AzureAIClientOptionsT], + Generic[AzureAIClientOptionsT], ): """Azure AI client with middleware, telemetry, and function invocation support. diff --git a/python/packages/azure-ai/agent_framework_azure_ai/_project_provider.py b/python/packages/azure-ai/agent_framework_azure_ai/_project_provider.py index 9c20e08b6c..e486a14560 100644 --- a/python/packages/azure-ai/agent_framework_azure_ai/_project_provider.py +++ b/python/packages/azure-ai/agent_framework_azure_ai/_project_provider.py @@ -47,17 +47,17 @@ logger = get_logger("agent_framework.azure") -# Type variable for options - allows typed ChatAgent[TOptions] returns +# Type variable for options - allows typed ChatAgent[OptionsT] returns # Default matches AzureAIClient's default options type -TOptions_co = TypeVar( - "TOptions_co", +OptionsCoT = TypeVar( + "OptionsCoT", bound=TypedDict, # type: ignore[valid-type] default="AzureAIProjectAgentOptions", covariant=True, ) -class AzureAIProjectAgentProvider(Generic[TOptions_co]): +class AzureAIProjectAgentProvider(Generic[OptionsCoT]): """Provider for Azure AI Agent Service (Responses API). This provider allows you to create, retrieve, and manage Azure AI agents @@ -167,10 +167,10 @@ async def create_agent( | MutableMapping[str, Any] | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, middleware: Sequence[MiddlewareTypes] | None = None, context_provider: ContextProvider | None = None, - ) -> ChatAgent[TOptions_co]: + ) -> ChatAgent[OptionsCoT]: """Create a new agent on the Azure AI service and return a local ChatAgent wrapper. Args: @@ -269,10 +269,10 @@ async def get_agent( | MutableMapping[str, Any] | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, middleware: Sequence[MiddlewareTypes] | None = None, context_provider: ContextProvider | None = None, - ) -> ChatAgent[TOptions_co]: + ) -> ChatAgent[OptionsCoT]: """Retrieve an existing agent from the Azure AI service and return a local ChatAgent wrapper. You must provide either name or reference. Use `as_agent()` if you already have @@ -329,10 +329,10 @@ def as_agent( | MutableMapping[str, Any] | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, middleware: Sequence[MiddlewareTypes] | None = None, context_provider: ContextProvider | None = None, - ) -> ChatAgent[TOptions_co]: + ) -> ChatAgent[OptionsCoT]: """Wrap an SDK agent version object into a ChatAgent without making HTTP calls. Use this when you already have an AgentVersionDetails from a previous API call. @@ -369,10 +369,10 @@ def _to_chat_agent_from_details( self, details: AgentVersionDetails, provided_tools: Sequence[ToolProtocol | MutableMapping[str, Any]] | None = None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, middleware: Sequence[MiddlewareTypes] | None = None, context_provider: ContextProvider | None = None, - ) -> ChatAgent[TOptions_co]: + ) -> ChatAgent[OptionsCoT]: """Create a ChatAgent from an AgentVersionDetails. Args: diff --git a/python/packages/azurefunctions/tests/test_app.py b/python/packages/azurefunctions/tests/test_app.py index f8b414fc34..5a454e6217 100644 --- a/python/packages/azurefunctions/tests/test_app.py +++ b/python/packages/azurefunctions/tests/test_app.py @@ -27,10 +27,10 @@ from agent_framework_azurefunctions import AgentFunctionApp from agent_framework_azurefunctions._entities import create_agent_entity -TFunc = TypeVar("TFunc", bound=Callable[..., Any]) +FuncT = TypeVar("FuncT", bound=Callable[..., Any]) -def _identity_decorator(func: TFunc) -> TFunc: +def _identity_decorator(func: FuncT) -> FuncT: return func @@ -165,8 +165,8 @@ def test_setup_creates_http_trigger(self) -> None: mock_agent = Mock() mock_agent.name = "TestAgent" - def passthrough_decorator(*args: Any, **kwargs: Any) -> Callable[[TFunc], TFunc]: - def decorator(func: TFunc) -> TFunc: + def passthrough_decorator(*args: Any, **kwargs: Any) -> Callable[[FuncT], FuncT]: + def decorator(func: FuncT) -> FuncT: return func return decorator @@ -190,15 +190,15 @@ def test_http_function_name_uses_prefix_format(self) -> None: def capture_function_name( self: AgentFunctionApp, name: str, *args: Any, **kwargs: Any - ) -> Callable[[TFunc], TFunc]: - def decorator(func: TFunc) -> TFunc: + ) -> Callable[[FuncT], FuncT]: + def decorator(func: FuncT) -> FuncT: captured_names.append(name) return func return decorator - def passthrough_decorator(*args: Any, **kwargs: Any) -> Callable[[TFunc], TFunc]: - def decorator(func: TFunc) -> TFunc: + def passthrough_decorator(*args: Any, **kwargs: Any) -> Callable[[FuncT], FuncT]: + def decorator(func: FuncT) -> FuncT: return func return decorator @@ -220,16 +220,16 @@ def test_setup_skips_http_trigger_when_disabled(self) -> None: captured_routes: list[str | None] = [] - def capture_route(*args: Any, **kwargs: Any) -> Callable[[TFunc], TFunc]: - def decorator(func: TFunc) -> TFunc: + def capture_route(*args: Any, **kwargs: Any) -> Callable[[FuncT], FuncT]: + def decorator(func: FuncT) -> FuncT: route_key = kwargs.get("route") if kwargs else None captured_routes.append(route_key) return func return decorator - def passthrough_decorator(*args: Any, **kwargs: Any) -> Callable[[TFunc], TFunc]: - def decorator(func: TFunc) -> TFunc: + def passthrough_decorator(*args: Any, **kwargs: Any) -> Callable[[FuncT], FuncT]: + def decorator(func: FuncT) -> FuncT: return func return decorator @@ -738,14 +738,14 @@ class TestHttpRunRoute: def _get_run_handler(agent: Mock) -> Callable[[func.HttpRequest, Any], Awaitable[func.HttpResponse]]: captured_handlers: dict[str | None, Callable[..., Awaitable[func.HttpResponse]]] = {} - def capture_decorator(*args: Any, **kwargs: Any) -> Callable[[TFunc], TFunc]: - def decorator(func: TFunc) -> TFunc: + def capture_decorator(*args: Any, **kwargs: Any) -> Callable[[FuncT], FuncT]: + def decorator(func: FuncT) -> FuncT: return func return decorator - def capture_route(*args: Any, **kwargs: Any) -> Callable[[TFunc], TFunc]: - def decorator(func: TFunc) -> TFunc: + def capture_route(*args: Any, **kwargs: Any) -> Callable[[FuncT], FuncT]: + def decorator(func: FuncT) -> FuncT: route_key = kwargs.get("route") if kwargs else None captured_handlers[route_key] = func return func @@ -1144,8 +1144,8 @@ def test_health_check_includes_mcp_tool_enabled(self) -> None: # Capture the health check handler function captured_handler: Callable[[func.HttpRequest], func.HttpResponse] | None = None - def capture_decorator(*args: Any, **kwargs: Any) -> Callable[[TFunc], TFunc]: - def decorator(func: TFunc) -> TFunc: + def capture_decorator(*args: Any, **kwargs: Any) -> Callable[[FuncT], FuncT]: + def decorator(func: FuncT) -> FuncT: nonlocal captured_handler captured_handler = func return func diff --git a/python/packages/azurefunctions/tests/test_entities.py b/python/packages/azurefunctions/tests/test_entities.py index 2294101164..eb740daddb 100644 --- a/python/packages/azurefunctions/tests/test_entities.py +++ b/python/packages/azurefunctions/tests/test_entities.py @@ -14,7 +14,7 @@ from agent_framework_azurefunctions._entities import create_agent_entity -TFunc = TypeVar("TFunc", bound=Callable[..., Any]) +FuncT = TypeVar("FuncT", bound=Callable[..., Any]) def _agent_response(text: str | None) -> AgentResponse: diff --git a/python/packages/bedrock/agent_framework_bedrock/_chat_client.py b/python/packages/bedrock/agent_framework_bedrock/_chat_client.py index ca851269dc..1a6bf01d59 100644 --- a/python/packages/bedrock/agent_framework_bedrock/_chat_client.py +++ b/python/packages/bedrock/agent_framework_bedrock/_chat_client.py @@ -62,7 +62,7 @@ "BedrockSettings", ] -TResponseModel = TypeVar("TResponseModel", bound=BaseModel | None, default=None) +ResponseModelT = TypeVar("ResponseModelT", bound=BaseModel | None, default=None) # region Bedrock Chat Options TypedDict @@ -91,7 +91,7 @@ class BedrockGuardrailConfig(TypedDict, total=False): """How to process guardrails during streaming (sync blocks, async does not).""" -class BedrockChatOptions(ChatOptions[TResponseModel], Generic[TResponseModel], total=False): +class BedrockChatOptions(ChatOptions[ResponseModelT], Generic[ResponseModelT], total=False): """Amazon Bedrock Converse API-specific chat options dict. Extends base ChatOptions with Bedrock-specific parameters. @@ -183,7 +183,7 @@ class BedrockChatOptions(ChatOptions[TResponseModel], Generic[TResponseModel], t } """Maps ChatOptions keys to Bedrock Converse API parameter names.""" -TBedrockChatOptions = TypeVar("TBedrockChatOptions", bound=TypedDict, default="BedrockChatOptions", covariant=True) # type: ignore[valid-type] +BedrockChatOptionsT = TypeVar("BedrockChatOptionsT", bound=TypedDict, default="BedrockChatOptions", covariant=True) # type: ignore[valid-type] # endregion @@ -219,11 +219,11 @@ class BedrockSettings(AFBaseSettings): class BedrockChatClient( - ChatMiddlewareLayer[TBedrockChatOptions], - FunctionInvocationLayer[TBedrockChatOptions], - ChatTelemetryLayer[TBedrockChatOptions], - BaseChatClient[TBedrockChatOptions], - Generic[TBedrockChatOptions], + ChatMiddlewareLayer[BedrockChatOptionsT], + FunctionInvocationLayer[BedrockChatOptionsT], + ChatTelemetryLayer[BedrockChatOptionsT], + BaseChatClient[BedrockChatOptionsT], + Generic[BedrockChatOptionsT], ): """Async chat client for Amazon Bedrock's Converse API with middleware, telemetry, and function invocation.""" diff --git a/python/packages/claude/agent_framework_claude/_agent.py b/python/packages/claude/agent_framework_claude/_agent.py index 579c2187ef..f5a343d6b9 100644 --- a/python/packages/claude/agent_framework_claude/_agent.py +++ b/python/packages/claude/agent_framework_claude/_agent.py @@ -139,15 +139,15 @@ class ClaudeAgentOptions(TypedDict, total=False): """Beta features to enable.""" -TOptions = TypeVar( - "TOptions", +OptionsT = TypeVar( + "OptionsT", bound=TypedDict, # type: ignore[valid-type] default="ClaudeAgentOptions", covariant=True, ) -class ClaudeAgent(BaseAgent, Generic[TOptions]): +class ClaudeAgent(BaseAgent, Generic[OptionsT]): """Claude Agent using Claude Code CLI. Wraps the Claude Agent SDK to provide agentic capabilities including @@ -223,7 +223,7 @@ def __init__( | str | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any] | str] | None = None, - default_options: TOptions | MutableMapping[str, Any] | None = None, + default_options: OptionsT | MutableMapping[str, Any] | None = None, env_file_path: str | None = None, env_file_encoding: str | None = None, ) -> None: @@ -330,7 +330,7 @@ def _normalize_tools( normalized = normalize_tools(tool) self._custom_tools.extend(normalized) - async def __aenter__(self) -> ClaudeAgent[TOptions]: + async def __aenter__(self) -> ClaudeAgent[OptionsT]: """Start the agent when entering async context.""" await self.start() return self @@ -561,7 +561,7 @@ def run( *, stream: Literal[True], thread: AgentThread | None = None, - options: TOptions | MutableMapping[str, Any] | None = None, + options: OptionsT | MutableMapping[str, Any] | None = None, **kwargs: Any, ) -> AsyncIterable[AgentResponseUpdate]: ... @@ -572,7 +572,7 @@ async def run( *, stream: Literal[False] = ..., thread: AgentThread | None = None, - options: TOptions | MutableMapping[str, Any] | None = None, + options: OptionsT | MutableMapping[str, Any] | None = None, **kwargs: Any, ) -> AgentResponse[Any]: ... @@ -582,7 +582,7 @@ def run( *, stream: bool = False, thread: AgentThread | None = None, - options: TOptions | MutableMapping[str, Any] | None = None, + options: OptionsT | MutableMapping[str, Any] | None = None, **kwargs: Any, ) -> AsyncIterable[AgentResponseUpdate] | Awaitable[AgentResponse[Any]]: """Run the agent with the given messages. @@ -611,7 +611,7 @@ async def _run_non_streaming( messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None, *, thread: AgentThread | None = None, - options: TOptions | MutableMapping[str, Any] | None = None, + options: OptionsT | MutableMapping[str, Any] | None = None, **kwargs: Any, ) -> AgentResponse[Any]: """Internal non-streaming implementation.""" @@ -625,7 +625,7 @@ async def _run_streaming( messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None, *, thread: AgentThread | None = None, - options: TOptions | MutableMapping[str, Any] | None = None, + options: OptionsT | MutableMapping[str, Any] | None = None, **kwargs: Any, ) -> AsyncIterable[AgentResponseUpdate]: """Internal streaming implementation.""" diff --git a/python/packages/core/agent_framework/_agents.py b/python/packages/core/agent_framework/_agents.py index 8d87e65000..58cec8f0b0 100644 --- a/python/packages/core/agent_framework/_agents.py +++ b/python/packages/core/agent_framework/_agents.py @@ -70,15 +70,15 @@ from ._types import ChatOptions -TResponseModel = TypeVar("TResponseModel", bound=BaseModel | None, default=None, covariant=True) -TResponseModelT = TypeVar("TResponseModelT", bound=BaseModel) +ResponseModelT = TypeVar("ResponseModelT", bound=BaseModel | None, default=None, covariant=True) +ResponseModelBoundT = TypeVar("ResponseModelBoundT", bound=BaseModel) logger = get_logger("agent_framework") -TThreadType = TypeVar("TThreadType", bound="AgentThread") -TOptions_co = TypeVar( - "TOptions_co", +ThreadTypeT = TypeVar("ThreadTypeT", bound="AgentThread") +OptionsCoT = TypeVar( + "OptionsCoT", bound=TypedDict, # type: ignore[valid-type] default="ChatOptions[None]", covariant=True, @@ -530,7 +530,7 @@ async def agent_wrapper(**kwargs: Any) -> str: # region ChatAgent -class RawChatAgent(BaseAgent, Generic[TOptions_co]): # type: ignore[misc] +class RawChatAgent(BaseAgent, Generic[OptionsCoT]): # type: ignore[misc] """A Chat Client Agent without middleware or telemetry layers. This is the core chat agent implementation. For most use cases, @@ -613,7 +613,7 @@ def get_weather(location: str) -> str: def __init__( self, - chat_client: ChatClientProtocol[TOptions_co], + chat_client: ChatClientProtocol[OptionsCoT], instructions: str | None = None, *, id: str | None = None, @@ -624,7 +624,7 @@ def __init__( | MutableMapping[str, Any] | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, chat_message_store_factory: Callable[[], ChatMessageStoreProtocol] | None = None, context_provider: ContextProvider | None = None, **kwargs: Any, @@ -789,9 +789,9 @@ def run( | MutableMapping[str, Any] | list[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - options: ChatOptions[TResponseModelT], + options: ChatOptions[ResponseModelBoundT], **kwargs: Any, - ) -> Awaitable[AgentResponse[TResponseModelT]]: ... + ) -> Awaitable[AgentResponse[ResponseModelBoundT]]: ... @overload def run( @@ -805,7 +805,7 @@ def run( | MutableMapping[str, Any] | list[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - options: TOptions_co | ChatOptions[None] | None = None, + options: OptionsCoT | ChatOptions[None] | None = None, **kwargs: Any, ) -> Awaitable[AgentResponse[Any]]: ... @@ -821,7 +821,7 @@ def run( | MutableMapping[str, Any] | list[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - options: TOptions_co | ChatOptions[Any] | None = None, + options: OptionsCoT | ChatOptions[Any] | None = None, **kwargs: Any, ) -> ResponseStream[AgentResponseUpdate, AgentResponse[Any]]: ... @@ -836,7 +836,7 @@ def run( | MutableMapping[str, Any] | list[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - options: TOptions_co | ChatOptions[Any] | None = None, + options: OptionsCoT | ChatOptions[Any] | None = None, **kwargs: Any, ) -> Awaitable[AgentResponse[Any]] | ResponseStream[AgentResponseUpdate, AgentResponse[Any]]: """Run the agent with the given messages and options. @@ -1375,8 +1375,8 @@ def _get_agent_name(self) -> str: class ChatAgent( AgentTelemetryLayer, AgentMiddlewareLayer, - RawChatAgent[TOptions_co], - Generic[TOptions_co], + RawChatAgent[OptionsCoT], + Generic[OptionsCoT], ): """A Chat Client Agent with middleware, telemetry, and full layer support. @@ -1389,7 +1389,7 @@ class ChatAgent( def __init__( self, - chat_client: ChatClientProtocol[TOptions_co], + chat_client: ChatClientProtocol[OptionsCoT], instructions: str | None = None, *, id: str | None = None, @@ -1400,7 +1400,7 @@ def __init__( | MutableMapping[str, Any] | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, chat_message_store_factory: Callable[[], ChatMessageStoreProtocol] | None = None, context_provider: ContextProvider | None = None, middleware: Sequence[MiddlewareTypes] | None = None, diff --git a/python/packages/core/agent_framework/_clients.py b/python/packages/core/agent_framework/_clients.py index d44c8e7f80..1893f27f80 100644 --- a/python/packages/core/agent_framework/_clients.py +++ b/python/packages/core/agent_framework/_clients.py @@ -58,10 +58,10 @@ from ._types import ChatOptions -TInput = TypeVar("TInput", contravariant=True) +InputT = TypeVar("InputT", contravariant=True) -TEmbedding = TypeVar("TEmbedding") -TBaseChatClient = TypeVar("TBaseChatClient", bound="BaseChatClient") +EmbeddingT = TypeVar("EmbeddingT") +BaseChatClientT = TypeVar("BaseChatClientT", bound="BaseChatClient") logger = get_logger() @@ -74,19 +74,19 @@ # region ChatClientProtocol Protocol # Contravariant for the Protocol -TOptions_contra = TypeVar( - "TOptions_contra", +OptionsContraT = TypeVar( + "OptionsContraT", bound=TypedDict, # type: ignore[valid-type] default="ChatOptions[None]", contravariant=True, ) # Used for the overloads that capture the response model type from options -TResponseModelT = TypeVar("TResponseModelT", bound=BaseModel) +ResponseModelBoundT = TypeVar("ResponseModelBoundT", bound=BaseModel) @runtime_checkable -class ChatClientProtocol(Protocol[TOptions_contra]): +class ChatClientProtocol(Protocol[OptionsContraT]): """A protocol for a chat client that can generate responses. This protocol defines the interface that all chat clients must implement, @@ -139,9 +139,9 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[False] = ..., - options: ChatOptions[TResponseModelT], + options: ChatOptions[ResponseModelBoundT], **kwargs: Any, - ) -> Awaitable[ChatResponse[TResponseModelT]]: ... + ) -> Awaitable[ChatResponse[ResponseModelBoundT]]: ... @overload def get_response( @@ -149,7 +149,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[False] = ..., - options: TOptions_contra | ChatOptions[None] | None = None, + options: OptionsContraT | ChatOptions[None] | None = None, **kwargs: Any, ) -> Awaitable[ChatResponse[Any]]: ... @@ -159,7 +159,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[True], - options: TOptions_contra | ChatOptions[Any] | None = None, + options: OptionsContraT | ChatOptions[Any] | None = None, **kwargs: Any, ) -> ResponseStream[ChatResponseUpdate, ChatResponse[Any]]: ... @@ -168,7 +168,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: bool = False, - options: TOptions_contra | ChatOptions[Any] | None = None, + options: OptionsContraT | ChatOptions[Any] | None = None, **kwargs: Any, ) -> Awaitable[ChatResponse[Any]] | ResponseStream[ChatResponseUpdate, ChatResponse[Any]]: """Send input and return the response. @@ -195,15 +195,15 @@ def get_response( # region ChatClientBase # Covariant for the BaseChatClient -TOptions_co = TypeVar( - "TOptions_co", +OptionsCoT = TypeVar( + "OptionsCoT", bound=TypedDict, # type: ignore[valid-type] default="ChatOptions[None]", covariant=True, ) -class BaseChatClient(SerializationMixin, ABC, Generic[TOptions_co]): +class BaseChatClient(SerializationMixin, ABC, Generic[OptionsCoT]): """Abstract base class for chat clients without middleware wrapping. This abstract base class provides core functionality for chat client implementations, @@ -368,9 +368,9 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[False] = ..., - options: ChatOptions[TResponseModelT], + options: ChatOptions[ResponseModelBoundT], **kwargs: Any, - ) -> Awaitable[ChatResponse[TResponseModelT]]: ... + ) -> Awaitable[ChatResponse[ResponseModelBoundT]]: ... @overload def get_response( @@ -378,7 +378,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[False] = ..., - options: TOptions_co | ChatOptions[None] | None = None, + options: OptionsCoT | ChatOptions[None] | None = None, **kwargs: Any, ) -> Awaitable[ChatResponse[Any]]: ... @@ -388,7 +388,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[True], - options: TOptions_co | ChatOptions[Any] | None = None, + options: OptionsCoT | ChatOptions[Any] | None = None, **kwargs: Any, ) -> ResponseStream[ChatResponseUpdate, ChatResponse[Any]]: ... @@ -397,7 +397,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: bool = False, - options: TOptions_co | ChatOptions[Any] | None = None, + options: OptionsCoT | ChatOptions[Any] | None = None, **kwargs: Any, ) -> Awaitable[ChatResponse[Any]] | ResponseStream[ChatResponseUpdate, ChatResponse[Any]]: """Get a response from a chat client. @@ -442,13 +442,13 @@ def as_agent( | MutableMapping[str, Any] | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - default_options: TOptions_co | Mapping[str, Any] | None = None, + default_options: OptionsCoT | Mapping[str, Any] | None = None, chat_message_store_factory: Callable[[], ChatMessageStoreProtocol] | None = None, context_provider: ContextProvider | None = None, middleware: Sequence[MiddlewareTypes] | None = None, function_invocation_configuration: FunctionInvocationConfiguration | None = None, **kwargs: Any, - ) -> ChatAgent[TOptions_co]: + ) -> ChatAgent[OptionsCoT]: """Create a ChatAgent with this client. This is a convenience method that creates a ChatAgent instance with this diff --git a/python/packages/core/agent_framework/_middleware.py b/python/packages/core/agent_framework/_middleware.py index 48f762cdaa..8d63aa2eba 100644 --- a/python/packages/core/agent_framework/_middleware.py +++ b/python/packages/core/agent_framework/_middleware.py @@ -40,7 +40,7 @@ from ._tools import FunctionTool from ._types import ChatOptions, ChatResponse, ChatResponseUpdate - TResponseModelT = TypeVar("TResponseModelT", bound=BaseModel) + ResponseModelBoundT = TypeVar("ResponseModelBoundT", bound=BaseModel) __all__ = [ "AgentContext", @@ -65,21 +65,21 @@ ] AgentT = TypeVar("AgentT", bound="SupportsAgentRun") -TContext = TypeVar("TContext") -TUpdate = TypeVar("TUpdate") +ContextT = TypeVar("ContextT") +UpdateT = TypeVar("UpdateT") -class _EmptyAsyncIterator(Generic[TUpdate]): +class _EmptyAsyncIterator(Generic[UpdateT]): """Empty async iterator that yields nothing. Used when middleware terminates without setting a result, and we need to provide an empty stream. """ - def __aiter__(self) -> _EmptyAsyncIterator[TUpdate]: + def __aiter__(self) -> _EmptyAsyncIterator[UpdateT]: return self - async def __anext__(self) -> TUpdate: + async def __anext__(self) -> UpdateT: raise StopAsyncIteration @@ -656,20 +656,20 @@ async def logging_middleware(context: ChatContext, call_next): return func -class MiddlewareWrapper(Generic[TContext]): +class MiddlewareWrapper(Generic[ContextT]): """Generic wrapper to convert pure functions into middleware protocol objects. This wrapper allows function-based middleware to be used alongside class-based middleware by providing a unified interface. Type Parameters: - TContext: The type of context object this middleware operates on. + ContextT: The type of context object this middleware operates on. """ - def __init__(self, func: Callable[[TContext, Callable[[TContext], Awaitable[None]]], Awaitable[None]]) -> None: + def __init__(self, func: Callable[[ContextT, Callable[[ContextT], Awaitable[None]]], Awaitable[None]]) -> None: self.func = func - async def process(self, context: TContext, call_next: Callable[[TContext], Awaitable[None]]) -> None: + async def process(self, context: ContextT, call_next: Callable[[ContextT], Awaitable[None]]) -> None: await self.func(context, call_next) @@ -953,15 +953,15 @@ async def current_handler(c: ChatContext) -> None: # Covariant for chat client options -TOptions_co = TypeVar( - "TOptions_co", +OptionsCoT = TypeVar( + "OptionsCoT", bound=TypedDict, # type: ignore[valid-type] default="ChatOptions[None]", covariant=True, ) -class ChatMiddlewareLayer(Generic[TOptions_co]): +class ChatMiddlewareLayer(Generic[OptionsCoT]): """Layer for chat clients to apply chat middleware around response generation.""" def __init__( @@ -983,9 +983,9 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[False] = ..., - options: ChatOptions[TResponseModelT], + options: ChatOptions[ResponseModelBoundT], **kwargs: Any, - ) -> Awaitable[ChatResponse[TResponseModelT]]: ... + ) -> Awaitable[ChatResponse[ResponseModelBoundT]]: ... @overload def get_response( @@ -993,7 +993,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[False] = ..., - options: TOptions_co | ChatOptions[None] | None = None, + options: OptionsCoT | ChatOptions[None] | None = None, **kwargs: Any, ) -> Awaitable[ChatResponse[Any]]: ... @@ -1003,7 +1003,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[True], - options: TOptions_co | ChatOptions[Any] | None = None, + options: OptionsCoT | ChatOptions[Any] | None = None, **kwargs: Any, ) -> ResponseStream[ChatResponseUpdate, ChatResponse[Any]]: ... @@ -1012,7 +1012,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: bool = False, - options: TOptions_co | ChatOptions[Any] | None = None, + options: OptionsCoT | ChatOptions[Any] | None = None, **kwargs: Any, ) -> Awaitable[ChatResponse[Any]] | ResponseStream[ChatResponseUpdate, ChatResponse[Any]]: """Execute the chat pipeline if middleware is configured.""" @@ -1102,9 +1102,9 @@ def run( stream: Literal[False] = ..., thread: AgentThread | None = None, middleware: Sequence[MiddlewareTypes] | None = None, - options: ChatOptions[TResponseModelT], + options: ChatOptions[ResponseModelBoundT], **kwargs: Any, - ) -> Awaitable[AgentResponse[TResponseModelT]]: ... + ) -> Awaitable[AgentResponse[ResponseModelBoundT]]: ... @overload def run( diff --git a/python/packages/core/agent_framework/_pydantic.py b/python/packages/core/agent_framework/_pydantic.py index a54f7b81af..b8652745b3 100644 --- a/python/packages/core/agent_framework/_pydantic.py +++ b/python/packages/core/agent_framework/_pydantic.py @@ -14,7 +14,7 @@ __all__ = ["AFBaseSettings", "HTTPsUrl"] -TSettings = TypeVar("TSettings", bound="AFBaseSettings") +SettingsT = TypeVar("SettingsT", bound="AFBaseSettings") class AFBaseSettings(BaseSettings): @@ -50,7 +50,7 @@ def __init__( kwargs = {k: v for k, v in kwargs.items() if v is not None} super().__init__(**kwargs) - def __new__(cls: type[TSettings], *args: Any, **kwargs: Any) -> TSettings: + def __new__(cls: type[SettingsT], *args: Any, **kwargs: Any) -> SettingsT: """Override the __new__ method to set the env_prefix.""" # for both, if supplied but None, set to default if "env_file_encoding" in kwargs and kwargs["env_file_encoding"] is not None: diff --git a/python/packages/core/agent_framework/_serialization.py b/python/packages/core/agent_framework/_serialization.py index c70f73e1d2..44de6ef848 100644 --- a/python/packages/core/agent_framework/_serialization.py +++ b/python/packages/core/agent_framework/_serialization.py @@ -11,8 +11,8 @@ logger = get_logger() -TClass = TypeVar("TClass", bound="SerializationMixin") -TProtocol = TypeVar("TProtocol", bound="SerializationProtocol") +ClassT = TypeVar("ClassT", bound="SerializationMixin") +ProtocolT = TypeVar("ProtocolT", bound="SerializationProtocol") # Regex pattern for converting CamelCase to snake_case _CAMEL_TO_SNAKE_PATTERN = re.compile(r"(? dict[str, Any]: ... @classmethod - def from_dict(cls: type[TProtocol], value: MutableMapping[str, Any], /, **kwargs: Any) -> TProtocol: + def from_dict(cls: type[ProtocolT], value: MutableMapping[str, Any], /, **kwargs: Any) -> ProtocolT: """Create an instance from a dictionary. Args: @@ -392,8 +392,8 @@ def to_json(self, *, exclude: set[str] | None = None, exclude_none: bool = True, @classmethod def from_dict( - cls: type[TClass], value: MutableMapping[str, Any], /, *, dependencies: MutableMapping[str, Any] | None = None - ) -> TClass: + cls: type[ClassT], value: MutableMapping[str, Any], /, *, dependencies: MutableMapping[str, Any] | None = None + ) -> ClassT: """Create an instance from a dictionary with optional dependency injection. This method reconstructs an object from its dictionary representation, automatically @@ -560,7 +560,7 @@ async def get_current_weather(location: Annotated[str, "The city name"]) -> str: return cls(**kwargs) @classmethod - def from_json(cls: type[TClass], value: str, /, *, dependencies: MutableMapping[str, Any] | None = None) -> TClass: + def from_json(cls: type[ClassT], value: str, /, *, dependencies: MutableMapping[str, Any] | None = None) -> ClassT: """Create an instance from a JSON string. This is a convenience method that parses the JSON string using ``json.loads()`` diff --git a/python/packages/core/agent_framework/_threads.py b/python/packages/core/agent_framework/_threads.py index 74462d3a90..df142643f6 100644 --- a/python/packages/core/agent_framework/_threads.py +++ b/python/packages/core/agent_framework/_threads.py @@ -182,7 +182,7 @@ def __init__( raise TypeError("Could not parse ChatMessageStoreState.") -TChatMessageStore = TypeVar("TChatMessageStore", bound="ChatMessageStore") +ChatMessageStoreT = TypeVar("ChatMessageStoreT", bound="ChatMessageStore") class ChatMessageStore: @@ -243,8 +243,8 @@ async def list_messages(self) -> list[ChatMessage]: @classmethod async def deserialize( - cls: type[TChatMessageStore], serialized_store_state: MutableMapping[str, Any], **kwargs: Any - ) -> TChatMessageStore: + cls: type[ChatMessageStoreT], serialized_store_state: MutableMapping[str, Any], **kwargs: Any + ) -> ChatMessageStoreT: """Create a new ChatMessageStore instance from serialized state data. Args: @@ -289,7 +289,7 @@ async def serialize(self, **kwargs: Any) -> dict[str, Any]: return state.to_dict() -TAgentThread = TypeVar("TAgentThread", bound="AgentThread") +AgentThreadT = TypeVar("AgentThreadT", bound="AgentThread") class AgentThread: @@ -437,12 +437,12 @@ async def serialize(self, **kwargs: Any) -> dict[str, Any]: @classmethod async def deserialize( - cls: type[TAgentThread], + cls: type[AgentThreadT], serialized_thread_state: MutableMapping[str, Any], *, message_store: ChatMessageStoreProtocol | None = None, **kwargs: Any, - ) -> TAgentThread: + ) -> AgentThreadT: """Deserializes the state from a dictionary into a new AgentThread instance. Args: diff --git a/python/packages/core/agent_framework/_tools.py b/python/packages/core/agent_framework/_tools.py index 9019e1dc4f..5e4dfe3c2e 100644 --- a/python/packages/core/agent_framework/_tools.py +++ b/python/packages/core/agent_framework/_tools.py @@ -76,7 +76,7 @@ ResponseStream, ) - TResponseModelT = TypeVar("TResponseModelT", bound=BaseModel) + ResponseModelBoundT = TypeVar("ResponseModelBoundT", bound=BaseModel) logger = get_logger() @@ -100,7 +100,7 @@ logger = get_logger() DEFAULT_MAX_ITERATIONS: Final[int] = 40 DEFAULT_MAX_CONSECUTIVE_ERRORS_PER_REQUEST: Final[int] = 3 -TChatClient = TypeVar("TChatClient", bound="ChatClientProtocol[Any]") +ChatClientT = TypeVar("ChatClientT", bound="ChatClientProtocol[Any]") # region Helpers ArgsT = TypeVar("ArgsT", bound=BaseModel, default=BaseModel) @@ -569,7 +569,7 @@ def _default_histogram() -> Histogram: ) -TClass = TypeVar("TClass", bound="SerializationMixin") +ClassT = TypeVar("ClassT", bound="SerializationMixin") class EmptyInputModel(BaseModel): @@ -2072,15 +2072,15 @@ async def _process_function_requests( return result -TOptions_co = TypeVar( - "TOptions_co", +OptionsCoT = TypeVar( + "OptionsCoT", bound=TypedDict, # type: ignore[valid-type] default="ChatOptions[None]", covariant=True, ) -class FunctionInvocationLayer(Generic[TOptions_co]): +class FunctionInvocationLayer(Generic[OptionsCoT]): """Layer for chat clients to apply function invocation around get_response.""" def __init__( @@ -2104,9 +2104,9 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[False] = ..., - options: ChatOptions[TResponseModelT], + options: ChatOptions[ResponseModelBoundT], **kwargs: Any, - ) -> Awaitable[ChatResponse[TResponseModelT]]: ... + ) -> Awaitable[ChatResponse[ResponseModelBoundT]]: ... @overload def get_response( @@ -2114,7 +2114,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[False] = ..., - options: TOptions_co | ChatOptions[None] | None = None, + options: OptionsCoT | ChatOptions[None] | None = None, **kwargs: Any, ) -> Awaitable[ChatResponse[Any]]: ... @@ -2124,7 +2124,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[True], - options: TOptions_co | ChatOptions[Any] | None = None, + options: OptionsCoT | ChatOptions[Any] | None = None, **kwargs: Any, ) -> ResponseStream[ChatResponseUpdate, ChatResponse[Any]]: ... @@ -2133,7 +2133,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: bool = False, - options: TOptions_co | ChatOptions[Any] | None = None, + options: OptionsCoT | ChatOptions[Any] | None = None, function_middleware: Sequence[FunctionMiddlewareTypes] | None = None, **kwargs: Any, ) -> Awaitable[ChatResponse[Any]] | ResponseStream[ChatResponseUpdate, ChatResponse[Any]]: diff --git a/python/packages/core/agent_framework/_types.py b/python/packages/core/agent_framework/_types.py index b5fc029894..9c28a5a7e1 100644 --- a/python/packages/core/agent_framework/_types.py +++ b/python/packages/core/agent_framework/_types.py @@ -36,17 +36,17 @@ "ChatResponse", "ChatResponseUpdate", "Content", + "FinalT", "FinishReason", "FinishReasonLiteral", + "OuterFinalT", + "OuterUpdateT", "ResponseStream", "Role", "RoleLiteral", - "TFinal", - "TOuterFinal", - "TOuterUpdate", - "TUpdate", "TextSpanRegion", "ToolMode", + "UpdateT", "UsageDetails", "add_usage_details", "detect_media_type_from_base64", @@ -305,12 +305,12 @@ def _serialize_value(value: Any, exclude_none: bool) -> Any: # region Constants and types _T = TypeVar("_T") -TEmbedding = TypeVar("TEmbedding") -TChatResponse = TypeVar("TChatResponse", bound="ChatResponse") -TToolMode = TypeVar("TToolMode", bound="ToolMode") -TAgentRunResponse = TypeVar("TAgentRunResponse", bound="AgentResponse") -TResponseModel = TypeVar("TResponseModel", bound=BaseModel | None, default=None, covariant=True) -TResponseModelT = TypeVar("TResponseModelT", bound=BaseModel) +EmbeddingT = TypeVar("EmbeddingT") +ChatResponseT = TypeVar("ChatResponseT", bound="ChatResponse") +ToolModeT = TypeVar("ToolModeT", bound="ToolMode") +AgentResponseT = TypeVar("AgentResponseT", bound="AgentResponse") +ResponseModelT = TypeVar("ResponseModelT", bound=BaseModel | None, default=None, covariant=True) +ResponseModelBoundT = TypeVar("ResponseModelBoundT", bound=BaseModel) CreatedAtT = str # Use a datetimeoffset type? Or a more specific type like datetime.datetime? @@ -389,7 +389,7 @@ class Annotation(TypedDict, total=False): raw_representation: Any -TContent = TypeVar("TContent", bound="Content") +ContentT = TypeVar("ContentT", bound="Content") # endregion @@ -544,13 +544,13 @@ def __init__( @classmethod def from_text( - cls: type[TContent], + cls: type[ContentT], text: str, *, annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create text content.""" return cls( "text", @@ -562,14 +562,14 @@ def from_text( @classmethod def from_text_reasoning( - cls: type[TContent], + cls: type[ContentT], *, text: str | None = None, protected_data: str | None = None, annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create text reasoning content.""" return cls( "text_reasoning", @@ -582,14 +582,14 @@ def from_text_reasoning( @classmethod def from_data( - cls: type[TContent], + cls: type[ContentT], data: bytes, media_type: str, *, annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: r"""Create data content from raw binary data. Use this to create content from binary data (images, audio, documents, etc.). @@ -658,14 +658,14 @@ def from_data( @classmethod def from_uri( - cls: type[TContent], + cls: type[ContentT], uri: str, *, media_type: str | None = None, annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create content from a URI, can be both data URI or external URI. Use this when you already have a properly formed data URI @@ -720,7 +720,7 @@ def from_uri( @classmethod def from_error( - cls: type[TContent], + cls: type[ContentT], *, message: str | None = None, error_code: str | None = None, @@ -728,7 +728,7 @@ def from_error( annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create error content.""" return cls( "error", @@ -742,7 +742,7 @@ def from_error( @classmethod def from_function_call( - cls: type[TContent], + cls: type[ContentT], call_id: str, name: str, *, @@ -751,7 +751,7 @@ def from_function_call( annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create function call content.""" return cls( "function_call", @@ -766,7 +766,7 @@ def from_function_call( @classmethod def from_function_result( - cls: type[TContent], + cls: type[ContentT], call_id: str, *, result: Any = None, @@ -774,7 +774,7 @@ def from_function_result( annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create function result content.""" return cls( "function_result", @@ -788,13 +788,13 @@ def from_function_result( @classmethod def from_usage( - cls: type[TContent], + cls: type[ContentT], usage_details: UsageDetails, *, annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create usage content.""" return cls( "usage", @@ -806,7 +806,7 @@ def from_usage( @classmethod def from_hosted_file( - cls: type[TContent], + cls: type[ContentT], file_id: str, *, media_type: str | None = None, @@ -814,7 +814,7 @@ def from_hosted_file( annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create hosted file content.""" return cls( "hosted_file", @@ -828,13 +828,13 @@ def from_hosted_file( @classmethod def from_hosted_vector_store( - cls: type[TContent], + cls: type[ContentT], vector_store_id: str, *, annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create hosted vector store content.""" return cls( "hosted_vector_store", @@ -846,14 +846,14 @@ def from_hosted_vector_store( @classmethod def from_code_interpreter_tool_call( - cls: type[TContent], + cls: type[ContentT], *, call_id: str | None = None, inputs: Sequence[Content] | None = None, annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create code interpreter tool call content.""" return cls( "code_interpreter_tool_call", @@ -866,14 +866,14 @@ def from_code_interpreter_tool_call( @classmethod def from_code_interpreter_tool_result( - cls: type[TContent], + cls: type[ContentT], *, call_id: str | None = None, outputs: Sequence[Content] | None = None, annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create code interpreter tool result content.""" return cls( "code_interpreter_tool_result", @@ -886,13 +886,13 @@ def from_code_interpreter_tool_result( @classmethod def from_image_generation_tool_call( - cls: type[TContent], + cls: type[ContentT], *, image_id: str | None = None, annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create image generation tool call content.""" return cls( "image_generation_tool_call", @@ -904,14 +904,14 @@ def from_image_generation_tool_call( @classmethod def from_image_generation_tool_result( - cls: type[TContent], + cls: type[ContentT], *, image_id: str | None = None, outputs: Any = None, annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create image generation tool result content.""" return cls( "image_generation_tool_result", @@ -924,7 +924,7 @@ def from_image_generation_tool_result( @classmethod def from_mcp_server_tool_call( - cls: type[TContent], + cls: type[ContentT], call_id: str, tool_name: str, *, @@ -933,7 +933,7 @@ def from_mcp_server_tool_call( annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create MCP server tool call content.""" return cls( "mcp_server_tool_call", @@ -948,14 +948,14 @@ def from_mcp_server_tool_call( @classmethod def from_mcp_server_tool_result( - cls: type[TContent], + cls: type[ContentT], call_id: str, *, output: Any = None, annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create MCP server tool result content.""" return cls( "mcp_server_tool_result", @@ -968,14 +968,14 @@ def from_mcp_server_tool_result( @classmethod def from_function_approval_request( - cls: type[TContent], + cls: type[ContentT], id: str, function_call: Content, *, annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create function approval request content.""" return cls( "function_approval_request", @@ -989,7 +989,7 @@ def from_function_approval_request( @classmethod def from_function_approval_response( - cls: type[TContent], + cls: type[ContentT], approved: bool, id: str, function_call: Content, @@ -997,7 +997,7 @@ def from_function_approval_response( annotations: Sequence[Annotation] | None = None, additional_properties: MutableMapping[str, Any] | None = None, raw_representation: Any = None, - ) -> TContent: + ) -> ContentT: """Create function approval response content.""" return cls( "function_approval_response", @@ -1091,7 +1091,7 @@ def __str__(self) -> str: return f"Content(type={self.type})" @classmethod - def from_dict(cls: type[TContent], data: Mapping[str, Any]) -> TContent: + def from_dict(cls: type[ContentT], data: Mapping[str, Any]) -> ContentT: """Create a Content instance from a mapping.""" if not (content_type := data.get("type")): raise ValueError("Content mapping requires 'type'") @@ -1796,7 +1796,7 @@ def _finalize_response(response: ChatResponse | AgentResponse) -> None: _coalesce_text_content(msg.contents, "text_reasoning") -class ChatResponse(SerializationMixin, Generic[TResponseModel]): +class ChatResponse(SerializationMixin, Generic[ResponseModelT]): """Represents the response to a chat request. Attributes: @@ -1859,7 +1859,7 @@ def __init__( created_at: CreatedAtT | None = None, finish_reason: FinishReasonLiteral | FinishReason | None = None, usage_details: UsageDetails | None = None, - value: TResponseModel | None = None, + value: ResponseModelT | None = None, response_format: type[BaseModel] | None = None, additional_properties: dict[str, Any] | None = None, raw_representation: Any | None = None, @@ -1903,7 +1903,7 @@ def __init__( finish_reason = finish_reason["value"] self.finish_reason = finish_reason self.usage_details = usage_details - self._value: TResponseModel | None = value + self._value: ResponseModelT | None = value self._response_format: type[BaseModel] | None = response_format self._value_parsed: bool = value is not None self.additional_properties = additional_properties or {} @@ -1915,8 +1915,8 @@ def from_updates( cls: type[ChatResponse[Any]], updates: Sequence[ChatResponseUpdate], *, - output_format_type: type[TResponseModelT], - ) -> ChatResponse[TResponseModelT]: ... + output_format_type: type[ResponseModelBoundT], + ) -> ChatResponse[ResponseModelBoundT]: ... @overload @classmethod @@ -1929,11 +1929,11 @@ def from_updates( @classmethod def from_updates( - cls: type[TChatResponse], + cls: type[ChatResponseT], updates: Sequence[ChatResponseUpdate], *, output_format_type: type[BaseModel] | None = None, - ) -> TChatResponse: + ) -> ChatResponseT: """Joins multiple updates into a single ChatResponse. Example: @@ -1970,8 +1970,8 @@ async def from_update_generator( cls: type[ChatResponse[Any]], updates: AsyncIterable[ChatResponseUpdate], *, - output_format_type: type[TResponseModelT], - ) -> ChatResponse[TResponseModelT]: ... + output_format_type: type[ResponseModelBoundT], + ) -> ChatResponse[ResponseModelBoundT]: ... @overload @classmethod @@ -1984,11 +1984,11 @@ async def from_update_generator( @classmethod async def from_update_generator( - cls: type[TChatResponse], + cls: type[ChatResponseT], updates: AsyncIterable[ChatResponseUpdate], *, output_format_type: type[BaseModel] | None = None, - ) -> TChatResponse: + ) -> ChatResponseT: """Joins multiple updates into a single ChatResponse. Example: @@ -2021,7 +2021,7 @@ def text(self) -> str: return ("\n".join(message.text for message in self.messages if isinstance(message, ChatMessage))).strip() @property - def value(self) -> TResponseModel | None: + def value(self) -> ResponseModelT | None: """Get the parsed structured output value. If a response_format was provided and parsing hasn't been attempted yet, @@ -2037,7 +2037,7 @@ def value(self) -> TResponseModel | None: and isinstance(self._response_format, type) and issubclass(self._response_format, BaseModel) ): - self._value = cast(TResponseModel, self._response_format.model_validate_json(self.text)) + self._value = cast(ResponseModelT, self._response_format.model_validate_json(self.text)) self._value_parsed = True return self._value @@ -2166,7 +2166,7 @@ def __str__(self) -> str: # region AgentResponse -class AgentResponse(SerializationMixin, Generic[TResponseModel]): +class AgentResponse(SerializationMixin, Generic[ResponseModelT]): """Represents the response to an Agent run request. Provides one or more response messages and metadata about the response. @@ -2220,7 +2220,7 @@ def __init__( agent_id: str | None = None, created_at: CreatedAtT | None = None, usage_details: UsageDetails | None = None, - value: TResponseModel | None = None, + value: ResponseModelT | None = None, response_format: type[BaseModel] | None = None, raw_representation: Any | None = None, additional_properties: dict[str, Any] | None = None, @@ -2258,7 +2258,7 @@ def __init__( self.agent_id = agent_id self.created_at = created_at self.usage_details = usage_details - self._value: TResponseModel | None = value + self._value: ResponseModelT | None = value self._response_format: type[BaseModel] | None = response_format self._value_parsed: bool = value is not None self.additional_properties = additional_properties or {} @@ -2270,7 +2270,7 @@ def text(self) -> str: return "".join(msg.text for msg in self.messages) if self.messages else "" @property - def value(self) -> TResponseModel | None: + def value(self) -> ResponseModelT | None: """Get the parsed structured output value. If a response_format was provided and parsing hasn't been attempted yet, @@ -2286,7 +2286,7 @@ def value(self) -> TResponseModel | None: and isinstance(self._response_format, type) and issubclass(self._response_format, BaseModel) ): - self._value = cast(TResponseModel, self._response_format.model_validate_json(self.text)) + self._value = cast(ResponseModelT, self._response_format.model_validate_json(self.text)) self._value_parsed = True return self._value @@ -2306,8 +2306,8 @@ def from_updates( cls: type[AgentResponse[Any]], updates: Sequence[AgentResponseUpdate], *, - output_format_type: type[TResponseModelT], - ) -> AgentResponse[TResponseModelT]: ... + output_format_type: type[ResponseModelBoundT], + ) -> AgentResponse[ResponseModelBoundT]: ... @overload @classmethod @@ -2320,11 +2320,11 @@ def from_updates( @classmethod def from_updates( - cls: type[TAgentRunResponse], + cls: type[AgentResponseT], updates: Sequence[AgentResponseUpdate], *, output_format_type: type[BaseModel] | None = None, - ) -> TAgentRunResponse: + ) -> AgentResponseT: """Joins multiple updates into a single AgentResponse. Args: @@ -2345,8 +2345,8 @@ async def from_update_generator( cls: type[AgentResponse[Any]], updates: AsyncIterable[AgentResponseUpdate], *, - output_format_type: type[TResponseModelT], - ) -> AgentResponse[TResponseModelT]: ... + output_format_type: type[ResponseModelBoundT], + ) -> AgentResponse[ResponseModelBoundT]: ... @overload @classmethod @@ -2359,11 +2359,11 @@ async def from_update_generator( @classmethod async def from_update_generator( - cls: type[TAgentRunResponse], + cls: type[AgentResponseT], updates: AsyncIterable[AgentResponseUpdate], *, output_format_type: type[BaseModel] | None = None, - ) -> TAgentRunResponse: + ) -> AgentResponseT: """Joins multiple updates into a single AgentResponse. Args: @@ -2520,23 +2520,23 @@ def map_chat_to_agent_update(update: ChatResponseUpdate, agent_name: str | None) # Type variables for ResponseStream -TUpdate = TypeVar("TUpdate") -TFinal = TypeVar("TFinal") -TOuterUpdate = TypeVar("TOuterUpdate") -TOuterFinal = TypeVar("TOuterFinal") +UpdateT = TypeVar("UpdateT") +FinalT = TypeVar("FinalT") +OuterUpdateT = TypeVar("OuterUpdateT") +OuterFinalT = TypeVar("OuterFinalT") -class ResponseStream(AsyncIterable[TUpdate], Generic[TUpdate, TFinal]): +class ResponseStream(AsyncIterable[UpdateT], Generic[UpdateT, FinalT]): """Async stream wrapper that supports iteration and deferred finalization.""" def __init__( self, - stream: AsyncIterable[TUpdate] | Awaitable[AsyncIterable[TUpdate]], + stream: AsyncIterable[UpdateT] | Awaitable[AsyncIterable[UpdateT]], *, - finalizer: Callable[[Sequence[TUpdate]], TFinal | Awaitable[TFinal]] | None = None, - transform_hooks: list[Callable[[TUpdate], TUpdate | Awaitable[TUpdate] | None]] | None = None, + finalizer: Callable[[Sequence[UpdateT]], FinalT | Awaitable[FinalT]] | None = None, + transform_hooks: list[Callable[[UpdateT], UpdateT | Awaitable[UpdateT] | None]] | None = None, cleanup_hooks: list[Callable[[], Awaitable[None] | None]] | None = None, - result_hooks: list[Callable[[TFinal], TFinal | Awaitable[TFinal | None] | None]] | None = None, + result_hooks: list[Callable[[FinalT], FinalT | Awaitable[FinalT | None] | None]] | None = None, ) -> None: """A Async Iterable stream of updates. @@ -2552,16 +2552,16 @@ def __init__( """ self._stream_source = stream self._finalizer = finalizer - self._stream: AsyncIterable[TUpdate] | None = None - self._iterator: AsyncIterator[TUpdate] | None = None - self._updates: list[TUpdate] = [] + self._stream: AsyncIterable[UpdateT] | None = None + self._iterator: AsyncIterator[UpdateT] | None = None + self._updates: list[UpdateT] = [] self._consumed: bool = False self._finalized: bool = False - self._final_result: TFinal | None = None - self._transform_hooks: list[Callable[[TUpdate], TUpdate | Awaitable[TUpdate] | None]] = ( + self._final_result: FinalT | None = None + self._transform_hooks: list[Callable[[UpdateT], UpdateT | Awaitable[UpdateT] | None]] = ( transform_hooks if transform_hooks is not None else [] ) - self._result_hooks: list[Callable[[TFinal], TFinal | Awaitable[TFinal | None] | None]] = ( + self._result_hooks: list[Callable[[FinalT], FinalT | Awaitable[FinalT | None] | None]] = ( result_hooks if result_hooks is not None else [] ) self._cleanup_hooks: list[Callable[[], Awaitable[None] | None]] = ( @@ -2575,9 +2575,9 @@ def __init__( def map( self, - transform: Callable[[TUpdate], TOuterUpdate | Awaitable[TOuterUpdate]], - finalizer: Callable[[Sequence[TOuterUpdate]], TOuterFinal | Awaitable[TOuterFinal]], - ) -> ResponseStream[TOuterUpdate, TOuterFinal]: + transform: Callable[[UpdateT], OuterUpdateT | Awaitable[OuterUpdateT]], + finalizer: Callable[[Sequence[OuterUpdateT]], OuterFinalT | Awaitable[OuterFinalT]], + ) -> ResponseStream[OuterUpdateT, OuterFinalT]: """Create a new stream that transforms each update. The returned stream delegates iteration to this stream, ensuring single consumption. @@ -2619,8 +2619,8 @@ def map( def with_finalizer( self, - finalizer: Callable[[Sequence[TUpdate]], TOuterFinal | Awaitable[TOuterFinal]], - ) -> ResponseStream[TUpdate, TOuterFinal]: + finalizer: Callable[[Sequence[UpdateT]], OuterFinalT | Awaitable[OuterFinalT]], + ) -> ResponseStream[UpdateT, OuterFinalT]: """Create a new stream with a different finalizer. The returned stream delegates iteration to this stream, ensuring single consumption. @@ -2647,8 +2647,8 @@ def with_finalizer( @classmethod def from_awaitable( cls, - awaitable: Awaitable[ResponseStream[TUpdate, TFinal]], - ) -> ResponseStream[TUpdate, TFinal]: + awaitable: Awaitable[ResponseStream[UpdateT, FinalT]], + ) -> ResponseStream[UpdateT, FinalT]: """Create a ResponseStream from an awaitable that resolves to a ResponseStream. This is useful when you have an async function that returns a ResponseStream @@ -2672,7 +2672,7 @@ def from_awaitable( stream._wrap_inner = True return stream # type: ignore[return-value] - async def _get_stream(self) -> AsyncIterable[TUpdate]: + async def _get_stream(self) -> AsyncIterable[UpdateT]: if self._stream is None: if hasattr(self._stream_source, "__aiter__"): self._stream = self._stream_source # type: ignore[assignment] @@ -2686,10 +2686,10 @@ async def _get_stream(self) -> AsyncIterable[TUpdate]: return self._stream return self._stream # type: ignore[return-value] - def __aiter__(self) -> ResponseStream[TUpdate, TFinal]: + def __aiter__(self) -> ResponseStream[UpdateT, FinalT]: return self - async def __anext__(self) -> TUpdate: + async def __anext__(self) -> UpdateT: if self._iterator is None: stream = await self._get_stream() self._iterator = stream.__aiter__() @@ -2718,19 +2718,19 @@ async def __anext__(self) -> TUpdate: return update def __await__(self) -> Any: - async def _wrap() -> ResponseStream[TUpdate, TFinal]: + async def _wrap() -> ResponseStream[UpdateT, FinalT]: await self._get_stream() return self return _wrap().__await__() - async def get_final_response(self) -> TFinal: + async def get_final_response(self) -> FinalT: """Get the final response by applying the finalizer to all collected updates. If a finalizer is configured, it receives the list of updates and returns the final type. Result hooks are then applied in order to transform the result. - If no finalizer is configured, returns the collected updates as Sequence[TUpdate]. + If no finalizer is configured, returns the collected updates as Sequence[UpdateT]. For wrapped streams (created via .map() or .from_awaitable()): - The inner stream's finalizer is called first to produce the inner final result. @@ -2815,16 +2815,16 @@ async def get_final_response(self) -> TFinal: def with_transform_hook( self, - hook: Callable[[TUpdate], TUpdate | Awaitable[TUpdate] | None], - ) -> ResponseStream[TUpdate, TFinal]: + hook: Callable[[UpdateT], UpdateT | Awaitable[UpdateT] | None], + ) -> ResponseStream[UpdateT, FinalT]: """Register a transform hook executed for each update during iteration.""" self._transform_hooks.append(hook) return self def with_result_hook( self, - hook: Callable[[TFinal], TFinal | Awaitable[TFinal | None] | None], - ) -> ResponseStream[TUpdate, TFinal]: + hook: Callable[[FinalT], FinalT | Awaitable[FinalT | None] | None], + ) -> ResponseStream[UpdateT, FinalT]: """Register a result hook executed after finalization.""" self._result_hooks.append(hook) self._finalized = False @@ -2834,7 +2834,7 @@ def with_result_hook( def with_cleanup_hook( self, hook: Callable[[], Awaitable[None] | None], - ) -> ResponseStream[TUpdate, TFinal]: + ) -> ResponseStream[UpdateT, FinalT]: """Register a cleanup hook executed after stream consumption (before finalizer).""" self._cleanup_hooks.append(hook) return self @@ -2849,7 +2849,7 @@ async def _run_cleanup_hooks(self) -> None: await result @property - def updates(self) -> Sequence[TUpdate]: + def updates(self) -> Sequence[UpdateT]: return self._updates @@ -2944,8 +2944,8 @@ class _ChatOptionsBase(TypedDict, total=False): if TYPE_CHECKING: - class ChatOptions(_ChatOptionsBase, Generic[TResponseModel], total=False): - response_format: type[TResponseModel] | Mapping[str, Any] | None # type: ignore[misc] + class ChatOptions(_ChatOptionsBase, Generic[ResponseModelT], total=False): + response_format: type[ResponseModelT] | Mapping[str, Any] | None # type: ignore[misc] else: ChatOptions = _ChatOptionsBase diff --git a/python/packages/core/agent_framework/_workflows/_model_utils.py b/python/packages/core/agent_framework/_workflows/_model_utils.py index 72380901c6..0627d716a8 100644 --- a/python/packages/core/agent_framework/_workflows/_model_utils.py +++ b/python/packages/core/agent_framework/_workflows/_model_utils.py @@ -9,7 +9,7 @@ else: from typing_extensions import Self # pragma: no cover -TModel = TypeVar("TModel", bound="DictConvertible") +ModelT = TypeVar("ModelT", bound="DictConvertible") class DictConvertible: @@ -19,7 +19,7 @@ def to_dict(self) -> dict[str, Any]: raise NotImplementedError @classmethod - def from_dict(cls: type[TModel], data: dict[str, Any]) -> TModel: + def from_dict(cls: type[ModelT], data: dict[str, Any]) -> ModelT: return cls(**data) # type: ignore[arg-type] def clone(self, *, deep: bool = True) -> Self: @@ -31,7 +31,7 @@ def to_json(self) -> str: return json.dumps(self.to_dict()) @classmethod - def from_json(cls: type[TModel], raw: str) -> TModel: + def from_json(cls: type[ModelT], raw: str) -> ModelT: import json data = json.loads(raw) diff --git a/python/packages/core/agent_framework/azure/_assistants_client.py b/python/packages/core/agent_framework/azure/_assistants_client.py index 3ded58e9b0..52d219529b 100644 --- a/python/packages/core/agent_framework/azure/_assistants_client.py +++ b/python/packages/core/agent_framework/azure/_assistants_client.py @@ -32,8 +32,8 @@ # region Azure OpenAI Assistants Options TypedDict -TAzureOpenAIAssistantsOptions = TypeVar( - "TAzureOpenAIAssistantsOptions", +AzureOpenAIAssistantsOptionsT = TypeVar( + "AzureOpenAIAssistantsOptionsT", bound=TypedDict, # type: ignore[valid-type] default="OpenAIAssistantsOptions", covariant=True, @@ -44,7 +44,7 @@ class AzureOpenAIAssistantsClient( - OpenAIAssistantsClient[TAzureOpenAIAssistantsOptions], Generic[TAzureOpenAIAssistantsOptions] + OpenAIAssistantsClient[AzureOpenAIAssistantsOptionsT], Generic[AzureOpenAIAssistantsOptionsT] ): """Azure OpenAI Assistants client.""" diff --git a/python/packages/core/agent_framework/azure/_chat_client.py b/python/packages/core/agent_framework/azure/_chat_client.py index a603af52cc..0fcf99823a 100644 --- a/python/packages/core/agent_framework/azure/_chat_client.py +++ b/python/packages/core/agent_framework/azure/_chat_client.py @@ -53,7 +53,7 @@ __all__ = ["AzureOpenAIChatClient", "AzureOpenAIChatOptions", "AzureUserSecurityContext"] -TResponseModel = TypeVar("TResponseModel", bound=BaseModel | None, default=None) +ResponseModelT = TypeVar("ResponseModelT", bound=BaseModel | None, default=None) # region Azure OpenAI Chat Options TypedDict @@ -81,7 +81,7 @@ class AzureUserSecurityContext(TypedDict, total=False): """The original client's IP address.""" -class AzureOpenAIChatOptions(OpenAIChatOptions[TResponseModel], Generic[TResponseModel], total=False): +class AzureOpenAIChatOptions(OpenAIChatOptions[ResponseModelT], Generic[ResponseModelT], total=False): """Azure OpenAI-specific chat options dict. Extends OpenAIChatOptions with Azure-specific options including @@ -136,8 +136,8 @@ class AzureOpenAIChatOptions(OpenAIChatOptions[TResponseModel], Generic[TRespons Note: You will be charged based on tokens across all choices. Keep n=1 to minimize costs.""" -TAzureOpenAIChatOptions = TypeVar( - "TAzureOpenAIChatOptions", +AzureOpenAIChatOptionsT = TypeVar( + "AzureOpenAIChatOptionsT", bound=TypedDict, # type: ignore[valid-type] default="AzureOpenAIChatOptions", covariant=True, @@ -146,17 +146,17 @@ class AzureOpenAIChatOptions(OpenAIChatOptions[TResponseModel], Generic[TRespons # endregion -TChatResponse = TypeVar("TChatResponse", ChatResponse, ChatResponseUpdate) -TAzureOpenAIChatClient = TypeVar("TAzureOpenAIChatClient", bound="AzureOpenAIChatClient") +ChatResponseT = TypeVar("ChatResponseT", ChatResponse, ChatResponseUpdate) +AzureOpenAIChatClientT = TypeVar("AzureOpenAIChatClientT", bound="AzureOpenAIChatClient") class AzureOpenAIChatClient( # type: ignore[misc] AzureOpenAIConfigMixin, - ChatMiddlewareLayer[TAzureOpenAIChatOptions], - FunctionInvocationLayer[TAzureOpenAIChatOptions], - ChatTelemetryLayer[TAzureOpenAIChatOptions], - RawOpenAIChatClient[TAzureOpenAIChatOptions], - Generic[TAzureOpenAIChatOptions], + ChatMiddlewareLayer[AzureOpenAIChatOptionsT], + FunctionInvocationLayer[AzureOpenAIChatOptionsT], + ChatTelemetryLayer[AzureOpenAIChatOptionsT], + RawOpenAIChatClient[AzureOpenAIChatOptionsT], + Generic[AzureOpenAIChatOptionsT], ): """Azure OpenAI Chat completion class with middleware, telemetry, and function invocation support.""" diff --git a/python/packages/core/agent_framework/azure/_responses_client.py b/python/packages/core/agent_framework/azure/_responses_client.py index 11eee1900f..cc57beb57c 100644 --- a/python/packages/core/agent_framework/azure/_responses_client.py +++ b/python/packages/core/agent_framework/azure/_responses_client.py @@ -41,8 +41,8 @@ __all__ = ["AzureOpenAIResponsesClient"] -TAzureOpenAIResponsesOptions = TypeVar( - "TAzureOpenAIResponsesOptions", +AzureOpenAIResponsesOptionsT = TypeVar( + "AzureOpenAIResponsesOptionsT", bound=TypedDict, # type: ignore[valid-type] default="OpenAIResponsesOptions", covariant=True, @@ -51,11 +51,11 @@ class AzureOpenAIResponsesClient( # type: ignore[misc] AzureOpenAIConfigMixin, - ChatMiddlewareLayer[TAzureOpenAIResponsesOptions], - FunctionInvocationLayer[TAzureOpenAIResponsesOptions], - ChatTelemetryLayer[TAzureOpenAIResponsesOptions], - RawOpenAIResponsesClient[TAzureOpenAIResponsesOptions], - Generic[TAzureOpenAIResponsesOptions], + ChatMiddlewareLayer[AzureOpenAIResponsesOptionsT], + FunctionInvocationLayer[AzureOpenAIResponsesOptionsT], + ChatTelemetryLayer[AzureOpenAIResponsesOptionsT], + RawOpenAIResponsesClient[AzureOpenAIResponsesOptionsT], + Generic[AzureOpenAIResponsesOptionsT], ): """Azure Responses completion class with middleware, telemetry, and function invocation support.""" diff --git a/python/packages/core/agent_framework/observability.py b/python/packages/core/agent_framework/observability.py index 9a839bb566..34c58b3b1a 100644 --- a/python/packages/core/agent_framework/observability.py +++ b/python/packages/core/agent_framework/observability.py @@ -54,7 +54,7 @@ ResponseStream, ) - TResponseModelT = TypeVar("TResponseModelT", bound=BaseModel) + ResponseModelBoundT = TypeVar("ResponseModelBoundT", bound=BaseModel) __all__ = [ "OBSERVABILITY_SETTINGS", @@ -71,7 +71,7 @@ AgentT = TypeVar("AgentT", bound="SupportsAgentRun") -TChatClient = TypeVar("TChatClient", bound="ChatClientProtocol[Any]") +ChatClientT = TypeVar("ChatClientT", bound="ChatClientProtocol[Any]") logger = get_logger() @@ -1049,15 +1049,15 @@ def _get_token_usage_histogram() -> metrics.Histogram: ) -TOptions_co = TypeVar( - "TOptions_co", +OptionsCoT = TypeVar( + "OptionsCoT", bound=TypedDict, # type: ignore[valid-type] default="ChatOptions[None]", covariant=True, ) -class ChatTelemetryLayer(Generic[TOptions_co]): +class ChatTelemetryLayer(Generic[OptionsCoT]): """Layer that wraps chat client get_response with OpenTelemetry tracing.""" def __init__(self, *args: Any, otel_provider_name: str | None = None, **kwargs: Any) -> None: @@ -1073,9 +1073,9 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[False] = ..., - options: ChatOptions[TResponseModelT], + options: ChatOptions[ResponseModelBoundT], **kwargs: Any, - ) -> Awaitable[ChatResponse[TResponseModelT]]: ... + ) -> Awaitable[ChatResponse[ResponseModelBoundT]]: ... @overload def get_response( @@ -1083,7 +1083,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[False] = ..., - options: TOptions_co | ChatOptions[None] | None = None, + options: OptionsCoT | ChatOptions[None] | None = None, **kwargs: Any, ) -> Awaitable[ChatResponse[Any]]: ... @@ -1093,7 +1093,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: Literal[True], - options: TOptions_co | ChatOptions[Any] | None = None, + options: OptionsCoT | ChatOptions[Any] | None = None, **kwargs: Any, ) -> ResponseStream[ChatResponseUpdate, ChatResponse[Any]]: ... @@ -1102,7 +1102,7 @@ def get_response( messages: str | ChatMessage | Sequence[str | ChatMessage], *, stream: bool = False, - options: TOptions_co | ChatOptions[Any] | None = None, + options: OptionsCoT | ChatOptions[Any] | None = None, **kwargs: Any, ) -> Awaitable[ChatResponse[Any]] | ResponseStream[ChatResponseUpdate, ChatResponse[Any]]: """Trace chat responses with OpenTelemetry spans and metrics.""" diff --git a/python/packages/core/agent_framework/openai/_assistant_provider.py b/python/packages/core/agent_framework/openai/_assistant_provider.py index 263c4dcab1..7b662e4c2a 100644 --- a/python/packages/core/agent_framework/openai/_assistant_provider.py +++ b/python/packages/core/agent_framework/openai/_assistant_provider.py @@ -33,10 +33,10 @@ __all__ = ["OpenAIAssistantProvider"] -# Type variable for options - allows typed ChatAgent[TOptions] returns +# Type variable for options - allows typed OpenAIAssistantProvider[OptionsCoT] returns # Default matches OpenAIAssistantsClient's default options type -TOptions_co = TypeVar( - "TOptions_co", +OptionsCoT = TypeVar( + "OptionsCoT", bound=TypedDict, # type: ignore[valid-type] default="OpenAIAssistantsOptions", covariant=True, @@ -50,7 +50,7 @@ ) -class OpenAIAssistantProvider(Generic[TOptions_co]): +class OpenAIAssistantProvider(Generic[OptionsCoT]): """Provider for creating ChatAgent instances from OpenAI Assistants API. This provider allows you to create, retrieve, and wrap OpenAI Assistants @@ -205,10 +205,10 @@ async def create_agent( description: str | None = None, tools: _ToolsType | None = None, metadata: dict[str, str] | None = None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, middleware: Sequence[MiddlewareTypes] | None = None, context_provider: ContextProvider | None = None, - ) -> ChatAgent[TOptions_co]: + ) -> ChatAgent[OptionsCoT]: """Create a new assistant on OpenAI and return a ChatAgent. This method creates a new assistant on the OpenAI service and wraps it @@ -313,10 +313,10 @@ async def get_agent( *, tools: _ToolsType | None = None, instructions: str | None = None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, middleware: Sequence[MiddlewareTypes] | None = None, context_provider: ContextProvider | None = None, - ) -> ChatAgent[TOptions_co]: + ) -> ChatAgent[OptionsCoT]: """Retrieve an existing assistant by ID and return a ChatAgent. This method fetches an existing assistant from OpenAI by its ID @@ -379,10 +379,10 @@ def as_agent( *, tools: _ToolsType | None = None, instructions: str | None = None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, middleware: Sequence[MiddlewareTypes] | None = None, context_provider: ContextProvider | None = None, - ) -> ChatAgent[TOptions_co]: + ) -> ChatAgent[OptionsCoT]: """Wrap an existing SDK Assistant object as a ChatAgent. This method does NOT make any HTTP calls. It simply wraps an already- @@ -524,9 +524,9 @@ def _create_chat_agent_from_assistant( instructions: str | None, middleware: Sequence[MiddlewareTypes] | None, context_provider: ContextProvider | None, - default_options: TOptions_co | None = None, + default_options: OptionsCoT | None = None, **kwargs: Any, - ) -> ChatAgent[TOptions_co]: + ) -> ChatAgent[OptionsCoT]: """Create a ChatAgent from an Assistant. Args: diff --git a/python/packages/core/agent_framework/openai/_assistants_client.py b/python/packages/core/agent_framework/openai/_assistants_client.py index 1f6bdb87dc..914109827b 100644 --- a/python/packages/core/agent_framework/openai/_assistants_client.py +++ b/python/packages/core/agent_framework/openai/_assistants_client.py @@ -79,7 +79,7 @@ # region OpenAI Assistants Options TypedDict -TResponseModel = TypeVar("TResponseModel", bound=BaseModel | None, default=None) +ResponseModelT = TypeVar("ResponseModelT", bound=BaseModel | None, default=None) class VectorStoreToolResource(TypedDict, total=False): @@ -109,7 +109,7 @@ class AssistantToolResources(TypedDict, total=False): """Resources for file search tool, including vector store IDs.""" -class OpenAIAssistantsOptions(ChatOptions[TResponseModel], Generic[TResponseModel], total=False): +class OpenAIAssistantsOptions(ChatOptions[ResponseModelT], Generic[ResponseModelT], total=False): """OpenAI Assistants API-specific options dict. Extends base ChatOptions with Assistants API-specific parameters @@ -193,8 +193,8 @@ class OpenAIAssistantsOptions(ChatOptions[TResponseModel], Generic[TResponseMode } """Maps ChatOptions keys to OpenAI Assistants API parameter names.""" -TOpenAIAssistantsOptions = TypeVar( - "TOpenAIAssistantsOptions", +OpenAIAssistantsOptionsT = TypeVar( + "OpenAIAssistantsOptionsT", bound=TypedDict, # type: ignore[valid-type] default="OpenAIAssistantsOptions", covariant=True, @@ -206,11 +206,11 @@ class OpenAIAssistantsOptions(ChatOptions[TResponseModel], Generic[TResponseMode class OpenAIAssistantsClient( # type: ignore[misc] OpenAIConfigMixin, - ChatMiddlewareLayer[TOpenAIAssistantsOptions], - FunctionInvocationLayer[TOpenAIAssistantsOptions], - ChatTelemetryLayer[TOpenAIAssistantsOptions], - BaseChatClient[TOpenAIAssistantsOptions], - Generic[TOpenAIAssistantsOptions], + ChatMiddlewareLayer[OpenAIAssistantsOptionsT], + FunctionInvocationLayer[OpenAIAssistantsOptionsT], + ChatTelemetryLayer[OpenAIAssistantsOptionsT], + BaseChatClient[OpenAIAssistantsOptionsT], + Generic[OpenAIAssistantsOptionsT], ): """OpenAI Assistants client with middleware, telemetry, and function invocation support.""" diff --git a/python/packages/core/agent_framework/openai/_chat_client.py b/python/packages/core/agent_framework/openai/_chat_client.py index 4ca47a4481..b3d54f251e 100644 --- a/python/packages/core/agent_framework/openai/_chat_client.py +++ b/python/packages/core/agent_framework/openai/_chat_client.py @@ -65,7 +65,7 @@ logger = get_logger("agent_framework.openai") -TResponseModel = TypeVar("TResponseModel", bound=BaseModel | None, default=None) +ResponseModelT = TypeVar("ResponseModelT", bound=BaseModel | None, default=None) # region OpenAI Chat Options TypedDict @@ -85,7 +85,7 @@ class Prediction(TypedDict, total=False): content: str | list[PredictionTextContent] -class OpenAIChatOptions(ChatOptions[TResponseModel], Generic[TResponseModel], total=False): +class OpenAIChatOptions(ChatOptions[ResponseModelT], Generic[ResponseModelT], total=False): """OpenAI-specific chat options dict. Extends ChatOptions with options specific to OpenAI's Chat Completions API. @@ -124,7 +124,7 @@ class OpenAIChatOptions(ChatOptions[TResponseModel], Generic[TResponseModel], to prediction: Prediction -TOpenAIChatOptions = TypeVar("TOpenAIChatOptions", bound=TypedDict, default="OpenAIChatOptions", covariant=True) # type: ignore[valid-type] +OpenAIChatOptionsT = TypeVar("OpenAIChatOptionsT", bound=TypedDict, default="OpenAIChatOptions", covariant=True) # type: ignore[valid-type] OPTION_TRANSLATIONS: dict[str, str] = { "model_id": "model", @@ -136,8 +136,8 @@ class OpenAIChatOptions(ChatOptions[TResponseModel], Generic[TResponseModel], to # region Base Client class RawOpenAIChatClient( # type: ignore[misc] OpenAIBase, - BaseChatClient[TOpenAIChatOptions], - Generic[TOpenAIChatOptions], + BaseChatClient[OpenAIChatOptionsT], + Generic[OpenAIChatOptionsT], ): """Raw OpenAI Chat completion class without middleware, telemetry, or function invocation. @@ -593,11 +593,11 @@ def service_url(self) -> str: class OpenAIChatClient( # type: ignore[misc] OpenAIConfigMixin, - ChatMiddlewareLayer[TOpenAIChatOptions], - FunctionInvocationLayer[TOpenAIChatOptions], - ChatTelemetryLayer[TOpenAIChatOptions], - RawOpenAIChatClient[TOpenAIChatOptions], - Generic[TOpenAIChatOptions], + ChatMiddlewareLayer[OpenAIChatOptionsT], + FunctionInvocationLayer[OpenAIChatOptionsT], + ChatTelemetryLayer[OpenAIChatOptionsT], + RawOpenAIChatClient[OpenAIChatOptionsT], + Generic[OpenAIChatOptionsT], ): """OpenAI Chat completion class with middleware, telemetry, and function invocation support.""" diff --git a/python/packages/core/agent_framework/openai/_responses_client.py b/python/packages/core/agent_framework/openai/_responses_client.py index b2b7451918..69da1df531 100644 --- a/python/packages/core/agent_framework/openai/_responses_client.py +++ b/python/packages/core/agent_framework/openai/_responses_client.py @@ -124,10 +124,10 @@ class StreamOptions(TypedDict, total=False): """Whether to include usage statistics in stream events.""" -TResponseFormat = TypeVar("TResponseFormat", bound=BaseModel | None, default=None) +ResponseFormatT = TypeVar("ResponseFormatT", bound=BaseModel | None, default=None) -class OpenAIResponsesOptions(ChatOptions[TResponseFormat], Generic[TResponseFormat], total=False): +class OpenAIResponsesOptions(ChatOptions[ResponseFormatT], Generic[ResponseFormatT], total=False): """OpenAI Responses API-specific chat options. Extends ChatOptions with options specific to OpenAI's Responses API. @@ -191,8 +191,8 @@ class OpenAIResponsesOptions(ChatOptions[TResponseFormat], Generic[TResponseForm - 'disabled': Fail with 400 error if exceeds context""" -TOpenAIResponsesOptions = TypeVar( - "TOpenAIResponsesOptions", +OpenAIResponsesOptionsT = TypeVar( + "OpenAIResponsesOptionsT", bound=TypedDict, # type: ignore[valid-type] default="OpenAIResponsesOptions", covariant=True, @@ -207,8 +207,8 @@ class OpenAIResponsesOptions(ChatOptions[TResponseFormat], Generic[TResponseForm class RawOpenAIResponsesClient( # type: ignore[misc] OpenAIBase, - BaseChatClient[TOpenAIResponsesOptions], - Generic[TOpenAIResponsesOptions], + BaseChatClient[OpenAIResponsesOptionsT], + Generic[OpenAIResponsesOptionsT], ): """Raw OpenAI Responses client without middleware, telemetry, or function invocation. @@ -1437,11 +1437,11 @@ def _get_metadata_from_response(self, output: Any) -> dict[str, Any]: class OpenAIResponsesClient( # type: ignore[misc] OpenAIConfigMixin, - ChatMiddlewareLayer[TOpenAIResponsesOptions], - FunctionInvocationLayer[TOpenAIResponsesOptions], - ChatTelemetryLayer[TOpenAIResponsesOptions], - RawOpenAIResponsesClient[TOpenAIResponsesOptions], - Generic[TOpenAIResponsesOptions], + ChatMiddlewareLayer[OpenAIResponsesOptionsT], + FunctionInvocationLayer[OpenAIResponsesOptionsT], + ChatTelemetryLayer[OpenAIResponsesOptionsT], + RawOpenAIResponsesClient[OpenAIResponsesOptionsT], + Generic[OpenAIResponsesOptionsT], ): """OpenAI Responses client class with middleware, telemetry, and function invocation support.""" diff --git a/python/packages/core/tests/core/conftest.py b/python/packages/core/tests/core/conftest.py index 7f987ca226..7cb5e63549 100644 --- a/python/packages/core/tests/core/conftest.py +++ b/python/packages/core/tests/core/conftest.py @@ -27,7 +27,7 @@ ToolProtocol, tool, ) -from agent_framework._clients import TOptions_co +from agent_framework._clients import OptionsCoT from agent_framework.observability import ChatTelemetryLayer if sys.version_info >= (3, 12): @@ -135,11 +135,11 @@ def _finalize(updates: Sequence[ChatResponseUpdate]) -> ChatResponse: class MockBaseChatClient( - ChatMiddlewareLayer[TOptions_co], - FunctionInvocationLayer[TOptions_co], - ChatTelemetryLayer[TOptions_co], - BaseChatClient[TOptions_co], - Generic[TOptions_co], + ChatMiddlewareLayer[OptionsCoT], + FunctionInvocationLayer[OptionsCoT], + ChatTelemetryLayer[OptionsCoT], + BaseChatClient[OptionsCoT], + Generic[OptionsCoT], ): """Mock implementation of a full-featured ChatClient.""" diff --git a/python/packages/declarative/agent_framework_declarative/_models.py b/python/packages/declarative/agent_framework_declarative/_models.py index 107978e36b..38bcbdd855 100644 --- a/python/packages/declarative/agent_framework_declarative/_models.py +++ b/python/packages/declarative/agent_framework_declarative/_models.py @@ -232,7 +232,7 @@ def to_json_schema(self) -> dict[str, Any]: return json_schema -TConnection = TypeVar("TConnection", bound="Connection") +ConnectionT = TypeVar("ConnectionT", bound="Connection") class Connection(SerializationMixin): @@ -250,12 +250,12 @@ def __init__( @classmethod def from_dict( - cls: type[TConnection], + cls: type[ConnectionT], value: MutableMapping[str, Any], /, *, dependencies: MutableMapping[str, Any] | None = None, - ) -> TConnection: + ) -> ConnectionT: """Create a Connection instance from a dictionary, dispatching to the appropriate subclass.""" # Only dispatch if we're being called on the base Connection class if cls is not Connection: @@ -507,7 +507,7 @@ def from_dict( return SerializationMixin.from_dict.__func__(cls, value, dependencies=dependencies) # type: ignore[attr-defined, no-any-return] -TTool = TypeVar("TTool", bound="Tool") +ToolT = TypeVar("ToolT", bound="Tool") class Tool(SerializationMixin): @@ -538,8 +538,8 @@ def __init__( @classmethod def from_dict( - cls: type[TTool], value: MutableMapping[str, Any], /, *, dependencies: MutableMapping[str, Any] | None = None - ) -> TTool: + cls: type[ToolT], value: MutableMapping[str, Any], /, *, dependencies: MutableMapping[str, Any] | None = None + ) -> ToolT: """Create a Tool instance from a dictionary, dispatching to the appropriate subclass.""" # Only dispatch if we're being called on the base Tool class if cls is not Tool: diff --git a/python/packages/devui/tests/devui/conftest.py b/python/packages/devui/tests/devui/conftest.py index b229b0e9e6..4d6f818795 100644 --- a/python/packages/devui/tests/devui/conftest.py +++ b/python/packages/devui/tests/devui/conftest.py @@ -29,7 +29,7 @@ Content, ResponseStream, ) -from agent_framework._clients import TOptions_co +from agent_framework._clients import OptionsCoT from agent_framework._workflows._agent_executor import AgentExecutorResponse from agent_framework._workflows._events import ( WorkflowErrorDetails, @@ -88,7 +88,7 @@ async def get_streaming_response( yield ChatResponseUpdate(contents=[Content.from_text(text="test streaming response")], role="assistant") -class MockBaseChatClient(BaseChatClient[TOptions_co], Generic[TOptions_co]): +class MockBaseChatClient(BaseChatClient[OptionsCoT], Generic[OptionsCoT]): """Full BaseChatClient mock with middleware support. Use this when testing features that require the full BaseChatClient interface. diff --git a/python/packages/durabletask/tests/test_durable_entities.py b/python/packages/durabletask/tests/test_durable_entities.py index e4516f1ce3..03e26784cc 100644 --- a/python/packages/durabletask/tests/test_durable_entities.py +++ b/python/packages/durabletask/tests/test_durable_entities.py @@ -26,7 +26,7 @@ ) from agent_framework_durabletask._entities import DurableTaskEntityStateProvider -TState = TypeVar("TState") +StateT = TypeVar("StateT") class MockEntityContext: @@ -37,8 +37,8 @@ def __init__(self, initial_state: Any = None) -> None: def get_state( self, - intended_type: type[TState] | None = None, - default: TState | None = None, + intended_type: type[StateT] | None = None, + default: StateT | None = None, ) -> Any: del intended_type if self._state is None: diff --git a/python/packages/foundry_local/agent_framework_foundry_local/_foundry_local_client.py b/python/packages/foundry_local/agent_framework_foundry_local/_foundry_local_client.py index 0ee6ce4ab0..5cf9e8c85d 100644 --- a/python/packages/foundry_local/agent_framework_foundry_local/_foundry_local_client.py +++ b/python/packages/foundry_local/agent_framework_foundry_local/_foundry_local_client.py @@ -38,13 +38,13 @@ "FoundryLocalSettings", ] -TResponseModel = TypeVar("TResponseModel", bound=BaseModel | None, default=None) +ResponseModelT = TypeVar("ResponseModelT", bound=BaseModel | None, default=None) # region Foundry Local Chat Options TypedDict -class FoundryLocalChatOptions(ChatOptions[TResponseModel], Generic[TResponseModel], total=False): +class FoundryLocalChatOptions(ChatOptions[ResponseModelT], Generic[ResponseModelT], total=False): """Azure Foundry Local (local model deployment) chat options dict. Extends base ChatOptions for local model inference via Foundry Local. @@ -104,8 +104,8 @@ class FoundryLocalChatOptions(ChatOptions[TResponseModel], Generic[TResponseMode } """Maps ChatOptions keys to OpenAI API parameter names (for compatibility).""" -TFoundryLocalChatOptions = TypeVar( - "TFoundryLocalChatOptions", +FoundryLocalChatOptionsT = TypeVar( + "FoundryLocalChatOptionsT", bound=TypedDict, # type: ignore[valid-type] default="FoundryLocalChatOptions", covariant=True, @@ -137,11 +137,11 @@ class FoundryLocalSettings(AFBaseSettings): class FoundryLocalClient( - ChatMiddlewareLayer[TFoundryLocalChatOptions], - FunctionInvocationLayer[TFoundryLocalChatOptions], - ChatTelemetryLayer[TFoundryLocalChatOptions], - RawOpenAIChatClient[TFoundryLocalChatOptions], - Generic[TFoundryLocalChatOptions], + ChatMiddlewareLayer[FoundryLocalChatOptionsT], + FunctionInvocationLayer[FoundryLocalChatOptionsT], + ChatTelemetryLayer[FoundryLocalChatOptionsT], + RawOpenAIChatClient[FoundryLocalChatOptionsT], + Generic[FoundryLocalChatOptionsT], ): """Foundry Local Chat completion class with middleware, telemetry, and function invocation support.""" diff --git a/python/packages/github_copilot/agent_framework_github_copilot/_agent.py b/python/packages/github_copilot/agent_framework_github_copilot/_agent.py index 46a92a6dc9..06fad5d126 100644 --- a/python/packages/github_copilot/agent_framework_github_copilot/_agent.py +++ b/python/packages/github_copilot/agent_framework_github_copilot/_agent.py @@ -91,15 +91,15 @@ class GitHubCopilotOptions(TypedDict, total=False): """ -TOptions = TypeVar( - "TOptions", +OptionsT = TypeVar( + "OptionsT", bound=TypedDict, # type: ignore[valid-type] default="GitHubCopilotOptions", covariant=True, ) -class GitHubCopilotAgent(BaseAgent, Generic[TOptions]): +class GitHubCopilotAgent(BaseAgent, Generic[OptionsT]): """A GitHub Copilot Agent. This agent wraps the GitHub Copilot SDK to provide Copilot agentic capabilities @@ -156,7 +156,7 @@ def __init__( | MutableMapping[str, Any] | Sequence[ToolProtocol | Callable[..., Any] | MutableMapping[str, Any]] | None = None, - default_options: TOptions | None = None, + default_options: OptionsT | None = None, env_file_path: str | None = None, env_file_encoding: str | None = None, ) -> None: @@ -225,7 +225,7 @@ def __init__( self._default_options = opts self._started = False - async def __aenter__(self) -> GitHubCopilotAgent[TOptions]: + async def __aenter__(self) -> GitHubCopilotAgent[OptionsT]: """Start the agent when entering async context.""" await self.start() return self @@ -282,7 +282,7 @@ def run( *, stream: Literal[False] = False, thread: AgentThread | None = None, - options: TOptions | None = None, + options: OptionsT | None = None, **kwargs: Any, ) -> Awaitable[AgentResponse]: ... @@ -293,7 +293,7 @@ def run( *, stream: Literal[True], thread: AgentThread | None = None, - options: TOptions | None = None, + options: OptionsT | None = None, **kwargs: Any, ) -> ResponseStream[AgentResponseUpdate, AgentResponse]: ... @@ -303,7 +303,7 @@ def run( *, stream: bool = False, thread: AgentThread | None = None, - options: TOptions | None = None, + options: OptionsT | None = None, **kwargs: Any, ) -> Awaitable[AgentResponse] | ResponseStream[AgentResponseUpdate, AgentResponse]: """Get a response from the agent. @@ -344,7 +344,7 @@ async def _run_impl( messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None, *, thread: AgentThread | None = None, - options: TOptions | None = None, + options: OptionsT | None = None, **kwargs: Any, ) -> AgentResponse: """Non-streaming implementation of run.""" @@ -392,7 +392,7 @@ async def _stream_updates( messages: str | ChatMessage | Sequence[str | ChatMessage] | None = None, *, thread: AgentThread | None = None, - options: TOptions | None = None, + options: OptionsT | None = None, **kwargs: Any, ) -> AsyncIterable[AgentResponseUpdate]: """Internal method to stream updates from GitHub Copilot. diff --git a/python/packages/ollama/agent_framework_ollama/_chat_client.py b/python/packages/ollama/agent_framework_ollama/_chat_client.py index 684e5c6d9d..8ffba3be3e 100644 --- a/python/packages/ollama/agent_framework_ollama/_chat_client.py +++ b/python/packages/ollama/agent_framework_ollama/_chat_client.py @@ -65,13 +65,13 @@ __all__ = ["OllamaChatClient", "OllamaChatOptions"] -TResponseModel = TypeVar("TResponseModel", bound=BaseModel | None, default=None) +ResponseModelT = TypeVar("ResponseModelT", bound=BaseModel | None, default=None) # region Ollama Chat Options TypedDict -class OllamaChatOptions(ChatOptions[TResponseModel], Generic[TResponseModel], total=False): +class OllamaChatOptions(ChatOptions[ResponseModelT], Generic[ResponseModelT], total=False): """Ollama-specific chat options dict. Extends base ChatOptions with Ollama-specific parameters. @@ -272,7 +272,7 @@ class OllamaChatOptions(ChatOptions[TResponseModel], Generic[TResponseModel], to } """Maps ChatOptions keys to Ollama model option parameter names.""" -TOllamaChatOptions = TypeVar("TOllamaChatOptions", bound=TypedDict, default="OllamaChatOptions", covariant=True) # type: ignore[valid-type] +OllamaChatOptionsT = TypeVar("OllamaChatOptionsT", bound=TypedDict, default="OllamaChatOptions", covariant=True) # type: ignore[valid-type] # endregion @@ -291,10 +291,10 @@ class OllamaSettings(AFBaseSettings): class OllamaChatClient( - ChatMiddlewareLayer[TOllamaChatOptions], - FunctionInvocationLayer[TOllamaChatOptions], - ChatTelemetryLayer[TOllamaChatOptions], - BaseChatClient[TOllamaChatOptions], + ChatMiddlewareLayer[OllamaChatOptionsT], + FunctionInvocationLayer[OllamaChatOptionsT], + ChatTelemetryLayer[OllamaChatOptionsT], + BaseChatClient[OllamaChatOptionsT], ): """Ollama Chat completion class with middleware, telemetry, and function invocation support.""" diff --git a/python/packages/purview/agent_framework_purview/_models.py b/python/packages/purview/agent_framework_purview/_models.py index 4e14147ac5..0e4985689e 100644 --- a/python/packages/purview/agent_framework_purview/_models.py +++ b/python/packages/purview/agent_framework_purview/_models.py @@ -177,7 +177,7 @@ def translate_activity(activity: Activity) -> ProtectionScopeActivities: # Simple value models # -------------------------------------------------------------------------------------- -TAliasSerializable = TypeVar("TAliasSerializable", bound="_AliasSerializable") +AliasSerializableT = TypeVar("AliasSerializableT", bound="_AliasSerializable") class _AliasSerializable(SerializationMixin): @@ -232,7 +232,7 @@ def model_dump_json(self, *, by_alias: bool = True, exclude_none: bool = True, * return json.dumps(self.model_dump(by_alias=by_alias, exclude_none=exclude_none, **kwargs)) @classmethod - def model_validate(cls: type[TAliasSerializable], value: MutableMapping[str, Any]) -> TAliasSerializable: # type: ignore[name-defined] + def model_validate(cls: type[AliasSerializableT], value: MutableMapping[str, Any]) -> AliasSerializableT: # type: ignore[name-defined] return cls(**value) # ------------------------------------------------------------------ diff --git a/python/samples/getting_started/chat_client/custom_chat_client.py b/python/samples/getting_started/chat_client/custom_chat_client.py index af56e5456f..149b7230e1 100644 --- a/python/samples/getting_started/chat_client/custom_chat_client.py +++ b/python/samples/getting_started/chat_client/custom_chat_client.py @@ -17,7 +17,7 @@ ResponseStream, Role, ) -from agent_framework._clients import TOptions_co +from agent_framework._clients import OptionsCoT from agent_framework.observability import ChatTelemetryLayer if sys.version_info >= (3, 13): @@ -38,7 +38,7 @@ """ -class EchoingChatClient(BaseChatClient[TOptions_co], Generic[TOptions_co]): +class EchoingChatClient(BaseChatClient[OptionsCoT], Generic[OptionsCoT]): """A custom chat client that echoes messages back with modifications. This demonstrates how to implement a custom chat client by extending BaseChatClient @@ -112,11 +112,11 @@ async def _stream() -> AsyncIterable[ChatResponseUpdate]: class EchoingChatClientWithLayers( # type: ignore[misc,type-var] - ChatMiddlewareLayer[TOptions_co], - ChatTelemetryLayer[TOptions_co], - FunctionInvocationLayer[TOptions_co], - EchoingChatClient[TOptions_co], - Generic[TOptions_co], + ChatMiddlewareLayer[OptionsCoT], + ChatTelemetryLayer[OptionsCoT], + FunctionInvocationLayer[OptionsCoT], + EchoingChatClient[OptionsCoT], + Generic[OptionsCoT], ): """Echoing chat client that explicitly composes middleware, telemetry, and function layers.""" diff --git a/python/samples/getting_started/observability/configure_otel_providers_with_parameters.py b/python/samples/getting_started/observability/configure_otel_providers_with_parameters.py index a5b0b3d7a8..e82cbdb2be 100644 --- a/python/samples/getting_started/observability/configure_otel_providers_with_parameters.py +++ b/python/samples/getting_started/observability/configure_otel_providers_with_parameters.py @@ -106,9 +106,15 @@ async def main(scenario: Literal["chat_client", "chat_client_stream", "tool", "a # Create custom OTLP exporters with specific configuration # Note: You need to install opentelemetry-exporter-otlp-proto-grpc or -http separately try: - from opentelemetry.exporter.otlp.proto.grpc._log_exporter import OTLPLogExporter - from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter - from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter + from opentelemetry.exporter.otlp.proto.grpc._log_exporter import ( # pyright: ignore[reportMissingImports] + OTLPLogExporter, + ) + from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import ( # pyright: ignore[reportMissingImports] + OTLPMetricExporter, + ) + from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import ( # pyright: ignore[reportMissingImports] + OTLPSpanExporter, + ) # Create exporters with custom configuration # These will be added to any exporters configured via environment variables diff --git a/python/uv.lock b/python/uv.lock index e762f40433..26d806817c 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -1542,101 +1542,115 @@ wheels = [ [[package]] name = "coverage" -version = "7.13.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/11/43/3e4ac666cc35f231fa70c94e9f38459299de1a152813f9d2f60fc5f3ecaf/coverage-7.13.3.tar.gz", hash = "sha256:f7f6182d3dfb8802c1747eacbfe611b669455b69b7c037484bb1efbbb56711ac", size = 826832, upload-time = "2026-02-03T14:02:30.944Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/07/1c8099563a8a6c389a31c2d0aa1497cee86d6248bb4b9ba5e779215db9f9/coverage-7.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0b4f345f7265cdbdb5ec2521ffff15fa49de6d6c39abf89fc7ad68aa9e3a55f0", size = 219143, upload-time = "2026-02-03T13:59:40.459Z" }, - { url = "https://files.pythonhosted.org/packages/69/39/a892d44af7aa092cab70e0cc5cdbba18eeccfe1d6930695dab1742eef9e9/coverage-7.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96c3be8bae9d0333e403cc1a8eb078a7f928b5650bae94a18fb4820cc993fb9b", size = 219663, upload-time = "2026-02-03T13:59:41.951Z" }, - { url = "https://files.pythonhosted.org/packages/9a/25/9669dcf4c2bb4c3861469e6db20e52e8c11908cf53c14ec9b12e9fd4d602/coverage-7.13.3-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d6f4a21328ea49d38565b55599e1c02834e76583a6953e5586d65cb1efebd8f8", size = 246424, upload-time = "2026-02-03T13:59:43.418Z" }, - { url = "https://files.pythonhosted.org/packages/f3/68/d9766c4e298aca62ea5d9543e1dd1e4e1439d7284815244d8b7db1840bfb/coverage-7.13.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fc970575799a9d17d5c3fafd83a0f6ccf5d5117cdc9ad6fbd791e9ead82418b0", size = 248228, upload-time = "2026-02-03T13:59:44.816Z" }, - { url = "https://files.pythonhosted.org/packages/f0/e2/eea6cb4a4bd443741adf008d4cccec83a1f75401df59b6559aca2bdd9710/coverage-7.13.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:87ff33b652b3556b05e204ae20793d1f872161b0fa5ec8a9ac76f8430e152ed6", size = 250103, upload-time = "2026-02-03T13:59:46.271Z" }, - { url = "https://files.pythonhosted.org/packages/db/77/664280ecd666c2191610842177e2fab9e5dbdeef97178e2078fed46a3d2c/coverage-7.13.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7df8759ee57b9f3f7b66799b7660c282f4375bef620ade1686d6a7b03699e75f", size = 247107, upload-time = "2026-02-03T13:59:48.53Z" }, - { url = "https://files.pythonhosted.org/packages/2b/df/2a672eab99e0d0eba52d8a63e47dc92245eee26954d1b2d3c8f7d372151f/coverage-7.13.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f45c9bcb16bee25a798ccba8a2f6a1251b19de6a0d617bb365d7d2f386c4e20e", size = 248143, upload-time = "2026-02-03T13:59:50.027Z" }, - { url = "https://files.pythonhosted.org/packages/a5/dc/a104e7a87c13e57a358b8b9199a8955676e1703bb372d79722b54978ae45/coverage-7.13.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:318b2e4753cbf611061e01b6cc81477e1cdfeb69c36c4a14e6595e674caadb56", size = 246148, upload-time = "2026-02-03T13:59:52.025Z" }, - { url = "https://files.pythonhosted.org/packages/2b/89/e113d3a58dc20b03b7e59aed1e53ebc9ca6167f961876443e002b10e3ae9/coverage-7.13.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:24db3959de8ee394eeeca89ccb8ba25305c2da9a668dd44173394cbd5aa0777f", size = 246414, upload-time = "2026-02-03T13:59:53.859Z" }, - { url = "https://files.pythonhosted.org/packages/3f/60/a3fd0a6e8d89b488396019a2268b6a1f25ab56d6d18f3be50f35d77b47dc/coverage-7.13.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:be14d0622125edef21b3a4d8cd2d138c4872bf6e38adc90fd92385e3312f406a", size = 247023, upload-time = "2026-02-03T13:59:55.454Z" }, - { url = "https://files.pythonhosted.org/packages/19/fa/de4840bb939dbb22ba0648a6d8069fa91c9cf3b3fca8b0d1df461e885b3d/coverage-7.13.3-cp310-cp310-win32.whl", hash = "sha256:53be4aab8ddef18beb6188f3a3fdbf4d1af2277d098d4e618be3a8e6c88e74be", size = 221751, upload-time = "2026-02-03T13:59:57.383Z" }, - { url = "https://files.pythonhosted.org/packages/de/87/233ff8b7ef62fb63f58c78623b50bef69681111e0c4d43504f422d88cda4/coverage-7.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:bfeee64ad8b4aae3233abb77eb6b52b51b05fa89da9645518671b9939a78732b", size = 222686, upload-time = "2026-02-03T13:59:58.825Z" }, - { url = "https://files.pythonhosted.org/packages/ec/09/1ac74e37cf45f17eb41e11a21854f7f92a4c2d6c6098ef4a1becb0c6d8d3/coverage-7.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5907605ee20e126eeee2abe14aae137043c2c8af2fa9b38d2ab3b7a6b8137f73", size = 219276, upload-time = "2026-02-03T14:00:00.296Z" }, - { url = "https://files.pythonhosted.org/packages/2e/cb/71908b08b21beb2c437d0d5870c4ec129c570ca1b386a8427fcdb11cf89c/coverage-7.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a88705500988c8acad8b8fd86c2a933d3aa96bec1ddc4bc5cb256360db7bbd00", size = 219776, upload-time = "2026-02-03T14:00:02.414Z" }, - { url = "https://files.pythonhosted.org/packages/09/85/c4f3dd69232887666a2c0394d4be21c60ea934d404db068e6c96aa59cd87/coverage-7.13.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7bbb5aa9016c4c29e3432e087aa29ebee3f8fda089cfbfb4e6d64bd292dcd1c2", size = 250196, upload-time = "2026-02-03T14:00:04.197Z" }, - { url = "https://files.pythonhosted.org/packages/9c/cc/560ad6f12010344d0778e268df5ba9aa990aacccc310d478bf82bf3d302c/coverage-7.13.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0c2be202a83dde768937a61cdc5d06bf9fb204048ca199d93479488e6247656c", size = 252111, upload-time = "2026-02-03T14:00:05.639Z" }, - { url = "https://files.pythonhosted.org/packages/f0/66/3193985fb2c58e91f94cfbe9e21a6fdf941e9301fe2be9e92c072e9c8f8c/coverage-7.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f45e32ef383ce56e0ca099b2e02fcdf7950be4b1b56afaab27b4ad790befe5b", size = 254217, upload-time = "2026-02-03T14:00:07.738Z" }, - { url = "https://files.pythonhosted.org/packages/c5/78/f0f91556bf1faa416792e537c523c5ef9db9b1d32a50572c102b3d7c45b3/coverage-7.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6ed2e787249b922a93cd95c671cc9f4c9797a106e81b455c83a9ddb9d34590c0", size = 250318, upload-time = "2026-02-03T14:00:09.224Z" }, - { url = "https://files.pythonhosted.org/packages/6f/aa/fc654e45e837d137b2c1f3a2cc09b4aea1e8b015acd2f774fa0f3d2ddeba/coverage-7.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:05dd25b21afffe545e808265897c35f32d3e4437663923e0d256d9ab5031fb14", size = 251909, upload-time = "2026-02-03T14:00:10.712Z" }, - { url = "https://files.pythonhosted.org/packages/73/4d/ab53063992add8a9ca0463c9d92cce5994a29e17affd1c2daa091b922a93/coverage-7.13.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:46d29926349b5c4f1ea4fca95e8c892835515f3600995a383fa9a923b5739ea4", size = 249971, upload-time = "2026-02-03T14:00:12.402Z" }, - { url = "https://files.pythonhosted.org/packages/29/25/83694b81e46fcff9899694a1b6f57573429cdd82b57932f09a698f03eea5/coverage-7.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:fae6a21537519c2af00245e834e5bf2884699cc7c1055738fd0f9dc37a3644ad", size = 249692, upload-time = "2026-02-03T14:00:13.868Z" }, - { url = "https://files.pythonhosted.org/packages/d4/ef/d68fc304301f4cb4bf6aefa0045310520789ca38dabdfba9dbecd3f37919/coverage-7.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c672d4e2f0575a4ca2bf2aa0c5ced5188220ab806c1bb6d7179f70a11a017222", size = 250597, upload-time = "2026-02-03T14:00:15.461Z" }, - { url = "https://files.pythonhosted.org/packages/8d/85/240ad396f914df361d0f71e912ddcedb48130c71b88dc4193fe3c0306f00/coverage-7.13.3-cp311-cp311-win32.whl", hash = "sha256:fcda51c918c7a13ad93b5f89a58d56e3a072c9e0ba5c231b0ed81404bf2648fb", size = 221773, upload-time = "2026-02-03T14:00:17.462Z" }, - { url = "https://files.pythonhosted.org/packages/2f/71/165b3a6d3d052704a9ab52d11ea64ef3426745de517dda44d872716213a7/coverage-7.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:d1a049b5c51b3b679928dd35e47c4a2235e0b6128b479a7596d0ef5b42fa6301", size = 222711, upload-time = "2026-02-03T14:00:19.449Z" }, - { url = "https://files.pythonhosted.org/packages/51/d0/0ddc9c5934cdd52639c5df1f1eb0fdab51bb52348f3a8d1c7db9c600d93a/coverage-7.13.3-cp311-cp311-win_arm64.whl", hash = "sha256:79f2670c7e772f4917895c3d89aad59e01f3dbe68a4ed2d0373b431fad1dcfba", size = 221377, upload-time = "2026-02-03T14:00:20.968Z" }, - { url = "https://files.pythonhosted.org/packages/94/44/330f8e83b143f6668778ed61d17ece9dc48459e9e74669177de02f45fec5/coverage-7.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ed48b4170caa2c4420e0cd27dc977caaffc7eecc317355751df8373dddcef595", size = 219441, upload-time = "2026-02-03T14:00:22.585Z" }, - { url = "https://files.pythonhosted.org/packages/08/e7/29db05693562c2e65bdf6910c0af2fd6f9325b8f43caf7a258413f369e30/coverage-7.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8f2adf4bcffbbec41f366f2e6dffb9d24e8172d16e91da5799c9b7ed6b5716e6", size = 219801, upload-time = "2026-02-03T14:00:24.186Z" }, - { url = "https://files.pythonhosted.org/packages/90/ae/7f8a78249b02b0818db46220795f8ac8312ea4abd1d37d79ea81db5cae81/coverage-7.13.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:01119735c690786b6966a1e9f098da4cd7ca9174c4cfe076d04e653105488395", size = 251306, upload-time = "2026-02-03T14:00:25.798Z" }, - { url = "https://files.pythonhosted.org/packages/62/71/a18a53d1808e09b2e9ebd6b47dad5e92daf4c38b0686b4c4d1b2f3e42b7f/coverage-7.13.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8bb09e83c603f152d855f666d70a71765ca8e67332e5829e62cb9466c176af23", size = 254051, upload-time = "2026-02-03T14:00:27.474Z" }, - { url = "https://files.pythonhosted.org/packages/4a/0a/eb30f6455d04c5a3396d0696cad2df0269ae7444bb322f86ffe3376f7bf9/coverage-7.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b607a40cba795cfac6d130220d25962931ce101f2f478a29822b19755377fb34", size = 255160, upload-time = "2026-02-03T14:00:29.024Z" }, - { url = "https://files.pythonhosted.org/packages/7b/7e/a45baac86274ce3ed842dbb84f14560c673ad30535f397d89164ec56c5df/coverage-7.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:44f14a62f5da2e9aedf9080e01d2cda61df39197d48e323538ec037336d68da8", size = 251709, upload-time = "2026-02-03T14:00:30.641Z" }, - { url = "https://files.pythonhosted.org/packages/c0/df/dd0dc12f30da11349993f3e218901fdf82f45ee44773596050c8f5a1fb25/coverage-7.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:debf29e0b157769843dff0981cc76f79e0ed04e36bb773c6cac5f6029054bd8a", size = 253083, upload-time = "2026-02-03T14:00:32.14Z" }, - { url = "https://files.pythonhosted.org/packages/ab/32/fc764c8389a8ce95cb90eb97af4c32f392ab0ac23ec57cadeefb887188d3/coverage-7.13.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:824bb95cd71604031ae9a48edb91fd6effde669522f960375668ed21b36e3ec4", size = 251227, upload-time = "2026-02-03T14:00:34.721Z" }, - { url = "https://files.pythonhosted.org/packages/dd/ca/d025e9da8f06f24c34d2da9873957cfc5f7e0d67802c3e34d0caa8452130/coverage-7.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8f1010029a5b52dc427c8e2a8dbddb2303ddd180b806687d1acd1bb1d06649e7", size = 250794, upload-time = "2026-02-03T14:00:36.278Z" }, - { url = "https://files.pythonhosted.org/packages/45/c7/76bf35d5d488ec8f68682eb8e7671acc50a6d2d1c1182de1d2b6d4ffad3b/coverage-7.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cd5dee4fd7659d8306ffa79eeaaafd91fa30a302dac3af723b9b469e549247e0", size = 252671, upload-time = "2026-02-03T14:00:38.368Z" }, - { url = "https://files.pythonhosted.org/packages/bf/10/1921f1a03a7c209e1cb374f81a6b9b68b03cdb3ecc3433c189bc90e2a3d5/coverage-7.13.3-cp312-cp312-win32.whl", hash = "sha256:f7f153d0184d45f3873b3ad3ad22694fd73aadcb8cdbc4337ab4b41ea6b4dff1", size = 221986, upload-time = "2026-02-03T14:00:40.442Z" }, - { url = "https://files.pythonhosted.org/packages/3c/7c/f5d93297f8e125a80c15545edc754d93e0ed8ba255b65e609b185296af01/coverage-7.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:03a6e5e1e50819d6d7436f5bc40c92ded7e484e400716886ac921e35c133149d", size = 222793, upload-time = "2026-02-03T14:00:42.106Z" }, - { url = "https://files.pythonhosted.org/packages/43/59/c86b84170015b4555ebabca8649bdf9f4a1f737a73168088385ed0f947c4/coverage-7.13.3-cp312-cp312-win_arm64.whl", hash = "sha256:51c4c42c0e7d09a822b08b6cf79b3c4db8333fffde7450da946719ba0d45730f", size = 221410, upload-time = "2026-02-03T14:00:43.726Z" }, - { url = "https://files.pythonhosted.org/packages/81/f3/4c333da7b373e8c8bfb62517e8174a01dcc373d7a9083698e3b39d50d59c/coverage-7.13.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:853c3d3c79ff0db65797aad79dee6be020efd218ac4510f15a205f1e8d13ce25", size = 219468, upload-time = "2026-02-03T14:00:45.829Z" }, - { url = "https://files.pythonhosted.org/packages/d6/31/0714337b7d23630c8de2f4d56acf43c65f8728a45ed529b34410683f7217/coverage-7.13.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f75695e157c83d374f88dcc646a60cb94173304a9258b2e74ba5a66b7614a51a", size = 219839, upload-time = "2026-02-03T14:00:47.407Z" }, - { url = "https://files.pythonhosted.org/packages/12/99/bd6f2a2738144c98945666f90cae446ed870cecf0421c767475fcf42cdbe/coverage-7.13.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2d098709621d0819039f3f1e471ee554f55a0b2ac0d816883c765b14129b5627", size = 250828, upload-time = "2026-02-03T14:00:49.029Z" }, - { url = "https://files.pythonhosted.org/packages/6f/99/97b600225fbf631e6f5bfd3ad5bcaf87fbb9e34ff87492e5a572ff01bbe2/coverage-7.13.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:16d23d6579cf80a474ad160ca14d8b319abaa6db62759d6eef53b2fc979b58c8", size = 253432, upload-time = "2026-02-03T14:00:50.655Z" }, - { url = "https://files.pythonhosted.org/packages/5f/5c/abe2b3490bda26bd4f5e3e799be0bdf00bd81edebedc2c9da8d3ef288fa8/coverage-7.13.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:00d34b29a59d2076e6f318b30a00a69bf63687e30cd882984ed444e753990cc1", size = 254672, upload-time = "2026-02-03T14:00:52.757Z" }, - { url = "https://files.pythonhosted.org/packages/31/ba/5d1957c76b40daff53971fe0adb84d9c2162b614280031d1d0653dd010c1/coverage-7.13.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ab6d72bffac9deb6e6cb0f61042e748de3f9f8e98afb0375a8e64b0b6e11746b", size = 251050, upload-time = "2026-02-03T14:00:54.332Z" }, - { url = "https://files.pythonhosted.org/packages/69/dc/dffdf3bfe9d32090f047d3c3085378558cb4eb6778cda7de414ad74581ed/coverage-7.13.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e129328ad1258e49cae0123a3b5fcb93d6c2fa90d540f0b4c7cdcdc019aaa3dc", size = 252801, upload-time = "2026-02-03T14:00:56.121Z" }, - { url = "https://files.pythonhosted.org/packages/87/51/cdf6198b0f2746e04511a30dc9185d7b8cdd895276c07bdb538e37f1cd50/coverage-7.13.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2213a8d88ed35459bda71597599d4eec7c2ebad201c88f0bfc2c26fd9b0dd2ea", size = 250763, upload-time = "2026-02-03T14:00:58.719Z" }, - { url = "https://files.pythonhosted.org/packages/d7/1a/596b7d62218c1d69f2475b69cc6b211e33c83c902f38ee6ae9766dd422da/coverage-7.13.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:00dd3f02de6d5f5c9c3d95e3e036c3c2e2a669f8bf2d3ceb92505c4ce7838f67", size = 250587, upload-time = "2026-02-03T14:01:01.197Z" }, - { url = "https://files.pythonhosted.org/packages/f7/46/52330d5841ff660f22c130b75f5e1dd3e352c8e7baef5e5fef6b14e3e991/coverage-7.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f9bada7bc660d20b23d7d312ebe29e927b655cf414dadcdb6335a2075695bd86", size = 252358, upload-time = "2026-02-03T14:01:02.824Z" }, - { url = "https://files.pythonhosted.org/packages/36/8a/e69a5be51923097ba7d5cff9724466e74fe486e9232020ba97c809a8b42b/coverage-7.13.3-cp313-cp313-win32.whl", hash = "sha256:75b3c0300f3fa15809bd62d9ca8b170eb21fcf0100eb4b4154d6dc8b3a5bbd43", size = 222007, upload-time = "2026-02-03T14:01:04.876Z" }, - { url = "https://files.pythonhosted.org/packages/0a/09/a5a069bcee0d613bdd48ee7637fa73bc09e7ed4342b26890f2df97cc9682/coverage-7.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:a2f7589c6132c44c53f6e705e1a6677e2b7821378c22f7703b2cf5388d0d4587", size = 222812, upload-time = "2026-02-03T14:01:07.296Z" }, - { url = "https://files.pythonhosted.org/packages/3d/4f/d62ad7dfe32f9e3d4a10c178bb6f98b10b083d6e0530ca202b399371f6c1/coverage-7.13.3-cp313-cp313-win_arm64.whl", hash = "sha256:123ceaf2b9d8c614f01110f908a341e05b1b305d6b2ada98763b9a5a59756051", size = 221433, upload-time = "2026-02-03T14:01:09.156Z" }, - { url = "https://files.pythonhosted.org/packages/04/b2/4876c46d723d80b9c5b695f1a11bf5f7c3dabf540ec00d6edc076ff025e6/coverage-7.13.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:cc7fd0f726795420f3678ac82ff882c7fc33770bd0074463b5aef7293285ace9", size = 220162, upload-time = "2026-02-03T14:01:11.409Z" }, - { url = "https://files.pythonhosted.org/packages/fc/04/9942b64a0e0bdda2c109f56bda42b2a59d9d3df4c94b85a323c1cae9fc77/coverage-7.13.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d358dc408edc28730aed5477a69338e444e62fba0b7e9e4a131c505fadad691e", size = 220510, upload-time = "2026-02-03T14:01:13.038Z" }, - { url = "https://files.pythonhosted.org/packages/5a/82/5cfe1e81eae525b74669f9795f37eb3edd4679b873d79d1e6c1c14ee6c1c/coverage-7.13.3-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5d67b9ed6f7b5527b209b24b3df9f2e5bf0198c1bbf99c6971b0e2dcb7e2a107", size = 261801, upload-time = "2026-02-03T14:01:14.674Z" }, - { url = "https://files.pythonhosted.org/packages/0b/ec/a553d7f742fd2cd12e36a16a7b4b3582d5934b496ef2b5ea8abeb10903d4/coverage-7.13.3-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:59224bfb2e9b37c1335ae35d00daa3a5b4e0b1a20f530be208fff1ecfa436f43", size = 263882, upload-time = "2026-02-03T14:01:16.343Z" }, - { url = "https://files.pythonhosted.org/packages/e1/58/8f54a2a93e3d675635bc406de1c9ac8d551312142ff52c9d71b5e533ad45/coverage-7.13.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae9306b5299e31e31e0d3b908c66bcb6e7e3ddca143dea0266e9ce6c667346d3", size = 266306, upload-time = "2026-02-03T14:01:18.02Z" }, - { url = "https://files.pythonhosted.org/packages/1a/be/e593399fd6ea1f00aee79ebd7cc401021f218d34e96682a92e1bae092ff6/coverage-7.13.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:343aaeb5f8bb7bcd38620fd7bc56e6ee8207847d8c6103a1e7b72322d381ba4a", size = 261051, upload-time = "2026-02-03T14:01:19.757Z" }, - { url = "https://files.pythonhosted.org/packages/5c/e5/e9e0f6138b21bcdebccac36fbfde9cf15eb1bbcea9f5b1f35cd1f465fb91/coverage-7.13.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b2182129f4c101272ff5f2f18038d7b698db1bf8e7aa9e615cb48440899ad32e", size = 263868, upload-time = "2026-02-03T14:01:21.487Z" }, - { url = "https://files.pythonhosted.org/packages/9a/bf/de72cfebb69756f2d4a2dde35efcc33c47d85cd3ebdf844b3914aac2ef28/coverage-7.13.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:94d2ac94bd0cc57c5626f52f8c2fffed1444b5ae8c9fc68320306cc2b255e155", size = 261498, upload-time = "2026-02-03T14:01:23.097Z" }, - { url = "https://files.pythonhosted.org/packages/f2/91/4a2d313a70fc2e98ca53afd1c8ce67a89b1944cd996589a5b1fe7fbb3e5c/coverage-7.13.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:65436cde5ecabe26fb2f0bf598962f0a054d3f23ad529361326ac002c61a2a1e", size = 260394, upload-time = "2026-02-03T14:01:24.949Z" }, - { url = "https://files.pythonhosted.org/packages/40/83/25113af7cf6941e779eb7ed8de2a677865b859a07ccee9146d4cc06a03e3/coverage-7.13.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:db83b77f97129813dbd463a67e5335adc6a6a91db652cc085d60c2d512746f96", size = 262579, upload-time = "2026-02-03T14:01:26.703Z" }, - { url = "https://files.pythonhosted.org/packages/1e/19/a5f2b96262977e82fb9aabbe19b4d83561f5d063f18dde3e72f34ffc3b2f/coverage-7.13.3-cp313-cp313t-win32.whl", hash = "sha256:dfb428e41377e6b9ba1b0a32df6db5409cb089a0ed1d0a672dc4953ec110d84f", size = 222679, upload-time = "2026-02-03T14:01:28.553Z" }, - { url = "https://files.pythonhosted.org/packages/81/82/ef1747b88c87a5c7d7edc3704799ebd650189a9158e680a063308b6125ef/coverage-7.13.3-cp313-cp313t-win_amd64.whl", hash = "sha256:5badd7e596e6b0c89aa8ec6d37f4473e4357f982ce57f9a2942b0221cd9cf60c", size = 223740, upload-time = "2026-02-03T14:01:30.776Z" }, - { url = "https://files.pythonhosted.org/packages/1c/4c/a67c7bb5b560241c22736a9cb2f14c5034149ffae18630323fde787339e4/coverage-7.13.3-cp313-cp313t-win_arm64.whl", hash = "sha256:989aa158c0eb19d83c76c26f4ba00dbb272485c56e452010a3450bdbc9daafd9", size = 221996, upload-time = "2026-02-03T14:01:32.495Z" }, - { url = "https://files.pythonhosted.org/packages/5e/b3/677bb43427fed9298905106f39c6520ac75f746f81b8f01104526a8026e4/coverage-7.13.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c6f6169bbdbdb85aab8ac0392d776948907267fcc91deeacf6f9d55f7a83ae3b", size = 219513, upload-time = "2026-02-03T14:01:34.29Z" }, - { url = "https://files.pythonhosted.org/packages/42/53/290046e3bbf8986cdb7366a42dab3440b9983711eaff044a51b11006c67b/coverage-7.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2f5e731627a3d5ef11a2a35aa0c6f7c435867c7ccbc391268eb4f2ca5dbdcc10", size = 219850, upload-time = "2026-02-03T14:01:35.984Z" }, - { url = "https://files.pythonhosted.org/packages/ea/2b/ab41f10345ba2e49d5e299be8663be2b7db33e77ac1b85cd0af985ea6406/coverage-7.13.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9db3a3285d91c0b70fab9f39f0a4aa37d375873677efe4e71e58d8321e8c5d39", size = 250886, upload-time = "2026-02-03T14:01:38.287Z" }, - { url = "https://files.pythonhosted.org/packages/72/2d/b3f6913ee5a1d5cdd04106f257e5fac5d048992ffc2d9995d07b0f17739f/coverage-7.13.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:06e49c5897cb12e3f7ecdc111d44e97c4f6d0557b81a7a0204ed70a8b038f86f", size = 253393, upload-time = "2026-02-03T14:01:40.118Z" }, - { url = "https://files.pythonhosted.org/packages/f0/f6/b1f48810ffc6accf49a35b9943636560768f0812330f7456aa87dc39aff5/coverage-7.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb25061a66802df9fc13a9ba1967d25faa4dae0418db469264fd9860a921dde4", size = 254740, upload-time = "2026-02-03T14:01:42.413Z" }, - { url = "https://files.pythonhosted.org/packages/57/d0/e59c54f9be0b61808f6bc4c8c4346bd79f02dd6bbc3f476ef26124661f20/coverage-7.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:99fee45adbb1caeb914da16f70e557fb7ff6ddc9e4b14de665bd41af631367ef", size = 250905, upload-time = "2026-02-03T14:01:44.163Z" }, - { url = "https://files.pythonhosted.org/packages/d5/f7/5291bcdf498bafbee3796bb32ef6966e9915aebd4d0954123c8eae921c32/coverage-7.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:318002f1fd819bdc1651c619268aa5bc853c35fa5cc6d1e8c96bd9cd6c828b75", size = 252753, upload-time = "2026-02-03T14:01:45.974Z" }, - { url = "https://files.pythonhosted.org/packages/a0/a9/1dcafa918c281554dae6e10ece88c1add82db685be123e1b05c2056ff3fb/coverage-7.13.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:71295f2d1d170b9977dc386d46a7a1b7cbb30e5405492529b4c930113a33f895", size = 250716, upload-time = "2026-02-03T14:01:48.844Z" }, - { url = "https://files.pythonhosted.org/packages/44/bb/4ea4eabcce8c4f6235df6e059fbc5db49107b24c4bdffc44aee81aeca5a8/coverage-7.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5b1ad2e0dc672625c44bc4fe34514602a9fd8b10d52ddc414dc585f74453516c", size = 250530, upload-time = "2026-02-03T14:01:50.793Z" }, - { url = "https://files.pythonhosted.org/packages/6d/31/4a6c9e6a71367e6f923b27b528448c37f4e959b7e4029330523014691007/coverage-7.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b2beb64c145593a50d90db5c7178f55daeae129123b0d265bdb3cbec83e5194a", size = 252186, upload-time = "2026-02-03T14:01:52.607Z" }, - { url = "https://files.pythonhosted.org/packages/27/92/e1451ef6390a4f655dc42da35d9971212f7abbbcad0bdb7af4407897eb76/coverage-7.13.3-cp314-cp314-win32.whl", hash = "sha256:3d1aed4f4e837a832df2f3b4f68a690eede0de4560a2dbc214ea0bc55aabcdb4", size = 222253, upload-time = "2026-02-03T14:01:55.071Z" }, - { url = "https://files.pythonhosted.org/packages/8a/98/78885a861a88de020c32a2693487c37d15a9873372953f0c3c159d575a43/coverage-7.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9f9efbbaf79f935d5fbe3ad814825cbce4f6cdb3054384cb49f0c0f496125fa0", size = 223069, upload-time = "2026-02-03T14:01:56.95Z" }, - { url = "https://files.pythonhosted.org/packages/eb/fb/3784753a48da58a5337972abf7ca58b1fb0f1bda21bc7b4fae992fd28e47/coverage-7.13.3-cp314-cp314-win_arm64.whl", hash = "sha256:31b6e889c53d4e6687ca63706148049494aace140cffece1c4dc6acadb70a7b3", size = 221633, upload-time = "2026-02-03T14:01:58.758Z" }, - { url = "https://files.pythonhosted.org/packages/40/f9/75b732d9674d32cdbffe801ed5f770786dd1c97eecedef2125b0d25102dc/coverage-7.13.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c5e9787cec750793a19a28df7edd85ac4e49d3fb91721afcdc3b86f6c08d9aa8", size = 220243, upload-time = "2026-02-03T14:02:01.109Z" }, - { url = "https://files.pythonhosted.org/packages/cf/7e/2868ec95de5a65703e6f0c87407ea822d1feb3619600fbc3c1c4fa986090/coverage-7.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e5b86db331c682fd0e4be7098e6acee5e8a293f824d41487c667a93705d415ca", size = 220515, upload-time = "2026-02-03T14:02:02.862Z" }, - { url = "https://files.pythonhosted.org/packages/7d/eb/9f0d349652fced20bcaea0f67fc5777bd097c92369f267975732f3dc5f45/coverage-7.13.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:edc7754932682d52cf6e7a71806e529ecd5ce660e630e8bd1d37109a2e5f63ba", size = 261874, upload-time = "2026-02-03T14:02:04.727Z" }, - { url = "https://files.pythonhosted.org/packages/ee/a5/6619bc4a6c7b139b16818149a3e74ab2e21599ff9a7b6811b6afde99f8ec/coverage-7.13.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d3a16d6398666510a6886f67f43d9537bfd0e13aca299688a19daa84f543122f", size = 264004, upload-time = "2026-02-03T14:02:06.634Z" }, - { url = "https://files.pythonhosted.org/packages/29/b7/90aa3fc645a50c6f07881fca4fd0ba21e3bfb6ce3a7078424ea3a35c74c9/coverage-7.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:303d38b19626c1981e1bb067a9928236d88eb0e4479b18a74812f05a82071508", size = 266408, upload-time = "2026-02-03T14:02:09.037Z" }, - { url = "https://files.pythonhosted.org/packages/62/55/08bb2a1e4dcbae384e638f0effef486ba5987b06700e481691891427d879/coverage-7.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:284e06eadfe15ddfee2f4ee56631f164ef897a7d7d5a15bca5f0bb88889fc5ba", size = 260977, upload-time = "2026-02-03T14:02:11.755Z" }, - { url = "https://files.pythonhosted.org/packages/9b/76/8bd4ae055a42d8fb5dd2230e5cf36ff2e05f85f2427e91b11a27fea52ed7/coverage-7.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d401f0864a1d3198422816878e4e84ca89ec1c1bf166ecc0ae01380a39b888cd", size = 263868, upload-time = "2026-02-03T14:02:13.565Z" }, - { url = "https://files.pythonhosted.org/packages/e3/f9/ba000560f11e9e32ec03df5aa8477242c2d95b379c99ac9a7b2e7fbacb1a/coverage-7.13.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3f379b02c18a64de78c4ccdddf1c81c2c5ae1956c72dacb9133d7dd7809794ab", size = 261474, upload-time = "2026-02-03T14:02:16.069Z" }, - { url = "https://files.pythonhosted.org/packages/90/4b/4de4de8f9ca7af4733bfcf4baa440121b7dbb3856daf8428ce91481ff63b/coverage-7.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:7a482f2da9086971efb12daca1d6547007ede3674ea06e16d7663414445c683e", size = 260317, upload-time = "2026-02-03T14:02:17.996Z" }, - { url = "https://files.pythonhosted.org/packages/05/71/5cd8436e2c21410ff70be81f738c0dddea91bcc3189b1517d26e0102ccb3/coverage-7.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:562136b0d401992118d9b49fbee5454e16f95f85b120a4226a04d816e33fe024", size = 262635, upload-time = "2026-02-03T14:02:20.405Z" }, - { url = "https://files.pythonhosted.org/packages/e7/f8/2834bb45bdd70b55a33ec354b8b5f6062fc90e5bb787e14385903a979503/coverage-7.13.3-cp314-cp314t-win32.whl", hash = "sha256:ca46e5c3be3b195098dd88711890b8011a9fa4feca942292bb84714ce5eab5d3", size = 223035, upload-time = "2026-02-03T14:02:22.323Z" }, - { url = "https://files.pythonhosted.org/packages/26/75/f8290f0073c00d9ae14056d2b84ab92dff21d5370e464cb6cb06f52bf580/coverage-7.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:06d316dbb3d9fd44cca05b2dbcfbef22948493d63a1f28e828d43e6cc505fed8", size = 224142, upload-time = "2026-02-03T14:02:24.143Z" }, - { url = "https://files.pythonhosted.org/packages/03/01/43ac78dfea8946c4a9161bbc034b5549115cb2b56781a4b574927f0d141a/coverage-7.13.3-cp314-cp314t-win_arm64.whl", hash = "sha256:299d66e9218193f9dc6e4880629ed7c4cd23486005166247c283fb98531656c3", size = 222166, upload-time = "2026-02-03T14:02:26.005Z" }, - { url = "https://files.pythonhosted.org/packages/7d/fb/70af542d2d938c778c9373ce253aa4116dbe7c0a5672f78b2b2ae0e1b94b/coverage-7.13.3-py3-none-any.whl", hash = "sha256:90a8af9dba6429b2573199622d72e0ebf024d6276f16abce394ad4d181bb0910", size = 211237, upload-time = "2026-02-03T14:02:27.986Z" }, +version = "7.13.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/56/95b7e30fa389756cb56630faa728da46a27b8c6eb46f9d557c68fff12b65/coverage-7.13.4.tar.gz", hash = "sha256:e5c8f6ed1e61a8b2dcdf31eb0b9bbf0130750ca79c1c49eb898e2ad86f5ccc91", size = 827239, upload-time = "2026-02-09T12:59:03.86Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/d4/7827d9ffa34d5d4d752eec907022aa417120936282fc488306f5da08c292/coverage-7.13.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0fc31c787a84f8cd6027eba44010517020e0d18487064cd3d8968941856d1415", size = 219152, upload-time = "2026-02-09T12:56:11.974Z" }, + { url = "https://files.pythonhosted.org/packages/35/b0/d69df26607c64043292644dbb9dc54b0856fabaa2cbb1eeee3331cc9e280/coverage-7.13.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a32ebc02a1805adf637fc8dec324b5cdacd2e493515424f70ee33799573d661b", size = 219667, upload-time = "2026-02-09T12:56:13.33Z" }, + { url = "https://files.pythonhosted.org/packages/82/a4/c1523f7c9e47b2271dbf8c2a097e7a1f89ef0d66f5840bb59b7e8814157b/coverage-7.13.4-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e24f9156097ff9dc286f2f913df3a7f63c0e333dcafa3c196f2c18b4175ca09a", size = 246425, upload-time = "2026-02-09T12:56:14.552Z" }, + { url = "https://files.pythonhosted.org/packages/f8/02/aa7ec01d1a5023c4b680ab7257f9bfde9defe8fdddfe40be096ac19e8177/coverage-7.13.4-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8041b6c5bfdc03257666e9881d33b1abc88daccaf73f7b6340fb7946655cd10f", size = 248229, upload-time = "2026-02-09T12:56:16.31Z" }, + { url = "https://files.pythonhosted.org/packages/35/98/85aba0aed5126d896162087ef3f0e789a225697245256fc6181b95f47207/coverage-7.13.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2a09cfa6a5862bc2fc6ca7c3def5b2926194a56b8ab78ffcf617d28911123012", size = 250106, upload-time = "2026-02-09T12:56:18.024Z" }, + { url = "https://files.pythonhosted.org/packages/96/72/1db59bd67494bc162e3e4cd5fbc7edba2c7026b22f7c8ef1496d58c2b94c/coverage-7.13.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:296f8b0af861d3970c2a4d8c91d48eb4dd4771bcef9baedec6a9b515d7de3def", size = 252021, upload-time = "2026-02-09T12:56:19.272Z" }, + { url = "https://files.pythonhosted.org/packages/9d/97/72899c59c7066961de6e3daa142d459d47d104956db43e057e034f015c8a/coverage-7.13.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e101609bcbbfb04605ea1027b10dc3735c094d12d40826a60f897b98b1c30256", size = 247114, upload-time = "2026-02-09T12:56:21.051Z" }, + { url = "https://files.pythonhosted.org/packages/39/1f/f1885573b5970235e908da4389176936c8933e86cb316b9620aab1585fa2/coverage-7.13.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:aa3feb8db2e87ff5e6d00d7e1480ae241876286691265657b500886c98f38bda", size = 248143, upload-time = "2026-02-09T12:56:22.585Z" }, + { url = "https://files.pythonhosted.org/packages/a8/cf/e80390c5b7480b722fa3e994f8202807799b85bc562aa4f1dde209fbb7be/coverage-7.13.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4fc7fa81bbaf5a02801b65346c8b3e657f1d93763e58c0abdf7c992addd81a92", size = 246152, upload-time = "2026-02-09T12:56:23.748Z" }, + { url = "https://files.pythonhosted.org/packages/44/bf/f89a8350d85572f95412debb0fb9bb4795b1d5b5232bd652923c759e787b/coverage-7.13.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:33901f604424145c6e9c2398684b92e176c0b12df77d52db81c20abd48c3794c", size = 249959, upload-time = "2026-02-09T12:56:25.209Z" }, + { url = "https://files.pythonhosted.org/packages/f7/6e/612a02aece8178c818df273e8d1642190c4875402ca2ba74514394b27aba/coverage-7.13.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:bb28c0f2cf2782508a40cec377935829d5fcc3ad9a3681375af4e84eb34b6b58", size = 246416, upload-time = "2026-02-09T12:56:26.475Z" }, + { url = "https://files.pythonhosted.org/packages/cb/98/b5afc39af67c2fa6786b03c3a7091fc300947387ce8914b096db8a73d67a/coverage-7.13.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9d107aff57a83222ddbd8d9ee705ede2af2cc926608b57abed8ef96b50b7e8f9", size = 247025, upload-time = "2026-02-09T12:56:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/51/30/2bba8ef0682d5bd210c38fe497e12a06c9f8d663f7025e9f5c2c31ce847d/coverage-7.13.4-cp310-cp310-win32.whl", hash = "sha256:a6f94a7d00eb18f1b6d403c91a88fd58cfc92d4b16080dfdb774afc8294469bf", size = 221758, upload-time = "2026-02-09T12:56:29.051Z" }, + { url = "https://files.pythonhosted.org/packages/78/13/331f94934cf6c092b8ea59ff868eb587bc8fe0893f02c55bc6c0183a192e/coverage-7.13.4-cp310-cp310-win_amd64.whl", hash = "sha256:2cb0f1e000ebc419632bbe04366a8990b6e32c4e0b51543a6484ffe15eaeda95", size = 222693, upload-time = "2026-02-09T12:56:30.366Z" }, + { url = "https://files.pythonhosted.org/packages/b4/ad/b59e5b451cf7172b8d1043dc0fa718f23aab379bc1521ee13d4bd9bfa960/coverage-7.13.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d490ba50c3f35dd7c17953c68f3270e7ccd1c6642e2d2afe2d8e720b98f5a053", size = 219278, upload-time = "2026-02-09T12:56:31.673Z" }, + { url = "https://files.pythonhosted.org/packages/f1/17/0cb7ca3de72e5f4ef2ec2fa0089beafbcaaaead1844e8b8a63d35173d77d/coverage-7.13.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:19bc3c88078789f8ef36acb014d7241961dbf883fd2533d18cb1e7a5b4e28b11", size = 219783, upload-time = "2026-02-09T12:56:33.104Z" }, + { url = "https://files.pythonhosted.org/packages/ab/63/325d8e5b11e0eaf6d0f6a44fad444ae58820929a9b0de943fa377fe73e85/coverage-7.13.4-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3998e5a32e62fdf410c0dbd3115df86297995d6e3429af80b8798aad894ca7aa", size = 250200, upload-time = "2026-02-09T12:56:34.474Z" }, + { url = "https://files.pythonhosted.org/packages/76/53/c16972708cbb79f2942922571a687c52bd109a7bd51175aeb7558dff2236/coverage-7.13.4-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8e264226ec98e01a8e1054314af91ee6cde0eacac4f465cc93b03dbe0bce2fd7", size = 252114, upload-time = "2026-02-09T12:56:35.749Z" }, + { url = "https://files.pythonhosted.org/packages/eb/c2/7ab36d8b8cc412bec9ea2d07c83c48930eb4ba649634ba00cb7e4e0f9017/coverage-7.13.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a3aa4e7b9e416774b21797365b358a6e827ffadaaca81b69ee02946852449f00", size = 254220, upload-time = "2026-02-09T12:56:37.796Z" }, + { url = "https://files.pythonhosted.org/packages/d6/4d/cf52c9a3322c89a0e6febdfbc83bb45c0ed3c64ad14081b9503adee702e7/coverage-7.13.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:71ca20079dd8f27fcf808817e281e90220475cd75115162218d0e27549f95fef", size = 256164, upload-time = "2026-02-09T12:56:39.016Z" }, + { url = "https://files.pythonhosted.org/packages/78/e9/eb1dd17bd6de8289df3580e967e78294f352a5df8a57ff4671ee5fc3dcd0/coverage-7.13.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e2f25215f1a359ab17320b47bcdaca3e6e6356652e8256f2441e4ef972052903", size = 250325, upload-time = "2026-02-09T12:56:40.668Z" }, + { url = "https://files.pythonhosted.org/packages/71/07/8c1542aa873728f72267c07278c5cc0ec91356daf974df21335ccdb46368/coverage-7.13.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d65b2d373032411e86960604dc4edac91fdfb5dca539461cf2cbe78327d1e64f", size = 251913, upload-time = "2026-02-09T12:56:41.97Z" }, + { url = "https://files.pythonhosted.org/packages/74/d7/c62e2c5e4483a748e27868e4c32ad3daa9bdddbba58e1bc7a15e252baa74/coverage-7.13.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94eb63f9b363180aff17de3e7c8760c3ba94664ea2695c52f10111244d16a299", size = 249974, upload-time = "2026-02-09T12:56:43.323Z" }, + { url = "https://files.pythonhosted.org/packages/98/9f/4c5c015a6e98ced54efd0f5cf8d31b88e5504ecb6857585fc0161bb1e600/coverage-7.13.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e856bf6616714c3a9fbc270ab54103f4e685ba236fa98c054e8f87f266c93505", size = 253741, upload-time = "2026-02-09T12:56:45.155Z" }, + { url = "https://files.pythonhosted.org/packages/bd/59/0f4eef89b9f0fcd9633b5d350016f54126ab49426a70ff4c4e87446cabdc/coverage-7.13.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:65dfcbe305c3dfe658492df2d85259e0d79ead4177f9ae724b6fb245198f55d6", size = 249695, upload-time = "2026-02-09T12:56:46.636Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2c/b7476f938deb07166f3eb281a385c262675d688ff4659ad56c6c6b8e2e70/coverage-7.13.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b507778ae8a4c915436ed5c2e05b4a6cecfa70f734e19c22a005152a11c7b6a9", size = 250599, upload-time = "2026-02-09T12:56:48.13Z" }, + { url = "https://files.pythonhosted.org/packages/b8/34/c3420709d9846ee3785b9f2831b4d94f276f38884032dca1457fa83f7476/coverage-7.13.4-cp311-cp311-win32.whl", hash = "sha256:784fc3cf8be001197b652d51d3fd259b1e2262888693a4636e18879f613a62a9", size = 221780, upload-time = "2026-02-09T12:56:50.479Z" }, + { url = "https://files.pythonhosted.org/packages/61/08/3d9c8613079d2b11c185b865de9a4c1a68850cfda2b357fae365cf609f29/coverage-7.13.4-cp311-cp311-win_amd64.whl", hash = "sha256:2421d591f8ca05b308cf0092807308b2facbefe54af7c02ac22548b88b95c98f", size = 222715, upload-time = "2026-02-09T12:56:51.815Z" }, + { url = "https://files.pythonhosted.org/packages/18/1a/54c3c80b2f056164cc0a6cdcb040733760c7c4be9d780fe655f356f433e4/coverage-7.13.4-cp311-cp311-win_arm64.whl", hash = "sha256:79e73a76b854d9c6088fe5d8b2ebe745f8681c55f7397c3c0a016192d681045f", size = 221385, upload-time = "2026-02-09T12:56:53.194Z" }, + { url = "https://files.pythonhosted.org/packages/d1/81/4ce2fdd909c5a0ed1f6dedb88aa57ab79b6d1fbd9b588c1ac7ef45659566/coverage-7.13.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:02231499b08dabbe2b96612993e5fc34217cdae907a51b906ac7fca8027a4459", size = 219449, upload-time = "2026-02-09T12:56:54.889Z" }, + { url = "https://files.pythonhosted.org/packages/5d/96/5238b1efc5922ddbdc9b0db9243152c09777804fb7c02ad1741eb18a11c0/coverage-7.13.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40aa8808140e55dc022b15d8aa7f651b6b3d68b365ea0398f1441e0b04d859c3", size = 219810, upload-time = "2026-02-09T12:56:56.33Z" }, + { url = "https://files.pythonhosted.org/packages/78/72/2f372b726d433c9c35e56377cf1d513b4c16fe51841060d826b95caacec1/coverage-7.13.4-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5b856a8ccf749480024ff3bd7310adaef57bf31fd17e1bfc404b7940b6986634", size = 251308, upload-time = "2026-02-09T12:56:57.858Z" }, + { url = "https://files.pythonhosted.org/packages/5d/a0/2ea570925524ef4e00bb6c82649f5682a77fac5ab910a65c9284de422600/coverage-7.13.4-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2c048ea43875fbf8b45d476ad79f179809c590ec7b79e2035c662e7afa3192e3", size = 254052, upload-time = "2026-02-09T12:56:59.754Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ac/45dc2e19a1939098d783c846e130b8f862fbb50d09e0af663988f2f21973/coverage-7.13.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b7b38448866e83176e28086674fe7368ab8590e4610fb662b44e345b86d63ffa", size = 255165, upload-time = "2026-02-09T12:57:01.287Z" }, + { url = "https://files.pythonhosted.org/packages/2d/4d/26d236ff35abc3b5e63540d3386e4c3b192168c1d96da5cb2f43c640970f/coverage-7.13.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:de6defc1c9badbf8b9e67ae90fd00519186d6ab64e5cc5f3d21359c2a9b2c1d3", size = 257432, upload-time = "2026-02-09T12:57:02.637Z" }, + { url = "https://files.pythonhosted.org/packages/ec/55/14a966c757d1348b2e19caf699415a2a4c4f7feaa4bbc6326a51f5c7dd1b/coverage-7.13.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7eda778067ad7ffccd23ecffce537dface96212576a07924cbf0d8799d2ded5a", size = 251716, upload-time = "2026-02-09T12:57:04.056Z" }, + { url = "https://files.pythonhosted.org/packages/77/33/50116647905837c66d28b2af1321b845d5f5d19be9655cb84d4a0ea806b4/coverage-7.13.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e87f6c587c3f34356c3759f0420693e35e7eb0e2e41e4c011cb6ec6ecbbf1db7", size = 253089, upload-time = "2026-02-09T12:57:05.503Z" }, + { url = "https://files.pythonhosted.org/packages/c2/b4/8efb11a46e3665d92635a56e4f2d4529de6d33f2cb38afd47d779d15fc99/coverage-7.13.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:8248977c2e33aecb2ced42fef99f2d319e9904a36e55a8a68b69207fb7e43edc", size = 251232, upload-time = "2026-02-09T12:57:06.879Z" }, + { url = "https://files.pythonhosted.org/packages/51/24/8cd73dd399b812cc76bb0ac260e671c4163093441847ffe058ac9fda1e32/coverage-7.13.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:25381386e80ae727608e662474db537d4df1ecd42379b5ba33c84633a2b36d47", size = 255299, upload-time = "2026-02-09T12:57:08.245Z" }, + { url = "https://files.pythonhosted.org/packages/03/94/0a4b12f1d0e029ce1ccc1c800944a9984cbe7d678e470bb6d3c6bc38a0da/coverage-7.13.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ee756f00726693e5ba94d6df2bdfd64d4852d23b09bb0bc700e3b30e6f333985", size = 250796, upload-time = "2026-02-09T12:57:10.142Z" }, + { url = "https://files.pythonhosted.org/packages/73/44/6002fbf88f6698ca034360ce474c406be6d5a985b3fdb3401128031eef6b/coverage-7.13.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fdfc1e28e7c7cdce44985b3043bc13bbd9c747520f94a4d7164af8260b3d91f0", size = 252673, upload-time = "2026-02-09T12:57:12.197Z" }, + { url = "https://files.pythonhosted.org/packages/de/c6/a0279f7c00e786be75a749a5674e6fa267bcbd8209cd10c9a450c655dfa7/coverage-7.13.4-cp312-cp312-win32.whl", hash = "sha256:01d4cbc3c283a17fc1e42d614a119f7f438eabb593391283adca8dc86eff1246", size = 221990, upload-time = "2026-02-09T12:57:14.085Z" }, + { url = "https://files.pythonhosted.org/packages/77/4e/c0a25a425fcf5557d9abd18419c95b63922e897bc86c1f327f155ef234a9/coverage-7.13.4-cp312-cp312-win_amd64.whl", hash = "sha256:9401ebc7ef522f01d01d45532c68c5ac40fb27113019b6b7d8b208f6e9baa126", size = 222800, upload-time = "2026-02-09T12:57:15.944Z" }, + { url = "https://files.pythonhosted.org/packages/47/ac/92da44ad9a6f4e3a7debd178949d6f3769bedca33830ce9b1dcdab589a37/coverage-7.13.4-cp312-cp312-win_arm64.whl", hash = "sha256:b1ec7b6b6e93255f952e27ab58fbc68dcc468844b16ecbee881aeb29b6ab4d8d", size = 221415, upload-time = "2026-02-09T12:57:17.497Z" }, + { url = "https://files.pythonhosted.org/packages/db/23/aad45061a31677d68e47499197a131eea55da4875d16c1f42021ab963503/coverage-7.13.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b66a2da594b6068b48b2692f043f35d4d3693fb639d5ea8b39533c2ad9ac3ab9", size = 219474, upload-time = "2026-02-09T12:57:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/a5/70/9b8b67a0945f3dfec1fd896c5cefb7c19d5a3a6d74630b99a895170999ae/coverage-7.13.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3599eb3992d814d23b35c536c28df1a882caa950f8f507cef23d1cbf334995ac", size = 219844, upload-time = "2026-02-09T12:57:20.66Z" }, + { url = "https://files.pythonhosted.org/packages/97/fd/7e859f8fab324cef6c4ad7cff156ca7c489fef9179d5749b0c8d321281c2/coverage-7.13.4-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:93550784d9281e374fb5a12bf1324cc8a963fd63b2d2f223503ef0fd4aa339ea", size = 250832, upload-time = "2026-02-09T12:57:22.007Z" }, + { url = "https://files.pythonhosted.org/packages/e4/dc/b2442d10020c2f52617828862d8b6ee337859cd8f3a1f13d607dddda9cf7/coverage-7.13.4-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b720ce6a88a2755f7c697c23268ddc47a571b88052e6b155224347389fdf6a3b", size = 253434, upload-time = "2026-02-09T12:57:23.339Z" }, + { url = "https://files.pythonhosted.org/packages/5a/88/6728a7ad17428b18d836540630487231f5470fb82454871149502f5e5aa2/coverage-7.13.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b322db1284a2ed3aa28ffd8ebe3db91c929b7a333c0820abec3d838ef5b3525", size = 254676, upload-time = "2026-02-09T12:57:24.774Z" }, + { url = "https://files.pythonhosted.org/packages/7c/bc/21244b1b8cedf0dff0a2b53b208015fe798d5f2a8d5348dbfece04224fff/coverage-7.13.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4594c67d8a7c89cf922d9df0438c7c7bb022ad506eddb0fdb2863359ff78242", size = 256807, upload-time = "2026-02-09T12:57:26.125Z" }, + { url = "https://files.pythonhosted.org/packages/97/a0/ddba7ed3251cff51006737a727d84e05b61517d1784a9988a846ba508877/coverage-7.13.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:53d133df809c743eb8bce33b24bcababb371f4441340578cd406e084d94a6148", size = 251058, upload-time = "2026-02-09T12:57:27.614Z" }, + { url = "https://files.pythonhosted.org/packages/9b/55/e289addf7ff54d3a540526f33751951bf0878f3809b47f6dfb3def69c6f7/coverage-7.13.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76451d1978b95ba6507a039090ba076105c87cc76fc3efd5d35d72093964d49a", size = 252805, upload-time = "2026-02-09T12:57:29.066Z" }, + { url = "https://files.pythonhosted.org/packages/13/4e/cc276b1fa4a59be56d96f1dabddbdc30f4ba22e3b1cd42504c37b3313255/coverage-7.13.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7f57b33491e281e962021de110b451ab8a24182589be17e12a22c79047935e23", size = 250766, upload-time = "2026-02-09T12:57:30.522Z" }, + { url = "https://files.pythonhosted.org/packages/94/44/1093b8f93018f8b41a8cf29636c9292502f05e4a113d4d107d14a3acd044/coverage-7.13.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1731dc33dc276dafc410a885cbf5992f1ff171393e48a21453b78727d090de80", size = 254923, upload-time = "2026-02-09T12:57:31.946Z" }, + { url = "https://files.pythonhosted.org/packages/8b/55/ea2796da2d42257f37dbea1aab239ba9263b31bd91d5527cdd6db5efe174/coverage-7.13.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:bd60d4fe2f6fa7dff9223ca1bbc9f05d2b6697bc5961072e5d3b952d46e1b1ea", size = 250591, upload-time = "2026-02-09T12:57:33.842Z" }, + { url = "https://files.pythonhosted.org/packages/d4/fa/7c4bb72aacf8af5020675aa633e59c1fbe296d22aed191b6a5b711eb2bc7/coverage-7.13.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9181a3ccead280b828fae232df12b16652702b49d41e99d657f46cc7b1f6ec7a", size = 252364, upload-time = "2026-02-09T12:57:35.743Z" }, + { url = "https://files.pythonhosted.org/packages/5c/38/a8d2ec0146479c20bbaa7181b5b455a0c41101eed57f10dd19a78ab44c80/coverage-7.13.4-cp313-cp313-win32.whl", hash = "sha256:f53d492307962561ac7de4cd1de3e363589b000ab69617c6156a16ba7237998d", size = 222010, upload-time = "2026-02-09T12:57:37.25Z" }, + { url = "https://files.pythonhosted.org/packages/e2/0c/dbfafbe90a185943dcfbc766fe0e1909f658811492d79b741523a414a6cc/coverage-7.13.4-cp313-cp313-win_amd64.whl", hash = "sha256:e6f70dec1cc557e52df5306d051ef56003f74d56e9c4dd7ddb07e07ef32a84dd", size = 222818, upload-time = "2026-02-09T12:57:38.734Z" }, + { url = "https://files.pythonhosted.org/packages/04/d1/934918a138c932c90d78301f45f677fb05c39a3112b96fd2c8e60503cdc7/coverage-7.13.4-cp313-cp313-win_arm64.whl", hash = "sha256:fb07dc5da7e849e2ad31a5d74e9bece81f30ecf5a42909d0a695f8bd1874d6af", size = 221438, upload-time = "2026-02-09T12:57:40.223Z" }, + { url = "https://files.pythonhosted.org/packages/52/57/ee93ced533bcb3e6df961c0c6e42da2fc6addae53fb95b94a89b1e33ebd7/coverage-7.13.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:40d74da8e6c4b9ac18b15331c4b5ebc35a17069410cad462ad4f40dcd2d50c0d", size = 220165, upload-time = "2026-02-09T12:57:41.639Z" }, + { url = "https://files.pythonhosted.org/packages/c5/e0/969fc285a6fbdda49d91af278488d904dcd7651b2693872f0ff94e40e84a/coverage-7.13.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4223b4230a376138939a9173f1bdd6521994f2aff8047fae100d6d94d50c5a12", size = 220516, upload-time = "2026-02-09T12:57:44.215Z" }, + { url = "https://files.pythonhosted.org/packages/b1/b8/9531944e16267e2735a30a9641ff49671f07e8138ecf1ca13db9fd2560c7/coverage-7.13.4-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1d4be36a5114c499f9f1f9195e95ebf979460dbe2d88e6816ea202010ba1c34b", size = 261804, upload-time = "2026-02-09T12:57:45.989Z" }, + { url = "https://files.pythonhosted.org/packages/8a/f3/e63df6d500314a2a60390d1989240d5f27318a7a68fa30ad3806e2a9323e/coverage-7.13.4-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:200dea7d1e8095cc6e98cdabe3fd1d21ab17d3cee6dab00cadbb2fe35d9c15b9", size = 263885, upload-time = "2026-02-09T12:57:47.42Z" }, + { url = "https://files.pythonhosted.org/packages/f3/67/7654810de580e14b37670b60a09c599fa348e48312db5b216d730857ffe6/coverage-7.13.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8eb931ee8e6d8243e253e5ed7336deea6904369d2fd8ae6e43f68abbf167092", size = 266308, upload-time = "2026-02-09T12:57:49.345Z" }, + { url = "https://files.pythonhosted.org/packages/37/6f/39d41eca0eab3cc82115953ad41c4e77935286c930e8fad15eaed1389d83/coverage-7.13.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:75eab1ebe4f2f64d9509b984f9314d4aa788540368218b858dad56dc8f3e5eb9", size = 267452, upload-time = "2026-02-09T12:57:50.811Z" }, + { url = "https://files.pythonhosted.org/packages/50/6d/39c0fbb8fc5cd4d2090811e553c2108cf5112e882f82505ee7495349a6bf/coverage-7.13.4-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c35eb28c1d085eb7d8c9b3296567a1bebe03ce72962e932431b9a61f28facf26", size = 261057, upload-time = "2026-02-09T12:57:52.447Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a2/60010c669df5fa603bb5a97fb75407e191a846510da70ac657eb696b7fce/coverage-7.13.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb88b316ec33760714a4720feb2816a3a59180fd58c1985012054fa7aebee4c2", size = 263875, upload-time = "2026-02-09T12:57:53.938Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d9/63b22a6bdbd17f1f96e9ed58604c2a6b0e72a9133e37d663bef185877cf6/coverage-7.13.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7d41eead3cc673cbd38a4417deb7fd0b4ca26954ff7dc6078e33f6ff97bed940", size = 261500, upload-time = "2026-02-09T12:57:56.012Z" }, + { url = "https://files.pythonhosted.org/packages/70/bf/69f86ba1ad85bc3ad240e4c0e57a2e620fbc0e1645a47b5c62f0e941ad7f/coverage-7.13.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:fb26a934946a6afe0e326aebe0730cdff393a8bc0bbb65a2f41e30feddca399c", size = 265212, upload-time = "2026-02-09T12:57:57.5Z" }, + { url = "https://files.pythonhosted.org/packages/ae/f2/5f65a278a8c2148731831574c73e42f57204243d33bedaaf18fa79c5958f/coverage-7.13.4-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:dae88bc0fc77edaa65c14be099bd57ee140cf507e6bfdeea7938457ab387efb0", size = 260398, upload-time = "2026-02-09T12:57:59.027Z" }, + { url = "https://files.pythonhosted.org/packages/ef/80/6e8280a350ee9fea92f14b8357448a242dcaa243cb2c72ab0ca591f66c8c/coverage-7.13.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:845f352911777a8e722bfce168958214951e07e47e5d5d9744109fa5fe77f79b", size = 262584, upload-time = "2026-02-09T12:58:01.129Z" }, + { url = "https://files.pythonhosted.org/packages/22/63/01ff182fc95f260b539590fb12c11ad3e21332c15f9799cb5e2386f71d9f/coverage-7.13.4-cp313-cp313t-win32.whl", hash = "sha256:2fa8d5f8de70688a28240de9e139fa16b153cc3cbb01c5f16d88d6505ebdadf9", size = 222688, upload-time = "2026-02-09T12:58:02.736Z" }, + { url = "https://files.pythonhosted.org/packages/a9/43/89de4ef5d3cd53b886afa114065f7e9d3707bdb3e5efae13535b46ae483d/coverage-7.13.4-cp313-cp313t-win_amd64.whl", hash = "sha256:9351229c8c8407645840edcc277f4a2d44814d1bc34a2128c11c2a031d45a5dd", size = 223746, upload-time = "2026-02-09T12:58:05.362Z" }, + { url = "https://files.pythonhosted.org/packages/35/39/7cf0aa9a10d470a5309b38b289b9bb07ddeac5d61af9b664fe9775a4cb3e/coverage-7.13.4-cp313-cp313t-win_arm64.whl", hash = "sha256:30b8d0512f2dc8c8747557e8fb459d6176a2c9e5731e2b74d311c03b78451997", size = 222003, upload-time = "2026-02-09T12:58:06.952Z" }, + { url = "https://files.pythonhosted.org/packages/92/11/a9cf762bb83386467737d32187756a42094927150c3e107df4cb078e8590/coverage-7.13.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:300deaee342f90696ed186e3a00c71b5b3d27bffe9e827677954f4ee56969601", size = 219522, upload-time = "2026-02-09T12:58:08.623Z" }, + { url = "https://files.pythonhosted.org/packages/d3/28/56e6d892b7b052236d67c95f1936b6a7cf7c3e2634bf27610b8cbd7f9c60/coverage-7.13.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29e3220258d682b6226a9b0925bc563ed9a1ebcff3cad30f043eceea7eaf2689", size = 219855, upload-time = "2026-02-09T12:58:10.176Z" }, + { url = "https://files.pythonhosted.org/packages/e5/69/233459ee9eb0c0d10fcc2fe425a029b3fa5ce0f040c966ebce851d030c70/coverage-7.13.4-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:391ee8f19bef69210978363ca930f7328081c6a0152f1166c91f0b5fdd2a773c", size = 250887, upload-time = "2026-02-09T12:58:12.503Z" }, + { url = "https://files.pythonhosted.org/packages/06/90/2cdab0974b9b5bbc1623f7876b73603aecac11b8d95b85b5b86b32de5eab/coverage-7.13.4-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0dd7ab8278f0d58a0128ba2fca25824321f05d059c1441800e934ff2efa52129", size = 253396, upload-time = "2026-02-09T12:58:14.615Z" }, + { url = "https://files.pythonhosted.org/packages/ac/15/ea4da0f85bf7d7b27635039e649e99deb8173fe551096ea15017f7053537/coverage-7.13.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78cdf0d578b15148b009ccf18c686aa4f719d887e76e6b40c38ffb61d264a552", size = 254745, upload-time = "2026-02-09T12:58:16.162Z" }, + { url = "https://files.pythonhosted.org/packages/99/11/bb356e86920c655ca4d61daee4e2bbc7258f0a37de0be32d233b561134ff/coverage-7.13.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:48685fee12c2eb3b27c62f2658e7ea21e9c3239cba5a8a242801a0a3f6a8c62a", size = 257055, upload-time = "2026-02-09T12:58:17.892Z" }, + { url = "https://files.pythonhosted.org/packages/c9/0f/9ae1f8cb17029e09da06ca4e28c9e1d5c1c0a511c7074592e37e0836c915/coverage-7.13.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4e83efc079eb39480e6346a15a1bcb3e9b04759c5202d157e1dd4303cd619356", size = 250911, upload-time = "2026-02-09T12:58:19.495Z" }, + { url = "https://files.pythonhosted.org/packages/89/3a/adfb68558fa815cbc29747b553bc833d2150228f251b127f1ce97e48547c/coverage-7.13.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ecae9737b72408d6a950f7e525f30aca12d4bd8dd95e37342e5beb3a2a8c4f71", size = 252754, upload-time = "2026-02-09T12:58:21.064Z" }, + { url = "https://files.pythonhosted.org/packages/32/b1/540d0c27c4e748bd3cd0bd001076ee416eda993c2bae47a73b7cc9357931/coverage-7.13.4-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ae4578f8528569d3cf303fef2ea569c7f4c4059a38c8667ccef15c6e1f118aa5", size = 250720, upload-time = "2026-02-09T12:58:22.622Z" }, + { url = "https://files.pythonhosted.org/packages/c7/95/383609462b3ffb1fe133014a7c84fc0dd01ed55ac6140fa1093b5af7ebb1/coverage-7.13.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:6fdef321fdfbb30a197efa02d48fcd9981f0d8ad2ae8903ac318adc653f5df98", size = 254994, upload-time = "2026-02-09T12:58:24.548Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ba/1761138e86c81680bfc3c49579d66312865457f9fe405b033184e5793cb3/coverage-7.13.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b0f6ccf3dbe577170bebfce1318707d0e8c3650003cb4b3a9dd744575daa8b5", size = 250531, upload-time = "2026-02-09T12:58:26.271Z" }, + { url = "https://files.pythonhosted.org/packages/f8/8e/05900df797a9c11837ab59c4d6fe94094e029582aab75c3309a93e6fb4e3/coverage-7.13.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75fcd519f2a5765db3f0e391eb3b7d150cce1a771bf4c9f861aeab86c767a3c0", size = 252189, upload-time = "2026-02-09T12:58:27.807Z" }, + { url = "https://files.pythonhosted.org/packages/00/bd/29c9f2db9ea4ed2738b8a9508c35626eb205d51af4ab7bf56a21a2e49926/coverage-7.13.4-cp314-cp314-win32.whl", hash = "sha256:8e798c266c378da2bd819b0677df41ab46d78065fb2a399558f3f6cae78b2fbb", size = 222258, upload-time = "2026-02-09T12:58:29.441Z" }, + { url = "https://files.pythonhosted.org/packages/a7/4d/1f8e723f6829977410efeb88f73673d794075091c8c7c18848d273dc9d73/coverage-7.13.4-cp314-cp314-win_amd64.whl", hash = "sha256:245e37f664d89861cf2329c9afa2c1fe9e6d4e1a09d872c947e70718aeeac505", size = 223073, upload-time = "2026-02-09T12:58:31.026Z" }, + { url = "https://files.pythonhosted.org/packages/51/5b/84100025be913b44e082ea32abcf1afbf4e872f5120b7a1cab1d331b1e13/coverage-7.13.4-cp314-cp314-win_arm64.whl", hash = "sha256:ad27098a189e5838900ce4c2a99f2fe42a0bf0c2093c17c69b45a71579e8d4a2", size = 221638, upload-time = "2026-02-09T12:58:32.599Z" }, + { url = "https://files.pythonhosted.org/packages/a7/e4/c884a405d6ead1370433dad1e3720216b4f9fd8ef5b64bfd984a2a60a11a/coverage-7.13.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:85480adfb35ffc32d40918aad81b89c69c9cc5661a9b8a81476d3e645321a056", size = 220246, upload-time = "2026-02-09T12:58:34.181Z" }, + { url = "https://files.pythonhosted.org/packages/81/5c/4d7ed8b23b233b0fffbc9dfec53c232be2e695468523242ea9fd30f97ad2/coverage-7.13.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:79be69cf7f3bf9b0deeeb062eab7ac7f36cd4cc4c4dd694bd28921ba4d8596cc", size = 220514, upload-time = "2026-02-09T12:58:35.704Z" }, + { url = "https://files.pythonhosted.org/packages/2f/6f/3284d4203fd2f28edd73034968398cd2d4cb04ab192abc8cff007ea35679/coverage-7.13.4-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:caa421e2684e382c5d8973ac55e4f36bed6821a9bad5c953494de960c74595c9", size = 261877, upload-time = "2026-02-09T12:58:37.864Z" }, + { url = "https://files.pythonhosted.org/packages/09/aa/b672a647bbe1556a85337dc95bfd40d146e9965ead9cc2fe81bde1e5cbce/coverage-7.13.4-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:14375934243ee05f56c45393fe2ce81fe5cc503c07cee2bdf1725fb8bef3ffaf", size = 264004, upload-time = "2026-02-09T12:58:39.492Z" }, + { url = "https://files.pythonhosted.org/packages/79/a1/aa384dbe9181f98bba87dd23dda436f0c6cf2e148aecbb4e50fc51c1a656/coverage-7.13.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25a41c3104d08edb094d9db0d905ca54d0cd41c928bb6be3c4c799a54753af55", size = 266408, upload-time = "2026-02-09T12:58:41.852Z" }, + { url = "https://files.pythonhosted.org/packages/53/5e/5150bf17b4019bc600799f376bb9606941e55bd5a775dc1e096b6ffea952/coverage-7.13.4-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6f01afcff62bf9a08fb32b2c1d6e924236c0383c02c790732b6537269e466a72", size = 267544, upload-time = "2026-02-09T12:58:44.093Z" }, + { url = "https://files.pythonhosted.org/packages/e0/ed/f1de5c675987a4a7a672250d2c5c9d73d289dbf13410f00ed7181d8017dd/coverage-7.13.4-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eb9078108fbf0bcdde37c3f4779303673c2fa1fe8f7956e68d447d0dd426d38a", size = 260980, upload-time = "2026-02-09T12:58:45.721Z" }, + { url = "https://files.pythonhosted.org/packages/b3/e3/fe758d01850aa172419a6743fe76ba8b92c29d181d4f676ffe2dae2ba631/coverage-7.13.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e086334e8537ddd17e5f16a344777c1ab8194986ec533711cbe6c41cde841b6", size = 263871, upload-time = "2026-02-09T12:58:47.334Z" }, + { url = "https://files.pythonhosted.org/packages/b6/76/b829869d464115e22499541def9796b25312b8cf235d3bb00b39f1675395/coverage-7.13.4-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:725d985c5ab621268b2edb8e50dfe57633dc69bda071abc470fed55a14935fd3", size = 261472, upload-time = "2026-02-09T12:58:48.995Z" }, + { url = "https://files.pythonhosted.org/packages/14/9e/caedb1679e73e2f6ad240173f55218488bfe043e38da577c4ec977489915/coverage-7.13.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:3c06f0f1337c667b971ca2f975523347e63ec5e500b9aa5882d91931cd3ef750", size = 265210, upload-time = "2026-02-09T12:58:51.178Z" }, + { url = "https://files.pythonhosted.org/packages/3a/10/0dd02cb009b16ede425b49ec344aba13a6ae1dc39600840ea6abcb085ac4/coverage-7.13.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:590c0ed4bf8e85f745e6b805b2e1c457b2e33d5255dd9729743165253bc9ad39", size = 260319, upload-time = "2026-02-09T12:58:53.081Z" }, + { url = "https://files.pythonhosted.org/packages/92/8e/234d2c927af27c6d7a5ffad5bd2cf31634c46a477b4c7adfbfa66baf7ebb/coverage-7.13.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:eb30bf180de3f632cd043322dad5751390e5385108b2807368997d1a92a509d0", size = 262638, upload-time = "2026-02-09T12:58:55.258Z" }, + { url = "https://files.pythonhosted.org/packages/2f/64/e5547c8ff6964e5965c35a480855911b61509cce544f4d442caa759a0702/coverage-7.13.4-cp314-cp314t-win32.whl", hash = "sha256:c4240e7eded42d131a2d2c4dec70374b781b043ddc79a9de4d55ca71f8e98aea", size = 223040, upload-time = "2026-02-09T12:58:56.936Z" }, + { url = "https://files.pythonhosted.org/packages/c7/96/38086d58a181aac86d503dfa9c47eb20715a79c3e3acbdf786e92e5c09a8/coverage-7.13.4-cp314-cp314t-win_amd64.whl", hash = "sha256:4c7d3cc01e7350f2f0f6f7036caaf5673fb56b6998889ccfe9e1c1fe75a9c932", size = 224148, upload-time = "2026-02-09T12:58:58.645Z" }, + { url = "https://files.pythonhosted.org/packages/ce/72/8d10abd3740a0beb98c305e0c3faf454366221c0f37a8bcf8f60020bb65a/coverage-7.13.4-cp314-cp314t-win_arm64.whl", hash = "sha256:23e3f687cf945070d1c90f85db66d11e3025665d8dafa831301a0e0038f3db9b", size = 222172, upload-time = "2026-02-09T12:59:00.396Z" }, + { url = "https://files.pythonhosted.org/packages/0d/4a/331fe2caf6799d591109bb9c08083080f6de90a823695d412a935622abb2/coverage-7.13.4-py3-none-any.whl", hash = "sha256:1af1641e57cf7ba1bd67d677c9abdbcd6cc2ab7da3bca7fa1e2b7e50e65f2ad0", size = 211242, upload-time = "2026-02-09T12:59:02.032Z" }, ] [package.optional-dependencies] @@ -1839,7 +1853,7 @@ wheels = [ [[package]] name = "fastapi" -version = "0.128.5" +version = "0.128.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, @@ -1848,9 +1862,9 @@ dependencies = [ { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "typing-inspection", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/02/d4/811e7283aaaa84f1e7bd55fb642b58f8c01895e4884a9b7628cb55e00d63/fastapi-0.128.5.tar.gz", hash = "sha256:a7173579fc162d6471e3c6fbd9a4b7610c7a3b367bcacf6c4f90d5d022cab711", size = 374636, upload-time = "2026-02-08T10:22:30.493Z" } +sdist = { url = "https://files.pythonhosted.org/packages/83/d1/195005b5e45b443e305136df47ee7df4493d782e0c039dd0d97065580324/fastapi-0.128.6.tar.gz", hash = "sha256:0cb3946557e792d731b26a42b04912f16367e3c3135ea8290f620e234f2b604f", size = 374757, upload-time = "2026-02-09T17:27:03.541Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/e0/511972dba23ee76c0e9d09d1ae95e916fc8ebce5322b2b8b65a481428b10/fastapi-0.128.5-py3-none-any.whl", hash = "sha256:bceec0de8aa6564599c5bcc0593b0d287703562c848271fca8546fd2c87bf4dd", size = 103677, upload-time = "2026-02-08T10:22:28.919Z" }, + { url = "https://files.pythonhosted.org/packages/24/58/a2c4f6b240eeb148fb88cdac48f50a194aba760c1ca4988c6031c66a20ee/fastapi-0.128.6-py3-none-any.whl", hash = "sha256:bb1c1ef87d6086a7132d0ab60869d6f1ee67283b20fbf84ec0003bd335099509", size = 103674, upload-time = "2026-02-09T17:27:02.355Z" }, ] [[package]] @@ -2945,7 +2959,7 @@ wheels = [ [[package]] name = "langfuse" -version = "3.13.0" +version = "3.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "backoff", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, @@ -2959,9 +2973,9 @@ dependencies = [ { name = "requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "wrapt", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/24/d0/744e5613c728427330ac2049da0f54fc313e8bf84622f71b025bfba65496/langfuse-3.13.0.tar.gz", hash = "sha256:dacea8111ca4442e97dbfec4f8d676cf9709b35357a26e468f8887b95de0012f", size = 233420, upload-time = "2026-02-06T19:54:14.415Z" } +sdist = { url = "https://files.pythonhosted.org/packages/24/7a/ddd8df7f2c5d8c2112a8b20fa88b2513917e2c25d2ef87034c0927f87596/langfuse-3.14.1.tar.gz", hash = "sha256:404a6104cd29353d7829aa417ec46565b04917e5599afdda96c5b0865f4bc991", size = 234530, upload-time = "2026-02-09T15:37:45.994Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/63/148382e8e79948f7e5c9c137288e504bb88117574eb7e7c886b4fb470b4b/langfuse-3.13.0-py3-none-any.whl", hash = "sha256:71912ddac1cc831a65df895eae538a556f564c094ae51473e747426e9ded1a9d", size = 417626, upload-time = "2026-02-06T19:54:12.547Z" }, + { url = "https://files.pythonhosted.org/packages/80/b9/e8ac3072469737358975da66ec4218dc1cee0051555dd4665b3e34a28420/langfuse-3.14.1-py3-none-any.whl", hash = "sha256:17bed605dbfc9947cbd1738a715f6d27c1b80b6da9f2946586171958fa5820d0", size = 420336, upload-time = "2026-02-09T15:37:44.381Z" }, ] [[package]] @@ -5319,14 +5333,14 @@ wheels = [ [[package]] name = "redis" -version = "7.1.0" +version = "7.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "async-timeout", marker = "(python_full_version < '3.11.3' and sys_platform == 'darwin') or (python_full_version < '3.11.3' and sys_platform == 'linux') or (python_full_version < '3.11.3' and sys_platform == 'win32')" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/43/c8/983d5c6579a411d8a99bc5823cc5712768859b5ce2c8afe1a65b37832c81/redis-7.1.0.tar.gz", hash = "sha256:b1cc3cfa5a2cb9c2ab3ba700864fb0ad75617b41f01352ce5779dabf6d5f9c3c", size = 4796669, upload-time = "2025-11-19T15:54:39.961Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/80/2971931d27651affa88a44c0ad7b8c4a19dc29c998abb20b23868d319b59/redis-7.1.1.tar.gz", hash = "sha256:a2814b2bda15b39dad11391cc48edac4697214a8a5a4bd10abe936ab4892eb43", size = 4800064, upload-time = "2026-02-09T18:39:40.292Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/89/f0/8956f8a86b20d7bb9d6ac0187cf4cd54d8065bc9a1a09eb8011d4d326596/redis-7.1.0-py3-none-any.whl", hash = "sha256:23c52b208f92b56103e17c5d06bdc1a6c2c0b3106583985a76a18f83b265de2b", size = 354159, upload-time = "2025-11-19T15:54:38.064Z" }, + { url = "https://files.pythonhosted.org/packages/29/55/1de1d812ba1481fa4b37fb03b4eec0fcb71b6a0d44c04ea3482eb017600f/redis-7.1.1-py3-none-any.whl", hash = "sha256:f77817f16071c2950492c67d40b771fa493eb3fccc630a424a10976dbb794b7a", size = 356057, upload-time = "2026-02-09T18:39:38.602Z" }, ] [[package]]