Detect HubAudio.kicad_pro from folder pick, not only File.name.

Safari/macOS often puts .kicad_pro on webkitRelativePath while name is
the stem. Match both, sniff JSON if the suffix is missing, and set
webkitdirectory on the input DOM so the folder picker actually recurses.
This commit is contained in:
2026-09-21 07:54:35 +02:00
parent bfb781f94f
commit fbf2fc87a6
8 changed files with 235 additions and 65 deletions
+53
View File
@@ -268,3 +268,56 @@ def test_api_folder_upload_no_csv(tmp_path: Path):
assert body["bom_saved"] is True
assert "U13" not in str(body)
assert body["parts"] >= 2
def _looks_like_kicad_pro(name: str, relative: str = "") -> bool:
"""Same rule as frontend looksLikeKicadPro (name and/or webkitRelativePath)."""
return any(".kicad_pro" in s.lower() for s in (name, relative, Path(relative or name).name))
def test_safari_stem_name_is_still_hubaudio_kicad_pro():
"""Live 2.60.6 checked only File.name.endsWith('.kicad_pro') and missed Safari."""
assert not "HubAudio".lower().endswith(".kicad_pro")
assert _looks_like_kicad_pro("HubAudio", "HubAudio/HubAudio.kicad_pro")
assert _looks_like_kicad_pro("HubAudio.kicad_pro", "")
assert sniff_netlist_kind(
_pro("HubAudio.kicad_sch").encode(), "HubAudio",
) == "kicad_pro"
def test_safari_stem_upload_writes_kicad_pro_suffix(tmp_path: Path):
src = tmp_path / "HubAudio"
_write_project(src)
pro = (src / "HubAudio.kicad_pro").read_bytes()
files = [
("HubAudio", pro),
("HubAudio.kicad_sch", (src / "HubAudio.kicad_sch").read_bytes()),
("Codec.kicad_sch", (src / "Codec.kicad_sch").read_bytes()),
("HubAudio.kicad_pcb", (src / "HubAudio.kicad_pcb").read_bytes()),
]
parsed = materialize_netlist_upload(files, tmp_path / "work")
assert parsed.root.name == "HubAudio.kicad_sch"
assert any(p.name == "HubAudio.kicad_pro" for p in (tmp_path / "work").rglob("*"))
parts, _nets, fmt = parse_netlist_any(parsed.root)
assert fmt == "kicad_sch"
assert "U9" in parts and "U13" not in parts
@pytest.mark.skipif(not (HUBAUDIO / "HubAudio.kicad_pro").is_file(), reason="HubAudio tree not on disk")
def test_real_hubaudio_kicad_pro_filename_and_folder_ingest(tmp_path: Path):
pro_path = HUBAUDIO / "HubAudio.kicad_pro"
assert pro_path.name == "HubAudio.kicad_pro"
data = pro_path.read_bytes()
assert sniff_kicad_pro(data, "HubAudio.kicad_pro")
assert sniff_netlist_kind(data, "HubAudio") == "kicad_pro"
files: list[tuple[str, bytes]] = []
for path in HUBAUDIO.iterdir():
if path.suffix.lower() in {".kicad_pro", ".kicad_sch", ".kicad_pcb"}:
files.append((f"HubAudio/{path.name}", path.read_bytes()))
assert any(name.endswith("HubAudio.kicad_pro") for name, _ in files)
parsed = materialize_netlist_upload(files, tmp_path / "work")
assert parsed.root.name == "HubAudio.kicad_sch"
assert parsed.pcb is not None
parts, _nets, fmt = parse_netlist_any(parsed.root)
assert fmt == "kicad_sch"
assert "U13" not in parts