schema validation with jsonschema, orgs

This commit is contained in:
lda
2026-05-08 22:55:02 +07:00 Verified
parent ea578d2e98
commit ca14d726d0
12 changed files with 674 additions and 533 deletions
+40 -9
View File
@@ -2,15 +2,46 @@ from __future__ import annotations
from typing import Any
from jsonschema import ValidationError, SchemaError, validators
from wf_core.errors import WorkflowExecutionError
from wf_core.models.schemas import SchemaRef
def validate_payload_against_schema(schema: Any, payload: Any, label: str) -> None:
if schema.type == "object":
if not isinstance(payload, dict):
raise WorkflowExecutionError(f"{label} must be an object")
for required_key in schema.required:
if required_key not in payload:
raise WorkflowExecutionError(
f"{label} is missing required field {required_key!r}"
)
def validate_payload_against_schema(
schema: SchemaRef | dict[str, Any],
payload: Any,
label: str,
) -> None:
"""Validate a runtime payload against the schema declared at a boundary.
The runtime delegates JSON Schema semantics to `jsonschema` instead of
maintaining hand-written type checks. Errors are wrapped in
`WorkflowExecutionError` so callers keep one execution-failure surface.
"""
schema_dict = _schema_dict(schema)
validator_cls = validators.validator_for(schema_dict)
try:
validator_cls.check_schema(schema_dict)
validator_cls(schema_dict).validate(payload)
except SchemaError as exc:
raise WorkflowExecutionError(
f"{label} has invalid schema: {exc.message}"
) from exc
except ValidationError as exc:
path = _format_error_path(exc)
raise WorkflowExecutionError(f"{label}{path}: {exc.message}") from exc
def _schema_dict(schema: SchemaRef | dict[str, Any]) -> dict[str, Any]:
"""Return a JSON-Schema-compatible dictionary for validation."""
if isinstance(schema, SchemaRef):
return schema.model_dump(exclude_none=True)
return schema
def _format_error_path(exc: ValidationError) -> str:
"""Render a compact JSON-path-like suffix for a validation error."""
if not exc.path:
return ""
return "".join(f"[{part!r}]" for part in exc.path)