Vitro
Vitro is a Python framework for setting up and operating testbed environments — deploying, configuring, and orchestrating the devices that make up a system under test. It is the second-generation successor to Boardfarm, distilling its lessons into a leaner, plugin-driven core.
Background
The previous generation packaged the framework, a large built-in device library, and test integrations together in a single project. Vitro splits those concerns: the core is a small orchestrator that knows nothing about specific devices or test runners. Device drivers, environment helpers, and reservation systems are contributed externally as plugins. A separate, shared template/operations pool can be layered on top to keep multiple plugins interoperable.
The result is a framework you can adopt for a single testbed without pulling in code for every device anyone has ever supported, while still allowing standardised test resources to be assembled across organisations.
What Vitro gives you
- Two-file environment model. A standardised
environment.json(devices and their roles) merged with a testbed-specificinventory.json(connection details) viajsonmerge. - Pluggable device registry. Plugins contribute device classes via the
vitro_add_deviceshook; Vitro wires them up by type string from the config. - Lifecycle hooks. Boot and configure phases, distinct for servers, devices, and attached devices, with sync and async variants.
- Plugin extension surface (pluggy). Reservation, command-line args, config parsing, environment setup, and shutdown are all hookable.
- Connection helpers. Pexpect-based SSH, serial, and local-command
connections in
vitro.libraries.connections. vitroCLI. A standalone entry point that drives the full reserve → register → boot → configure cycle from a JSON config pair.
Quick start
Install:
pip install vitro
A minimal device plugin lives in your own package. The device class
subclasses VitroDevice and implements lifecycle methods that Vitro
discovers by name; a module-level @hookimpl registers the device type
string with the framework:
# my_plugin/__init__.py
from vitro import hookimpl
from vitro.devices.base_devices import VitroDevice
class MyBox(VitroDevice):
"""Driver for the device type "my_box"."""
def vitro_device_boot(self, config, cmdline_args, device_manager):
"""Boot sequence — connect, verify required tools, etc."""
...
def vitro_device_configure(self, config, cmdline_args, device_manager):
"""Apply post-boot configuration."""
...
@hookimpl
def vitro_add_devices() -> dict[str, type[VitroDevice]]:
"""Tell Vitro about our device type."""
return {"my_box": MyBox}
Register the package as a Vitro plugin via a setuptools entry point:
# pyproject.toml
[project.entry-points."vitro"]
my_plugin = "my_plugin"
With an environment.json that references "type": "my_box" for one or
more devices, and an inventory.json providing their connection details,
run:
vitro --board-name my-testbed \
--env-config environment.json \
--inventory-config inventory.json
Vitro will reserve, register, boot, and configure the devices, then keep
them available for the next stage of your workflow — interactive
exploration, automated tests via pytest-vitro, or any other consumer
of the live device manager.
Where it fits
Vitro is deliberately framework-agnostic. It does not assume a particular test runner, a particular device library, or a particular reservation system. Two companion projects layer on top when useful:
- A pytest bridge (
pytest-vitro) exposes the live device manager as fixtures so you can write tests against booted devices. - A shared template/operations pool (
vitro-commons) can sit between Vitro and your plugins, providing standardised contracts that multiple testbed plugins can conform to. This is the path for sharing tests across organisations.
Both are separate, optional packages — Vitro can be used without either.
Contributing
Contributions are welcome. Please open an issue describing the change you have in mind before sending a substantial pull request.
License
See LICENSE.
Metadata
Release files for vitro 0.8.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vitro-0.8.1-py3-none-any.whl | Python 3 | none | any | Details |
Release files / vitro-0.8.1-py3-none-any.whl
| Download URL | vitro-0.8.1-py3-none-any.whl |
|---|---|
| Size | 47.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
68b01d2d87337ff5e6e6cb4756e08969f247d5003139ee2b9183c73a8e174318
|
|
BLAKE2b-256 checksum How to use checksums |
7c10a01823d9f9311fcb049b10a3d334a5c5a54a01888d122bae49a0f93f6eb2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logSecurity for vitro 0.8.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 1 file in this release has been uploaded with provenance metadata.
Attestation for vitro-0.8.1-py3-none-any.whl
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.