init: cobol-java migration verification platform v3 (42 tests, JCL module)

This commit is contained in:
hangshuo652
2026-05-27 08:42:41 +08:00
parent faeedbc77b
commit 7fcdb41a85
21 changed files with 870 additions and 148 deletions
+54 -45
View File
@@ -1,80 +1,89 @@
"""Web API layer — wraps orchestrator with 202+ polling pattern."""
import uuid, json, shutil, sys, os
import uuid, json, sys, os
from pathlib import Path
from datetime import datetime
from fastapi import FastAPI, UploadFile, File, Form, HTTPException
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from starlette.requests import Request
sys.path.insert(0, str(Path(__file__).parent.parent))
from config import Config
from orchestrator import run_pipeline
app = FastAPI(title="COBOLJava Verify")
app.mount("/static", StaticFiles(directory=str(Path(__file__).parent / "static")), name="static")
templates = Jinja2Templates(directory=str(Path(__file__).parent / "templates"))
app = FastAPI(title="COBOL->Java Verify")
BASE = Path(__file__).parent
app.mount("/static", StaticFiles(directory=str(BASE / "static")), name="static")
TASKS_DIR = Path("tasks")
TASKS_DIR.mkdir(exist_ok=True)
UPLOAD_DIR = Path("uploads")
UPLOAD_DIR.mkdir(exist_ok=True)
MAX_SIZE = 10 * 1024 * 1024 # 10MB
TASKS_DIR = Path("tasks"); TASKS_DIR.mkdir(exist_ok=True)
UPLOAD_DIR = Path("uploads"); UPLOAD_DIR.mkdir(exist_ok=True)
MAX_SIZE = 10 * 1024 * 1024
@app.get("/", response_class=HTMLResponse)
async def index(request: Request):
return templates.TemplateResponse("upload.html", {"request": request})
async def index():
return (BASE / "templates" / "upload.html").read_text(encoding="utf-8")
@app.post("/verify")
async def verify(
copybook: UploadFile = File(...),
cobol_src: UploadFile = File(...),
java_src: UploadFile = File(...),
mapping: UploadFile = File(...),
copybook: UploadFile = File(...), cobol_src: UploadFile = File(...),
java_src: UploadFile = File(...), mapping: UploadFile = File(...),
runner: str = Form("native"),
):
task_id = str(uuid.uuid4())[:8]
task_dir = UPLOAD_DIR / task_id
task_dir.mkdir(parents=True, exist_ok=True)
for f, name in [(copybook, "copybook.cpy"), (cobol_src, "program.cbl"),
(java_src, "java"), (mapping, "mapping.yaml")]:
task_dir = UPLOAD_DIR / task_id; task_dir.mkdir(parents=True, exist_ok=True)
for f, name in [(copybook,"copybook.cpy"),(cobol_src,"program.cbl"),
(java_src,"java"),(mapping,"mapping.yaml")]:
content = await f.read()
if len(content) > MAX_SIZE:
raise HTTPException(413, f"{f.filename} exceeds 10MB limit")
dest = task_dir / name
dest.write_bytes(content)
task_file = TASKS_DIR / f"{task_id}.json"
task_file.write_text(json.dumps({
"id": task_id, "status": "queued",
"copybook": str(task_dir / "copybook.cpy"),
"cobol_src": str(task_dir / "program.cbl"),
"java_src": str(task_dir / "java"),
"mapping": str(task_dir / "mapping.yaml"),
"runner": runner, "created": datetime.now().isoformat()
}))
return JSONResponse({"task_id": task_id, "status": "queued"}, status_code=202)
raise HTTPException(413, f"{f.filename} exceeds 10MB")
(task_dir / name).write_bytes(content)
(TASKS_DIR / f"{task_id}.json").write_text(json.dumps({
"id":task_id,"status":"queued","copybook":str(task_dir/"copybook.cpy"),
"cobol_src":str(task_dir/"program.cbl"),"java_src":str(task_dir/"java"),
"mapping":str(task_dir/"mapping.yaml"),"runner":runner,
"created":datetime.now().isoformat()}))
return JSONResponse({"task_id":task_id,"status":"queued"}, status_code=202)
@app.get("/status/{task_id}")
async def status(task_id: str):
tf = TASKS_DIR / f"{task_id}.json"
if not tf.exists():
raise HTTPException(404, "task not found")
if not tf.exists(): raise HTTPException(404, "task not found")
data = json.loads(tf.read_text())
return JSONResponse({"task_id": task_id, "status": data.get("status", "unknown"),
"result": data.get("result")})
return JSONResponse({"task_id":task_id,"status":data.get("status","unknown"),
"result":data.get("result"),"fields":data.get("fields",[])})
@app.get("/fields/{task_id}")
async def fields(task_id: str):
tf = TASKS_DIR / f"{task_id}.json"
if not tf.exists(): raise HTTPException(404, "task not found")
data = json.loads(tf.read_text())
return JSONResponse({"task_id":task_id,"fields":data.get("fields",[]),
"debug":data.get("debug",{}),
"build_log":data.get("build_log","")})
@app.get("/result/{task_id}", response_class=HTMLResponse)
async def result(request: Request, task_id: str):
async def result(task_id: str):
tf = TASKS_DIR / f"{task_id}.json"
if not tf.exists():
raise HTTPException(404, "task not found")
if not tf.exists(): raise HTTPException(404, "task not found")
data = json.loads(tf.read_text())
return templates.TemplateResponse("result.html", {"request": request, "task": data})
html = (BASE / "templates" / "result.html").read_text(encoding="utf-8")
html = html.replace("{{ task.id }}", data.get("id", task_id))
if data.get("status") == "done" and data.get("result"):
r = data["result"]
html = html.replace("{{ task.status }}", "done")
html = html.replace("{{ task.result.status }}", r.get("status",""))
html = html.replace("{{ task.result.program }}", r.get("program",""))
html = html.replace("{{ task.result.matched }}", str(r.get("matched",0)))
html = html.replace("{{ task.result.mismatched }}", str(r.get("mismatched",0)))
html = html.replace("{{ task.result.runner }}", r.get("runner",""))
html = html.replace("{{ task.result.duration }}", str(r.get("duration",0)))
elif data.get("status") == "error":
html = html.replace("{{ task.status }}", "error")
html = html.replace("{{ task.result.status }}", data.get("result",""))
else:
html = html.replace("{{ task.status }}", data.get("status","queued"))
return HTMLResponse(html)