@@ -15,28 +15,40 @@ local spawn = require "mason-core.spawn"
1515local M = {}
1616
1717local use_uv = settings .current .pip .use_uv
18- local VENV_DIR = " venv"
18+ local VENV_DIR
19+ if use_uv then
20+ VENV_DIR = " .venv"
21+ else
22+ VENV_DIR = " venv"
23+ end
1924
2025--- @async
2126--- @param candidates string[]
2227local function resolve_python3 (candidates )
2328 local is_executable = _ .compose (_ .equals (1 ), vim .fn .executable )
2429 a .scheduler ()
25- if use_uv then
26- candidates = { " uv" }
27- end
2830 local available_candidates = _ .filter (is_executable , candidates )
31+ vim .print (" starting resolve_python3" )
2932 for __ , candidate in ipairs (available_candidates ) do
30- --- @type string
31- local version_output = spawn [candidate ]({ " --version" }):map (_ .prop " stdout" ):get_or_else " "
32- local ok , version
33- if use_uv then
34- ok , version = pcall (semver .new , version_output :match " uv (%d+.%d+.%d+)" )
35- else
36- ok , version = pcall (semver .new , version_output :match " Python (3%.%d+.%d+)" )
37- end
38- if ok then
39- return { executable = candidate , version = version }
33+ if use_uv and candidate == " uv" then
34+ --- @type string
35+ vim .print (" Calling uv" )
36+ local version_output = spawn [candidate ]({ " --version" }):map (_ .prop " stdout" ):get_or_else " "
37+ vim .print (" Got version output" .. version_output )
38+ local ok , version = pcall (semver .new , version_output :match " uv (%d+.%d+.%d+).*" )
39+ vim .print (" Ok is " .. tostring (ok ))
40+ vim .print (" Version is " .. tostring (version ))
41+ if ok then
42+ vim .print (" Returning" )
43+ return { executable = candidate , version = version }
44+ end
45+ elseif not use_uv then
46+ --- @type string
47+ local version_output = spawn [candidate ]({ " --version" }):map (_ .prop " stdout" ):get_or_else " "
48+ local ok , version = pcall (semver .new , version_output :match " Python (3%.%d+.%d+)" )
49+ if ok then
50+ return { executable = candidate , version = version }
51+ end
4052 end
4153 end
4254 return nil
4658--- @param specifiers string
4759local function pep440_check_version (version , specifiers )
4860 -- The version check only implements a subset of the PEP440 specification and may error with certain inputs.
61+ vim .print (" starting pep440" )
4962 local ok , result = pcall (pep440 .check_version , version , specifiers )
5063 if not ok then
5164 log .fmt_warn (
6174
6275--- @param supported_python_versions string
6376local function get_versioned_candidates (supported_python_versions )
77+ vim .print (" starting get_versioned_candidates" )
6478 return _ .filter_map (function (pair )
6579 local version , executable = unpack (pair )
6680 if not pep440_check_version (tostring (version ), supported_python_versions ) then
@@ -71,29 +85,30 @@ local function get_versioned_candidates(supported_python_versions)
7185 { semver .new " 3.12.0" , " python3.12" },
7286 { semver .new " 3.11.0" , " python3.11" },
7387 { semver .new " 3.10.0" , " python3.10" },
74- { semver .new " 3.9.0" , " python3.9" },
75- { semver .new " 3.8.0" , " python3.8" },
76- { semver .new " 3.7.0" , " python3.7" },
77- { semver .new " 3.6.0" , " python3.6" },
88+ { semver .new " 3.9.0" , " python3.9" },
89+ { semver .new " 3.8.0" , " python3.8" },
90+ { semver .new " 3.7.0" , " python3.7" },
91+ { semver .new " 3.6.0" , " python3.6" },
7892 })
7993end
8094
8195--- @async
8296--- @param pkg { name : string , version : string }
8397local function create_venv (pkg )
98+ vim .print (" starting create_venv" )
8499 local ctx = installer .context ()
85100 --- @type string ?
86101 local supported_python_versions = providers .pypi .get_supported_python_versions (pkg .name , pkg .version ):get_or_nil ()
87102
88103 -- 1. Resolve stock python3 installation.
89- local stock_candidates = platform .is .win and { " python" , " python3" } or { " python3" , " python" }
104+ local stock_candidates = platform .is .win and { " python" , " python3" , " uv " } or { " python3" , " python" , " uv " }
90105 local stock_target = resolve_python3 (stock_candidates )
91106 if stock_target then
92107 log .fmt_debug (" Resolved stock python3 installation version %s" , stock_target .version )
93108 end
94109
95110 -- 2. Resolve suitable versioned python3 installation (python3.12, python3.11, etc.).
96- local versioned_candidates = {}
111+ local versioned_candidates = { " uv " }
97112 if supported_python_versions ~= nil then
98113 if stock_target and not pep440_check_version (tostring (stock_target .version ), supported_python_versions ) then
99114 log .fmt_debug (" Finding versioned candidates for %s" , supported_python_versions )
@@ -113,32 +128,35 @@ local function create_venv(pkg)
113128 -- 3. If a versioned python3 installation was not found, warn the user if the stock python3 installation is outside
114129 -- the supported version range.
115130 if
116- target == stock_target
131+ use_uv == false
132+ and target == stock_target
117133 and supported_python_versions ~= nil
118134 and not pep440_check_version (tostring (target .version ), supported_python_versions )
119135 then
120136 if ctx .opts .force then
121137 ctx .stdio_sink .stderr (
122- (" Warning: The resolved python3 version %s is not compatible with the required Python versions: %s.\n " ):format (
138+ (" Warning: The resolved python3 version %s is not compatible with the required Python versions: %s.\n " )
139+ :format (
123140 target .version ,
124141 supported_python_versions
125142 )
126143 )
127144 else
128145 ctx .stdio_sink .stderr " Run with :MasonInstall --force to bypass this version validation.\n "
129146 return Result .failure (
130- (" Failed to find a python3 installation in PATH that meets the required versions (%s). Found version: %s." ):format (
147+ (" Failed to find a python3 installation in PATH that meets the required versions (%s). Found version: %s." )
148+ :format (
131149 supported_python_versions ,
132150 target .version
133151 )
134152 )
135153 end
136154 end
137155
138- log .fmt_debug (" Found python3 installation version=%s, executable=%s" , target .version , target .executable )
139156 ctx .stdio_sink .stdout " Creating virtual environment…\n "
140-
157+ print ( vim . inspect ( " Creating virtualenv " ))
141158 if use_uv then
159+ print (vim .inspect (" with uv" ))
142160 log .fmt_debug (" Found uv installation version=%s, executable=%s" , target .version , target .executable )
143161 return ctx .spawn [target .executable ] { " venv" , VENV_DIR }
144162 else
170188--- @param args SpawnArgs
171189local function venv_python (args )
172190 local ctx = installer .context ()
191+ if use_uv then
192+ return ctx .spawn [{ " uv" , " venv" }](args )
193+ end
173194 return find_venv_executable (ctx , " python" ):and_then (function (python_path )
174195 return ctx .spawn [path .concat { ctx .cwd :get (), python_path }](args )
175196 end )
@@ -181,14 +202,14 @@ end
181202local function pip_install (pkgs , extra_args )
182203 if use_uv then
183204 local ctx = installer .context ()
205+
184206 local task = ctx .spawn [" uv" ] {
185207 " pip" ,
186208 " install" ,
187209 " -U" ,
188210 extra_args or vim .NIL ,
189211 pkgs ,
190212 }
191- -- vim.api.nvim_set_current_dir(curdir)
192213 return task
193214 else
194215 return venv_python {
0 commit comments