Skip to content

Vendoring compas inside another Rhino/Grasshopper package pulls in compas_ghpython's .ghuser components (stray broken COMPAS tab) #1523

Open

Description

@mengxihex

Describe the problem

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.

Activity

  1. gonzalocasas commented on Aug 5, 2026

    @gonzalocasas
    Member

    @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!

  2. gonzalocasas commented on Aug 5, 2026

    @gonzalocasas
    Member
  3. mengxihex commented on Aug 5, 2026

    @mengxihex
    ContributorAuthor

    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.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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions