Increase ruff coverage (#23644)
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions
CI / Jetson Jetpack 6 (push) Waiting to run

* Pin ruff

* Add python upgrade fixes

This enables python upgrade checks in ruff to look for deprecated types and patterns. This namely fixes:
- usage of deprecated `Typing` which is now built in
- some specific exceptions which are caught and have new aliases

Some specific UP checks were also ignored as they are stylistic / unimportant and likely to cause bugs

* Remove async blocking calls

Use asyncio.to_thread on two remaining blocking calls to fix hanging event thread loop. Enable this specific rule to block it in the future.

* Use proper logging mechanism

* Correctly format logs

* Raise with context

When raising an exception include the from context to improve debugging

* Cleanup
This commit is contained in:
Nicolas Mowen
2026-07-06 12:28:02 -05:00
committed by GitHub
parent 455b8687e8
commit 4ee12e6237
169 changed files with 1053 additions and 1150 deletions
+13 -12
View File
@@ -3,7 +3,8 @@
import base64
import json
import logging
from typing import Any, AsyncGenerator, Optional
from collections.abc import AsyncGenerator
from typing import Any
from httpx import TimeoutException
from openai import OpenAI
@@ -14,7 +15,7 @@ from frigate.genai import GenAIClient, register_genai_provider
logger = logging.getLogger(__name__)
def _stats_from_openai_usage(usage: Any) -> Optional[dict[str, Any]]:
def _stats_from_openai_usage(usage: Any) -> dict[str, Any] | None:
"""Build a stats dict from an OpenAI-compatible usage object."""
if usage is None:
return None
@@ -35,7 +36,7 @@ class OpenAIClient(GenAIClient):
"""Generative AI client for Frigate using OpenAI."""
provider: OpenAI
context_size: Optional[int] = None
context_size: int | None = None
def _init_provider(self) -> OpenAI:
"""Initialize the client.
@@ -60,9 +61,9 @@ class OpenAIClient(GenAIClient):
self,
prompt: str,
images: list[bytes],
response_format: Optional[dict] = None,
response_format: dict | None = None,
enable_thinking: bool = False,
) -> Optional[str]:
) -> str | None:
"""Submit a request to OpenAI."""
encoded_images = [base64.b64encode(image).decode("utf-8") for image in images]
messages_content: list[dict] = [
@@ -186,9 +187,9 @@ class OpenAIClient(GenAIClient):
def chat_with_tools(
self,
messages: list[dict[str, Any]],
tools: Optional[list[dict[str, Any]]] = None,
tool_choice: Optional[str] = "auto",
enable_thinking: Optional[bool] = None,
tools: list[dict[str, Any]] | None = None,
tool_choice: str | None = "auto",
enable_thinking: bool | None = None,
) -> dict[str, Any]:
"""
Send chat messages to OpenAI with optional tool definitions.
@@ -307,9 +308,9 @@ class OpenAIClient(GenAIClient):
async def chat_with_tools_stream(
self,
messages: list[dict[str, Any]],
tools: Optional[list[dict[str, Any]]] = None,
tool_choice: Optional[str] = "auto",
enable_thinking: Optional[bool] = None,
tools: list[dict[str, Any]] | None = None,
tool_choice: str | None = "auto",
enable_thinking: bool | None = None,
) -> AsyncGenerator[tuple[str, Any], None]:
"""
Stream chat with tools; yields content deltas then final message.
@@ -357,7 +358,7 @@ class OpenAIClient(GenAIClient):
reasoning_parts: list[str] = []
tool_calls_by_index: dict[int, dict[str, Any]] = {}
finish_reason = "stop"
usage_stats: Optional[dict[str, Any]] = None
usage_stats: dict[str, Any] | None = None
stream = self.provider.chat.completions.create(**request_params)