feat(bootstrap): replace exec()-based addon loading with manifest-driven loader #256

Merged
forbes merged 1 commits from feat/manifest-addon-loader into main 2026-02-16 19:18:03 +00:00
Owner

Summary

Replaces the hard-coded exec() addon loading in src/Mod/Create/Init.py and InitGui.py with a manifest-driven loader that scans mods/, parses package.xml manifests, validates compatibility, resolves dependency order, and exposes a runtime addon registry.

Closes #248

Changes

  • src/Mod/Create/addon_loader.py (new) — six-stage pipeline:

    1. Scan mods/ for package.xml at depth 1-2
    2. Parse standard fields + optional <kindred> extensions via ElementTree
    3. Validate version compatibility (min_create_version, max_create_version) and path existence
    4. Sort by dependencies via graphlib.TopologicalSorter, with legacy fallback when no <kindred> elements exist
    5. Load Init.py/InitGui.py via exec() (same mechanism, now ordered)
    6. Register in AddonRegistry exposed as FreeCAD.KindredAddons
  • src/Mod/Create/Init.py — replaced setup_kindred_addons() with load_addons(gui=False)

  • src/Mod/Create/InitGui.py — replaced setup_kindred_workbenches() with load_addons(gui=True); all QTimer Silo integration code unchanged

  • src/Mod/Create/CMakeLists.txt — added addon_loader.py to install list

Backward compatibility

Addons without <kindred> elements in their package.xml load with no constraints. When no addons declare <kindred>, the loader uses a legacy order matching the current hard-coded ztools-then-silo sequence.

Testing

  • All 3 Python files compile cleanly
  • Discovery finds both addons at correct paths (mods/ztools/package.xml at depth 1, mods/silo/freecad/package.xml at depth 2)
  • Parsing resolves workbench subdirectories correctly
  • Legacy order preserves current behavior (ZTools before Kindred Silo)
  • Version gating correctly skips incompatible addons
  • Registry API works: repr, get(), loaded(), is_loaded(), all()
## Summary Replaces the hard-coded `exec()` addon loading in `src/Mod/Create/Init.py` and `InitGui.py` with a manifest-driven loader that scans `mods/`, parses `package.xml` manifests, validates compatibility, resolves dependency order, and exposes a runtime addon registry. Closes #248 ## Changes - **`src/Mod/Create/addon_loader.py`** (new) — six-stage pipeline: 1. **Scan** `mods/` for `package.xml` at depth 1-2 2. **Parse** standard fields + optional `<kindred>` extensions via ElementTree 3. **Validate** version compatibility (`min_create_version`, `max_create_version`) and path existence 4. **Sort** by dependencies via `graphlib.TopologicalSorter`, with legacy fallback when no `<kindred>` elements exist 5. **Load** `Init.py`/`InitGui.py` via `exec()` (same mechanism, now ordered) 6. **Register** in `AddonRegistry` exposed as `FreeCAD.KindredAddons` - **`src/Mod/Create/Init.py`** — replaced `setup_kindred_addons()` with `load_addons(gui=False)` - **`src/Mod/Create/InitGui.py`** — replaced `setup_kindred_workbenches()` with `load_addons(gui=True)`; all QTimer Silo integration code unchanged - **`src/Mod/Create/CMakeLists.txt`** — added `addon_loader.py` to install list ## Backward compatibility Addons without `<kindred>` elements in their `package.xml` load with no constraints. When no addons declare `<kindred>`, the loader uses a legacy order matching the current hard-coded ztools-then-silo sequence. ## Testing - All 3 Python files compile cleanly - Discovery finds both addons at correct paths (`mods/ztools/package.xml` at depth 1, `mods/silo/freecad/package.xml` at depth 2) - Parsing resolves workbench subdirectories correctly - Legacy order preserves current behavior (ZTools before Kindred Silo) - Version gating correctly skips incompatible addons - Registry API works: `repr`, `get()`, `loaded()`, `is_loaded()`, `all()`
forbes added 2 commits 2026-02-16 19:14:51 +00:00
docs: extend README with architecture, platform support, and usage detail
All checks were successful
Build and Test / build (pull_request) Successful in 35m8s
a8df078eb3
Add editing context system description, built-in context table, and
Python API reference. Add architecture section covering addon
integration and unified origin system. Expand ztools and Silo usage
sections with command breakdowns. Add platform support table. Expand
project structure tree with Kindred-specific files.
feat(bootstrap): replace exec()-based addon loading with manifest-driven loader
All checks were successful
Build and Test / build (pull_request) Successful in 34m4s
60ceb47e4f
Add addon_loader.py implementing a six-stage pipeline: scan mods/ for
package.xml files, parse standard fields and optional <kindred>
extensions via ElementTree, validate version compatibility, resolve
load order via graphlib.TopologicalSorter (with legacy fallback),
exec() Init.py/InitGui.py, and populate a runtime AddonRegistry
exposed as FreeCAD.KindredAddons.

Replace hard-coded addon lists in Init.py and InitGui.py with calls
to addon_loader.load_addons(). All QTimer-based Silo integration code
in InitGui.py is unchanged.

Backward compatible: addons without <kindred> elements load with no
constraints using the existing ztools-then-silo order.

Closes #248
forbes merged commit 587a95dd66 into main 2026-02-16 19:18:03 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kindred/create#256