2.home-manager/tests/modules/programs/uv/tool.nix
Peter Bittner c51ac59e59 uv: manage Python versions and tools
Add programs.uv.python.{versions,default,prune} and
programs.uv.tool.{packages,prune} to install uv-managed Python versions
and tools during activation.

Install requests are passed verbatim to uv. Unpinned entries track the
latest release on each activation while pinned ones stay put: Python
requests without a patch component are installed with `uv python install
--upgrade` (exact patches, which uv refuses to upgrade, get a plain
install), and tools are refreshed with `uv tool upgrade <packages>`
scoped to the configured list. Both upgrades are scoped to the managed
entries, so installs Home Manager does not own are left untouched. prune
makes a set declarative by running `uv ... uninstall --all` before
reinstalling the listed entries.

The activation blocks run after linkGeneration so uv sees the freshly
linked uv.toml, and a null programs.uv.package is rejected once the
module emits activation commands.
2026-06-17 15:47:24 -05:00

30 lines
968 B
Nix

{
programs.uv = {
enable = true;
tool.packages = [
"ruff"
"black==24.1.0"
"poetry[plugin]"
];
};
test.stubs.uv.name = "uv";
nmt.script = ''
# Each tool is installed individually, preserving extras and specifiers.
assertFileContains activate \
'run @uv@/bin/uv tool install $VERBOSE_ARG ruff'
assertFileContains activate \
"run @uv@/bin/uv tool install \$VERBOSE_ARG 'black==24.1.0'"
assertFileContains activate \
"run @uv@/bin/uv tool install \$VERBOSE_ARG 'poetry[plugin]'"
# Upgrading is delegated to uv but scoped to the configured tools, so tools
# installed outside this option are untouched; per-tool constraints hold.
assertFileContains activate \
"run @uv@/bin/uv tool upgrade \$VERBOSE_ARG ruff 'black==24.1.0' 'poetry[plugin]'"
# Without prune the performant path is used: no uninstall/reinstall churn.
assertFileNotRegex activate 'tool uninstall'
'';
}