lint: replace no-op flake8 script with gating ruff check, fix findings
CI / skip-ci-check (push) Successful in 18s
CI / python-lint (push) Failing after 19s
CI / docker-ci (push) Successful in 21s
CI / secret-scan (push) Successful in 30s
CI / skip-ci-check (pull_request) Successful in 27s
CI / python-lint (pull_request) Failing after 21s
CI / docker-ci (pull_request) Successful in 22s
CI / admin-unit (push) Successful in 44s
CI / secret-scan (pull_request) Successful in 45s
CI / admin-unit (pull_request) Successful in 55s
CI / viewer-unit (push) Successful in 1m54s
CI / viewer-unit (pull_request) Successful in 1m45s
CI / e2e (push) Failing after 6m5s
CI / e2e (pull_request) Successful in 6m43s

This commit is contained in:
2026-07-26 16:01:28 -04:00
parent abb7b34700
commit fc3960afa9
32 changed files with 218 additions and 218 deletions
+40 -45
View File
@@ -3,57 +3,57 @@
from __future__ import annotations
from datetime import datetime
from fastapi import APIRouter, Depends, HTTPException, Query, status
from fastapi.responses import FileResponse, Response
from rq import Queue
from redis import Redis
from sqlalchemy import func
from sqlalchemy.orm import Session
from typing import Annotated
from backend.db.session import get_db
from fastapi import APIRouter, Depends, HTTPException, Query, status
from fastapi.responses import Response
from redis import Redis
from rq import Queue
from sqlalchemy import func
from sqlalchemy.orm import Session
from backend.api.auth import get_current_user_with_id
from backend.db.models import Face, Person, PersonEncoding, Photo
from backend.db.session import get_db
from backend.schemas.faces import (
ProcessFacesRequest,
ProcessFacesResponse,
UnidentifiedFacesQuery,
UnidentifiedFacesResponse,
FaceItem,
SimilarFacesResponse,
SimilarFaceItem,
BatchSimilarityRequest,
BatchSimilarityResponse,
FaceSimilarityPair,
IdentifyFaceRequest,
IdentifyFaceResponse,
FaceUnmatchResponse,
BatchUnmatchRequest,
BatchUnmatchResponse,
AutoMatchRequest,
AutoMatchResponse,
AutoMatchPersonItem,
AutoMatchFaceItem,
AutoMatchPeopleResponse,
AutoMatchPersonSummary,
AutoMatchPersonItem,
AutoMatchPersonMatchesResponse,
AcceptMatchesRequest,
MaintenanceFacesResponse,
MaintenanceFaceItem,
AutoMatchPersonSummary,
AutoMatchRequest,
AutoMatchResponse,
BatchSimilarityRequest,
BatchSimilarityResponse,
BatchUnmatchRequest,
BatchUnmatchResponse,
DeleteFacesRequest,
DeleteFacesResponse,
FaceItem,
FaceSimilarityPair,
FaceUnmatchResponse,
IdentifyFaceRequest,
IdentifyFaceResponse,
MaintenanceFaceItem,
MaintenanceFacesResponse,
ProcessFacesRequest,
ProcessFacesResponse,
SimilarFaceItem,
SimilarFacesResponse,
UnidentifiedFacesResponse,
)
from backend.schemas.people import PersonCreateRequest, PersonResponse
from backend.db.models import Face, Person, PersonEncoding, Photo
from backend.services.face_service import (
list_unidentified_faces,
find_similar_faces,
accept_auto_match_matches,
calculate_batch_similarities,
find_auto_match_matches,
accept_auto_match_matches,
find_similar_faces,
get_auto_match_people_list,
list_unidentified_faces,
)
from backend.services.face_service import (
get_auto_match_person_matches as get_person_matches_service,
)
# Note: Function passed as string path to avoid RQ serialization issues
router = APIRouter(prefix="/faces", tags=["faces"])
@@ -202,6 +202,7 @@ def get_similar_faces(
) -> SimilarFacesResponse:
"""Return similar unidentified faces for a given face."""
import logging
import numpy as np
logger = logging.getLogger(__name__)
logger.info(f"API: get_similar_faces called for face_id={face_id}, include_excluded={include_excluded}, debug={debug}")
@@ -369,11 +370,12 @@ def identify_face(
@router.get("/{face_id}/crop")
def get_face_crop(face_id: int, db: Session = Depends(get_db)) -> Response:
"""Serve face crop image extracted from photo using face location."""
import os
import json
import ast
import tempfile
import json
import os
from PIL import Image
from backend.db.models import Face, Photo
from src.utils.exif_utils import EXIFOrientationHandler
@@ -549,8 +551,6 @@ def batch_unmatch_faces(request: BatchUnmatchRequest, db: Session = Depends(get_
# Unmatch all matched faces
face_ids_to_unmatch = [f.id for f in matched_faces]
# Collect person_ids that will be affected (before unlinking)
affected_person_ids = {f.person_id for f in matched_faces if f.person_id is not None}
for face in matched_faces:
face.person_id = None
@@ -620,7 +620,6 @@ def auto_match_faces(
- Only auto-accepts faces with quality > 50% (quality_score > 0.5)
"""
from backend.db.models import Person, Photo
from sqlalchemy import func
# Track statistics for auto-accept
auto_accepted_faces = 0
@@ -997,10 +996,6 @@ def delete_faces(
detail=f"Faces not found: {sorted(missing_ids)}",
)
# Collect person_ids that will be affected (before deletion)
# Only include faces that are identified (have a person_id)
affected_person_ids = {f.person_id for f in faces if f.person_id is not None}
# Delete associated person_encodings for these faces
db.query(PersonEncoding).filter(PersonEncoding.face_id.in_(request.face_ids)).delete(synchronize_session=False)