23edb39f52
Build PCM package / build (push) Successful in 5s
Second Mac run (KiCad demo board opened from the mounted installer image) got past the dialog and died twice: 1. make_output_dir crashed with OSError 30: the demos volume is a read-only filesystem. Now falls back to a temp directory named after the board, with the path printed (the Messages panel showed it is actually read there). 2. The error figure - and every other figure - could never render: matplotlib refused with Cannot load backend TkAgg ... as qt is currently running. macOS bundled Python ships tkinter, so the old tk-first probe picked TkAgg while the PySide6 dialog and progress window had already made this a Qt process. Windows never saw it because KiCad Python there has no tkinter. Qt now comes first - PySide6 is a hard dependency, so it is always there. Both covered by tests that fail on the old code: the dev env has both toolkits installed, so the backend-order assertion is exercised for real, and the RO fallback is simulated by denying mkdir under the board dir. 140 passed on the dev stack and on the Python 3.9 + numpy 2.0 / scipy 1.13 / matplotlib 3.9 / PySide6 6.10 stack that a Mac venv resolves. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
46 lines
1.7 KiB
Python
46 lines
1.7 KiB
Python
"""Regressions from the first macOS field test.
|
|
|
|
Two failures that only a non-Windows KiCad could produce: the board
|
|
directory was read-only (demo project opened straight from the mounted
|
|
installer image), and matplotlib picked TkAgg - macOS' bundled Python
|
|
ships tkinter, unlike KiCad's Windows Python - then refused to create
|
|
any figure because the PySide6 dialog already had a Qt event loop in
|
|
the process.
|
|
"""
|
|
import pathlib
|
|
|
|
from fill_resistance import plots, report
|
|
|
|
|
|
def test_backend_prefers_qt_over_tk():
|
|
# The dev environment has both toolkits installed, so this asserts
|
|
# the preference order for real: Qt must win, because the selection
|
|
# dialog / progress window make the process a Qt process before the
|
|
# first figure exists.
|
|
assert plots._pick_backend() in ("QtAgg", "Qt5Agg")
|
|
|
|
|
|
def test_output_dir_falls_back_when_board_dir_unwritable(
|
|
tmp_path, monkeypatch, capsys):
|
|
board_dir = tmp_path / "board"
|
|
board_dir.mkdir()
|
|
real_mkdir = pathlib.Path.mkdir
|
|
|
|
def deny_under_board(self, *args, **kwargs):
|
|
if str(self).startswith(str(board_dir)):
|
|
raise OSError(30, "Read-only file system", str(self))
|
|
return real_mkdir(self, *args, **kwargs)
|
|
|
|
monkeypatch.setattr(pathlib.Path, "mkdir", deny_under_board)
|
|
out = report.make_output_dir(board_dir)
|
|
assert out.is_dir()
|
|
assert not str(out).startswith(str(board_dir))
|
|
assert board_dir.name in out.name # traceable back to the board
|
|
assert "not writable" in capsys.readouterr().out
|
|
|
|
|
|
def test_output_dir_normal_case_unchanged(tmp_path):
|
|
out = report.make_output_dir(tmp_path)
|
|
assert out.is_dir()
|
|
assert out.parent.parent == tmp_path
|