vision: anteprima DXF nel worker e nel backend (Refs #101)
Worker: POST /dxf/preview legge il DXF con read_xld_dxf (lo stesso lettore di CompareDxf) e ritorna contorni in mm con y verso il basso, bbox, dimensioni, entita e punti (tetto 20000, decimazione uniforme). Backend: POST /api/vision/dxf-preview (Maker) che inoltra al worker; 422 inoltrato. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -80,3 +80,67 @@ async def test_dxf_compare_immagine_non_decodificabile_e_422():
|
||||
async def test_dxf_compare_parametro_fuori_range_e_422():
|
||||
response = await _post(_png(a_scene(0.0)), SAMPLE_DXF.read_bytes(), polarity="grigio")
|
||||
assert response.status_code == 422
|
||||
|
||||
|
||||
# --- #101: POST /dxf/preview ---------------------------------------------------
|
||||
|
||||
def _rect_dxf(width: float, height: float, y0: float = 3.0) -> bytes:
|
||||
"""DXF minimo con ezdxf: un rettangolo chiuso, y in alto rispetto a 0."""
|
||||
import ezdxf
|
||||
doc = ezdxf.new()
|
||||
doc.modelspace().add_lwpolyline(
|
||||
[(1, y0), (1 + width, y0), (1 + width, y0 + height), (1, y0 + height)], close=True,
|
||||
)
|
||||
buffer = io.StringIO()
|
||||
doc.write(buffer)
|
||||
return buffer.getvalue().encode("utf-8")
|
||||
|
||||
|
||||
def _post_preview(dxf: bytes):
|
||||
# TestClient sincrono: non serve pytest-asyncio (assente nel venv del worker)
|
||||
from fastapi.testclient import TestClient
|
||||
return TestClient(app).post(
|
||||
"/dxf/preview", files={"dxf": ("d.dxf", dxf, "application/octet-stream")},
|
||||
)
|
||||
|
||||
|
||||
def test_dxf_preview_rettangolo_10x5():
|
||||
resp = _post_preview(_rect_dxf(10, 5))
|
||||
assert resp.status_code == 200, resp.text
|
||||
body = resp.json()
|
||||
assert body["larghezza_mm"] == 10 and body["altezza_mm"] == 5
|
||||
assert body["entita"] == 1 and body["punti"] == sum(len(c) for c in body["contorni"])
|
||||
# y ribaltata: il rettangolo stava a y 3..8 nel DXF, ora a -8..-3 (asse verso il basso)
|
||||
assert body["bbox"] == {"xmin": 1, "ymin": -8, "xmax": 11, "ymax": -3}
|
||||
ring = body["contorni"][0]
|
||||
assert ring[0] == ring[-1] # contorno chiuso: primo == ultimo
|
||||
assert all(-8 <= y <= -3 for _, y in ring)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("content", [b"", b"questo non e' un dxf"])
|
||||
def test_dxf_preview_illeggibile_e_422(content):
|
||||
resp = _post_preview(content)
|
||||
assert resp.status_code == 422
|
||||
assert resp.json()["detail"].startswith("DXF")
|
||||
|
||||
|
||||
def test_dxf_preview_senza_geometria_e_422():
|
||||
import ezdxf
|
||||
doc = ezdxf.new()
|
||||
buffer = io.StringIO()
|
||||
doc.write(buffer)
|
||||
resp = _post_preview(buffer.getvalue().encode("utf-8"))
|
||||
assert resp.status_code == 422
|
||||
assert "senza geometria" in resp.json()["detail"]
|
||||
|
||||
|
||||
def test_dxf_preview_decima_oltre_il_tetto(monkeypatch):
|
||||
from src.vision_worker import main
|
||||
monkeypatch.setattr(main, "_PREVIEW_MAX_POINTS", 50)
|
||||
import ezdxf
|
||||
doc = ezdxf.new()
|
||||
doc.modelspace().add_circle((0, 0), 20)
|
||||
buffer = io.StringIO()
|
||||
doc.write(buffer)
|
||||
full = main._dxf_preview(buffer.getvalue().encode("utf-8"))
|
||||
assert full["punti"] <= 50 + 1 and full["larghezza_mm"] == pytest.approx(40, abs=0.01) # dimensioni dai punti completi
|
||||
|
||||
Reference in New Issue
Block a user