mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-08-11 13:21:10 +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:
+16
-16
@@ -9,9 +9,9 @@ import shutil
|
||||
import string
|
||||
import subprocess as sp
|
||||
import threading
|
||||
from collections.abc import Callable
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from typing import Callable, Optional
|
||||
|
||||
import pytz # type: ignore[import-untyped]
|
||||
from peewee import DoesNotExist
|
||||
@@ -209,17 +209,17 @@ class RecordingExporter(threading.Thread):
|
||||
config: FrigateConfig,
|
||||
id: str,
|
||||
camera: str,
|
||||
name: Optional[str],
|
||||
image: Optional[str],
|
||||
name: str | None,
|
||||
image: str | None,
|
||||
start_time: int,
|
||||
end_time: int,
|
||||
playback_source: PlaybackSourceEnum,
|
||||
export_case_id: Optional[str] = None,
|
||||
ffmpeg_input_args: Optional[str] = None,
|
||||
ffmpeg_output_args: Optional[str] = None,
|
||||
export_case_id: str | None = None,
|
||||
ffmpeg_input_args: str | None = None,
|
||||
ffmpeg_output_args: str | None = None,
|
||||
cpu_fallback: bool = False,
|
||||
chapters: Optional[ChaptersEnum] = None,
|
||||
on_progress: Optional[Callable[[str, float], None]] = None,
|
||||
chapters: ChaptersEnum | None = None,
|
||||
on_progress: Callable[[str, float], None] | None = None,
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.config = config
|
||||
@@ -283,7 +283,7 @@ class RecordingExporter(threading.Thread):
|
||||
|
||||
return input_duration * factor
|
||||
|
||||
def _sum_source_duration_seconds(self) -> Optional[float]:
|
||||
def _sum_source_duration_seconds(self) -> float | None:
|
||||
"""Sum saved-video seconds inside [start_time, end_time].
|
||||
|
||||
Queries Recordings or Previews depending on the playback source,
|
||||
@@ -383,7 +383,7 @@ class RecordingExporter(threading.Thread):
|
||||
def _chapter_metadata_path(self) -> str:
|
||||
return os.path.join(CACHE_DIR, f"export_chapters_{self.export_id}.txt")
|
||||
|
||||
def _build_chapter_metadata_file(self, recordings: list) -> Optional[str]:
|
||||
def _build_chapter_metadata_file(self, recordings: list) -> str | None:
|
||||
"""Write an FFmpeg metadata file with chapters for review items in range.
|
||||
|
||||
Chapter offsets are computed in *output time*: the VOD endpoint
|
||||
@@ -514,7 +514,7 @@ class RecordingExporter(threading.Thread):
|
||||
|
||||
def _build_recording_segment_chapter_metadata_file(
|
||||
self, recordings: list
|
||||
) -> Optional[str]:
|
||||
) -> str | None:
|
||||
"""Write an FFmpeg metadata file with one chapter per recording segment.
|
||||
|
||||
Each chapter's title is the segment's wallclock start time in
|
||||
@@ -530,14 +530,14 @@ class RecordingExporter(threading.Thread):
|
||||
return None
|
||||
|
||||
tz_name = self.config.ui.timezone
|
||||
tz: Optional[datetime.tzinfo] = None
|
||||
tz: datetime.tzinfo | None = None
|
||||
if tz_name:
|
||||
try:
|
||||
tz = pytz.timezone(tz_name)
|
||||
except pytz.UnknownTimeZoneError:
|
||||
tz = None
|
||||
if tz is None:
|
||||
tz = datetime.timezone.utc
|
||||
tz = datetime.UTC
|
||||
|
||||
chapter_blocks: list[str] = []
|
||||
output_offset_ms = 0
|
||||
@@ -591,7 +591,7 @@ class RecordingExporter(threading.Thread):
|
||||
|
||||
if (
|
||||
self.start_time
|
||||
< datetime.datetime.now(datetime.timezone.utc)
|
||||
< datetime.datetime.now(datetime.UTC)
|
||||
.replace(minute=0, second=0, microsecond=0)
|
||||
.timestamp()
|
||||
):
|
||||
@@ -767,7 +767,7 @@ class RecordingExporter(threading.Thread):
|
||||
# add metadata
|
||||
title = f"Frigate Recording for {self.camera}, {self.get_datetime_from_timestamp(self.start_time)} - {self.get_datetime_from_timestamp(self.end_time)}"
|
||||
creation_time = datetime.datetime.fromtimestamp(
|
||||
self.start_time, tz=datetime.timezone.utc
|
||||
self.start_time, tz=datetime.UTC
|
||||
).strftime("%Y-%m-%dT%H:%M:%S.%fZ")
|
||||
ffmpeg_cmd.extend(
|
||||
[
|
||||
@@ -876,7 +876,7 @@ class RecordingExporter(threading.Thread):
|
||||
# add metadata
|
||||
title = f"Frigate Preview for {self.camera}, {self.get_datetime_from_timestamp(self.start_time)} - {self.get_datetime_from_timestamp(self.end_time)}"
|
||||
creation_time = datetime.datetime.fromtimestamp(
|
||||
self.start_time, tz=datetime.timezone.utc
|
||||
self.start_time, tz=datetime.UTC
|
||||
).strftime("%Y-%m-%dT%H:%M:%S.%fZ")
|
||||
ffmpeg_cmd.extend(
|
||||
[
|
||||
|
||||
@@ -11,7 +11,7 @@ import time
|
||||
from collections import defaultdict
|
||||
from multiprocessing.synchronize import Event as MpEvent
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional, Tuple
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
import psutil
|
||||
@@ -100,7 +100,7 @@ class RecordingMaintainer(threading.Thread):
|
||||
self.stop_event = stop_event
|
||||
self.object_recordings_info: dict[str, list] = defaultdict(list)
|
||||
self.audio_recordings_info: dict[str, list] = defaultdict(list)
|
||||
self.end_time_cache: dict[str, Tuple[datetime.datetime, float]] = {}
|
||||
self.end_time_cache: dict[str, tuple[datetime.datetime, float]] = {}
|
||||
self.unexpected_cache_files_logged: bool = False
|
||||
|
||||
async def move_files(self) -> None:
|
||||
@@ -127,7 +127,7 @@ class RecordingMaintainer(threading.Thread):
|
||||
|
||||
start_time = datetime.datetime.strptime(
|
||||
date, CACHE_SEGMENT_FORMAT
|
||||
).astimezone(datetime.timezone.utc)
|
||||
).astimezone(datetime.UTC)
|
||||
if (
|
||||
camera not in newest_cache_segments
|
||||
or start_time > newest_cache_segments[camera]["start_time"]
|
||||
@@ -187,7 +187,7 @@ class RecordingMaintainer(threading.Thread):
|
||||
# important that start_time is utc because recordings are stored and compared in utc
|
||||
start_time = datetime.datetime.strptime(
|
||||
date, CACHE_SEGMENT_FORMAT
|
||||
).astimezone(datetime.timezone.utc)
|
||||
).astimezone(datetime.UTC)
|
||||
|
||||
grouped_recordings[camera].append(
|
||||
{
|
||||
@@ -305,9 +305,7 @@ class RecordingMaintainer(threading.Thread):
|
||||
|
||||
self._expire_stale_recordings_info(grouped_recordings)
|
||||
|
||||
recordings_to_insert: list[Optional[dict[str, Any]]] = await asyncio.gather(
|
||||
*tasks
|
||||
)
|
||||
recordings_to_insert: list[dict[str, Any] | None] = await asyncio.gather(*tasks)
|
||||
|
||||
# fire and forget recordings entries
|
||||
self.requestor.send_data(
|
||||
@@ -336,7 +334,7 @@ class RecordingMaintainer(threading.Thread):
|
||||
|
||||
async def validate_and_move_segment(
|
||||
self, camera: str, reviews: Any, recording: dict[str, Any]
|
||||
) -> Optional[dict[str, Any]]:
|
||||
) -> dict[str, Any] | None:
|
||||
cache_path: str = recording["cache_path"]
|
||||
start_time: datetime.datetime = recording["start_time"]
|
||||
|
||||
@@ -413,7 +411,7 @@ class RecordingMaintainer(threading.Thread):
|
||||
if (
|
||||
datetime.datetime.fromtimestamp(
|
||||
most_recently_processed_frame_time
|
||||
).astimezone(datetime.timezone.utc)
|
||||
).astimezone(datetime.UTC)
|
||||
>= end_time
|
||||
):
|
||||
record_mode = (
|
||||
@@ -495,7 +493,7 @@ class RecordingMaintainer(threading.Thread):
|
||||
)
|
||||
retain_cutoff = datetime.datetime.fromtimestamp(
|
||||
most_recently_processed_frame_time - record_config.event_pre_capture
|
||||
).astimezone(datetime.timezone.utc)
|
||||
).astimezone(datetime.UTC)
|
||||
|
||||
if end_time < retain_cutoff:
|
||||
self.drop_segment(cache_path)
|
||||
@@ -621,7 +619,7 @@ class RecordingMaintainer(threading.Thread):
|
||||
duration: float,
|
||||
cache_path: str,
|
||||
segment_info: SegmentInfo,
|
||||
) -> Optional[dict[str, Any]]:
|
||||
) -> dict[str, Any] | None:
|
||||
# directory will be in utc due to start_time being in utc
|
||||
directory = os.path.join(
|
||||
RECORD_DIR,
|
||||
|
||||
Reference in New Issue
Block a user