@@ -56,10 +56,18 @@ export async function clearPipenvCache(): Promise<void> {
5656 * This allows the manager to be registered even if the CLI is not found.
5757 */
5858export async function hasPipenvEnvironments ( nativeFinder : NativePythonFinder ) : Promise < boolean > {
59- const data = await nativeFinder . refresh ( false ) ;
60- return data
61- . filter ( ( e ) => isNativeEnvInfo ( e ) )
62- . some ( ( e ) => ( e as NativeEnvInfo ) . kind === NativePythonEnvironmentKind . pipenv ) ;
59+ let stage = 'nativeFinderRefresh' ;
60+ try {
61+ const data = await nativeFinder . refresh ( false ) ;
62+ stage = 'filterPipenvEnvs' ;
63+ return data
64+ . filter ( ( e ) => isNativeEnvInfo ( e ) )
65+ . some ( ( e ) => ( e as NativeEnvInfo ) . kind === NativePythonEnvironmentKind . pipenv ) ;
66+ } catch ( ex ) {
67+ const err = ex instanceof Error ? ex : new Error ( String ( ex ) ) ;
68+ ( err as Error & { failureStage ?: string } ) . failureStage = `hasPipenvEnvironments:${ stage } ` ;
69+ throw err ;
70+ }
6371}
6472
6573function getPipenvPathFromSettings ( ) : string | undefined {
@@ -68,61 +76,78 @@ function getPipenvPathFromSettings(): string | undefined {
6876}
6977
7078export async function getPipenv ( native ?: NativePythonFinder ) : Promise < string | undefined > {
71- // Priority 1: Settings (if explicitly set and valid)
72- const settingPath = getPipenvPathFromSettings ( ) ;
73- if ( settingPath ) {
74- if ( await fs . exists ( untildify ( settingPath ) ) ) {
75- traceInfo ( `Using pipenv from settings: ${ settingPath } ` ) ;
76- return untildify ( settingPath ) ;
79+ let stage = 'checkSettings' ;
80+ try {
81+ // Priority 1: Settings (if explicitly set and valid)
82+ const settingPath = getPipenvPathFromSettings ( ) ;
83+ if ( settingPath ) {
84+ stage = 'validateSettingsPath' ;
85+ if ( await fs . exists ( untildify ( settingPath ) ) ) {
86+ traceInfo ( `Using pipenv from settings: ${ settingPath } ` ) ;
87+ return untildify ( settingPath ) ;
88+ }
89+ traceInfo ( `Pipenv path from settings does not exist: ${ settingPath } ` ) ;
7790 }
78- traceInfo ( `Pipenv path from settings does not exist: ${ settingPath } ` ) ;
79- }
8091
81- // Priority 2: In-memory cache
82- if ( pipenvPath ) {
83- if ( await fs . exists ( untildify ( pipenvPath ) ) ) {
84- return untildify ( pipenvPath ) ;
92+ // Priority 2: In-memory cache
93+ stage = 'checkCache' ;
94+ if ( pipenvPath ) {
95+ stage = 'validateCachePath' ;
96+ if ( await fs . exists ( untildify ( pipenvPath ) ) ) {
97+ return untildify ( pipenvPath ) ;
98+ }
99+ pipenvPath = undefined ;
85100 }
86- pipenvPath = undefined ;
87- }
88101
89- // Priority 3: Persistent state
90- const state = await getWorkspacePersistentState ( ) ;
91- const storedPath = await state . get < string > ( PIPENV_PATH_KEY ) ;
92- if ( storedPath ) {
93- if ( await fs . exists ( untildify ( storedPath ) ) ) {
94- pipenvPath = storedPath ;
95- traceInfo ( `Using pipenv from persistent state: ${ pipenvPath } ` ) ;
96- return untildify ( pipenvPath ) ;
102+ // Priority 3: Persistent state
103+ stage = 'getPersistentState' ;
104+ const state = await getWorkspacePersistentState ( ) ;
105+ stage = 'checkPersistentState' ;
106+ const storedPath = await state . get < string > ( PIPENV_PATH_KEY ) ;
107+ if ( storedPath ) {
108+ stage = 'validatePersistentStatePath' ;
109+ if ( await fs . exists ( untildify ( storedPath ) ) ) {
110+ pipenvPath = storedPath ;
111+ traceInfo ( `Using pipenv from persistent state: ${ pipenvPath } ` ) ;
112+ return untildify ( pipenvPath ) ;
113+ }
114+ await state . set ( PIPENV_PATH_KEY , undefined ) ;
97115 }
98- await state . set ( PIPENV_PATH_KEY , undefined ) ;
99- }
100116
101- // Priority 4: PATH lookup
102- const foundPipenv = await findPipenv ( ) ;
103- if ( foundPipenv ) {
104- pipenvPath = foundPipenv ;
105- traceInfo ( `Found pipenv in PATH: ${ foundPipenv } ` ) ;
106- return foundPipenv ;
107- }
117+ // Priority 4: PATH lookup
118+ stage = 'pathLookup' ;
119+ const foundPipenv = await findPipenv ( ) ;
120+ if ( foundPipenv ) {
121+ pipenvPath = foundPipenv ;
122+ traceInfo ( `Found pipenv in PATH: ${ foundPipenv } ` ) ;
123+ return foundPipenv ;
124+ }
108125
109- // Priority 5: Native finder as fallback
110- if ( native ) {
111- const data = await native . refresh ( false ) ;
112- const managers = data
113- . filter ( ( e ) => ! isNativeEnvInfo ( e ) )
114- . map ( ( e ) => e as NativeEnvManagerInfo )
115- . filter ( ( e ) => e . tool . toLowerCase ( ) === 'pipenv' ) ;
116- if ( managers . length > 0 ) {
117- pipenvPath = managers [ 0 ] . executable ;
118- traceInfo ( `Using pipenv from native finder: ${ pipenvPath } ` ) ;
119- await state . set ( PIPENV_PATH_KEY , pipenvPath ) ;
120- return pipenvPath ;
126+ // Priority 5: Native finder as fallback
127+ stage = 'nativeFinderRefresh' ;
128+ if ( native ) {
129+ const data = await native . refresh ( false ) ;
130+ stage = 'filterNativeFinderResults' ;
131+ const managers = data
132+ . filter ( ( e ) => ! isNativeEnvInfo ( e ) )
133+ . map ( ( e ) => e as NativeEnvManagerInfo )
134+ . filter ( ( e ) => e . tool . toLowerCase ( ) === 'pipenv' ) ;
135+ if ( managers . length > 0 ) {
136+ pipenvPath = managers [ 0 ] . executable ;
137+ traceInfo ( `Using pipenv from native finder: ${ pipenvPath } ` ) ;
138+ stage = 'persistNativeFinderResult' ;
139+ await state . set ( PIPENV_PATH_KEY , pipenvPath ) ;
140+ return pipenvPath ;
141+ }
121142 }
122- }
123143
124- traceInfo ( 'Pipenv not found' ) ;
125- return undefined ;
144+ traceInfo ( 'Pipenv not found' ) ;
145+ return undefined ;
146+ } catch ( ex ) {
147+ const err = ex instanceof Error ? ex : new Error ( String ( ex ) ) ;
148+ ( err as Error & { failureStage ?: string } ) . failureStage = `getPipenv:${ stage } ` ;
149+ throw err ;
150+ }
126151}
127152
128153async function nativeToPythonEnv (
0 commit comments