← Commit history

v0.9.190: THE #34 ROOT CAUSE, and it was mine - a dedupe edit stripped 'import sys' from inside the GENERATED loader's source text, so every fresh deploy shipped a loader that died with NameError at import and logged it silently. Restored, plus the generated sources are now executed in a sandbox at import time so this class of break is loud

John Lauer ·4f2cf2cf22 ·1mo ago ·parent 5de2ca1
5 files changed +42−7
BRIDGE_VERSION+1−1
@@ -1 +1 @@-0.9.189+0.9.190
adom-bridge-kicad-manifest.json+5−5
@@ -1,15 +1,15 @@ {   "manifest_version": 1,   "name": "kicad",-  "version": "0.9.189",-  "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.189/adom-bridge-kicad-v0.9.189.zip",-  "sha256": "7f13596197384490e009ecea5f1a5cd8732d435a5f5b59e149be3a7ffbcaf451",-  "size": 458771,+  "version": "0.9.190",+  "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.190/adom-bridge-kicad-v0.9.190.zip",+  "sha256": "236a0956ddb424a4137f079597f585193aabad886f56f0c1990601d9e471be00",+  "size": 459265,   "verbPrefixes": [     "kicad_"   ],   "healthEndpoint": "/status",-  "released_at": "2026-08-19T20:51:11Z",+  "released_at": "2026-08-19T20:53:17Z",   "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png",   "languages": [     "Python",
adom-bridge-kicad-v0.9.190.zipadded
⋯ 1 unchanged line ⋯
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "kicad",   "displayName": "KiCad EDA",-  "version": "0.9.189",+  "version": "0.9.190",   "description": "Reverse bridge for KiCad \u2014 board/schematic introspection, lint via kicad-cli, plugin install, multi-instance probe, in-process DRC.",   "homepage": "https://wiki.adom.inc/adom/adom-bridge",   "author": "Adom Inc.",
plugin_install.py+35
@@ -155,6 +155,7 @@ has finished setting Python up. Everything is logged to %TEMP%/adom-kicad-plugin-loader.log so a failure is one file away. \"\"\" import os+import sys import tempfile import threading import time@@ -212,6 +213,40 @@ except Exception: """  +def _selftest_generated_sources() -> None:+    """Run the generated loaders in a sandbox at import time.++    They are shipped as TEXT, so nothing type-checks or imports them here, and+    they deliberately swallow their own exceptions into a log file - which means+    a broken one fails SILENTLY on the user's machine. Executing them in a throw+    away namespace turns that into an immediate, loud failure for us instead.+    """+    import tempfile as _tf+    for name, src in (("adom_bridge_plugin.py", _PLUGIN_DIR_LOADER),+                      ("adom_bridge_boot.py", _BOOT_PY)):+        ns = {"__name__": "__selftest__"}+        log = os.path.join(_tf.gettempdir(), "adom-kicad-plugin-loader.log")+        before = os.path.getsize(log) if os.path.exists(log) else 0+        try:+            exec(compile(src, name, "exec"), ns)      # noqa: S102 - our own text+        except SystemExit:+            pass+        except Exception as e:                        # pragma: no cover+            raise RuntimeError(f"generated {name} is broken: {type(e).__name__}: {e}")+        try:+            if os.path.exists(log) and os.path.getsize(log) > before:+                with open(log, encoding="utf-8", errors="replace") as fh:+                    fh.seek(before)+                    tail = fh.read()+                if "Traceback" in tail or "Error" in tail:+                    raise RuntimeError(f"generated {name} logged a failure: {tail[:200]}")+        except OSError:+            pass+++_selftest_generated_sources()++ def _kicad_plugin_dirs(version: str):     """KiCad's own scripting-plugin directories (it imports every .py here at     startup). %APPDATA%/kicad/<version>/scripting/plugins on Windows."""