fix(board-view): KiCad 10 kicad-cli svg export compatibility (#209)

KiCad 10 changed `kicad-cli pcb export svg` in three ways that broke
get_board_2d_view (reported with a verified fix in #209):
  - `--output` is now a FILE path, not a directory (a dir fails with
    "Failed to create file '<dir>'").
  - `--mode-single` is required to merge layers into one SVG (the default
    multi-file behavior is deprecated).
  - exit code 2 is returned for the deprecation warning even on success.

Pass a file path to `--output` and add `--mode-single` (both also valid on
KiCad 8/9). Stop gating on the exit code — judge success by whether an SVG was
actually produced — so the exit-2 deprecation warning is no longer a false
failure. Add regression tests for the exit-2-is-success case and the command
shape (file output + --mode-single).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
mixelpixx
2026-05-30 09:42:20 -04:00
parent 5493a37024
commit 066e7f63d4
2 changed files with 87 additions and 10 deletions

View File

@@ -182,7 +182,23 @@ class BoardViewCommands:
}
with tempfile.TemporaryDirectory() as tmpdir:
cmd = [kicad_cli, "pcb", "export", "svg", "--output", tmpdir, "--black-and-white"]
# KiCad 10 changed `pcb export svg`:
# - `--output` is now a FILE path, not a directory (a directory
# fails with "Failed to create file '<dir>'").
# - `--mode-single` is required to merge layers into one SVG
# (the default multi-file behavior is deprecated).
# These flags also work on KiCad 8/9, so we always pass them.
output_svg = os.path.join(tmpdir, "board.svg")
cmd = [
kicad_cli,
"pcb",
"export",
"svg",
"--output",
output_svg,
"--mode-single",
"--black-and-white",
]
if layers:
cmd += ["--layers", ",".join(layers)]
cmd.append(pcb_path)
@@ -196,21 +212,22 @@ class BoardViewCommands:
"errorDetails": " ".join(cmd),
}
if result.returncode != 0:
# Do NOT gate on the exit code: KiCad 9+/10 returns exit code 2
# for a deprecation warning even when the SVG is written
# correctly. Use "was an SVG actually produced?" as the success
# signal instead — robust across versions and modes.
svg_files = (
[output_svg]
if os.path.exists(output_svg)
else glob.glob(os.path.join(tmpdir, "*.svg"))
)
if not svg_files:
return {
"success": False,
"message": "kicad-cli SVG export failed",
"errorDetails": result.stderr.strip() or result.stdout.strip(),
}
svg_files = glob.glob(os.path.join(tmpdir, "*.svg"))
if not svg_files:
return {
"success": False,
"message": "kicad-cli produced no SVG output",
"errorDetails": result.stdout.strip(),
}
svg_path = svg_files[0]
# --- Render to bytes (shared for both response modes) ---