chore: snapshot workflow migration progress
This commit is contained in:
@@ -1,17 +1,20 @@
|
||||
"""Render Templates API — CRUD + .blend file upload/download + material library."""
|
||||
import json
|
||||
import uuid
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form, status
|
||||
from fastapi.responses import FileResponse
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select, update as sql_update, delete as sql_delete
|
||||
from pydantic import BaseModel
|
||||
from pydantic import BaseModel, TypeAdapter, ValidationError
|
||||
|
||||
from app.database import get_db
|
||||
from app.config import settings as app_settings
|
||||
from app.domains.rendering.workflow_node_registry import WorkflowNodeFieldDefinition
|
||||
from app.models.user import User
|
||||
from app.models.render_template import RenderTemplate
|
||||
from app.models.output_type import OutputType
|
||||
@@ -46,6 +49,7 @@ class RenderTemplateOut(BaseModel):
|
||||
lighting_only: bool
|
||||
shadow_catcher_enabled: bool
|
||||
camera_orbit: bool
|
||||
workflow_input_schema: list[WorkflowNodeFieldDefinition]
|
||||
is_active: bool
|
||||
created_at: str
|
||||
updated_at: str
|
||||
@@ -62,6 +66,7 @@ class RenderTemplateUpdate(BaseModel):
|
||||
lighting_only: bool | None = None
|
||||
shadow_catcher_enabled: bool | None = None
|
||||
camera_orbit: bool | None = None
|
||||
workflow_input_schema: list[WorkflowNodeFieldDefinition] | None = None
|
||||
is_active: bool | None = None
|
||||
|
||||
|
||||
@@ -72,6 +77,29 @@ class MaterialLibraryInfo(BaseModel):
|
||||
path: str | None = None
|
||||
|
||||
|
||||
_workflow_input_schema_adapter = TypeAdapter(list[WorkflowNodeFieldDefinition])
|
||||
|
||||
|
||||
def _normalize_workflow_input_schema(schema: Any) -> list[dict[str, Any]]:
|
||||
if schema in (None, "", "null"):
|
||||
return []
|
||||
try:
|
||||
validated = _workflow_input_schema_adapter.validate_python(schema)
|
||||
except ValidationError as exc:
|
||||
raise HTTPException(status_code=422, detail={"workflow_input_schema": exc.errors()}) from exc
|
||||
return [field.model_dump(mode="json") for field in validated]
|
||||
|
||||
|
||||
def _parse_form_workflow_input_schema(raw_schema: str | None) -> list[dict[str, Any]]:
|
||||
if raw_schema in (None, "", "null"):
|
||||
return []
|
||||
try:
|
||||
payload = json.loads(raw_schema)
|
||||
except json.JSONDecodeError as exc:
|
||||
raise HTTPException(status_code=422, detail="workflow_input_schema must be valid JSON") from exc
|
||||
return _normalize_workflow_input_schema(payload)
|
||||
|
||||
|
||||
def _to_out(t: RenderTemplate) -> dict:
|
||||
ot_name = None
|
||||
if t.output_type:
|
||||
@@ -94,6 +122,7 @@ def _to_out(t: RenderTemplate) -> dict:
|
||||
"lighting_only": t.lighting_only,
|
||||
"shadow_catcher_enabled": t.shadow_catcher_enabled,
|
||||
"camera_orbit": t.camera_orbit,
|
||||
"workflow_input_schema": t.workflow_input_schema or [],
|
||||
"is_active": t.is_active,
|
||||
"created_at": t.created_at.isoformat() if t.created_at else "",
|
||||
"updated_at": t.updated_at.isoformat() if t.updated_at else "",
|
||||
@@ -126,6 +155,7 @@ async def create_render_template(
|
||||
lighting_only: bool = Form(False),
|
||||
shadow_catcher_enabled: bool = Form(False),
|
||||
camera_orbit: bool = Form(True),
|
||||
workflow_input_schema: str | None = Form(None),
|
||||
user: User = Depends(require_admin_or_pm),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
@@ -182,6 +212,7 @@ async def create_render_template(
|
||||
lighting_only=lighting_only,
|
||||
shadow_catcher_enabled=shadow_catcher_enabled,
|
||||
camera_orbit=camera_orbit,
|
||||
workflow_input_schema=_parse_form_workflow_input_schema(workflow_input_schema),
|
||||
)
|
||||
db.add(tmpl)
|
||||
await db.flush()
|
||||
@@ -224,6 +255,8 @@ async def update_render_template(
|
||||
# Normalise empty strings to None for nullable fields
|
||||
if "category_key" in updates and updates["category_key"] in ("", "null"):
|
||||
updates["category_key"] = None
|
||||
if "workflow_input_schema" in updates:
|
||||
updates["workflow_input_schema"] = _normalize_workflow_input_schema(updates["workflow_input_schema"])
|
||||
|
||||
# Handle M2M output_type_ids
|
||||
new_ot_ids: list[str] | None = updates.pop("output_type_ids", None)
|
||||
|
||||
Reference in New Issue
Block a user