@@ -9,10 +9,12 @@ local pep440 = require "mason-core.pep440"
99local platform = require " mason-core.platform"
1010local providers = require " mason-core.providers"
1111local semver = require " mason-core.semver"
12+ local settings = require " mason.settings"
1213local spawn = require " mason-core.spawn"
1314
1415local M = {}
1516
17+ local use_uv = settings .current .pip .use_uv
1618local VENV_DIR = " venv"
1719
1820--- @async
@@ -22,11 +24,20 @@ local function resolve_python3(candidates)
2224 a .scheduler ()
2325 local available_candidates = _ .filter (is_executable , candidates )
2426 for __ , candidate in ipairs (available_candidates ) do
25- --- @type string
26- local version_output = spawn [candidate ]({ " --version" }):map (_ .prop " stdout" ):get_or_else " "
27- local ok , version = pcall (semver .new , version_output :match " Python (3%.%d+.%d+)" )
28- if ok then
29- return { executable = candidate , version = version }
27+ if use_uv and candidate == " uv" then
28+ --- @type string
29+ local version_output = spawn [candidate ]({ " --version" }):map (_ .prop " stdout" ):get_or_else " "
30+ local ok , version = pcall (semver .new , version_output :match " uv (%d+.%d+.%d+).*" )
31+ if ok then
32+ return { executable = candidate , version = version }
33+ end
34+ elseif not use_uv then
35+ --- @type string
36+ local version_output = spawn [candidate ]({ " --version" }):map (_ .prop " stdout" ):get_or_else " "
37+ local ok , version = pcall (semver .new , version_output :match " Python (3%.%d+.%d+)" )
38+ if ok then
39+ return { executable = candidate , version = version }
40+ end
3041 end
3142 end
3243 return nil
@@ -76,14 +87,14 @@ local function create_venv(pkg)
7687 local supported_python_versions = providers .pypi .get_supported_python_versions (pkg .name , pkg .version ):get_or_nil ()
7788
7889 -- 1. Resolve stock python3 installation.
79- local stock_candidates = platform .is .win and { " python" , " python3" } or { " python3" , " python" }
90+ local stock_candidates = platform .is .win and { " python" , " python3" , " uv " } or { " python3" , " python" , " uv " }
8091 local stock_target = resolve_python3 (stock_candidates )
8192 if stock_target then
8293 log .fmt_debug (" Resolved stock python3 installation version %s" , stock_target .version )
8394 end
8495
8596 -- 2. Resolve suitable versioned python3 installation (python3.12, python3.11, etc.).
86- local versioned_candidates = {}
97+ local versioned_candidates = { " uv " }
8798 if supported_python_versions ~= nil then
8899 if stock_target and not pep440_check_version (tostring (stock_target .version ), supported_python_versions ) then
89100 log .fmt_debug (" Finding versioned candidates for %s" , supported_python_versions )
@@ -103,7 +114,8 @@ local function create_venv(pkg)
103114 -- 3. If a versioned python3 installation was not found, warn the user if the stock python3 installation is outside
104115 -- the supported version range.
105116 if
106- target == stock_target
117+ use_uv == false
118+ and target == stock_target
107119 and supported_python_versions ~= nil
108120 and not pep440_check_version (tostring (target .version ), supported_python_versions )
109121 then
@@ -125,9 +137,14 @@ local function create_venv(pkg)
125137 end
126138 end
127139
128- log .fmt_debug (" Found python3 installation version=%s, executable=%s" , target .version , target .executable )
129140 ctx .stdio_sink .stdout " Creating virtual environment…\n "
130- return ctx .spawn [target .executable ] { " -m" , " venv" , " --system-site-packages" , VENV_DIR }
141+ if use_uv then
142+ log .fmt_debug (" Found uv installation version=%s, executable=%s" , target .version , target .executable )
143+ return ctx .spawn [target .executable ] { " venv" , VENV_DIR }
144+ else
145+ log .fmt_debug (" Found python3 installation version=%s, executable=%s" , target .version , target .executable )
146+ return ctx .spawn [target .executable ] { " -m" , " venv" , " --system-site-packages" , VENV_DIR }
147+ end
131148end
132149
133150--- @param ctx InstallContext
153170--- @param args SpawnArgs
154171local function venv_python (args )
155172 local ctx = installer .context ()
173+ if use_uv then
174+ return ctx .spawn [" uv" ](args )
175+ end
156176 return find_venv_executable (ctx , " python" ):and_then (function (python_path )
157177 return ctx .spawn [path .concat { ctx .cwd :get (), python_path }](args )
158178 end )
@@ -162,16 +182,28 @@ end
162182--- @param pkgs string[]
163183--- @param extra_args ? string[]
164184local function pip_install (pkgs , extra_args )
165- return venv_python {
166- " -m" ,
167- " pip" ,
168- " --disable-pip-version-check" ,
169- " install" ,
170- " --ignore-installed" ,
171- " -U" ,
172- extra_args or vim .NIL ,
173- pkgs ,
174- }
185+ if use_uv then
186+ return venv_python {
187+ " pip" ,
188+ " install" ,
189+ " --directory" ,
190+ " venv" ,
191+ " -U" ,
192+ extra_args or vim .NIL ,
193+ pkgs ,
194+ }
195+ else
196+ return venv_python {
197+ " -m" ,
198+ " pip" ,
199+ " --disable-pip-version-check" ,
200+ " install" ,
201+ " --ignore-installed" ,
202+ " -U" ,
203+ extra_args or vim .NIL ,
204+ pkgs ,
205+ }
206+ end
175207end
176208
177209--- @async
@@ -185,7 +217,7 @@ function M.init(opts)
185217 ctx :promote_cwd ()
186218 try (create_venv (opts .package ))
187219
188- if opts .upgrade_pip then
220+ if opts .upgrade_pip and not use_uv then
189221 ctx .stdio_sink .stdout " Upgrading pip inside the virtual environment…\n "
190222 try (pip_install ({ " pip" }, opts .install_extra_args ))
191223 end
0 commit comments