VENDORING.md 4.3 KB

Vendoring chattolib

This plugin ships a vendored copy of chattolib and all its dependencies in vendor/. Nothing has to be installed separately — the plugin brings its own dependency tree.

Why Vendoring?

  • No dependencies to install: hermes plugin install works immediately
  • No lazy-import complexity: no ensure() or lazy_import mechanisms
  • Isolated: the vendored copy cannot conflict with a system-installed one
  • Offline-friendly: works in air-gapped environments

Layout

Three of the vendored packages contain compiled extension modules and are therefore platform-specific: pyqwest (~15 MB, the HTTP core used by connectrpc), protobuf and protobuf-py-ext. Everything else is pure Python. The tree is split accordingly, so the shared part is stored once:

vendor/
├── __init__.py
├── common/                    # pure-Python packages (~8 MB), all platforms
│   ├── chattolib/
│   ├── connectrpc/
│   ├── httpx/ httpcore/ h11/ anyio/ idna/ certifi/
│   └── opentelemetry/ protobuf/ typing_extensions.py
└── platform/                  # compiled extensions, ~16 MB per platform
    ├── linux-x86_64/          #   pyqwest/, protobuf_ext/, google/
    ├── linux-aarch64/
    └── macos-arm64/

vendor_path.py derives the platform tag from platform.system() / platform.machine() at import time and prepends vendor/platform/<tag> and vendor/common to sys.path — platform directory first, so the right binaries win. Both adapter.py and platform_config.py call setup_vendor_path() before importing anything from chattolib.

If the current platform was not vendored, the import fails with an explicit message naming the available platforms — rather than a cryptic dlopen error about an invalid Mach-O/ELF file.

Updating or rebuilding

# Default platform set: linux-x86_64, linux-aarch64, macos-arm64
./vendor_chattolib.sh

# A single platform
PLATFORMS="linux-x86_64" ./vendor_chattolib.sh

# Add another one (see the table below for valid tags)
PLATFORMS="linux-x86_64 linux-aarch64 macos-arm64 windows-amd64" ./vendor_chattolib.sh

# Pin a specific chattolib version
CHATTOLIB_SPEC="chattolib==0.4.20" ./vendor_chattolib.sh

The script wipes vendor/, installs the dependency tree once per platform via uv pip install --python-platform …, splits the result with vendor_split.py, and verifies that import chattolib works on the machine you ran it on. Afterwards: git add vendor/.

Supported platform tags

Tag uv --python-platform vendored by default
linux-x86_64 x86_64-unknown-linux-gnu
linux-aarch64 aarch64-unknown-linux-gnu
macos-arm64 aarch64-apple-darwin
linux-x86_64-musl x86_64-unknown-linux-musl
linux-aarch64-musl aarch64-unknown-linux-musl
macos-x86_64 x86_64-apple-darwin
windows-amd64 x86_64-pc-windows-msvc

All seven are available as binary wheels upstream; only the default three are committed, to keep the repository at a reasonable size (~59 MB for vendor/).

Python versions

The script resolves wheels for Python 3.11 (PYTHON_VERSION), which is the project minimum. At that version the three binary packages still provide cp310-abi3 wheels, and the stable ABI is forward compatible — so one build covers 3.11 through 3.14. Resolving for 3.12+ would instead pull version-specific wheels (cp312-…) that only work on that exact version.

If you raise PYTHON_VERSION, check that the resulting .so files are still named *.abi3.so. If they are not, the vendored tree silently becomes Python-version-specific.

Development without vendoring

pip install chattolib

A system-installed chattolib is only used if vendor/ is absent — the vendored copy is deliberately prepended to sys.path and therefore wins.

License

The vendored chattolib is licensed under MPL-2.0 + Apache-2.0 (see vendor/common/chattolib-*.dist-info/). Upstream source: https://github.com/chattocorp/chatto