Development tools

MAFw ships with a unified development tool called devtools that supports maintenance tasks such as building versioned documentation trees, preparing tagged releases, and verifying dependency compatibility.

These tools are not part of the scientific user-facing workflow: a typical MAFw user does not need them, and can safely ignore this section. They exist for the benefit of the development team and for community members who want to contribute to MAFw in a consistent, reproducible way.

Requirements

The devtools CLI requires additional Python packages that are installed when MAFw is set up with the optional [devtools] or [dev] feature:

pip install mafw[devtools]

Dependency

Minimum supported version

Description

packaging

>=26.2

to parse and compare dependency version specifiers

requests

>=2.34.0

to interact with the GitLab API for registry operations

psutil

>=7.2.2

to manage background processes (documentation server)

How to invoke devtools

The unified tool is available as a console entry point from an activated development environment:

devtools --help

Or via Hatch (recommended for CI/CD and for reproducible local runs):

hatch run dev.py3.14:devtools --help

Note

The Hatch environment name includes the Python version (for example dev.py3.14). On CI, the version is typically driven by the PYTHON_VERSION variable in .gitlab-ci.yml.

Command structure

devtools
├── completion       Manage shell completion
│   ├── install
│   ├── uninstall
│   └── show
├── documentation    Build and manage versioned documentation
│   ├── build          Build multiversion documentation tree
│   ├── current        Build only the current working tree
│   ├── clean          Remove output directories
│   ├── prune          Remove old versions to respect a size limit
│   ├── redirects      Generate GitLab Pages _redirects file
│   ├── landing        Generate root landing page
│   ├── requirements   Generate RST requirement files from pyproject.toml
│   ├── registry       Interact with the GitLab Generic Package Registry
│   │   ├── upload
│   │   ├── download
│   │   └── delete
│   └── server         Local HTTP server helper
│       ├── start
│       ├── status
│       ├── stop
│       └── restart
├── release          Release lifecycle management
│   └── create        Prepare a new tagged release
└── dependencies     Dependency verification and maintenance
    ├── freeze         Freeze dependency upper bounds in pyproject.toml
    ├── unfreeze       Remove frozen dependency upper bounds
    ├── latest         Rolling compatibility for the latest dependencies
    │   ├── check        Verify compatibility with newest dependencies
    │   └── compare      Compare dependencies against reference pylock files
    ├── oldest         Oldest dependency stack verification
    │   └── check        Verify compatibility with oldest supported dependencies
    ├── audit          Audit dependency vulnerabilities using pip-audit
    └── registry       GitLab registry for dependency reference files
        ├── upload
        ├── download
        ├── delete
        └── prune

Shell completion

devtools exposes shell TAB completion through the completion command group. The feature is available for bash, zsh and fish.

Install it in the active virtual environment with:

devtools completion install

If you only want to activate directly (but not permanently) the completion functionality, use:

eval "$(devtools completion show)"

Documentation commands

Purpose and idea

The documentation group builds the MAFw documentation using Sphinx and produces a directory tree that contains:

  • One folder per stable tag (for example v2.1.0).

  • A stable alias pointing to the latest stable tag.

  • Optionally a dev alias for the current branch if it is ahead of stable.

  • A latest folder containing a build of the current working tree.

This makes it possible to publish multiple documentation versions (HTML and optionally PDF) in a single GitLab Pages site, while keeping the workflow reproducible and CI-friendly.

Typical usage examples

Build only the current documentation (current)

This is the fastest way to validate documentation changes on your current branch.

devtools documentation current -y

Rebuild from scratch:

devtools documentation current -y --from-scratch

Build a multiversion documentation tree (build)

devtools documentation build --min-vers v1.0.0 --build-pdf

How documentation is built on CI

In the GitLab pipeline, the multiversion documentation is generated by the doc_build_all job:

hatch run dev.py${PYTHON_VERSION}:devtools documentation build \
  --min-vers $DOC_MIN_VERS \
  --build-pdf \
  --max-size $DOC_MAX_SIZE \
  --zip-filepath /tmp/zips \
  --with-zip-file \
  --with-upload-zip \
  --with-cached-packages

Start a local documentation server

After building the documentation locally, serve the generated tree over HTTP:

devtools documentation server start -d docs/build -p 8000

Even though one can browse directly the generated files in the browser (file:///), serving the pages via a real server assures the proper functioning of all JavaScript and version switching mechanism.

Release commands

Purpose and idea

The release group orchestrates the MAFw release lifecycle: version bumps, changelog updates, and tagging. It enforces consistency and automates repetitive tasks.

Release reproducibility and rolling compatibility

MAFw uses open lower bounds during development (for example rich>=13.9.4) to allow working against newer upstream releases. For tagged releases, however, reproducibility matters.

The release create command applies a freeze → release → unfreeze pattern:

  1. Freeze: rewrite dependency specifiers with explicit upper bounds based on the highest resolved version.

  2. Release: the release commit includes the frozen pyproject.toml.

  3. Unfreeze: remove the computed upper bounds so development continues unrestricted.

Documentation target version

The documentation target version is the major.minor value used by the release workflow to annotate public API docstrings with Sphinx directives such as versionadded and versionchanged.

Prepare a new release (release create)

The release create command automates the entire release pipeline. It requires a positional argument SEGMENTS which is passed to Hatch (e.g., minor,rc, rc, or release).

devtools release create minor,rc --dry-run

Logical workflow summary

  1. Safety checks: Verify the current branch is main and the working tree is clean.

  2. Freeze: Rewrite pyproject.toml to add explicit upper bounds to dependencies.

  3. Bump: Update the project version using hatch version.

  4. Doc target: Update the documentation target version used by docstring version directives.

  5. Metadata: Update NOTICE.txt and CHANGELOG.md.

  6. Requirements: Update the requirements RST files and README.rst with frozen dependencies.

  7. Notes: Optionally generate a release_note_vX.Y.Z.md file.

  8. Tag: Commit the changes and create a local git tag.

  9. Unfreeze: Remove the computed upper bounds from pyproject.toml.

  10. Requirements: Restore the requirements RST files and README.rst to open upper bounds.

  11. Commit: Create a second commit on main with the unfrozen dependencies.

  12. Push: Optionally push both commits and the tag to the remote repository.

Dependencies commands

Purpose and idea

The dependencies group ensures MAFw is compatible with both the latest and oldest supported dependency stacks. It also provides tools for freezing upper bounds, auditing vulnerabilities, and managing reference files in the GitLab Generic Package Registry.

Verify dependency stacks

Verify against newest dependencies:

devtools dependencies latest check

Verify against oldest supported dependencies (using lowest-direct resolution):

devtools dependencies oldest check

Both commands support --preserve-envs to keep hatch environments for local debugging.

Deprecated since version 2.3: The --remove-envs/--no-remove-envs option on dependencies oldest check is deprecated. Use --preserve-envs instead.

Compare dependency versions (dependencies latest compare)

The compare subcommand detects ecosystem drift by comparing the latest resolved dependency versions against reference pylock files.

devtools dependencies latest compare
devtools dependencies latest compare -o drift-report.md -f markdown
devtools dependencies latest compare -o drift-report.json -f json
devtools dependencies latest compare --gitlab-ref

Freeze and unfreeze

devtools dependencies freeze
devtools dependencies unfreeze

Manage dependency reference files (dependencies registry)

To speed up CI/CD pipelines, devtools can cache dependency reference files in the GitLab Generic Package Registry.

devtools dependencies registry upload --all
devtools dependencies registry download --all
devtools dependencies registry prune

Added in version 2.3: The dependencies registry prune command.

Vulnerabilities check (dependencies audit)

A scheduled pipeline executed every night verifies that there are no known vulnerabilities for all MAFw dependencies. To run the audit manually:

devtools dependencies audit