fix(types): resolve pre-existing basedpyright errors in py/ and standalone.py

Fix ~950 basedpyright errors across the backend:
- Convert ineffective # type: ignore comments to # pyright: ignore[rule]
- Add missing generic type arguments (Dict[str, Any], list[Any], ...)
- Annotate dynamic dict literals and runtime-initialized attributes
- Widen CivitAI provider tuple signatures in recipe parsers
- Remove dead LoraRoutes handlers calling nonexistent LoraService methods
- Suppress unavoidable ServiceRegistry import cycles (basedpyright counts
  function-local imports as cycle edges)
This commit is contained in:
Will Miao
2026-08-08 20:12:52 +08:00
parent 6fcdeb799d
commit 8e724538bd
103 changed files with 1184 additions and 1015 deletions

View File

@@ -4,13 +4,13 @@ import logging
import os
import struct
from io import BytesIO
from typing import Any, Optional, Tuple
from typing import Any, Optional, Tuple, cast
import piexif
import piexif # pyright: ignore[reportMissingTypeStubs]
from PIL import Image, PngImagePlugin
try:
import brotli
import brotli # pyright: ignore[reportMissingTypeStubs]
_BROTLI_AVAILABLE = True
except ImportError:
brotli = None
@@ -38,7 +38,7 @@ class ExifUtils:
"""Utility functions for working with EXIF data in images"""
@staticmethod
def _parse_isobmff_boxes(data: bytes, offset: int = 0) -> list[dict]:
def _parse_isobmff_boxes(data: bytes, offset: int = 0) -> list[dict[str, Any]]:
boxes = []
while offset + 8 <= len(data):
size = struct.unpack('>I', data[offset:offset + 4])[0]
@@ -78,7 +78,7 @@ class ExifUtils:
_BROTLI_MAX_DECOMPRESSED = 2 * 1024 * 1024
@staticmethod
def _extract_isobmff_brotli(image_path: str) -> Optional[dict]:
def _extract_isobmff_brotli(image_path: str) -> Optional[dict[str, Any]]:
try:
with open(image_path, 'rb') as f:
data = f.read()
@@ -107,7 +107,7 @@ class ExifUtils:
if _BROTLI_AVAILABLE:
try:
decompressed = brotli.decompress(compressed)
decompressed = brotli.decompress(compressed) # pyright: ignore[reportOptionalMemberAccess]
if len(decompressed) > ExifUtils._BROTLI_MAX_DECOMPRESSED:
logger.warning(
"Brotli metadata too large (%d bytes, max %d), ignoring",
@@ -126,7 +126,9 @@ class ExifUtils:
except Exception:
return None
result = {"parameters": None, "prompt": None, "workflow": None, "comment": None}
result: dict[str, Optional[str]] = {
"parameters": None, "prompt": None, "workflow": None, "comment": None
}
if isinstance(meta.get("prompt"), (dict, list)):
result["prompt"] = json.dumps(meta["prompt"])
elif isinstance(meta.get("prompt"), str):
@@ -161,7 +163,7 @@ class ExifUtils:
@staticmethod
def _load_structured_metadata(image_path: str) -> dict[str, Optional[str]]:
metadata = {
metadata: dict[str, Optional[str]] = {
"parameters": None,
"prompt": None,
"workflow": None,
@@ -197,13 +199,14 @@ class ExifUtils:
logger.debug(f"Error loading EXIF data: {e}")
exif_dict = {}
if piexif.ExifIFD.UserComment in exif_dict.get("Exif", {}):
exif_ifd = exif_dict.get("Exif")
if exif_ifd and piexif.ExifIFD.UserComment in exif_ifd:
metadata["comment"] = ExifUtils._decode_user_comment(
exif_dict["Exif"][piexif.ExifIFD.UserComment]
exif_ifd[piexif.ExifIFD.UserComment]
)
image_description = ExifUtils._decode_exif_text(
exif_dict.get("0th", {}).get(piexif.ImageIFD.ImageDescription)
(exif_dict.get("0th") or {}).get(piexif.ImageIFD.ImageDescription)
)
if image_description:
if image_description.startswith("Workflow:"):
@@ -253,19 +256,26 @@ class ExifUtils:
workflow = metadata_fields.get("workflow")
prompt = metadata_fields.get("prompt")
# Work on local references, then write the (possibly new) IFD dicts back.
exif_ifd = exif_dict.get("Exif") or {}
exif_0th = exif_dict.get("0th") or {}
if parameters:
exif_dict["Exif"][piexif.ExifIFD.UserComment] = (
exif_ifd[piexif.ExifIFD.UserComment] = (
b"UNICODE\0" + parameters.encode("utf-16be")
)
else:
exif_dict["Exif"].pop(piexif.ExifIFD.UserComment, None)
exif_ifd.pop(piexif.ExifIFD.UserComment, None)
if workflow:
exif_dict["0th"][piexif.ImageIFD.ImageDescription] = f"Workflow:{workflow}"
exif_0th[piexif.ImageIFD.ImageDescription] = f"Workflow:{workflow}"
elif prompt:
exif_dict["0th"][piexif.ImageIFD.ImageDescription] = prompt
exif_0th[piexif.ImageIFD.ImageDescription] = prompt
else:
exif_dict["0th"].pop(piexif.ImageIFD.ImageDescription, None)
exif_0th.pop(piexif.ImageIFD.ImageDescription, None)
exif_dict["Exif"] = exif_ifd
exif_dict["0th"] = exif_0th
return piexif.dump(exif_dict)
@@ -326,7 +336,7 @@ class ExifUtils:
exif_bytes = ExifUtils._build_exif_bytes(
metadata_fields, img.info.get("exif")
)
save_kwargs = {"exif": exif_bytes}
save_kwargs: dict[str, Any] = {"exif": exif_bytes}
if img_format == "WEBP":
save_kwargs["quality"] = 85
@@ -499,12 +509,12 @@ class ExifUtils:
else:
# It's binary data - validate data
try:
with BytesIO(image_data) as temp_buf:
with BytesIO(cast(bytes, image_data)) as temp_buf:
test_img = Image.open(temp_buf)
# Verify the image can be fully loaded
width, height = test_img.size
# If successful, reopen for processing
img = Image.open(BytesIO(image_data))
img = Image.open(BytesIO(cast(bytes, image_data)))
except Exception as e:
logger.error(f"Invalid binary image data: {e}")
raise ValueError(f"Cannot process corrupt image data: {e}")
@@ -521,7 +531,7 @@ class ExifUtils:
import tempfile
with tempfile.NamedTemporaryFile(suffix='.jpg', delete=False) as temp_file:
temp_path = temp_file.name
temp_file.write(image_data)
temp_file.write(cast(bytes, image_data))
try:
metadata_fields = ExifUtils._load_structured_metadata(temp_path)
except Exception as e:
@@ -542,7 +552,7 @@ class ExifUtils:
# Resize the image with error handling
try:
resized_img = img.resize((target_width, new_height), Image.LANCZOS)
resized_img = img.resize((target_width, new_height), Image.Resampling.LANCZOS)
except Exception as e:
logger.error(f"Failed to resize image: {e}")
# Return original image if resize fails