Update Python tools

This commit is contained in:
ajp_anton
2026-08-09 02:31:54 +00:00
parent b0c707d624
commit 6d28257b54
10 changed files with 362 additions and 12 deletions
+51 -3
View File
@@ -6,11 +6,11 @@ import ipaddress
from datetime import datetime
from pathlib import Path
from flask import Flask, abort, redirect, render_template, request, url_for
from flask import Flask, abort, redirect, render_template, request, send_file, url_for
from .config import Settings
from .discovery import TaskCatalog
from .inputs import validate_inputs
from .inputs import validate_inputs, validate_uploads
from .runner import RunManager
from .scheduler import BackgroundScheduler
from .store import RunStore
@@ -23,6 +23,7 @@ def create_app(settings: Settings | None = None) -> Flask:
store.initialize()
store.mark_interrupted()
manager = RunManager(settings, catalog, store)
manager.cleanup_transient_files()
scheduler = BackgroundScheduler(catalog, manager)
scheduler.start()
@@ -95,6 +96,8 @@ def create_app(settings: Settings | None = None) -> Flask:
field.name: request.form.getlist(field.name) for field in task.inputs
}
input_data, errors = validate_inputs(task.inputs, submitted_values)
uploads, upload_errors = validate_uploads(task.inputs, request.files)
errors.update(upload_errors)
if errors:
if request.accept_mimetypes.best == "application/json":
return {"errors": errors}, 400
@@ -103,9 +106,10 @@ def create_app(settings: Settings | None = None) -> Flask:
input_errors={task.id: errors},
status=400,
)
run, _ = manager.run_task(task, input_data)
run, _ = manager.run_task(task, input_data, uploads)
if request.accept_mimetypes.best == "application/json":
return {
"artifacts_url": url_for("run_artifacts", run_id=run.id),
"detail_url": url_for("run_detail", run_id=run.id),
"output_url": url_for("run_output", run_id=run.id),
"run_id": run.id,
@@ -151,6 +155,50 @@ def create_app(settings: Settings | None = None) -> Flask:
except FileNotFoundError:
return {"output": ""}
@app.get("/runs/<int:run_id>/artifacts")
def run_artifacts(run_id: int):
run = store.get(run_id)
if run is None:
abort(404)
return {
"artifacts": [
{
"name": name,
"url": url_for("download_artifact", run_id=run.id, filename=name),
}
for name in manager.artifacts(run.id)
]
}
@app.get("/runs/<int:run_id>/artifacts/<filename>")
def download_artifact(run_id: int, filename: str):
run = store.get(run_id)
if run is None or run.status != "succeeded":
abort(404)
artifact = manager.artifact_path(run.id, filename)
if artifact is None:
abort(404)
response = send_file(
artifact,
as_attachment=True,
download_name=artifact.name,
conditional=False,
)
original_response = response.response
def delete_after_transfer():
try:
yield from original_response
finally:
close = getattr(original_response, "close", None)
if close is not None:
close()
manager.delete_artifact(run.id, artifact.name)
response.response = delete_after_transfer()
response.direct_passthrough = False
return response
@app.get("/runs/<int:run_id>/state")
def run_state(run_id: int):
run = store.get(run_id)