mpt-extension-contrib is a uv workspace monorepo
of independently released Python libraries for SoftwareONE MPT extensions.
- The root
pyproject.tomldefines the uv workspace and the shared tool configuration (ruff, flake8, mypy, pytest, coverage). It is not an installable distribution — there is no umbrellampt-extension-contribpackage. - A single
uv.locklocks the whole workspace. - Each top-level directory is one independently released distribution. The live list
of packages is the package table in the root
README.md(kept in sync bymake create-module).
For a module <module>:
Repository directory: <module> (kebab-case)
Distribution name: mpt-extension-contrib-<module>
Python import: mpt_extension_contrib.<module_with_underscores>
Directories and distribution names use hyphens; the Python import segment uses underscores.
All distributions share the PEP 420 namespace package mpt_extension_contrib.
No distribution may contain mpt_extension_contrib/__init__.py — that file would
claim the namespace and shadow sibling distributions installed alongside it. Only a
concrete module directory owns an __init__.py, e.g. mpt_extension_contrib/shared/.
This invariant is enforced two ways:
scripts/check_repository.py(run bymake check/make repo-check) fails if a namespace-root__init__.pyexists.tests/test_namespace.pyasserts the installed packages coexist under one namespace root.
See the "Two views" section of the README for the on-disk vs installed picture.
shared/ (mpt-extension-contrib-shared) holds internal helpers reused
by other contrib modules. It is internal API: extension repositories should not depend
on it directly. It is released independently, and a breaking change to shared does
not require updating every consumer in the same change — consumers bump their declared
mpt-extension-contrib-shared constraint when they adopt a new release.
Each distribution is versioned and released independently:
- a change limited to one module releases only that module;
- a compatible change to
sharedis released before any consumer that needs it (the release workflow publishes in workspace order, one module at a time).
Git tags use <module>-<version>; each module gets its own GitHub Release. See
releases.md.
The PR workflow (.github/workflows/pr-build-merge.yml)
classifies changed files with
scripts/detect_changed_packages.py and
builds/tests only the affected modules; a change to shared tooling fans out to every
module. See contributing.md and testing.md.