The 'cmd <<EOF || { ... }' pattern confuses bash's parser — the closing
brace of the inline error block collides with the function's closing
brace. Rewrote to capture the python script into a local var via
$(cat <<EOF), then run it with -c and a plain 'if !' guard.
- compile_and_strip_sources: stop deleting .py files after compileall.
OpenCV's loader does literal file I/O on cv2/config.py (not a Python
import), so stripping it breaks `import cv2` with "missing
configuration file: ['config.py']". Other packages may do similar
file-based introspection tricks — the ~30% size win isn't worth
playing whack-a-mole with broken installers. We already hit this
with numpy.linalg and zeroconf._services; enough incidents.
- smoke_test_imports: only assert importability for modules whose
top-level dir actually exists in site-packages. Pillow for example
is a Windows-only dep, and was failing the Linux build spuriously.
Rewrote as a heredoc for readability.
- build-common.sh: remove zeroconf/_services from the strip list.
zeroconf's compiled Cython _listener.pyd imports from _services
internally, so stripping it broke `import zeroconf` at runtime with
ModuleNotFoundError — same class of bug as the numpy.linalg strip.
- build-common.sh: add smoke_test_imports() that imports every top-level
dependency against the stripped site-packages. Catches "we stripped
something that was actually needed" regressions at build time instead
of on a user's machine after install.
- build-dist.sh: wire smoke test into the Linux flow (runs real imports).
- build-dist-windows.sh: cross-build can't load win_amd64 .pyd files with
the host python, so instead verify that the known-required submodule
dirs (numpy.linalg/lib/matrixlib/ma, zeroconf._services) exist after
cleanup. Fails loud if any future strip-rule removes them.
numpy's own __init__.py imports lib and matrixlib (which in turn imports
numpy.linalg via defmatrix.py). Removing any of these submodules to save
dist size makes `import numpy` raise ModuleNotFoundError on the target,
which cascades into every wled_controller import.
Symptom: v0.0.0.dev0 Windows installer showed a tray icon but uvicorn
died silently in its background thread and port 8080 never listened —
browser got ERR_CONNECTION_REFUSED.
Keep stripping: polynomial, distutils, f2py, typing, _pyinstaller.
These are genuinely unused by numpy's own import chain.
- build-common.sh: detect_version() normalizes non-PEP440 labels (e.g. 'dev',
'nightly') to 0.0.0.dev0 so stamping pyproject.toml doesn't break pip install.
- build-common.sh: split .py deletion out of cleanup_site_packages into a new
compile_and_strip_sources() that runs 'compileall -b' FIRST, then removes
sources. compileall now fails loud instead of silently no-op'ing.
- build-dist.sh: add missing compile_and_strip_sources call on Linux site-packages
(previous tarballs shipped empty packages with no .py and no .pyc).
- build-dist-windows.sh: reorder so compile_and_strip_sources runs right after
cleanup_site_packages, not after .py files have already been deleted.
- installer.nsi: RMDir /r payload dirs (python/, app/, scripts/) and delete
LedGrab.bat at the top of SecCore before File /r. NSIS File /r MERGES into
existing dirs, so upgrades left half-old/half-new state that surfaced as
'version mismatch' or duplicate-package ImportErrors. data/ and logs/ remain
untouched to preserve user config.
- Create utils/image_codec.py with cv2-based image helpers
- Replace PIL usage across all routes, filters, and engines with cv2
- Move Pillow from core deps to [tray] optional in pyproject.toml
- Extract shared build logic into build-common.sh (detect_version, cleanup, etc.)
- Strip unused NumPy/PIL/zeroconf/debug files in build scripts