Packaging¶
Distribution and packaging reference for repomatic, aimed at downstream packagers.
Dependencies¶
This is a graph of the Python package’s dependencies. Boxes hold the directly-declared dependencies (main set and each development group), drawn as hexagons; transitive dependencies render outside the boxes as ovals:
flowchart LR
repomatic[["`repomatic`"]]
subgraph primary-deps [Primary dependencies]
click_extra{{"`click-extra`"}}
vt_py{{"`vt-py`"}}
arrow{{"`arrow`"}}
wcmatch{{"`wcmatch`"}}
py_walk{{"`py-walk`"}}
pyproject_metadata{{"`pyproject-metadata`"}}
tomlrt{{"`tomlrt`"}}
packaging{{"`packaging`"}}
pyyaml{{"`pyyaml`"}}
boltons{{"`boltons`"}}
extra_platforms{{"`extra-platforms`"}}
backports_strenum{{"`backports-strenum`"}}
pyelftools{{"`pyelftools`"}}
end
aiohttp(["`aiohttp`"])
typing_extensions(["`typing-extensions`"])
pygments(["`pygments`"])
requests(["`requests`"])
jinja2(["`jinja2`"])
yarl(["`yarl`"])
aiosignal(["`aiosignal`"])
beautifulsoup4(["`beautifulsoup4`"])
click_0(["`click`"])
cloup(["`cloup`"])
colorama(["`colorama`"])
docutils(["`docutils`"])
markdown_it_py(["`markdown-it-py`"])
multidict(["`multidict`"])
tomli(["`tomli`"])
accessible_pygments(["`accessible-pygments`"])
exceptiongroup(["`exceptiongroup`"])
frozenlist(["`frozenlist`"])
idna(["`idna`"])
mdit_py_plugins(["`mdit-py-plugins`"])
pluggy(["`pluggy`"])
propcache(["`propcache`"])
python_dateutil(["`python-dateutil`"])
sphinx_basic_ng(["`sphinx-basic-ng`"])
tabulate(["`tabulate`"])
wcwidth(["`wcwidth`"])
aiofiles(["`aiofiles`"])
aiohappyeyeballs(["`aiohappyeyeballs`"])
alabaster(["`alabaster`"])
async_timeout(["`async-timeout`"])
attrs(["`attrs`"])
babel(["`babel`"])
bracex(["`bracex`"])
certifi(["`certifi`"])
charset_normalizer(["`charset-normalizer`"])
deepmerge(["`deepmerge`"])
execnet(["`execnet`"])
imagesize(["`imagesize`"])
iniconfig(["`iniconfig`"])
markupsafe(["`markupsafe`"])
mdurl(["`mdurl`"])
psutil(["`psutil`"])
roman_numerals(["`roman-numerals`"])
six(["`six`"])
sly(["`sly`"])
snowballstemmer(["`snowballstemmer`"])
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`"])
urllib3(["`urllib3`"])
subgraph grp_docs [--group docs]
sphinx{{"`sphinx >=8`"}}
myst_parser{{"`myst-parser >=5.1`"}}
furo{{"`furo >=2025.9.25`"}}
sphinx_datatables{{"`sphinx-datatables >=1`"}}
sphinxcontrib_mermaid{{"`sphinxcontrib-mermaid >=1.2.3`"}}
sphinxcontrib_jquery{{"`sphinxcontrib-jquery >=4`"}}
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`"}}
end
subgraph grp_test [--group test]
pytest{{"`pytest >=9`"}}
pytest_cov{{"`pytest-cov >=4`"}}
pytest_xdist{{"`pytest-xdist >=3.7`"}}
coverage{{"`coverage >=7.11`"}}
pytest_github_actions_annotate_failures{{"`pytest-github-actions-annotate-failures >=0.2`"}}
pytest_randomly{{"`pytest-randomly >=3`"}}
end
subgraph grp_typing [--group typing]
types_boltons{{"`types-boltons >=25.0.0.20250822`"}}
types_docutils{{"`types-docutils >=0.22.3.20251115`"}}
types_pyyaml{{"`types-pyyaml >=6.0.12.9`"}}
end
repomatic ==>|" >=8.8 "| click_extra
repomatic ==>|" >=17 "| packaging
repomatic ==>|" >=1.3 "| arrow
repomatic ==>|" >=6.0.3 "| pyyaml
repomatic ==>|" >=0.18 "| vt_py
repomatic ==>|" >=10 "| wcmatch
repomatic ==>|" >=25 "| boltons
repomatic ==>|" >=12.0.2 "| extra_platforms
repomatic ==>|" >=0.3.1 "| py_walk
repomatic ==>|" >=0.9 "| pyproject_metadata
repomatic ==>|" >=1.7.6 "| tomlrt
repomatic ==>|" >=1 "| backports_strenum
repomatic ==>|" >=0.33 "| pyelftools
sphinx --> packaging
sphinx --> pygments
sphinx --> requests
sphinx --> jinja2
sphinx --> colorama
sphinx --> docutils
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 --> pygments
click_extra --> click_0
click_extra --> cloup
click_extra --> docutils
click_extra --> tomli
click_extra --> wcmatch
click_extra --> boltons
click_extra --> extra_platforms
click_extra --> tabulate
click_extra --> wcwidth
click_extra --> deepmerge
pytest --> packaging
pytest --> pygments
pytest --> colorama
pytest --> tomli
pytest --> exceptiongroup
pytest --> pluggy
pytest --> iniconfig
myst_parser --> sphinx
myst_parser --> jinja2
myst_parser --> docutils
myst_parser --> markdown_it_py
myst_parser --> pyyaml
myst_parser --> mdit_py_plugins
furo --> sphinx
furo --> pygments
furo --> beautifulsoup4
furo --> accessible_pygments
furo --> sphinx_basic_ng
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 --> jinja2
sphinxcontrib_mermaid --> pyyaml
arrow --> python_dateutil
arrow --> tzdata
coverage --> tomli
sphinxcontrib_jquery --> sphinx
vt_py --> aiohttp
vt_py --> aiofiles
wcmatch --> bracex
py_walk --> sly
pyproject_metadata --> packaging
pytest_github_actions_annotate_failures --> pytest
pytest_randomly --> pytest
sphinx_autodoc_typehints --> sphinx
sphinx_copybutton --> sphinx
sphinx_design --> sphinx
sphinxext_opengraph --> sphinx
tomlrt --> typing_extensions
aiohttp --> typing_extensions
aiohttp --> yarl
aiohttp --> aiosignal
aiohttp --> multidict
aiohttp --> frozenlist
aiohttp --> propcache
aiohttp --> aiohappyeyeballs
aiohttp --> async_timeout
aiohttp --> attrs
requests --> idna
requests --> certifi
requests --> charset_normalizer
requests --> urllib3
jinja2 --> markupsafe
beautifulsoup4 --> typing_extensions
beautifulsoup4 --> soupsieve
click_0 --> colorama
cloup --> typing_extensions
cloup --> click_0
markdown_it_py --> mdurl
accessible_pygments --> pygments
exceptiongroup --> typing_extensions
mdit_py_plugins --> markdown_it_py
python_dateutil --> six
sphinx_basic_ng --> sphinx
tabulate --> wcwidth
yarl --> multidict
yarl --> idna
yarl --> propcache
aiosignal --> typing_extensions
aiosignal --> frozenlist
multidict --> typing_extensions
repomatic -.-> grp_docs
repomatic -.-> grp_test
repomatic -.-> grp_typing
click accessible_pygments "https://pypi.org/project/accessible-pygments/" _blank
click aiofiles "https://pypi.org/project/aiofiles/" _blank
click aiohappyeyeballs "https://pypi.org/project/aiohappyeyeballs/" _blank
click aiohttp "https://pypi.org/project/aiohttp/" _blank
click aiosignal "https://pypi.org/project/aiosignal/" _blank
click alabaster "https://pypi.org/project/alabaster/" _blank
click arrow "https://pypi.org/project/arrow/" _blank
click async_timeout "https://pypi.org/project/async-timeout/" _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 beautifulsoup4 "https://pypi.org/project/beautifulsoup4/" _blank
click boltons "https://pypi.org/project/boltons/" _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 deepmerge "https://pypi.org/project/deepmerge/" _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 frozenlist "https://pypi.org/project/frozenlist/" _blank
click furo "https://pypi.org/project/furo/" _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 jinja2 "https://pypi.org/project/jinja2/" _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 multidict "https://pypi.org/project/multidict/" _blank
click myst_parser "https://pypi.org/project/myst-parser/" _blank
click packaging "https://pypi.org/project/packaging/" _blank
click pluggy "https://pypi.org/project/pluggy/" _blank
click propcache "https://pypi.org/project/propcache/" _blank
click psutil "https://pypi.org/project/psutil/" _blank
click py_walk "https://pypi.org/project/py-walk/" _blank
click pyelftools "https://pypi.org/project/pyelftools/" _blank
click pygments "https://pypi.org/project/pygments/" _blank
click pyproject_metadata "https://pypi.org/project/pyproject-metadata/" _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 repomatic "https://pypi.org/project/repomatic/" _blank
click requests "https://pypi.org/project/requests/" _blank
click roman_numerals "https://pypi.org/project/roman-numerals/" _blank
click six "https://pypi.org/project/six/" _blank
click sly "https://pypi.org/project/sly/" _blank
click snowballstemmer "https://pypi.org/project/snowballstemmer/" _blank
click soupsieve "https://pypi.org/project/soupsieve/" _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 tomlrt "https://pypi.org/project/tomlrt/" _blank
click types_boltons "https://pypi.org/project/types-boltons/" _blank
click types_docutils "https://pypi.org/project/types-docutils/" _blank
click types_pyyaml "https://pypi.org/project/types-pyyaml/" _blank
click typing_extensions "https://pypi.org/project/typing-extensions/" _blank
click tzdata "https://pypi.org/project/tzdata/" _blank
click urllib3 "https://pypi.org/project/urllib3/" _blank
click vt_py "https://pypi.org/project/vt-py/" _blank
click wcmatch "https://pypi.org/project/wcmatch/" _blank
click wcwidth "https://pypi.org/project/wcwidth/" _blank
click yarl "https://pypi.org/project/yarl/" _blank
style repomatic stroke-width:3px
style arrow 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 extra_platforms stroke-width:3px
style furo stroke-width:3px
style myst_parser stroke-width:3px
style packaging stroke-width:3px
style py_walk stroke-width:3px
style pyelftools stroke-width:3px
style pyproject_metadata 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 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_jquery stroke-width:3px
style sphinxcontrib_mermaid stroke-width:3px
style sphinxext_opengraph stroke-width:3px
style tomlrt stroke-width:3px
style types_boltons stroke-width:3px
style types_docutils stroke-width:3px
style types_pyyaml stroke-width:3px
style vt_py stroke-width:3px
style wcmatch stroke-width:3px
style primary-deps fill:#1565C020,stroke:#42A5F5
style grp_docs fill:#546E7A20,stroke:#90A4AE
style grp_test fill:#546E7A20,stroke:#90A4AE
style grp_typing fill:#546E7A20,stroke:#90A4AE
Build backends¶
A repomatic-managed project declares uv_build as its build backend. Distribution channels do not all have it: a packager whose toolchain predates uv-build, or whose policy forbids fetching it, falls back to setuptools, and setuptools then runs its own automatic package discovery over the repository root.
That discovery fails on any repository holding more than one top-level directory, which is every project of this shape:
error: Multiple top-level packages discovered in a flat-layout: ['docs', 'tests', 'my_package'].
The fix is one section naming the package explicitly:
[tool.setuptools]
# Distributors lacking uv-build fall back to setuptools, whose automatic
# discovery then sees docs/, tests/ and every other top-level directory as a
# package and fails. uv-build ignores this section entirely, relying on
# [tool.uv] build-backend instead, so it costs a released wheel nothing.
packages.find.include = ["my_package*"]
Two things make this worth knowing rather than obvious. It is invisible upstream: uv build, uv sync and every wheel published from CI ignore the section, so the failure only ever appears in a downstream packager’s build log, usually weeks after the release that introduced the second top-level directory. And the trailing * matters, since it is what keeps subpackages in.
repomatic init does not write this section. The value it must carry is the package’s own import name, and a bundled template can only approximate that with a list of directories to exclude, which is a worse default than the one line a project can write once and never revisit.