mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-03-09 07:10:10 +00:00
Add optional blake3 hashing during asset scanning
- Make blake3 import lazy in hashing.py (only imported when needed) - Add compute_hashes parameter to AssetSeeder.start(), build_asset_specs(), and seed_assets() - Fix missing tag clearing: include is_missing states in sync when update_missing_tags=True - Clear is_missing flag on cache states when files are restored with matching mtime/size - Fix validation error serialization in routes.py (use json.loads(ve.json())) Amp-Thread-ID: https://ampcode.com/threads/T-019c3614-56d4-74a8-a717-19922d6dbbee Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -79,7 +79,9 @@ def _build_error_response(
|
||||
|
||||
|
||||
def _build_validation_error_response(code: str, ve: ValidationError) -> web.Response:
|
||||
return _build_error_response(400, code, "Validation failed.", {"errors": ve.json()})
|
||||
import json
|
||||
errors = json.loads(ve.json())
|
||||
return _build_error_response(400, code, "Validation failed.", {"errors": errors})
|
||||
|
||||
|
||||
def _validate_sort_field(requested: str | None) -> str:
|
||||
@@ -123,11 +125,8 @@ async def list_assets_route(request: web.Request) -> web.Response:
|
||||
return _build_validation_error_response("INVALID_QUERY", ve)
|
||||
|
||||
sort = _validate_sort_field(q.sort)
|
||||
order = (
|
||||
"desc"
|
||||
if (q.order or "desc").lower() not in {"asc", "desc"}
|
||||
else q.order.lower()
|
||||
)
|
||||
order_candidate = (q.order or "desc").lower()
|
||||
order = order_candidate if order_candidate in {"asc", "desc"} else "desc"
|
||||
|
||||
result = list_assets_page(
|
||||
owner_id=USER_MANAGER.get_request_user_id(request),
|
||||
@@ -233,7 +232,7 @@ async def download_asset_content(request: web.Request) -> web.Response:
|
||||
)
|
||||
|
||||
quoted = (filename or "").replace("\r", "").replace("\n", "").replace('"', "'")
|
||||
cd = f"{disposition}; filename=\"{quoted}\"; filename*=UTF-8''{urllib.parse.quote(filename)}"
|
||||
cd = f"{disposition}; filename=\"{quoted}\"; filename*=UTF-8''{urllib.parse.quote(quoted)}"
|
||||
|
||||
file_size = os.path.getsize(abs_path)
|
||||
logging.info(
|
||||
@@ -490,15 +489,9 @@ async def get_tags(request: web.Request) -> web.Response:
|
||||
try:
|
||||
query = schemas_in.TagsListQuery.model_validate(query_map)
|
||||
except ValidationError as e:
|
||||
return web.json_response(
|
||||
{
|
||||
"error": {
|
||||
"code": "INVALID_QUERY",
|
||||
"message": "Invalid query parameters",
|
||||
"details": e.errors(),
|
||||
}
|
||||
},
|
||||
status=400,
|
||||
import json
|
||||
return _build_error_response(
|
||||
400, "INVALID_QUERY", "Invalid query parameters", {"errors": json.loads(e.json())}
|
||||
)
|
||||
|
||||
rows, total = list_tags(
|
||||
|
||||
@@ -28,6 +28,7 @@ class AssetValidationError(Exception):
|
||||
def __init__(self, code: str, message: str):
|
||||
super().__init__(message)
|
||||
self.code = code
|
||||
self.message = message
|
||||
|
||||
|
||||
class AssetNotFoundError(Exception):
|
||||
@@ -35,12 +36,15 @@ class AssetNotFoundError(Exception):
|
||||
|
||||
def __init__(self, message: str):
|
||||
super().__init__(message)
|
||||
self.message = message
|
||||
|
||||
|
||||
class HashMismatchError(Exception):
|
||||
"""Uploaded file hash does not match provided hash."""
|
||||
|
||||
pass
|
||||
def __init__(self, message: str):
|
||||
super().__init__(message)
|
||||
self.message = message
|
||||
|
||||
|
||||
class DependencyMissingError(Exception):
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
import os
|
||||
import uuid
|
||||
from typing import Callable
|
||||
@@ -83,7 +84,10 @@ async def parse_multipart_upload(
|
||||
provided_hash = normalize_and_validate_hash(s)
|
||||
try:
|
||||
provided_hash_exists = check_hash_exists(provided_hash)
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
logging.warning(
|
||||
"check_hash_exists failed for hash=%s: %s", provided_hash, e
|
||||
)
|
||||
provided_hash_exists = None # do not fail the whole request here
|
||||
|
||||
elif fname == "file":
|
||||
@@ -162,5 +166,5 @@ def delete_temp_file_if_exists(tmp_path: str | None) -> None:
|
||||
try:
|
||||
if os.path.exists(tmp_path):
|
||||
os.remove(tmp_path)
|
||||
except Exception:
|
||||
pass
|
||||
except OSError as e:
|
||||
logging.debug("Failed to delete temp file %s: %s", tmp_path, e)
|
||||
|
||||
Reference in New Issue
Block a user