From 96039fc9839947d1fa2a3a27968631e7615e85c0 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Sun, 24 May 2026 12:20:36 -0400 Subject: [PATCH] fix(ext): wrap /api/extension/manifest filesystem work in asyncio.to_thread (ruff ASYNC240) Co-Authored-By: Claude Opus 4.7 (1M context) --- backend/app/api/extension.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/backend/app/api/extension.py b/backend/app/api/extension.py index 99bf5e2..54d569f 100644 --- a/backend/app/api/extension.py +++ b/backend/app/api/extension.py @@ -4,6 +4,7 @@ from __future__ import annotations +import asyncio import hashlib import re from pathlib import Path @@ -86,18 +87,28 @@ async def quick_add_source(): return jsonify(result), (201 if result["created_source"] else 200) -@extension_bp.route("/manifest", methods=["GET"]) -async def extension_manifest(): +def _read_manifest_sync() -> dict | None: + """All the filesystem-touching work for /api/extension/manifest, + in a sync helper so the async route can dispatch it via + asyncio.to_thread (ASYNC240: no pathlib I/O in async functions).""" if not XPI_DIR.is_dir(): - return jsonify({"installed": False}), 404 + return None xpis = sorted(XPI_DIR.glob("fabledcurator-*.xpi"), key=lambda p: p.stat().st_mtime) if not xpis: - return jsonify({"installed": False}), 404 + return None latest = xpis[-1] - return jsonify({ + return { "installed": True, "version": _extract_version(latest.name), "xpi_url": f"/extension/{latest.name}", "latest_url": "/extension/fabledcurator-latest.xpi", "sha256": _sha256(latest), - }) + } + + +@extension_bp.route("/manifest", methods=["GET"]) +async def extension_manifest(): + info = await asyncio.to_thread(_read_manifest_sync) + if info is None: + return jsonify({"installed": False}), 404 + return jsonify(info)