77 TaskRevealKind ,
88 TaskScope ,
99} from 'vscode' ;
10- import { PythonEnvironmentApi } from '../../api' ;
1110import { spawnProcess } from '../../common/childProcess.apis' ;
1211import { UvInstallStrings } from '../../common/localize' ;
1312import { traceError , traceInfo , traceLog } from '../../common/logging' ;
@@ -141,6 +140,27 @@ export async function installUv(_log?: LogOutputChannel): Promise<boolean> {
141140 return success ;
142141}
143142
143+ /**
144+ * Gets the path to the uv-managed Python installation.
145+ * @returns Promise that resolves to the Python path, or undefined if not found
146+ */
147+ export async function getUvPythonPath ( ) : Promise < string | undefined > {
148+ return new Promise ( ( resolve ) => {
149+ const chunks : string [ ] = [ ] ;
150+ const proc = spawnProcess ( 'uv' , [ 'python' , 'find' ] ) ;
151+ proc . stdout ?. on ( 'data' , ( data ) => chunks . push ( data . toString ( ) ) ) ;
152+ proc . on ( 'error' , ( ) => resolve ( undefined ) ) ;
153+ proc . on ( 'exit' , ( code ) => {
154+ if ( code === 0 && chunks . length > 0 ) {
155+ const pythonPath = chunks . join ( '' ) . trim ( ) ;
156+ resolve ( pythonPath || undefined ) ;
157+ } else {
158+ resolve ( undefined ) ;
159+ }
160+ } ) ;
161+ } ) ;
162+ }
163+
144164/**
145165 * Installs Python using uv.
146166 * @param log Optional log output channel
@@ -171,21 +191,19 @@ export async function installPythonViaUv(_log?: LogOutputChannel, version?: stri
171191 * Respects the "Don't ask again" setting.
172192 *
173193 * @param trigger What triggered this prompt ('activation' or 'createEnvironment')
174- * @param api The Python environment API (used to refresh environments after installation)
175194 * @param log Optional log output channel
176- * @returns Promise that resolves to true if Python was successfully installed
195+ * @returns Promise that resolves to the installed Python path, or undefined if not installed
177196 */
178197export async function promptInstallPythonViaUv (
179198 trigger : 'activation' | 'createEnvironment' ,
180- api : PythonEnvironmentApi ,
181199 log ?: LogOutputChannel ,
182- ) : Promise < boolean > {
200+ ) : Promise < string | undefined > {
183201 const state = await getGlobalPersistentState ( ) ;
184202 const dontAsk = await state . get < boolean > ( UV_INSTALL_PYTHON_DONT_ASK_KEY ) ;
185203
186204 if ( dontAsk ) {
187205 traceLog ( 'Skipping Python install prompt: user selected "Don\'t ask again"' ) ;
188- return false ;
206+ return undefined ;
189207 }
190208
191209 sendTelemetryEvent ( EventNames . UV_PYTHON_INSTALL_PROMPTED , undefined , { trigger } ) ;
@@ -205,25 +223,24 @@ export async function promptInstallPythonViaUv(
205223 if ( result === UvInstallStrings . dontAskAgain ) {
206224 await state . set ( UV_INSTALL_PYTHON_DONT_ASK_KEY , true ) ;
207225 traceLog ( 'User selected "Don\'t ask again" for Python install prompt' ) ;
208- return false ;
226+ return undefined ;
209227 }
210228
211229 if ( result === UvInstallStrings . installPython ) {
212- return await installPythonWithUv ( api , log ) ;
230+ return await installPythonWithUv ( log ) ;
213231 }
214232
215- return false ;
233+ return undefined ;
216234}
217235
218236/**
219237 * Installs Python using uv. If uv is not installed, installs it first.
220238 * This is the main entry point for programmatic Python installation.
221239 *
222- * @param api The Python environment API (used to refresh environments after installation)
223240 * @param log Optional log output channel
224- * @returns Promise that resolves to true if Python was successfully installed
241+ * @returns Promise that resolves to the installed Python path, or undefined on failure
225242 */
226- export async function installPythonWithUv ( api : PythonEnvironmentApi , log ?: LogOutputChannel ) : Promise < boolean > {
243+ export async function installPythonWithUv ( log ?: LogOutputChannel ) : Promise < string | undefined > {
227244 const uvInstalled = await isUvInstalled ( log ) ;
228245
229246 sendTelemetryEvent ( EventNames . UV_PYTHON_INSTALL_STARTED , undefined , { uvAlreadyInstalled : uvInstalled } ) ;
@@ -243,7 +260,7 @@ export async function installPythonWithUv(api: PythonEnvironmentApi, log?: LogOu
243260 if ( ! uvSuccess ) {
244261 sendTelemetryEvent ( EventNames . UV_PYTHON_INSTALL_FAILED , undefined , { stage : 'uvInstall' } ) ;
245262 showErrorMessage ( UvInstallStrings . uvInstallFailed ) ;
246- return false ;
263+ return undefined ;
247264 }
248265 }
249266
@@ -252,17 +269,23 @@ export async function installPythonWithUv(api: PythonEnvironmentApi, log?: LogOu
252269 if ( ! pythonSuccess ) {
253270 sendTelemetryEvent ( EventNames . UV_PYTHON_INSTALL_FAILED , undefined , { stage : 'pythonInstall' } ) ;
254271 showErrorMessage ( UvInstallStrings . installFailed ) ;
255- return false ;
272+ return undefined ;
256273 }
257274
258- // Step 3: Refresh environments to detect newly installed Python
259- traceInfo ( 'Refreshing environments after Python installation...' ) ;
260- await api . refreshEnvironments ( undefined ) ;
275+ // Step 3: Get the installed Python path using uv python find
276+ const pythonPath = await getUvPythonPath ( ) ;
277+ if ( ! pythonPath ) {
278+ traceError ( 'Python installed but could not find the path via uv python find' ) ;
279+ sendTelemetryEvent ( EventNames . UV_PYTHON_INSTALL_FAILED , undefined , { stage : 'findPath' } ) ;
280+ showErrorMessage ( UvInstallStrings . installFailed ) ;
281+ return undefined ;
282+ }
261283
284+ traceInfo ( `Python installed successfully at: ${ pythonPath } ` ) ;
262285 sendTelemetryEvent ( EventNames . UV_PYTHON_INSTALL_COMPLETED ) ;
263- showInformationMessage ( UvInstallStrings . installComplete ) ;
286+ showInformationMessage ( UvInstallStrings . installCompleteWithPath ( pythonPath ) ) ;
264287
265- return true ;
288+ return pythonPath ;
266289 } ,
267290 ) ;
268291}
0 commit comments