Skip to content

Commit 0514854

Browse files
feat: add update to README
feat: add uv as an installer for python UV is a very fast installer for python packages that can be 10-100x faster to resolve packages. This adds an option for Mason to use it instead of pip to resolve python packages that are installed via Mason. More info about the replacement: https://github.com/astral-sh/uv I have no relationship with uv, it is just very fast and it would be nice to have updates for packages like sqlfluff take a lot less time than they currently do to resolve during updates.
1 parent 3b5068f commit 0514854

File tree

6 files changed

+60
-13
lines changed

6 files changed

+60
-13
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,10 @@ local DEFAULT_SETTINGS = {
252252
-- Whether to upgrade pip to the latest version in the virtual environment before installing packages.
253253
upgrade_pip = false,
254254

255+
---@since 1.8.0
256+
-- Whether to use uv to install packages instead of pip
257+
use_uv = false,
258+
255259
---@since 1.0.0
256260
-- These args will be added to `pip install` calls. Note that setting extra args might impact intended behavior
257261
-- and is not recommended.

doc/mason.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ Example:
314314
-- Whether to upgrade pip to the latest version in the virtual environment before installing packages.
315315
upgrade_pip = false,
316316

317+
---@since 1.8.0
318+
-- Whether to use uv to install packages instead of pip
319+
use_uv = false,
320+
317321
---@since 1.0.0
318322
-- These args will be added to `pip install` calls. Note that setting extra args might impact intended behavior
319323
-- and is not recommended.

lua/mason-core/installer/managers/pypi.lua

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,36 @@ local log = require "mason-core.log"
77
local path = require "mason-core.path"
88
local platform = require "mason-core.platform"
99
local semver = require "mason-core.semver"
10+
local settings = require "mason.settings"
1011
local spawn = require "mason-core.spawn"
1112

1213
local M = {}
1314

15+
local use_uv = settings.current.pip.use_uv
1416
local VENV_DIR = "venv"
17+
if use_uv then
18+
VENV_DIR = ".venv"
19+
end
1520

1621
local is_executable = _.compose(_.equals(1), vim.fn.executable)
1722

1823
---@async
1924
---@param candidates string[]
2025
local function resolve_python3(candidates)
2126
a.scheduler()
27+
if use_uv then
28+
candidates = { "uv" }
29+
end
2230
local available_candidates = _.filter(is_executable, candidates)
2331
for __, candidate in ipairs(available_candidates) do
2432
---@type string
2533
local version_output = spawn[candidate]({ "--version" }):map(_.prop "stdout"):get_or_else ""
26-
local ok, version = pcall(semver.new, version_output:match "Python (3%.%d+.%d+)")
34+
local ok, version
35+
if use_uv then
36+
ok, version = pcall(semver.new, version_output:match "uv (%d+.%d+.%d+)")
37+
else
38+
ok, version = pcall(semver.new, version_output:match "Python (3%.%d+.%d+)")
39+
end
2740
if ok then
2841
return { executable = candidate, version = version }
2942
end
@@ -70,9 +83,14 @@ local function create_venv()
7083
)
7184
return Result.failure "Failed to find python3 installation."
7285
end
73-
log.fmt_debug("Found python3 installation version=%s, executable=%s", target.version, target.executable)
7486
ctx.stdio_sink.stdout "Creating virtual environment…\n"
75-
return ctx.spawn[target.executable] { "-m", "venv", VENV_DIR }
87+
if use_uv then
88+
log.fmt_debug("Found uv installation version=%s, executable=%s", target.version, target.executable)
89+
return ctx.spawn[target.executable] { "venv", VENV_DIR }
90+
else
91+
log.fmt_debug("Found python3 installation version=%s, executable=%s", target.version, target.executable)
92+
return ctx.spawn[target.executable] { "-m", "venv", VENV_DIR }
93+
end
7694
end
7795

7896
---@param ctx InstallContext
@@ -107,15 +125,28 @@ end
107125
---@param pkgs string[]
108126
---@param extra_args? string[]
109127
local function pip_install(pkgs, extra_args)
110-
return venv_python {
111-
"-m",
112-
"pip",
113-
"--disable-pip-version-check",
114-
"install",
115-
"-U",
116-
extra_args or vim.NIL,
117-
pkgs,
118-
}
128+
if use_uv then
129+
local ctx = installer.context()
130+
local task = ctx.spawn["uv"] {
131+
"pip",
132+
"install",
133+
"-U",
134+
extra_args or vim.NIL,
135+
pkgs,
136+
}
137+
-- vim.api.nvim_set_current_dir(curdir)
138+
return task
139+
else
140+
return venv_python {
141+
"-m",
142+
"pip",
143+
"--disable-pip-version-check",
144+
"install",
145+
"-U",
146+
extra_args or vim.NIL,
147+
pkgs,
148+
}
149+
end
119150
end
120151

121152
---@async
@@ -129,7 +160,7 @@ function M.init(opts)
129160
ctx:promote_cwd()
130161
try(create_venv())
131162

132-
if opts.upgrade_pip then
163+
if opts.upgrade_pip and not use_uv then
133164
ctx.stdio_sink.stdout "Upgrading pip inside the virtual environment…\n"
134165
try(pip_install({ "pip" }, opts.install_extra_args))
135166
end

lua/mason-core/installer/registry/providers/pypi.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ function M.parse(source, purl)
2727
pip = {
2828
upgrade = settings.current.pip.upgrade_pip,
2929
extra_args = settings.current.pip.install_args,
30+
use_uv = settings.current.pip.use_uv,
3031
},
3132
}
3233

@@ -44,11 +45,13 @@ function M.install(ctx, source)
4445
try(pypi.init {
4546
upgrade_pip = source.pip.upgrade,
4647
install_extra_args = source.pip.extra_args,
48+
use_uv = source.pip.use_uv,
4749
})
4850
try(pypi.install(source.package, source.version, {
4951
extra = source.extra,
5052
extra_packages = source.extra_packages,
5153
install_extra_args = source.pip.extra_args,
54+
use_uv = source.pip.use_uv,
5255
}))
5356
end)
5457
end

lua/mason/settings.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ local DEFAULT_SETTINGS = {
6060
-- Whether to upgrade pip to the latest version in the virtual environment before installing packages.
6161
upgrade_pip = false,
6262

63+
---@since 1.8.0
64+
-- Whether to use uv to install packages instead of pip
65+
use_uv = false,
66+
6367
---@since 1.0.0
6468
-- These args will be added to `pip install` calls. Note that setting extra args might impact intended behavior
6569
-- and is not recommended.

tests/mason-core/installer/registry/providers/pypi_spec.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ describe("pypi provider :: parsing", function()
3131
pip = {
3232
upgrade = true,
3333
extra_args = { "--proxy", "http://localghost" },
34+
use_uv = false,
3435
},
3536
},
3637
pypi.parse({ extra_packages = { "extra" } }, purl())

0 commit comments

Comments
 (0)