diff --git a/src/rpmroute/cli.py b/src/rpmroute/cli.py index 468d929..2879603 100644 --- a/src/rpmroute/cli.py +++ b/src/rpmroute/cli.py @@ -94,11 +94,12 @@ def build_parser() -> argparse.ArgumentParser: parser.add_argument( "--engine", choices=sorted(ENGINE_OPTIONS), - default="grid", + default="exact", help=( - "routing track: grid (default; multi-layer rip-up maze, highest coverage), " - "exact (orthogonal, exact-geometry DRC-verified output), " - "room (continuous expansion rooms, routes off-grid channels)" + "routing track: exact (default; every route checked against exact pad and " + "copper shapes, DRC-clean output), grid (quick maze on the grid alone: its " + "copper is NOT clearance-checked and can short), room (continuous expansion " + "rooms, routes off-grid channels; not clearance-checked either)" ), ) parser.add_argument( @@ -386,6 +387,17 @@ def main(argv: list[str] | None = None) -> int: for net, a, b, zone in in_zone: print(f" {net}: {a} to {b} (both in zone {zone})", file=sys.stderr) + if args.engine != "exact": + # These engines route on approximations and do not check the copper + # they write against exact shapes: a board can come out with shorts + # that this report would otherwise never mention. + print( + f"rpmroute: WARNING: the {args.engine} engine does not check its copper for " + "clearance or shorts; run KiCad's DRC on the result, or route with " + "--engine exact (the default)", + file=sys.stderr, + ) + if args.output: with open(args.output, "w", encoding="utf-8") as f: f.write(ses_text) diff --git a/tests/test_cli.py b/tests/test_cli.py index cc64dc7..f0d129e 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -71,13 +71,25 @@ def test_cli_every_engine_routes_a_fixture(engine, tmp_path): assert "(wire" in text -def test_cli_default_engine_is_grid(tmp_path): - """The default must stay grid — the drop-in JAR replacement behaviour.""" +def test_cli_default_engine_is_exact(tmp_path): + """The default is the engine that checks its copper: grid output can short + and say nothing (a user routing with no flags shipped 15 crossings).""" default = tmp_path / "default.ses" - grid = tmp_path / "grid.ses" + exact = tmp_path / "exact.ses" assert main([str(FIXTURE), "-do", str(default)]) == 0 - assert main([str(FIXTURE), "--engine", "grid", "-do", str(grid)]) == 0 - assert default.read_text() == grid.read_text() + assert main([str(FIXTURE), "--engine", "exact", "-do", str(exact)]) == 0 + assert default.read_text() == exact.read_text() + + +@pytest.mark.parametrize("engine", ["grid", "room"]) +def test_unchecked_engines_say_so(tmp_path, capsys, engine): + assert main([str(FIXTURE), "--engine", engine, "-do", str(tmp_path / "out.ses")]) == 0 + assert "does not check its copper" in capsys.readouterr().err + + +def test_the_exact_engine_does_not_warn(tmp_path, capsys): + assert main([str(FIXTURE), "-do", str(tmp_path / "out.ses")]) == 0 + assert "WARNING" not in capsys.readouterr().err def test_cli_room_pack_routes(tmp_path):