Downstream packagingΒΆ

This page is for distribution packagers, and for anyone building mpm from the packaging specs maintained in this repository: how to wire the test suite into a package build, which dependency constraints to pin against, and where each distribution channel stands.

To install mpm on your own system, head to the installation methods instead. For the release-time automation that keeps the in-repo specs fresh, see the releasing page.

Test suiteΒΆ

The mpm test suite splits into two layers, separated by the integration pytest marker:

  • A hermetic layer (everything not marked integration) needs no network, no package managers and no writable $HOME. It runs cleanly inside a build sandbox. Beyond pytest it imports pyyaml and tomlkit (both pulled in by tests/test_docs.py); the SBOM tests additionally want the [sbom-offline] and [sbom-online] extras but skip themselves when those are absent, so a lean build never has to ignore them. pyproject-fmt stays optional too, its formatting-fixpoint test auto-skipping when missing.

  • An integration layer (marked integration: tests/test_manager_*.py, tests/test_cli*.py and the Xbar/SwiftBar plugin suite) drives the ~70 real package managers (apt, brew, pip, npm, and more) and the mpm CLI end-to-end. It cannot run in a hermetic builder.

Pick the skip path that fits the builder. Either way no per-module ignore list is needed, and the selection stays correct as test modules are added:

  • Writable-$HOME builders (Alpine’s abuild, Debian buildd, RPM mock, and similar) select the hermetic layer explicitly:

    $ pytest -m "not integration"
    
  • Sandbox builders that set HOME=/homeless-shelter (Guix, Nix) get the integration layer auto-skipped through extra_platforms.pytest.skip_guix_build (wired up in tests/conftest.py), so a plain pytest already runs only the hermetic layer. Do not override $HOME back to a writable path, or the auto-skip stops firing and the integration tests fail.

Repo-maintenance sync guards (which regenerate a committed artifact from the installed tooling and compare) skip automatically outside a git checkout, so a tarball or sdist build never trips on a tooling-version mismatch. A builder that packages the SBOM extras can install [sbom-offline] / [sbom-online] to exercise the SBOM tests instead of skipping them.

Running only the sanity-check phase (or its equivalent) stays a valid minimal option: it confirms the package imports cleanly and its declared dependencies resolve. Full functional verification of the integration layer is covered by the project’s own GitHub Actions CI, where the package managers are pre-installed.

The --skip-destructive and pytest -m "not destructive" selectors exist for developer environments where some package managers are present but mutating them would be undesirable. They do not make the suite hermetic.

Note

As of mpm > 7.3.0, the PyPI sdist ships tests/, docs/ and the .github/ workflow files the docs tests parse, so a build can run the suite straight from the sdist. Earlier releases shipped no tests: those builds must start from the GitHub tag tarballs instead.

DependenciesΒΆ

This is a graph of the default, main dependencies of the Python package:

        flowchart LR
    meta_package_manager[["`meta-package-manager`"]]

    subgraph primary-deps [Primary dependencies]
        click_extra{{"`click-extra`"}}
        tomli{{"`tomli`"}}
        xmltodict{{"`xmltodict`"}}
        boltons{{"`boltons`"}}
        extra_platforms{{"`extra-platforms`"}}
        packageurl_python{{"`packageurl-python`"}}
        backports_strenum{{"`backports-strenum`"}}
        tomli_w{{"`tomli-w`"}}
    end

    jsonschema(["`jsonschema`"])
    referencing(["`referencing`"])
    typing_extensions(["`typing-extensions`"])
    pygments(["`pygments`"])
    requests(["`requests`"])
    anyio(["`anyio`"])
    click_0(["`click`"])
    idna(["`idna`"])
    jinja2(["`jinja2`"])
    arrow(["`arrow`"])
    beautifulsoup4(["`beautifulsoup4`"])
    certifi(["`certifi`"])
    cloup(["`cloup`"])
    colorama(["`colorama`"])
    docutils(["`docutils`"])
    exceptiongroup(["`exceptiongroup`"])
    httpcore(["`httpcore`"])
    license_expression(["`license-expression`"])
    markdown_it_py(["`markdown-it-py`"])
    packaging(["`packaging`"])
    rdflib(["`rdflib`"])
    accessible_pygments(["`accessible-pygments`"])
    attrs(["`attrs`"])
    isoduration(["`isoduration`"])
    jsonschema_specifications(["`jsonschema-specifications`"])
    mdit_py_plugins(["`mdit-py-plugins`"])
    pluggy(["`pluggy`"])
    py_serializable(["`py-serializable`"])
    python_dateutil(["`python-dateutil`"])
    rfc3339_validator(["`rfc3339-validator`"])
    rfc3987_syntax(["`rfc3987-syntax`"])
    rpds_py(["`rpds-py`"])
    six(["`six`"])
    sphinx_basic_ng(["`sphinx-basic-ng`"])
    sphinxcontrib_jquery(["`sphinxcontrib-jquery`"])
    tabulate(["`tabulate`"])
    wcmatch(["`wcmatch`"])
    wcwidth(["`wcwidth`"])
    alabaster(["`alabaster`"])
    babel(["`babel`"])
    beartype(["`beartype`"])
    boolean_py(["`boolean-py`"])
    bracex(["`bracex`"])
    charset_normalizer(["`charset-normalizer`"])
    deepmerge(["`deepmerge`"])
    defusedxml(["`defusedxml`"])
    execnet(["`execnet`"])
    fqdn(["`fqdn`"])
    h11(["`h11`"])
    hjson(["`hjson`"])
    imagesize(["`imagesize`"])
    iniconfig(["`iniconfig`"])
    isodate(["`isodate`"])
    json_with_comments(["`json-with-comments`"])
    json5(["`json5`"])
    jsonpointer(["`jsonpointer`"])
    lark(["`lark`"])
    lxml(["`lxml`"])
    markupsafe(["`markupsafe`"])
    mdurl(["`mdurl`"])
    ply(["`ply`"])
    psutil(["`psutil`"])
    pyparsing(["`pyparsing`"])
    rfc3986_validator(["`rfc3986-validator`"])
    roman_numerals(["`roman-numerals`"])
    semantic_version(["`semantic-version`"])
    snowballstemmer(["`snowballstemmer`"])
    sortedcontainers(["`sortedcontainers`"])
    soupsieve(["`soupsieve`"])
    sphinxcontrib_applehelp(["`sphinxcontrib-applehelp`"])
    sphinxcontrib_devhelp(["`sphinxcontrib-devhelp`"])
    sphinxcontrib_htmlhelp(["`sphinxcontrib-htmlhelp`"])
    sphinxcontrib_jsmath(["`sphinxcontrib-jsmath`"])
    sphinxcontrib_qthelp(["`sphinxcontrib-qthelp`"])
    sphinxcontrib_serializinghtml(["`sphinxcontrib-serializinghtml`"])
    tzdata(["`tzdata`"])
    uri_template(["`uri-template`"])
    uritools(["`uritools`"])
    urllib3(["`urllib3`"])
    webcolors(["`webcolors`"])

    subgraph ext_sbom-offline [--extra sbom-offline]
        ext_sbom-offline_spdx_tools{{"`spdx-tools >=0.8.2`"}}
        ext_sbom-offline_cyclonedx_python_lib{{"`cyclonedx-python-lib >=11.9`"}}
    end

    subgraph ext_sbom-online [--extra sbom-online]
        platformdirs{{"`platformdirs >=4`"}}
        ext_sbom-online_httpx{{"`httpx >=0.27`"}}
    end

    subgraph grp_docs [--group docs]
        sphinx{{"`sphinx >=8`"}}
        myst_parser{{"`myst-parser >=4`"}}
        furo{{"`furo >=2025.9.25`"}}
        sphinx_datatables{{"`sphinx-datatables >=1`"}}
        sphinxcontrib_mermaid{{"`sphinxcontrib-mermaid >=1.2.3`"}}
        sphinx_autodoc_typehints{{"`sphinx-autodoc-typehints >=2.4`"}}
        sphinx_copybutton{{"`sphinx-copybutton >=0.5.2`"}}
        sphinx_design{{"`sphinx-design >=0.6`"}}
        sphinxext_opengraph{{"`sphinxext-opengraph >=0.13`"}}
        tomlkit{{"`tomlkit >=0.13`"}}
    end

    subgraph grp_test [--group test]
        pytest{{"`pytest >=9`"}}
        spdx_tools{{"`spdx-tools`"}}
        cyclonedx_python_lib{{"`cyclonedx-python-lib`"}}
        httpx{{"`httpx >=0.27`"}}
        pyyaml{{"`pyyaml >=6`"}}
        pytest_cov{{"`pytest-cov >=7`"}}
        pytest_xdist{{"`pytest-xdist >=3.7`"}}
        coverage{{"`coverage >=7.11`"}}
        pytest_github_actions_annotate_failures{{"`pytest-github-actions-annotate-failures >=0.3`"}}
        pytest_randomly{{"`pytest-randomly >=4.0.1`"}}
        respx{{"`respx >=0.22`"}}
        pyproject_fmt{{"`pyproject-fmt >=2.25.1`"}}
    end

    subgraph grp_typing [--group typing]
        types_boltons{{"`types-boltons >=25.0.0.20250919`"}}
        types_pyyaml{{"`types-pyyaml >=6.0.12.9`"}}
        types_xmltodict{{"`types-xmltodict >=1.0.1.20250920`"}}
    end

    meta_package_manager ==>|" >=8.4 "| click_extra
    meta_package_manager ==>|" >=2 "| tomli
    meta_package_manager ==>|" >=0.12 "| xmltodict
    meta_package_manager ==>|" >=25 "| boltons
    meta_package_manager ==>|" >=13.1 "| extra_platforms
    meta_package_manager ==>|" >=0.11 "| packageurl_python
    meta_package_manager ==>|" >=1 "| backports_strenum
    meta_package_manager ==>|" >=1 "| tomli_w
    sphinx --> pygments
    sphinx --> requests
    sphinx --> tomli
    sphinx --> jinja2
    sphinx --> colorama
    sphinx --> docutils
    sphinx --> packaging
    sphinx --> alabaster
    sphinx --> babel
    sphinx --> imagesize
    sphinx --> roman_numerals
    sphinx --> snowballstemmer
    sphinx --> sphinxcontrib_applehelp
    sphinx --> sphinxcontrib_devhelp
    sphinx --> sphinxcontrib_htmlhelp
    sphinx --> sphinxcontrib_jsmath
    sphinx --> sphinxcontrib_qthelp
    sphinx --> sphinxcontrib_serializinghtml
    click_extra --> sphinx
    click_extra --> pytest
    click_extra --> pygments
    click_extra --> pyyaml
    click_extra --> tomli
    click_extra --> click_0
    click_extra --> cloup
    click_extra --> docutils
    click_extra --> xmltodict
    click_extra --> boltons
    click_extra --> extra_platforms
    click_extra --> tabulate
    click_extra --> tomlkit
    click_extra --> wcmatch
    click_extra --> wcwidth
    click_extra --> deepmerge
    click_extra --> hjson
    click_extra --> json_with_comments
    click_extra --> json5
    pytest --> pygments
    pytest --> tomli
    pytest --> colorama
    pytest --> exceptiongroup
    pytest --> packaging
    pytest --> pluggy
    pytest --> iniconfig
    spdx_tools --> pyyaml
    spdx_tools --> click_0
    spdx_tools --> license_expression
    spdx_tools --> rdflib
    spdx_tools --> xmltodict
    spdx_tools --> beartype
    spdx_tools --> ply
    spdx_tools --> semantic_version
    spdx_tools --> uritools
    cyclonedx_python_lib --> jsonschema
    cyclonedx_python_lib --> referencing
    cyclonedx_python_lib --> typing_extensions
    cyclonedx_python_lib --> license_expression
    cyclonedx_python_lib --> packageurl_python
    cyclonedx_python_lib --> py_serializable
    cyclonedx_python_lib --> lxml
    cyclonedx_python_lib --> sortedcontainers
    myst_parser --> sphinx
    myst_parser --> pyyaml
    myst_parser --> jinja2
    myst_parser --> docutils
    myst_parser --> markdown_it_py
    myst_parser --> mdit_py_plugins
    furo --> sphinx
    furo --> pygments
    furo --> beautifulsoup4
    furo --> accessible_pygments
    furo --> sphinx_basic_ng
    httpx --> anyio
    httpx --> idna
    httpx --> certifi
    httpx --> httpcore
    pytest_cov --> pytest
    pytest_cov --> coverage
    pytest_cov --> pluggy
    pytest_xdist --> pytest
    pytest_xdist --> execnet
    pytest_xdist --> psutil
    sphinx_datatables --> sphinx
    sphinx_datatables --> packaging
    sphinx_datatables --> sphinxcontrib_jquery
    sphinxcontrib_mermaid --> sphinx
    sphinxcontrib_mermaid --> pyyaml
    sphinxcontrib_mermaid --> jinja2
    coverage --> tomli
    pytest_github_actions_annotate_failures --> pytest
    pytest_randomly --> pytest
    respx --> httpx
    sphinx_autodoc_typehints --> sphinx
    sphinx_copybutton --> sphinx
    sphinx_design --> sphinx
    sphinxext_opengraph --> sphinx
    jsonschema --> referencing
    jsonschema --> idna
    jsonschema --> attrs
    jsonschema --> isoduration
    jsonschema --> jsonschema_specifications
    jsonschema --> rfc3339_validator
    jsonschema --> rfc3987_syntax
    jsonschema --> rpds_py
    jsonschema --> fqdn
    jsonschema --> jsonpointer
    jsonschema --> rfc3986_validator
    jsonschema --> uri_template
    jsonschema --> webcolors
    referencing --> typing_extensions
    referencing --> attrs
    referencing --> rpds_py
    requests --> idna
    requests --> certifi
    requests --> charset_normalizer
    requests --> urllib3
    anyio --> typing_extensions
    anyio --> idna
    anyio --> exceptiongroup
    click_0 --> colorama
    jinja2 --> markupsafe
    beautifulsoup4 --> typing_extensions
    beautifulsoup4 --> soupsieve
    cloup --> typing_extensions
    cloup --> click_0
    exceptiongroup --> typing_extensions
    httpcore --> certifi
    httpcore --> h11
    license_expression --> boolean_py
    markdown_it_py --> mdurl
    rdflib --> isodate
    rdflib --> pyparsing
    accessible_pygments --> pygments
    mdit_py_plugins --> markdown_it_py
    py_serializable --> defusedxml
    sphinx_basic_ng --> sphinx
    sphinxcontrib_jquery --> sphinx
    tabulate --> wcwidth
    wcmatch --> bracex
    isoduration --> arrow
    jsonschema_specifications --> referencing
    rfc3339_validator --> six
    rfc3987_syntax --> lark
    arrow --> python_dateutil
    arrow --> tzdata
    python_dateutil --> six
    meta_package_manager -.-> ext_sbom-offline
    meta_package_manager -.-> ext_sbom-online
    meta_package_manager -.-> grp_docs
    meta_package_manager -.-> grp_test
    meta_package_manager -.-> grp_typing
    ext_sbom-offline_spdx_tools -.- spdx_tools
    ext_sbom-offline_cyclonedx_python_lib -.- cyclonedx_python_lib
    ext_sbom-online_httpx -.- httpx

    click accessible_pygments "https://pypi.org/project/accessible-pygments/" _blank
    click alabaster "https://pypi.org/project/alabaster/" _blank
    click anyio "https://pypi.org/project/anyio/" _blank
    click arrow "https://pypi.org/project/arrow/" _blank
    click attrs "https://pypi.org/project/attrs/" _blank
    click babel "https://pypi.org/project/babel/" _blank
    click backports_strenum "https://pypi.org/project/backports-strenum/" _blank
    click beartype "https://pypi.org/project/beartype/" _blank
    click beautifulsoup4 "https://pypi.org/project/beautifulsoup4/" _blank
    click boltons "https://pypi.org/project/boltons/" _blank
    click boolean_py "https://pypi.org/project/boolean-py/" _blank
    click bracex "https://pypi.org/project/bracex/" _blank
    click certifi "https://pypi.org/project/certifi/" _blank
    click charset_normalizer "https://pypi.org/project/charset-normalizer/" _blank
    click click_0 "https://pypi.org/project/click/" _blank
    click click_extra "https://pypi.org/project/click-extra/" _blank
    click cloup "https://pypi.org/project/cloup/" _blank
    click colorama "https://pypi.org/project/colorama/" _blank
    click coverage "https://pypi.org/project/coverage/" _blank
    click cyclonedx_python_lib "https://pypi.org/project/cyclonedx-python-lib/" _blank
    click deepmerge "https://pypi.org/project/deepmerge/" _blank
    click defusedxml "https://pypi.org/project/defusedxml/" _blank
    click docutils "https://pypi.org/project/docutils/" _blank
    click exceptiongroup "https://pypi.org/project/exceptiongroup/" _blank
    click execnet "https://pypi.org/project/execnet/" _blank
    click extra_platforms "https://pypi.org/project/extra-platforms/" _blank
    click fqdn "https://pypi.org/project/fqdn/" _blank
    click furo "https://pypi.org/project/furo/" _blank
    click h11 "https://pypi.org/project/h11/" _blank
    click hjson "https://pypi.org/project/hjson/" _blank
    click httpcore "https://pypi.org/project/httpcore/" _blank
    click httpx "https://pypi.org/project/httpx/" _blank
    click idna "https://pypi.org/project/idna/" _blank
    click imagesize "https://pypi.org/project/imagesize/" _blank
    click iniconfig "https://pypi.org/project/iniconfig/" _blank
    click isodate "https://pypi.org/project/isodate/" _blank
    click isoduration "https://pypi.org/project/isoduration/" _blank
    click jinja2 "https://pypi.org/project/jinja2/" _blank
    click json_with_comments "https://pypi.org/project/json-with-comments/" _blank
    click json5 "https://pypi.org/project/json5/" _blank
    click jsonpointer "https://pypi.org/project/jsonpointer/" _blank
    click jsonschema "https://pypi.org/project/jsonschema/" _blank
    click jsonschema_specifications "https://pypi.org/project/jsonschema-specifications/" _blank
    click lark "https://pypi.org/project/lark/" _blank
    click license_expression "https://pypi.org/project/license-expression/" _blank
    click lxml "https://pypi.org/project/lxml/" _blank
    click markdown_it_py "https://pypi.org/project/markdown-it-py/" _blank
    click markupsafe "https://pypi.org/project/markupsafe/" _blank
    click mdit_py_plugins "https://pypi.org/project/mdit-py-plugins/" _blank
    click mdurl "https://pypi.org/project/mdurl/" _blank
    click meta_package_manager "https://pypi.org/project/meta-package-manager/" _blank
    click myst_parser "https://pypi.org/project/myst-parser/" _blank
    click packageurl_python "https://pypi.org/project/packageurl-python/" _blank
    click packaging "https://pypi.org/project/packaging/" _blank
    click platformdirs "https://pypi.org/project/platformdirs/" _blank
    click pluggy "https://pypi.org/project/pluggy/" _blank
    click ply "https://pypi.org/project/ply/" _blank
    click psutil "https://pypi.org/project/psutil/" _blank
    click py_serializable "https://pypi.org/project/py-serializable/" _blank
    click pygments "https://pypi.org/project/pygments/" _blank
    click pyparsing "https://pypi.org/project/pyparsing/" _blank
    click pyproject_fmt "https://pypi.org/project/pyproject-fmt/" _blank
    click pytest "https://pypi.org/project/pytest/" _blank
    click pytest_cov "https://pypi.org/project/pytest-cov/" _blank
    click pytest_github_actions_annotate_failures "https://pypi.org/project/pytest-github-actions-annotate-failures/" _blank
    click pytest_randomly "https://pypi.org/project/pytest-randomly/" _blank
    click pytest_xdist "https://pypi.org/project/pytest-xdist/" _blank
    click python_dateutil "https://pypi.org/project/python-dateutil/" _blank
    click pyyaml "https://pypi.org/project/pyyaml/" _blank
    click rdflib "https://pypi.org/project/rdflib/" _blank
    click referencing "https://pypi.org/project/referencing/" _blank
    click requests "https://pypi.org/project/requests/" _blank
    click respx "https://pypi.org/project/respx/" _blank
    click rfc3339_validator "https://pypi.org/project/rfc3339-validator/" _blank
    click rfc3986_validator "https://pypi.org/project/rfc3986-validator/" _blank
    click rfc3987_syntax "https://pypi.org/project/rfc3987-syntax/" _blank
    click roman_numerals "https://pypi.org/project/roman-numerals/" _blank
    click rpds_py "https://pypi.org/project/rpds-py/" _blank
    click semantic_version "https://pypi.org/project/semantic-version/" _blank
    click six "https://pypi.org/project/six/" _blank
    click snowballstemmer "https://pypi.org/project/snowballstemmer/" _blank
    click sortedcontainers "https://pypi.org/project/sortedcontainers/" _blank
    click soupsieve "https://pypi.org/project/soupsieve/" _blank
    click spdx_tools "https://pypi.org/project/spdx-tools/" _blank
    click sphinx "https://pypi.org/project/sphinx/" _blank
    click sphinx_autodoc_typehints "https://pypi.org/project/sphinx-autodoc-typehints/" _blank
    click sphinx_basic_ng "https://pypi.org/project/sphinx-basic-ng/" _blank
    click sphinx_copybutton "https://pypi.org/project/sphinx-copybutton/" _blank
    click sphinx_datatables "https://pypi.org/project/sphinx-datatables/" _blank
    click sphinx_design "https://pypi.org/project/sphinx-design/" _blank
    click sphinxcontrib_applehelp "https://pypi.org/project/sphinxcontrib-applehelp/" _blank
    click sphinxcontrib_devhelp "https://pypi.org/project/sphinxcontrib-devhelp/" _blank
    click sphinxcontrib_htmlhelp "https://pypi.org/project/sphinxcontrib-htmlhelp/" _blank
    click sphinxcontrib_jquery "https://pypi.org/project/sphinxcontrib-jquery/" _blank
    click sphinxcontrib_jsmath "https://pypi.org/project/sphinxcontrib-jsmath/" _blank
    click sphinxcontrib_mermaid "https://pypi.org/project/sphinxcontrib-mermaid/" _blank
    click sphinxcontrib_qthelp "https://pypi.org/project/sphinxcontrib-qthelp/" _blank
    click sphinxcontrib_serializinghtml "https://pypi.org/project/sphinxcontrib-serializinghtml/" _blank
    click sphinxext_opengraph "https://pypi.org/project/sphinxext-opengraph/" _blank
    click tabulate "https://pypi.org/project/tabulate/" _blank
    click tomli "https://pypi.org/project/tomli/" _blank
    click tomli_w "https://pypi.org/project/tomli-w/" _blank
    click tomlkit "https://pypi.org/project/tomlkit/" _blank
    click types_boltons "https://pypi.org/project/types-boltons/" _blank
    click types_pyyaml "https://pypi.org/project/types-pyyaml/" _blank
    click types_xmltodict "https://pypi.org/project/types-xmltodict/" _blank
    click typing_extensions "https://pypi.org/project/typing-extensions/" _blank
    click tzdata "https://pypi.org/project/tzdata/" _blank
    click uri_template "https://pypi.org/project/uri-template/" _blank
    click uritools "https://pypi.org/project/uritools/" _blank
    click urllib3 "https://pypi.org/project/urllib3/" _blank
    click wcmatch "https://pypi.org/project/wcmatch/" _blank
    click wcwidth "https://pypi.org/project/wcwidth/" _blank
    click webcolors "https://pypi.org/project/webcolors/" _blank
    click xmltodict "https://pypi.org/project/xmltodict/" _blank
    click ext_sbom-offline_spdx_tools "https://pypi.org/project/spdx-tools/" _blank
    click ext_sbom-offline_cyclonedx_python_lib "https://pypi.org/project/cyclonedx-python-lib/" _blank
    click ext_sbom-online_httpx "https://pypi.org/project/httpx/" _blank

    style meta_package_manager stroke-width:3px
    style backports_strenum stroke-width:3px
    style boltons stroke-width:3px
    style click_extra stroke-width:3px
    style coverage stroke-width:3px
    style cyclonedx_python_lib stroke-width:3px
    style extra_platforms stroke-width:3px
    style furo stroke-width:3px
    style httpx stroke-width:3px
    style myst_parser stroke-width:3px
    style packageurl_python stroke-width:3px
    style platformdirs stroke-width:3px
    style pyproject_fmt stroke-width:3px
    style pytest stroke-width:3px
    style pytest_cov stroke-width:3px
    style pytest_github_actions_annotate_failures stroke-width:3px
    style pytest_randomly stroke-width:3px
    style pytest_xdist stroke-width:3px
    style pyyaml stroke-width:3px
    style respx stroke-width:3px
    style spdx_tools stroke-width:3px
    style sphinx stroke-width:3px
    style sphinx_autodoc_typehints stroke-width:3px
    style sphinx_copybutton stroke-width:3px
    style sphinx_datatables stroke-width:3px
    style sphinx_design stroke-width:3px
    style sphinxcontrib_mermaid stroke-width:3px
    style sphinxext_opengraph stroke-width:3px
    style tomli stroke-width:3px
    style tomli_w stroke-width:3px
    style tomlkit stroke-width:3px
    style types_boltons stroke-width:3px
    style types_pyyaml stroke-width:3px
    style types_xmltodict stroke-width:3px
    style xmltodict stroke-width:3px
    style ext_sbom-offline_spdx_tools stroke-width:3px,stroke-dasharray:5 5
    style ext_sbom-offline_cyclonedx_python_lib stroke-width:3px,stroke-dasharray:5 5
    style ext_sbom-online_httpx stroke-width:3px,stroke-dasharray:5 5

    style primary-deps fill:#1565C020,stroke:#42A5F5
    style ext_sbom-offline fill:#7B1FA220,stroke:#BA68C8
    style ext_sbom-online fill:#7B1FA220,stroke:#BA68C8
    style grp_docs fill:#546E7A20,stroke:#90A4AE
    style grp_test fill:#546E7A20,stroke:#90A4AE
    style grp_typing fill:#546E7A20,stroke:#90A4AE

    

The extra dependencies table lists the optional extras and the features they unlock.

click-extra compatibilityΒΆ

mpm builds its CLI on click-extra, and the two evolve in lockstep: most mpm releases raise their click-extra floor to pick up features and fixes. The table below shows which click-extra versions each mpm release range accepts at install time, derived from the click-extra requirement specifier across release tags. Columns are minor-grouped where the specifiers only distinguish minors, and split per patch where a floor pins a specific patch; the right edge is the click-extra version currently resolved in uv.lock. Rows start at 6.0.0 to keep the column set readable, and the table is regenerated by the same matrix mechanism as the Python compatibility one:

mpm

Released

Spec

7.2

7.5.0

7.5.1

7.6.0

7.6.2

7.7

7.11

7.15

7.16.0

7.16.1

7.19

8.1.0

8.1.1

8.2

8.3

8.4

7.3.0

2026-07-17

>=8.4

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

βœ…

7.2.0

2026-07-09

>=8.3

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

βœ…

βœ…

7.1.0

2026-07-07

>=8.2

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

βœ…

βœ…

βœ…

7.0.x

2026-06-26

>=8.1.1

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

βœ…

βœ…

βœ…

βœ…

6.6.0

2026-06-17

>=7.19

❌

❌

❌

❌

❌

❌

❌

❌

❌

❌

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

6.5.x

2026-05-25

>=7.16.1

❌

❌

❌

❌

❌

❌

❌

❌

❌

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

6.4.x

2026-05-04

>=7.15

❌

❌

❌

❌

❌

❌

❌

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

6.4.0

2026-04-27

>=7.11

❌

❌

❌

❌

❌

❌

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

6.2.x β†’ 6.3.x

2026-03-26

>=7.7.0

❌

❌

❌

❌

❌

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

6.2.0

2026-03-25

>=7.6.2

❌

❌

❌

❌

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

6.1.1

2026-02-05

>=7.5.1

❌

❌

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

6.0.x β†’ 6.1.x

2025-12-08

>=7.2.0

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

βœ…

ChannelsΒΆ

Where mpm stands on each distribution channel whose packaging is maintained from this repository, plus the community-maintained AUR entry. Channels needing no in-repo spec (PyPI, Homebrew, Scoop, GitHub Releases, Stew, ZeroBrew) are covered by the installation methods directly.

Channel

Spec

Upstream status

CI check

Release bump

Alpine Linux

packaging/alpine/

aports submission in preparation

apk-source

manual

Arch Linux (AUR)

community-maintained

released

pacaur, paru, yay

n/a

Chocolatey

packaging/choco/

community repository rejected the submission

choco-source

manual

Guix

packaging/guix/

landed upstream on 2026-06-28

guix-source

automated

MacPorts

packaging/macports/

pending review

macports-source

manual

Nix

packaging/nix/

pending review

nix-source

automated

Void Linux

void-packages fork

pending review

β€”

manual

The *-source jobs of tests-install.yaml build and install each in-repo spec on every change to it and on a weekly schedule. Automated bumps are performed by release.yaml jobs right after each release (see releasing); manual specs pin the released version and its source checksums, refreshed by hand at each release.

Alpine LinuxΒΆ

Build and install from the APKBUILD overlay maintained in the repository. It targets Alpine edge, the only branch shipping py3-uv-build (mpm’s build backend) and py3-boltons >= 25.

As a member of the abuild group, with a signing key set up:

$ doas apk add alpine-sdk
$ abuild-keygen --append --install -n
$ git clone https://github.com/kdeldycke/meta-package-manager.git
$ cd ./meta-package-manager/packaging/alpine
$ abuild -C ./py3-cloup -r
$ abuild -C ./py3-extra-platforms -r
$ abuild -C ./py3-packageurl -r
$ abuild -C ./py3-click-extra -r
$ abuild -C ./meta-package-manager -r
$ doas apk add --repository ~/.local/share/abuild/alpine meta-package-manager

Each abuild run drops its packages in ~/.local/share/abuild/alpine (abuild’s default REPODEST), where the next builds and the final apk add pick them up.

The overlay carries the 4 dependency packages missing from the official aports tree (py3-click-extra, py3-cloup, py3-extra-platforms, py3-packageurl).

ChocolateyΒΆ

Build and install from the nuspec maintained in the repository:

> git clone https://github.com/kdeldycke/meta-package-manager.git
> cd meta-package-manager\packaging\choco\meta-package-manager
> choco pack
> choco install meta-package-manager --source .

This is the only supported install route: the Chocolatey community repository rejected the package over antivirus false positives on the bundled Windows binary.

GuixΒΆ

mpm landed in GNU Guix on 2026-06-28, so the in-repo definition is only needed to build the bleeding-edge version:

$ git clone https://github.com/kdeldycke/meta-package-manager.git
$ guix install --load-path=./meta-package-manager/packaging/guix meta-package-manager

MacPortsΒΆ

Build and install from the Portfile overlay maintained in the repository:

$ git clone https://github.com/kdeldycke/meta-package-manager.git
$ portindex ./meta-package-manager/packaging/macports

Then register the overlay as your first ports tree, by adding its absolute path at the top of /opt/local/etc/macports/sources.conf:

file:///path/to/meta-package-manager/packaging/macports

Finally:

$ sudo port install meta-package-manager

The overlay carries the 5 dependency ports missing from the official tree (py-click-extra, py-cloup, py-deepmerge, py-extra-platforms, py-packageurl-python), plus a py-boltons version bump.

Help land it in MacPorts

The port is pending review at macports/macports-ports#33609. Once merged, installation will be a one-liner:

$ sudo port install meta-package-manager

You can help move it forward by showing your support on the pull request.

NixΒΆ

Build and install from the definition maintained in the repository:

$ git clone https://github.com/kdeldycke/meta-package-manager.git
$ nix-env -f ./meta-package-manager/packaging/nix -i

On flake-enabled systems:

$ nix run github:kdeldycke/meta-package-manager?dir=packaging/nix -- --version

Help land it in nixpkgs

The nixpkgs package is pending review at NixOS/nixpkgs#506145. Once merged, installation will be a one-liner:

$ nix-env --install --attr nixpkgs.meta-package-manager

Or, without installing:

$ nix-shell -p meta-package-manager --run "mpm --version"

On flake-enabled systems:

$ nix run nixpkgs#meta-package-manager -- --version

You can help move it forward by showing your support on the pull request.

Void LinuxΒΆ

While the package is pending upstream review, build and install it from my fork’s mpm branch:

$ git clone --depth 1 --branch mpm https://github.com/kdeldycke/void-packages.git
$ cd ./void-packages
$ ./xbps-src binary-bootstrap
$ ./xbps-src pkg mpm
$ sudo xbps-install --repository=./hostdir/binpkgs/mpm mpm

./xbps-src pkg mpm cascades through and builds the 16 dependency packages introduced by the fork (15 new Python packages plus an in-place bump of python3-boltons from 20.2.1 to 25.0.0 for Python 3.14 compatibility).

Help land it in void-packages

The Void package is pending review at void-linux/void-packages#60532. Once merged, installation will be a one-liner:

$ xbps-install --sync mpm

You can help move it forward by showing your support on the pull request.