You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Vendoring compas inside another Rhino/Grasshopper package pulls in compas_ghpython's .ghuser components (stray broken COMPAS tab) #1523
The compas wheel ships compas_rhino, compas_ghpython, and compas_blender alongside the core library. We bundle our Grasshopper plugin as a Yak package that vendors its Python dependencies inside the package folder (Rhino 8, CPython 3.9) — and because Grasshopper scans installed package folders recursively for .ghuser files, the five components under compas_ghpython/components/ghuser/ get loaded into every user's ribbon. They then fail with No module named compas_bootstrapper, since the environment was never set up via compas_rhino.install (nor should it be, in this deployment model — core compas works perfectly for us as a plain vendored library).
Our workaround is to strip the three CAD packages from the wheel at build time, which works fine (core compas has no hard imports of them). Raising this in case the use case is worth supporting more directly — e.g. publishing the CAD integrations as extras/separate dists (pip install compas[rhino]), or relocating the prebuilt .ghuser payload so it isn't discovered by Grasshopper's folder scan when the wheel is merely vendored. Happy to provide details of the deployment layout if useful.
@mengxihex that's a very good point, the bootstrapper is nowadays almost irrelevant, since Rhino 8 default install mode is using # r: compas and doesn't require the compas_rhino.install method anymore, but I see that at least one of the GH components still has an unguarded import of compas_bootstrapper that would make it fail.
Raising this in case the use case is worth supporting more directly — e.g. publishing the CAD integrations as extras/separate dists (pip install compas[rhino]), or relocating the prebuilt .ghuser payload so it isn't discovered by Grasshopper's folder scan when the wheel is merely vendored
Both are possible options. The latter probably the easiest to do in the short term.
Happy to provide details of the deployment layout if useful.
Yes, would be super nice!
Also it's nice to know that this is a way that compas is used out there!
The plugin lands in Rhino's standard packages folder; its Python dependencies
are pip-installed at build time into a plain folder inside the package, which
the components put on sys.path at runtime. Schematically:
.../McNeel/Rhinoceros/packages/8.0/<PluginName>/<version>/
├── <plugin components>
└── <vendored-libs>/ <- pip install --target, plain folder
├── compas/ <- only core compas is ever imported
├── compas_ghpython/ <- force-included by the wheel
│ └── components/ghuser/*.ghuser <- Grasshopper's recursive scan loads these
├── compas_rhino/ compas_blender/ <- also unused
└── numpy/ ...
The stray tab is also reproducible standalone: pip install --target ./libs compas inside any folder under the packages dir, then restart Grasshopper.
Relocating the .ghuser payload out of the importable package would fully fix
it for this deployment model.
Activity
gonzalocasas commentedon Aug 5, 2026
@mengxihex that's a very good point, the bootstrapper is nowadays almost irrelevant, since Rhino 8 default install mode is using
# r: compasand doesn't require thecompas_rhino.installmethod anymore, but I see that at least one of the GH components still has an unguarded import ofcompas_bootstrapperthat would make it fail.Both are possible options. The latter probably the easiest to do in the short term.
Yes, would be super nice!
Also it's nice to know that this is a way that compas is used out there!
gonzalocasas commentedon Aug 5, 2026
/cc @tomvanmele
mengxihex commentedon Aug 5, 2026
Thanks @gonzalocasas! Here's the layout.
The plugin lands in Rhino's standard packages folder; its Python dependencies
are pip-installed at build time into a plain folder inside the package, which
the components put on
sys.pathat runtime. Schematically:The stray tab is also reproducible standalone:
pip install --target ./libs compasinside any folder under the packages dir, then restart Grasshopper.Relocating the
.ghuserpayload out of the importable package would fully fixit for this deployment model.