mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-28 02:28:59 +03:00
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
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:
+24
-24
@@ -7,8 +7,8 @@ import string
|
||||
import time
|
||||
import zipfile
|
||||
from collections import deque
|
||||
from collections.abc import Iterator
|
||||
from pathlib import Path
|
||||
from typing import Iterator, List, Optional
|
||||
|
||||
import psutil
|
||||
from fastapi import APIRouter, Depends, Query, Request
|
||||
@@ -89,7 +89,7 @@ def _generate_export_id(camera_name: str) -> str:
|
||||
|
||||
def _create_export_case_record(
|
||||
name: str,
|
||||
description: Optional[str],
|
||||
description: str | None,
|
||||
) -> ExportCase:
|
||||
now = datetime.datetime.fromtimestamp(time.time())
|
||||
return ExportCase.create(
|
||||
@@ -101,7 +101,7 @@ def _create_export_case_record(
|
||||
)
|
||||
|
||||
|
||||
def _validate_camera_name(request: Request, camera_name: str) -> Optional[JSONResponse]:
|
||||
def _validate_camera_name(request: Request, camera_name: str) -> JSONResponse | None:
|
||||
if camera_name and request.app.frigate_config.cameras.get(camera_name):
|
||||
return None
|
||||
|
||||
@@ -111,7 +111,7 @@ def _validate_camera_name(request: Request, camera_name: str) -> Optional[JSONRe
|
||||
)
|
||||
|
||||
|
||||
def _validate_export_case(export_case_id: Optional[str]) -> Optional[JSONResponse]:
|
||||
def _validate_export_case(export_case_id: str | None) -> JSONResponse | None:
|
||||
if export_case_id is None:
|
||||
return None
|
||||
|
||||
@@ -127,8 +127,8 @@ def _validate_export_case(export_case_id: Optional[str]) -> Optional[JSONRespons
|
||||
|
||||
|
||||
def _sanitize_existing_image(
|
||||
image_path: Optional[str],
|
||||
) -> tuple[Optional[str], Optional[JSONResponse]]:
|
||||
image_path: str | None,
|
||||
) -> tuple[str | None, JSONResponse | None]:
|
||||
# sanitize_filepath normalizes "\" to "/" but leaves ".." intact, so a path
|
||||
# like "clips\..\..\etc/passwd" passes the CLIPS_DIR prefix check yet still
|
||||
# escapes the directory once resolved. A valid snapshot path never uses "..".
|
||||
@@ -154,7 +154,7 @@ def _validate_export_source(
|
||||
start_time: float,
|
||||
end_time: float,
|
||||
playback_source: PlaybackSourceEnum,
|
||||
) -> Optional[str]:
|
||||
) -> str | None:
|
||||
if playback_source == PlaybackSourceEnum.recordings:
|
||||
recordings_count = (
|
||||
Recordings.select()
|
||||
@@ -257,14 +257,14 @@ def _build_export_job(
|
||||
camera_name: str,
|
||||
start_time: float,
|
||||
end_time: float,
|
||||
friendly_name: Optional[str],
|
||||
existing_image: Optional[str],
|
||||
friendly_name: str | None,
|
||||
existing_image: str | None,
|
||||
playback_source: PlaybackSourceEnum,
|
||||
export_case_id: Optional[str],
|
||||
ffmpeg_input_args: Optional[str] = None,
|
||||
ffmpeg_output_args: Optional[str] = None,
|
||||
export_case_id: str | None,
|
||||
ffmpeg_input_args: str | None = None,
|
||||
ffmpeg_output_args: str | None = None,
|
||||
cpu_fallback: bool = False,
|
||||
chapters: Optional[ChaptersEnum] = None,
|
||||
chapters: ChaptersEnum | None = None,
|
||||
) -> ExportJob:
|
||||
return ExportJob(
|
||||
id=_generate_export_id(camera_name),
|
||||
@@ -302,11 +302,11 @@ def _export_case_to_dict(case: ExportCase) -> dict[str, object]:
|
||||
Returns a list of exports ordered by date (most recent first).""",
|
||||
)
|
||||
def get_exports(
|
||||
allowed_cameras: List[str] = Depends(get_allowed_cameras_for_filter),
|
||||
export_case_id: Optional[str] = None,
|
||||
cameras: Optional[str] = Query(default="all"),
|
||||
start_date: Optional[float] = None,
|
||||
end_date: Optional[float] = None,
|
||||
allowed_cameras: list[str] = Depends(get_allowed_cameras_for_filter),
|
||||
export_case_id: str | None = None,
|
||||
cameras: str | None = Query(default="all"),
|
||||
start_date: float | None = None,
|
||||
end_date: float | None = None,
|
||||
):
|
||||
query = Export.select().where(Export.camera << allowed_cameras)
|
||||
|
||||
@@ -422,7 +422,7 @@ def _unique_archive_name(export: Export, used: set[str]) -> str:
|
||||
return candidate
|
||||
|
||||
|
||||
def _stream_case_archive(exports: List[Export]) -> Iterator[bytes]:
|
||||
def _stream_case_archive(exports: list[Export]) -> Iterator[bytes]:
|
||||
"""Yield bytes of a zip archive built from the given exports' mp4 files."""
|
||||
buffer = _StreamingZipBuffer()
|
||||
used_names: set[str] = set()
|
||||
@@ -466,7 +466,7 @@ def _stream_case_archive(exports: List[Export]) -> Iterator[bytes]:
|
||||
)
|
||||
def download_export_case(
|
||||
case_id: str,
|
||||
allowed_cameras: List[str] = Depends(get_allowed_cameras_for_filter),
|
||||
allowed_cameras: list[str] = Depends(get_allowed_cameras_for_filter),
|
||||
):
|
||||
try:
|
||||
case = ExportCase.get(ExportCase.id == case_id)
|
||||
@@ -580,7 +580,7 @@ def delete_export_case(case_id: str, request: Request, delete_exports: bool = Fa
|
||||
)
|
||||
def get_active_export_jobs(
|
||||
request: Request,
|
||||
allowed_cameras: List[str] = Depends(get_allowed_cameras_for_filter),
|
||||
allowed_cameras: list[str] = Depends(get_allowed_cameras_for_filter),
|
||||
):
|
||||
jobs = list_active_export_jobs(request.app.frigate_config)
|
||||
return JSONResponse(
|
||||
@@ -622,7 +622,7 @@ async def get_export_job_status(export_id: str, request: Request):
|
||||
def export_recordings_batch(
|
||||
request: Request,
|
||||
body: BatchExportBody,
|
||||
allowed_cameras: List[str] = Depends(get_allowed_cameras_for_filter),
|
||||
allowed_cameras: list[str] = Depends(get_allowed_cameras_for_filter),
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
if isinstance(current_user, JSONResponse):
|
||||
@@ -662,7 +662,7 @@ def export_recordings_batch(
|
||||
|
||||
# Sanitize each item's image_path up front. A bad path in any item
|
||||
# kills the whole request, consistent with single-export behavior.
|
||||
sanitized_images: list[Optional[str]] = []
|
||||
sanitized_images: list[str | None] = []
|
||||
for item in body.items:
|
||||
existing_image, image_validation_error = _sanitize_existing_image(
|
||||
item.image_path
|
||||
@@ -713,7 +713,7 @@ def export_recordings_batch(
|
||||
export_case_id = export_case.id
|
||||
|
||||
export_ids: list[str] = []
|
||||
results: list[dict[str, Optional[str] | bool | int]] = []
|
||||
results: list[dict[str, str | None | bool | int]] = []
|
||||
for index, item in enumerate(body.items):
|
||||
if index in item_errors:
|
||||
results.append(
|
||||
|
||||
Reference in New Issue
Block a user