fix(vision): file non immagine e grafo malformato non escono più come 500 (#15)
Worker: Image.open().convert() in try/except (422 "image is not decodable"); il grafo deve essere un dict (422 altrimenti); run_graph distingue costruzione (GraphBuildError -> 422) da esecuzione (500 con motivo). Router: verifica dei magic bytes (PNG/JPEG/BMP/TIFF/WebP/GIF) prima di chiamare il worker. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+22
-1
@@ -22,6 +22,14 @@ from visionsuite.task import Task
|
||||
_SUBMODULE = Path(__file__).resolve().parents[2] / "vendor" / "visionsuite"
|
||||
|
||||
|
||||
class GraphBuildError(ValueError):
|
||||
"""`Task.from_dict` refused the graph itself - a bad request, not a
|
||||
server fault (a missing "kind", an unknown schema version, a graph that
|
||||
is not even a dict). Kept apart from an error raised once the task is
|
||||
actually running: the worker maps this one to 422, everything else that
|
||||
can go wrong inside `task.run()` to 500."""
|
||||
|
||||
|
||||
@dataclass
|
||||
class ToolFailure:
|
||||
tool_id: str
|
||||
@@ -103,8 +111,21 @@ def run_graph(
|
||||
`image` is whatever the caller already has in hand: a plain numpy array is
|
||||
wrapped into the `visionsuite.core.image.Image` that vs-measure's tools
|
||||
actually read via `.pixels`; an `Image` passed in is used as-is.
|
||||
|
||||
Two phases, on purpose: building the task from `graph` can fail on
|
||||
nothing but the caller's input (a bad schema version, a tool with no
|
||||
"kind", a graph that is not a dict at all) - that is `GraphBuildError`,
|
||||
a 422 for the worker. Once the task exists, `task.run()` is the engine's
|
||||
own business; an exception from there is not the caller's mistake, and
|
||||
the worker must not call it one.
|
||||
"""
|
||||
task = Task.from_dict(graph)
|
||||
try:
|
||||
task = Task.from_dict(graph)
|
||||
except (KeyError, TypeError, AttributeError, ValueError) as exc:
|
||||
raise GraphBuildError(
|
||||
f"malformed graph: {type(exc).__name__}: {exc}"
|
||||
) from exc
|
||||
|
||||
wrapped_image = image if isinstance(image, Image) else Image(pixels=np.asarray(image))
|
||||
context: dict[str, Any] = {"image": wrapped_image}
|
||||
if calibration is not None:
|
||||
|
||||
Reference in New Issue
Block a user