Adds production-grade engineering features and tools: 2D GD&T (feature control frames + datum features) via engineering/gdt.py, ISO‑129 dimension tolerance support (engineering/tolerances.py) and an ezdxf/COM plumbing for toleranced dims, a scalar drawing score + invalidity ratio (engineering/scoring.py) wired into drawing_finalize, in-place entity editors (entity_edit_text/entity_edit_geometry), and a friendly drawing_settings facade. Includes server tool wiring, COM/ezdxf backend implementations, datum-consistency critique, many unit tests, README/CLAUDE/CHANGELOG updates, and a version bump to 1.2.0. Also corrects COM backend capability label (entities_2d).
72 lines
2.1 KiB
Python
72 lines
2.1 KiB
Python
"""Tests for the scalar drawing-score / invalidity-ratio (engineering/scoring.py)
|
|
and its wiring into drawing_finalize."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from engineering.scoring import combine, score_findings
|
|
|
|
pytestmark = pytest.mark.asyncio
|
|
|
|
|
|
async def test_clean_drawing_scores_100():
|
|
s = score_findings(0, 0, 0)
|
|
assert s["score"] == 100.0
|
|
assert s["invalidity_ratio"] == 0.0
|
|
assert s["grade"] == "A"
|
|
|
|
|
|
async def test_errors_dominate_penalty():
|
|
err = score_findings(1, 0, 0)["score"]
|
|
warn = score_findings(0, 1, 0)["score"]
|
|
info = score_findings(0, 0, 1)["score"]
|
|
assert err < warn < info < 100.0
|
|
|
|
|
|
async def test_score_clamped_to_zero():
|
|
s = score_findings(100, 100, 100)
|
|
assert s["score"] == 0.0
|
|
assert s["grade"] == "F"
|
|
|
|
|
|
async def test_invalidity_ratio_is_error_fraction():
|
|
s = score_findings(1, 3, 0) # 1 of 4 findings is a hard error
|
|
assert s["invalidity_ratio"] == 0.25
|
|
|
|
|
|
async def test_combine_sums_summaries():
|
|
a = {"error": 1, "warning": 0, "info": 0}
|
|
b = {"error": 0, "warning": 2, "info": 1}
|
|
combined = combine(a, b)
|
|
assert combined["errors"] == 1
|
|
assert combined["warnings"] == 2
|
|
assert combined["info"] == 1
|
|
|
|
|
|
# ── finalize wiring ─────────────────────────────────────────────────────────
|
|
|
|
|
|
class _FakeCtx:
|
|
def __init__(self, backend):
|
|
self.lifespan_context = {"backend": backend}
|
|
|
|
async def warning(self, message):
|
|
pass
|
|
|
|
|
|
async def test_finalize_payload_carries_score(backend, tmp_path):
|
|
import server
|
|
|
|
await backend.drawing_apply_iso_layers("mech")
|
|
await backend.entity_create_line(0, 0, 100, 0, layer="GEOMETRY")
|
|
ctx = _FakeCtx(backend)
|
|
payload = await server.drawing_finalize(
|
|
save_path=str(tmp_path / "part.dxf"),
|
|
ctx=ctx,
|
|
)
|
|
assert "score" in payload
|
|
assert 0.0 <= payload["score"]["score"] <= 100.0
|
|
assert "invalidity_ratio" in payload["score"]
|
|
assert payload["score"]["grade"] in ("A", "B", "C", "D", "F")
|