Majordome
Majordome
Getting Started
If you do not intend to build/develop the package, you can find us on Majordome on PyPI and install it with pip:
pip install majordomeTo register majordome as a Jupyter kernel, run:
majordome --install-kernelYou can customize the kernel identity if needed:
majordome --install-kernel `
--kernel-name majordome-dev `
--display-name "Majordome (dev)"If you don’t fit in the first group, you can build the package from source. For that, please refer to the development section below.
If you just prefer to compile locally without delving into the development environment, you can install both Rust and uv and then run uv build --wheel to generate the wheel for your platform. This will generate a wheel that you can install with uv pip install dist/*.whl or pip install dist/*.whl in the current environment. Note that this wheel will be specific to your platform and may not be compatible with other platforms, so it is recommended to use the release wheels for distribution. For more details, check the development section below.
Development
The development focuses on portability and ease of setup, so by default any dependency relying on a C/C++ compiler is forbidden. This means that the development environment can be set up on any platform without needing to install additional compilers or tools.
Majordome code is documented using Numpydoc style docstrings, and the documentation is generated by module majordome_build.documents using Quarto markdown. This design choice reflects the academic aim of the package, with reporting and notebook support as first-class citizens.
Majordome is mainly organized as a Python package with a set of Rust crates developed in separate repositories. Developing in Rust is the preferred mode as it is safer and more performant than Python, though Python is used for most day-to-day development until new functionalities reach maturity.
For the sake of compatibility with maturin and for avoiding large binaries, a single entrypoint crate is provided in the main repository at src/lib.rs, which exposes the Python API of all the other crates. Furthermore, for performance reasons and low import times, the main Python package modules are split into smaller submodules and lazy import mechanism is implemented with help of __getattr__ in __init__.py.
Project guidelines
The following project guidelines must be followed:
Each commit that may affect user interaction with the Python or Rust libraries must be accompanied by a short comment in the code explaining the change in the
CHANGELOG.mdfile.Tests should be added for any new functionality, bug fixes, or performance improvements. If possible, the tests should be added in the same commit as the change.
Before committing a modification in any of the crates, make sure that building them with
uv run majordome-buildworks. This enforces a greedy mechanism for quality control of the code base. It is also recommended to runcargo checkandcargo testmanually during development at intermediate points.
Environment
The environment for developing Majordome requires at least a reasonably modern version of Python and Rust; documentation depends on Quarto and uv is used for managing the environment. The exact versions may change over time, but as of the last update, the following (minimum) versions are recommended:
Ubuntu users can bootstrap the environment with the following commands; make sure to check the latest versions of the tools and update the commands accordingly. Podman is required for building the manylinux wheel inside a container for compatibility and release in PyPI.
sudo apt-get install -y podman
sudo apt-get install -y python3-dev
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"
curl -LsSf https://astral.sh/uv/install.sh | sh
source "$HOME/.local/bin/env"
quarto_repo="https://github.com/quarto-dev/quarto-cli"
quarto_deb="quarto-1.9.37-linux-amd64.deb"
wget $quarto_repo/releases/download/v1.9.37/$quarto_deb
sudo apt-get install -y ./$quarto_debAutomated release
In addition to what is described in the manual release section below, developers may also need to publish the docs, update the version, and publish the new version to GitHub and PyPI. This is fully automated by release.ps1 to ensure consistency in actions.
Make sure the package builds in both Windows and Linux, and that the documentation builds (many tests are included in the documentation, so this is a good sanity check for the code as well). The following commands provide a good starting point for the verifications in Windows:
# If not yet available, install set-version: cargo install cargo-set-version # Check the sanity of the package: cargo check # Run Rust tests: cargo test # Run Python tests: uv sync --all-extras uv run pytest -v # Manually generate a wheel and check it: uv build --wheel uv run python -m zipfile -l dist/*.whlFrom WSL or a Linux machine, repeat the above but also try generating the Linux wheel inside the compliant manylinux container:
./release.shOnce verifications are done, run one of the following:
# - You fixed something small: ./release.ps1 patch # - You added a new (non-breaking) feature: ./release.ps1 minor # - You made a breaking change: ./release.ps1 major # - Avoid this, unless you know exactly what you are doing: ./release.ps1 1.0.0
Manual release steps
The release script is useful but it can be fragile; it is better to have a fall-back plan in case something goes wrong.
Select the new version to release:
$version = "major" $version = "minor" $version = "patch"Update the version in both
Cargo.tomlandpyproject.toml:# If not yet available, install set-version: cargo install cargo-set-version # First, test with --dry-run to check the changes that will be made: uv version --bump $version --dry-run # After testing with the above, remove --dry-run: uv version --bump $version # Update cargo version to match the new version in pyproject.toml: cargo set-version (uv version --short)You can manually check the changes in the version files; alternatively, the following snipet can be used to extract the version from
Cargo.tomland use it for the commit message and GitHub release tag:$inSection = $false $version = $null foreach ($line in Get-Content "Cargo.toml") { if ($line -match '^\[(.+)\]\s*$') { $inSection = $Matches[1] -eq "package" continue } if ($inSection -and $line -match '^version\s*=\s*"([^"]+)"') { $version = $Matches[1] break } }Generate the command for WSL build and inspect it before running:
$winPath = (Get-Location).Path.Replace("\", "/") $wslPath = (wsl wslpath $winPath).Trim() $nixCmd = "cd $wslPath && source ~/.bashrc && ./release.sh"Build the wheels in both Windows and Linux (inside the compliant manylinux container):
Remove-Item -Force -Recurse "dist/" -ErrorAction Ignore uv build --wheel wsl -d Ubuntu -- bash -c $nixCmd- Inspect the wheels (especially if new data was included):
python -m zipfile -l dist/*.whlIf everything is fine, commit the changes, push to the repository:
git add "Cargo.toml" "pyproject.toml" "Cargo.lock" "uv.lock" git commit -m "Release version $version" git tag "v$version" git push origin main --tagsCreate and activate a virtual environment:
uv venv --python python3.12 .venv # Activate on Windows: . .venv/Scripts/activate # Activate on Unix: . .venv/bin/activateInstall the package before generating the documentation:
uv pip install .[docs]Point Quarto to the virtual environment:
# Windows: $env:QUARTO_PYTHON = ".venv/Scripts/python.exe" # Unix: export QUARTO_PYTHON=".venv/bin/python"Generate the documentation and publish it to GitHub Pages:
quarto render docs --to html quarto publish gh-pages --no-prompt --no-browser docsCreate the release on GitHub:
gh release create "v$version" dist/*.whl --generate-notesPublish the new version to PyPI (owners only) is done manually with
uv:uv publish --token <copy token here>