Fix symbol library resolution on macOS and without a sym-lib-table
Two bugs left built-in symbols (Device, Connector, ...) unresolvable, which
cascaded into every batch place/label/wire producing zero results:
- get_kicad_symbol_dir() only checked KICAD9/KICAD8_SYMBOL_DIR and a single
Linux path. It ignored the generic KICAD_SYMBOL_DIR, KiCad 10, and the
macOS/Windows install locations, so it returned None on macOS even with the
symbols present. Now checks KICAD_SYMBOL_DIR + KICAD{10,9,8,7}_SYMBOL_DIR and
per-platform default paths.
- resolve_library_path() never searched the system symbol directory for
<lib>.kicad_sym; the system dir was only used for variable substitution
inside a sym-lib-table. With no table configured (tests, fresh installs),
built-in libraries were unreachable. Added a system-dir fallback and covered
the KiCad 10/7 global-table config dirs.
Update test_env_override to clear ambient symbol-dir vars so the override under
test is decisive regardless of the host environment.
This commit is contained in:
parent
57872e59c1
commit
1dca4d6912
@ -106,9 +106,12 @@ def resolve_library_path(
|
|||||||
|
|
||||||
Search order:
|
Search order:
|
||||||
1. Project sym-lib-table (if project_dir given)
|
1. Project sym-lib-table (if project_dir given)
|
||||||
2. Global sym-lib-table (KiCad 9, then 8)
|
2. Global sym-lib-table (KiCad 10, 9, 8, 7)
|
||||||
3. Direct file search (project dir, libs/, ../libs/)
|
3. Direct file search (project dir, libs/, ../libs/)
|
||||||
|
4. System symbol directory (built-in libraries like Device)
|
||||||
"""
|
"""
|
||||||
|
filename = f"{library_name}.kicad_sym"
|
||||||
|
|
||||||
# 1. Project sym-lib-table
|
# 1. Project sym-lib-table
|
||||||
if project_dir:
|
if project_dir:
|
||||||
table_path = os.path.join(project_dir, "sym-lib-table")
|
table_path = os.path.join(project_dir, "sym-lib-table")
|
||||||
@ -119,8 +122,8 @@ def resolve_library_path(
|
|||||||
if os.path.isfile(uri):
|
if os.path.isfile(uri):
|
||||||
return uri
|
return uri
|
||||||
|
|
||||||
# 2. Global sym-lib-tables (KiCad 9 first, then 8)
|
# 2. Global sym-lib-tables (newest KiCad first)
|
||||||
for version_dir in ("9.0", "8.0"):
|
for version_dir in ("10.0", "9.0", "8.0", "7.0"):
|
||||||
config_dir = os.path.expanduser(f"~/.config/kicad/{version_dir}")
|
config_dir = os.path.expanduser(f"~/.config/kicad/{version_dir}")
|
||||||
table_path = os.path.join(config_dir, "sym-lib-table")
|
table_path = os.path.join(config_dir, "sym-lib-table")
|
||||||
if os.path.isfile(table_path):
|
if os.path.isfile(table_path):
|
||||||
@ -132,7 +135,6 @@ def resolve_library_path(
|
|||||||
|
|
||||||
# 3. Direct file search (fallback for projects without sym-lib-table)
|
# 3. Direct file search (fallback for projects without sym-lib-table)
|
||||||
if project_dir:
|
if project_dir:
|
||||||
filename = f"{library_name}.kicad_sym"
|
|
||||||
candidates = [
|
candidates = [
|
||||||
os.path.join(project_dir, filename),
|
os.path.join(project_dir, filename),
|
||||||
os.path.join(project_dir, "libs", filename),
|
os.path.join(project_dir, "libs", filename),
|
||||||
@ -143,6 +145,14 @@ def resolve_library_path(
|
|||||||
if os.path.isfile(resolved):
|
if os.path.isfile(resolved):
|
||||||
return resolved
|
return resolved
|
||||||
|
|
||||||
|
# 4. System symbol directory (built-in libraries, e.g. Device, Connector).
|
||||||
|
# This is the authoritative source when no sym-lib-table is configured.
|
||||||
|
symbol_dir = get_kicad_symbol_dir()
|
||||||
|
if symbol_dir:
|
||||||
|
resolved = os.path.join(symbol_dir, filename)
|
||||||
|
if os.path.isfile(resolved):
|
||||||
|
return resolved
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@ -249,16 +259,33 @@ def extract_symbol_sexp_text(
|
|||||||
def get_kicad_symbol_dir() -> str | None:
|
def get_kicad_symbol_dir() -> str | None:
|
||||||
"""Detect the KiCad system symbol directory.
|
"""Detect the KiCad system symbol directory.
|
||||||
|
|
||||||
Checks ``KICAD9_SYMBOL_DIR`` and ``KICAD8_SYMBOL_DIR`` env vars,
|
Checks, in order, the generic ``KICAD_SYMBOL_DIR`` env var, the
|
||||||
then falls back to the standard Linux install path.
|
version-specific ``KICAD{10,9,8,7}_SYMBOL_DIR`` vars, then the standard
|
||||||
|
install paths for macOS, Linux, and Windows.
|
||||||
"""
|
"""
|
||||||
for env_var in ("KICAD9_SYMBOL_DIR", "KICAD8_SYMBOL_DIR"):
|
for env_var in (
|
||||||
|
"KICAD_SYMBOL_DIR",
|
||||||
|
"KICAD10_SYMBOL_DIR",
|
||||||
|
"KICAD9_SYMBOL_DIR",
|
||||||
|
"KICAD8_SYMBOL_DIR",
|
||||||
|
"KICAD7_SYMBOL_DIR",
|
||||||
|
):
|
||||||
val = os.environ.get(env_var)
|
val = os.environ.get(env_var)
|
||||||
if val and os.path.isdir(val):
|
if val and os.path.isdir(val):
|
||||||
return val
|
return val
|
||||||
|
|
||||||
# Standard paths
|
# Standard per-platform install paths
|
||||||
for path in ("/usr/share/kicad/symbols",):
|
candidates = [
|
||||||
|
# macOS
|
||||||
|
"/Applications/KiCad/KiCad.app/Contents/SharedSupport/symbols",
|
||||||
|
# Linux
|
||||||
|
"/usr/share/kicad/symbols",
|
||||||
|
"/usr/local/share/kicad/symbols",
|
||||||
|
# Windows
|
||||||
|
r"C:\Program Files\KiCad\10.0\share\kicad\symbols",
|
||||||
|
r"C:\Program Files\KiCad\9.0\share\kicad\symbols",
|
||||||
|
]
|
||||||
|
for path in candidates:
|
||||||
if os.path.isdir(path):
|
if os.path.isdir(path):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,6 @@ from mckicad.utils.lib_resolver import (
|
|||||||
)
|
)
|
||||||
from mckicad.utils.sexp_tree import find_recursive, parse
|
from mckicad.utils.sexp_tree import find_recursive, parse
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Fixtures
|
# Fixtures
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@ -69,7 +68,7 @@ def project_with_lib(tmp_path):
|
|||||||
"(sym_lib_table\n"
|
"(sym_lib_table\n"
|
||||||
" (version 7)\n"
|
" (version 7)\n"
|
||||||
' (lib (name "MyLib")(type "KiCad")'
|
' (lib (name "MyLib")(type "KiCad")'
|
||||||
f'(uri "${{KIPRJMOD}}/MyLib.kicad_sym")(options "")(descr ""))\n'
|
'(uri "${KIPRJMOD}/MyLib.kicad_sym")(options "")(descr ""))\n'
|
||||||
")\n"
|
")\n"
|
||||||
)
|
)
|
||||||
table_file = tmp_path / "sym-lib-table"
|
table_file = tmp_path / "sym-lib-table"
|
||||||
@ -138,7 +137,7 @@ def multi_unit_lib(tmp_path):
|
|||||||
"(sym_lib_table\n"
|
"(sym_lib_table\n"
|
||||||
" (version 7)\n"
|
" (version 7)\n"
|
||||||
' (lib (name "OpAmps")(type "KiCad")'
|
' (lib (name "OpAmps")(type "KiCad")'
|
||||||
f'(uri "${{KIPRJMOD}}/OpAmps.kicad_sym")(options "")(descr ""))\n'
|
'(uri "${KIPRJMOD}/OpAmps.kicad_sym")(options "")(descr ""))\n'
|
||||||
")\n"
|
")\n"
|
||||||
)
|
)
|
||||||
(tmp_path / "sym-lib-table").write_text(table_content)
|
(tmp_path / "sym-lib-table").write_text(table_content)
|
||||||
@ -368,6 +367,17 @@ class TestGetKicadSymbolDir:
|
|||||||
assert os.path.isfile(os.path.join(sym_dir, "Device.kicad_sym"))
|
assert os.path.isfile(os.path.join(sym_dir, "Device.kicad_sym"))
|
||||||
|
|
||||||
def test_env_override(self, tmp_path, monkeypatch):
|
def test_env_override(self, tmp_path, monkeypatch):
|
||||||
|
# Clear any ambient symbol-dir vars so the override under test is the
|
||||||
|
# only candidate (a real KICAD_SYMBOL_DIR or install path would
|
||||||
|
# otherwise take precedence).
|
||||||
|
for var in (
|
||||||
|
"KICAD_SYMBOL_DIR",
|
||||||
|
"KICAD10_SYMBOL_DIR",
|
||||||
|
"KICAD9_SYMBOL_DIR",
|
||||||
|
"KICAD8_SYMBOL_DIR",
|
||||||
|
"KICAD7_SYMBOL_DIR",
|
||||||
|
):
|
||||||
|
monkeypatch.delenv(var, raising=False)
|
||||||
monkeypatch.setenv("KICAD9_SYMBOL_DIR", str(tmp_path))
|
monkeypatch.setenv("KICAD9_SYMBOL_DIR", str(tmp_path))
|
||||||
sym_dir = get_kicad_symbol_dir()
|
sym_dir = get_kicad_symbol_dir()
|
||||||
assert sym_dir == str(tmp_path)
|
assert sym_dir == str(tmp_path)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user