From 9b8880a3da4e0f803c01fc0aa16f675a85608c96 Mon Sep 17 00:00:00 2001 From: nanxun Date: Wed, 12 Aug 2026 20:58:33 +0800 Subject: [PATCH] fix(ci): satisfy backend lint checks --- backend/imagefind/api.py | 109 +++++++++++++++++++---------------- backend/imagefind/uploads.py | 37 +++++------- 2 files changed, 73 insertions(+), 73 deletions(-) diff --git a/backend/imagefind/api.py b/backend/imagefind/api.py index 5afbad6..f0f41a2 100644 --- a/backend/imagefind/api.py +++ b/backend/imagefind/api.py @@ -64,9 +64,7 @@ async def _background_api_with_fallback(function, fallback, /, *args, **kwargs): task = asyncio.create_task(_background_api(function, *args, **kwargs)) try: - return await asyncio.wait_for( - asyncio.shield(task), timeout=API_READ_DEADLINE_SECONDS - ) + return await asyncio.wait_for(asyncio.shield(task), timeout=API_READ_DEADLINE_SECONDS) except TimeoutError: # asyncio.to_thread cannot stop a running database call. Let it refresh # the service cache, consume any eventual exception, and serve the last @@ -627,9 +625,7 @@ def _set_session( *, client_key: str = "local", ) -> dict: - token, csrf, expires = app.auth.login( - password, remember_device=remember_device, client_key=client_key - ) + token, csrf, expires = app.auth.login(password, remember_device=remember_device, client_key=client_key) return _set_cookie( response, app, @@ -1390,13 +1386,11 @@ def home_feed( for row in tag_rows ] unorganized_items = ( - videos(app, current_user, organized=False, sort="added", limit=item_limit) - if unorganized_count - else [] + videos(app, current_user, organized=False, sort="added", limit=item_limit) if unorganized_count else [] ) - hide_unorganized = unorganized_count <= item_limit and { - item["id"] for item in unorganized_items - } == {item["id"] for item in recent} + hide_unorganized = unorganized_count <= item_limit and {item["id"] for item in unorganized_items} == { + item["id"] for item in recent + } actor_items = sorted( (item for item in list_actors(app, current_user) if int(item["video_count"] or 0) > 0), key=lambda item: (-int(item["video_count"] or 0), str(item["name"]).casefold()), @@ -1788,9 +1782,7 @@ async def jobs( if page is not None: if page < 1 or page_size < 1 or page_size > 50: raise HTTPException(422, "page 必须大于 0,page_size 必须在 1–50 之间") - return await _background_api( - app.jobs.paginate, page, page_size, lane=lane, status=status - ) + return await _background_api(app.jobs.paginate, page, page_size, lane=lane, status=status) return await _background_api(app.jobs.list, limit, lane=lane, status=status) @@ -1905,27 +1897,43 @@ async def search( if isinstance(rebuild, dict) and rebuild.get("status") in {"running", "failed"}: if rebuild.get("status") == "running": with app.db.read() as conn: - remaining = int(conn.execute( - "SELECT count(*) FROM videos WHERE available=1 AND audio_index_revision=?", - (rebuild.get("started_at") or "",), - ).fetchone()[0]) + remaining = int( + conn.execute( + "SELECT count(*) FROM videos WHERE available=1 AND audio_index_revision=?", # noqa: E501 + (rebuild.get("started_at") or "",), + ).fetchone()[0] + ) if active == 0: status = "completed" if remaining == 0 else "failed" - rebuild = {**rebuild, "status": status, "remaining": remaining, "failed_jobs": failed, "finished_at": utcnow()} + rebuild = { + **rebuild, + "status": status, + "remaining": remaining, + "failed_jobs": failed, + "finished_at": utcnow(), + } app.db.set_setting("audio_rebuild", rebuild) if rebuild.get("status") == "completed": rebuild = {} else: requested = set(body.recognition_types or []) if "audio" in requested: - message = "音频索引全库重建存在失败任务,修复前音频搜索保持暂停" if rebuild.get("status") == "failed" else "音频索引正在全库重建,音频搜索暂时不可用" + message = ( + "音频索引全库重建存在失败任务,修复前音频搜索保持暂停" + if rebuild.get("status") == "failed" + else "音频索引正在全库重建,音频搜索暂时不可用" + ) raise HTTPException(409, message) if body.recognition_types is None: body.recognition_types = ["visual", "ocr", "person", "subtitle", "metadata"] @@ -1969,8 +1977,7 @@ async def search( cjk = sum("\u3400" <= character <= "\u9fff" for character in compact) if compact and ((cjk == len(compact) and cjk < 2) or (cjk == 0 and len(compact) < 3)): result["query_notice"] = ( - "关键词过短,仅进行精确人物、标签和标题匹配;" - "搜索语音/OCR 至少输入 2 个汉字或 3 个拉丁字符。" + "关键词过短,仅进行精确人物、标签和标题匹配;搜索语音/OCR 至少输入 2 个汉字或 3 个拉丁字符。" ) return result except ValueError as exc: @@ -2161,17 +2168,23 @@ def speech_rebuild_status( if not isinstance(state, dict) or state.get("status") != "running": return state with app.db.read() as conn: - completed = int(conn.execute( - "SELECT count(*) FROM videos WHERE available=1 AND audio_index_revision>=?", - (SPEECH_INDEX_REVISION,), - ).fetchone()[0]) - remaining = int(conn.execute( - "SELECT count(*) FROM videos WHERE available=1 AND audio_index_revision=?", + (SPEECH_INDEX_REVISION,), + ).fetchone()[0] + ) + remaining = int( + conn.execute( + "SELECT count(*) FROM videos WHERE available=1 AND audio_index_revision=0.55", - (video_id,), + "SELECT count(*) FROM text_entries WHERE video_id=? AND kind='audio' " + "AND coalesce(quality_score,1)>=0.55", + (video_id,), ).fetchone()[0] ) rows = conn.execute( @@ -2658,9 +2671,7 @@ async def list_uploads( source_id, query, ) - return await _background_api_with_fallback( - app.uploads.list, app.uploads.cached_list, limit - ) + return await _background_api_with_fallback(app.uploads.list, app.uploads.cached_list, limit) @router.post("/v1/uploads", status_code=201) @@ -3032,9 +3043,7 @@ def restore_trash( "ORDER BY updated_at DESC LIMIT 1", (item["source_id"], item["original_key"], item["physical_original_path"]), ).fetchone() - if item - and item["storage_backend"] == "openlist_native" - and item["physical_original_path"] + if item and item["storage_backend"] == "openlist_native" and item["physical_original_path"] else None ) key = app.storage.restore(trash_id) diff --git a/backend/imagefind/uploads.py b/backend/imagefind/uploads.py index 2bf688d..054f652 100644 --- a/backend/imagefind/uploads.py +++ b/backend/imagefind/uploads.py @@ -86,14 +86,13 @@ class UploadService: recovery_state = str(result.get("recovery_state") or "") if status in {"failed", "cancelled"} and recovery_state in {"", "receiving"}: original = Path(str(result.get("temp_path") or "")).is_file() - encrypted = bool( - result.get("external_local_path") - and Path(str(result["external_local_path"])).is_file() - ) + encrypted = bool(result.get("external_local_path") and Path(str(result["external_local_path"])).is_file()) catalog = bool(result.get("failure_stage") == "catalog" and result.get("target_key")) recovery_state = "available" if original or encrypted else "catalog" if catalog else "missing" result["recovery_state"] = recovery_state - result["recovery_mode"] = "original" if original else "encrypted" if encrypted else "catalog" if catalog else None + result["recovery_mode"] = ( + "original" if original else "encrypted" if encrypted else "catalog" if catalog else None + ) result["deduplicated"] = bool(result.get("deduplicated", False)) result.pop("temp_path", None) result.pop("target_key", None) @@ -136,15 +135,15 @@ class UploadService: local_done = phase not in {"receiving", "queued", "encrypting", "local_processing"} remote_required = result.get("storage_backend") == "openlist_native" remote_done = ( - (not remote_required) - or phase in {"cataloging", "ai_queued", "completed"} - or status == "completed" + (not remote_required) or phase in {"cataloging", "ai_queued", "completed"} or status == "completed" ) catalog_done = phase in {"ai_queued", "completed"} or status == "completed" + def step_state(done: bool, active: bool) -> str: if terminal_state: return terminal_state return "completed" if done else "active" if active else "pending" + result["stages"] = [ { "key": "receiving", @@ -427,6 +426,7 @@ class UploadService: received = list(range(total_chunks)) if staged_path is not None else [] bytes_received = size_bytes if staged_path is not None else 0 try: + def insert_upload(conn): conn.execute( "INSERT INTO uploads(id,source_id,relative_path,filename,title,collection_id,collection_parent_id," @@ -632,6 +632,7 @@ class UploadService: missing = sorted(set(range(upload["total_chunks"])) - set(upload["received_chunks"])) if missing: return {"completed": False, "missing_chunks": missing} + def queue_transfer(conn): job_id = self.jobs.enqueue( "transfer_upload", @@ -685,9 +686,7 @@ class UploadService: def _refresh_recovery_state(self, upload_id: str) -> str: upload = self._get(upload_id) original = Path(upload["temp_path"]).is_file() - encrypted = bool( - upload.get("external_local_path") and Path(str(upload["external_local_path"])).is_file() - ) + encrypted = bool(upload.get("external_local_path") and Path(str(upload["external_local_path"])).is_file()) catalog = bool(upload.get("failure_stage") == "catalog" and upload.get("target_key")) state = "available" if original or encrypted else "catalog" if catalog else "missing" mode = "original" if original else "encrypted" if encrypted else "catalog" if catalog else None @@ -706,9 +705,7 @@ class UploadService: if upload["status"] not in {"failed", "cancelled", "completed"}: raise ValueError("任务仍在执行,请先取消") if upload.get("storage_backend") == "openlist_native" and self.openlist_native is not None: - self.openlist_native.cleanup( - upload["source_id"], upload_id, upload.get("external_staged_path") - ) + self.openlist_native.cleanup(upload["source_id"], upload_id, upload.get("external_staged_path")) Path(upload["temp_path"]).unlink(missing_ok=True) with self.db.transaction() as conn: conn.execute("DELETE FROM ingest_guards WHERE upload_id=?", (upload_id,)) @@ -736,9 +733,7 @@ class UploadService: ) else: staged_local = ( - upload.get("external_local_path") - if upload.get("storage_backend") == "openlist_native" - else None + upload.get("external_local_path") if upload.get("storage_backend") == "openlist_native" else None ) if not Path(upload["temp_path"]).is_file() and not (staged_local and Path(staged_local).is_file()): raise ValueError("上传暂存文件不存在,无法重试") @@ -1058,9 +1053,7 @@ class UploadService: if not upload.get("external_source_path"): path = Path(upload["temp_path"]) - paths = self.openlist_native.prepare( - upload["source_id"], upload_id, str(target_key), path - ) + paths = self.openlist_native.prepare(upload["source_id"], upload_id, str(target_key), path) self.db.write_with_retry( lambda conn: conn.execute( "UPDATE uploads SET status='transferring',phase='external_copying'," @@ -1469,9 +1462,7 @@ class UploadService: temp_path = Path(upload["temp_path"]) external_local = upload.get("external_local_path") recoverable_native = bool( - upload.get("storage_backend") == "openlist_native" - and external_local - and Path(external_local).is_file() + upload.get("storage_backend") == "openlist_native" and external_local and Path(external_local).is_file() ) if not committed and not temp_path.is_file() and not recoverable_native: expires = datetime.now(UTC) + timedelta(hours=self.settings.upload_failed_hours)