docstrings

This commit is contained in:
Josh Hawkins
2026-10-30 21:51:55 -05:00
parent e3cb3412d6
commit 00214bcec8
7 changed files with 23 additions and 4 deletions
+6 -1
View File
@@ -35,6 +35,7 @@ QUALITIES = frozenset(ConnectionQuality)
def height_bucket(height: int) -> HeightBucket: def height_bucket(height: int) -> HeightBucket:
"""The nearest standard resolution bucket for a detect height."""
for limit, bucket in HEIGHT_BUCKETS: for limit, bucket in HEIGHT_BUCKETS:
if height <= limit: if height <= limit:
return bucket return bucket
@@ -43,6 +44,7 @@ def height_bucket(height: int) -> HeightBucket:
def fps_bucket(fps: int) -> FpsBucket: def fps_bucket(fps: int) -> FpsBucket:
"""The bucket for a detect fps."""
if fps <= 5: if fps <= 5:
return FpsBucket.le_5 return FpsBucket.le_5
@@ -53,6 +55,7 @@ def fps_bucket(fps: int) -> FpsBucket:
def retain_bucket(days: float) -> RetainBucket: def retain_bucket(days: float) -> RetainBucket:
"""The bucket for a retention period in days."""
if days <= 0: if days <= 0:
return RetainBucket.zero return RetainBucket.zero
@@ -77,6 +80,7 @@ def preset_key(args: str | list[str], enum: Any) -> Any:
def is_restream(path: str) -> bool: def is_restream(path: str) -> bool:
"""Whether an input reads from the local go2rtc restream."""
try: try:
url = urlsplit(path) url = urlsplit(path)
return url.hostname in RESTREAM_HOSTS and url.port == RESTREAM_PORT return url.hostname in RESTREAM_HOSTS and url.port == RESTREAM_PORT
@@ -85,11 +89,12 @@ def is_restream(path: str) -> bool:
def role_input(camera: CameraConfig, role: CameraRoleEnum) -> CameraInput | None: def role_input(camera: CameraConfig, role: CameraRoleEnum) -> CameraInput | None:
"""The camera's first input with the given role."""
return next((i for i in camera.ffmpeg.inputs if role in i.roles), None) return next((i for i in camera.ffmpeg.inputs if role in i.roles), None)
def object_masks(camera: CameraConfig) -> int: def object_masks(camera: CameraConfig) -> int:
# parsing copies camera-wide masks into every filter as global_<id> """Camera and per-label object masks, minus the global_<id> filter copies."""
own = sum(1 for mask in camera.objects.mask.values() if mask is not None) own = sum(1 for mask in camera.objects.mask.values() if mask is not None)
per_label = sum( per_label = sum(
1 1
+4 -1
View File
@@ -50,6 +50,7 @@ def enrichment_device(label: object) -> EnrichmentDevice | None:
def model_name(model: object) -> str | None: def model_name(model: object) -> str | None:
"""The model's config value as a string."""
if model is None: if model is None:
return None return None
@@ -57,7 +58,7 @@ def model_name(model: object) -> str | None:
def semantic_model(model: object) -> SemanticSearchModel | None: def semantic_model(model: object) -> SemanticSearchModel | None:
# any string that isn't a built-in model names a GenAI provider """A built-in Jina model, or genai for any GenAI provider name."""
name = model_name(model) name = model_name(model)
if name is None: if name is None:
@@ -70,6 +71,7 @@ def semantic_model(model: object) -> SemanticSearchModel | None:
def transcription_model(model: object) -> TranscriptionModel | None: def transcription_model(model: object) -> TranscriptionModel | None:
"""Whisper, or genai for any GenAI provider name."""
name = model_name(model) name = model_name(model)
if name is None: if name is None:
@@ -79,6 +81,7 @@ def transcription_model(model: object) -> TranscriptionModel | None:
def users() -> dict[UserRole, int]: def users() -> dict[UserRole, int]:
"""Count users by role, with any custom role counted as custom."""
roles: Counter[UserRole] = Counter( roles: Counter[UserRole] = Counter(
closed(UserRole, user.role, UserRole.custom) for user in User.select(User.role) closed(UserRole, user.role, UserRole.custom) for user in User.select(User.role)
) )
+7 -1
View File
@@ -49,6 +49,7 @@ def cpu_model() -> str:
def gpus(stats: dict[str, Any]) -> list[GpuInfo]: def gpus(stats: dict[str, Any]) -> list[GpuInfo]:
"""GPUs with a stats entry, by vendor and capped name."""
found: list[GpuInfo] = [] found: list[GpuInfo] = []
for name, entry in stats.get("gpu_usages", {}).items(): for name, entry in stats.get("gpu_usages", {}).items():
@@ -64,6 +65,7 @@ def gpus(stats: dict[str, Any]) -> list[GpuInfo]:
def decode_families() -> list[DecodeFamily]: def decode_families() -> list[DecodeFamily]:
"""Hardware decode families the host supports."""
_, available = hwaccel_options() _, available = hwaccel_options()
families = [ families = [
closed(DecodeFamily, family.key, DecodeFamily.other) for family in available closed(DecodeFamily, family.key, DecodeFamily.other) for family in available
@@ -72,6 +74,7 @@ def decode_families() -> list[DecodeFamily]:
def detection_hardware() -> dict[HardwareKey, int]: def detection_hardware() -> dict[HardwareKey, int]:
"""Detection accelerators found by the hardware probe, by unit count."""
units: Counter[HardwareKey] = Counter() units: Counter[HardwareKey] = Counter()
for found in hardware_prober.probe(): for found in hardware_prober.probe():
@@ -81,7 +84,10 @@ def detection_hardware() -> dict[HardwareKey, int]:
def storage(stats: dict[str, Any]) -> StorageInfo: def storage(stats: dict[str, Any]) -> StorageInfo:
# stats report sizes in MB """Filesystem, size, and usage of the recordings volume.
Stats report sizes in MB.
"""
entry = stats.get("service", {}).get("storage", {}).get(RECORD_DIR) or {} entry = stats.get("service", {}).get("storage", {}).get(RECORD_DIR) or {}
total_mb = float(entry.get("total") or 0) total_mb = float(entry.get("total") or 0)
used_mb = float(entry.get("used") or 0) used_mb = float(entry.get("used") or 0)
+3 -1
View File
@@ -21,7 +21,7 @@ def image_variant(value: str | None) -> ImageVariant:
def install_type() -> InstallType: def install_type() -> InstallType:
# the add-on is a container too, so it has to be checked first """How Frigate runs; the add-on is a container too, so it's checked first."""
if os.path.isfile("/data/options.json"): if os.path.isfile("/data/options.json"):
return InstallType.ha_addon return InstallType.ha_addon
@@ -38,6 +38,7 @@ def install_type() -> InstallType:
def arch(machine: str) -> Arch: def arch(machine: str) -> Arch:
"""The CPU architecture for a platform.machine() value."""
match machine.lower(): match machine.lower():
case "x86_64" | "amd64": case "x86_64" | "amd64":
return Arch.x86_64 return Arch.x86_64
@@ -48,6 +49,7 @@ def arch(machine: str) -> Arch:
def kernel(release: str) -> str: def kernel(release: str) -> str:
"""The major.minor of a kernel release string, or unknown."""
match = KERNEL_PATTERN.match(release) match = KERNEL_PATTERN.match(release)
return f"{match.group(1)}.{match.group(2)}" if match else "unknown" return f"{match.group(1)}.{match.group(2)}" if match else "unknown"
+1
View File
@@ -75,6 +75,7 @@ class AnalyticsReporter(threading.Thread):
return INTERVAL_S + self.rng.uniform(-JITTER_S, JITTER_S) return INTERVAL_S + self.rng.uniform(-JITTER_S, JITTER_S)
def run(self) -> None: def run(self) -> None:
"""Tick every wake until stopped; a failed tick never ends the thread."""
while True: while True:
try: try:
self.tick() self.tick()
+1
View File
@@ -188,6 +188,7 @@ def metric(description: str, *, public: bool = True, **kwargs: Any) -> Any:
def count(description: str) -> Any: def count(description: str) -> Any:
"""Declare a non-negative count field."""
return metric(description, ge=0) return metric(description, ge=0)
+1
View File
@@ -22,6 +22,7 @@ OUTPUT = Path(__file__).parent / "docs" / "static" / "frigate-analytics-schema.j
def render() -> str: def render() -> str:
"""The JSON Schema for the current report models."""
schema = AnalyticsReport.model_json_schema() schema = AnalyticsReport.model_json_schema()
schema["$schema"] = "https://json-schema.org/draft/2020-12/schema" schema["$schema"] = "https://json-schema.org/draft/2020-12/schema"
schema["$id"] = "https://docs.frigate.video/frigate-analytics-schema.json" schema["$id"] = "https://docs.frigate.video/frigate-analytics-schema.json"