@@ -10,6 +10,7 @@ import { getWorkspaceStateValue, updateWorkspaceStateValue } from '../../common/
1010import { traceError } from '../../logging' ;
1111import { IExtensionActivationService } from '../../activation/types' ;
1212import { StopWatch } from '../../common/utils/stopWatch' ;
13+ import { isParentPath } from '../../common/platform/fs-paths' ;
1314
1415const MEMENTO_KEY = 'userSelectedEnvPath' ;
1516
@@ -75,13 +76,24 @@ export class RecommendedEnvironmentService implements IRecommendedEnvironmentSer
7576 if ( recommendedEnv ) {
7677 return { environment : recommendedEnv , reason : preferred . reason } ;
7778 }
79+ const globalEnv = await this . api . resolveEnvironment ( this . api . getActiveEnvironmentPath ( ) ) ;
80+ if ( activeEnv && globalEnv ?. path !== activeEnv ?. path ) {
81+ // User has definitely got a workspace specific environment selected.
82+ // Given the fact that global !== workspace env, we can safely assume that
83+ // at some time, the user has selected a workspace specific environment.
84+ // This applies to cases where the user has selected a workspace specific environment before this version of the extension
85+ // and we did not store it in the workspace state.
86+ // So we can safely return the global environment as the recommended environment.
87+ return { environment : activeEnv , reason : 'workspaceUserSelected' } ;
88+ }
7889 return undefined ;
7990 }
80- getRecommededInternal (
91+ async getRecommededInternal (
8192 resource : Resource ,
82- ) :
93+ ) : Promise <
8394 | { environmentPath : string ; reason : 'globalUserSelected' | 'workspaceUserSelected' | 'defaultRecommended' }
84- | undefined {
95+ | undefined
96+ > {
8597 let workspaceState : string | undefined = undefined ;
8698 try {
8799 workspaceState = getWorkspaceStateValue < string > ( MEMENTO_KEY ) ;
@@ -106,6 +118,16 @@ export class RecommendedEnvironmentService implements IRecommendedEnvironmentSer
106118 }
107119 }
108120
121+ if ( workspace . workspaceFolders ?. length && this . api ) {
122+ // Check if we have a .venv or .conda environment in the workspace
123+ // This is required for cases where user has selected a workspace specific environment
124+ // but before this version of the extension, we did not store it in the workspace state.
125+ const workspaceEnv = await getWorkspaceSpecificVirtualEnvironment ( this . api , resource ) ;
126+ if ( workspaceEnv ) {
127+ return { environmentPath : workspaceEnv . path , reason : 'workspaceUserSelected' } ;
128+ }
129+ }
130+
109131 const globalSelectedEnvPath = this . extensionContext . globalState . get < string | undefined > ( MEMENTO_KEY ) ;
110132 if ( globalSelectedEnvPath ) {
111133 return { environmentPath : globalSelectedEnvPath , reason : 'globalUserSelected' } ;
@@ -119,6 +141,37 @@ export class RecommendedEnvironmentService implements IRecommendedEnvironmentSer
119141 }
120142}
121143
144+ async function getWorkspaceSpecificVirtualEnvironment ( api : PythonExtension [ 'environments' ] , resource : Resource ) {
145+ const workspaceUri =
146+ ( resource ? workspace . getWorkspaceFolder ( resource ) ?. uri : undefined ) ||
147+ ( workspace . workspaceFolders ?. length ? workspace . workspaceFolders [ 0 ] . uri : undefined ) ;
148+ if ( ! workspaceUri ) {
149+ return undefined ;
150+ }
151+ let workspaceEnv = api . known . find ( ( env ) => {
152+ if ( ! env . environment ?. folderUri ) {
153+ return false ;
154+ }
155+ if ( env . environment . type !== 'VirtualEnvironment' && env . environment . type !== 'Conda' ) {
156+ return false ;
157+ }
158+ return isParentPath ( env . environment . folderUri . fsPath , workspaceUri . fsPath ) ;
159+ } ) ;
160+ let resolvedEnv = workspaceEnv ? api . resolveEnvironment ( workspaceEnv ) : undefined ;
161+ if ( resolvedEnv ) {
162+ return resolvedEnv ;
163+ }
164+ workspaceEnv = api . known . find ( ( env ) => {
165+ // Look for any other type of env thats inside this workspace
166+ // Or look for an env thats associated with this workspace (pipenv or the like).
167+ return (
168+ ( env . environment ?. folderUri && isParentPath ( env . environment . folderUri . fsPath , workspaceUri . fsPath ) ) ||
169+ ( env . environment ?. workspaceFolder && env . environment . workspaceFolder . uri . fsPath === workspaceUri . fsPath )
170+ ) ;
171+ } ) ;
172+ return workspaceEnv ? api . resolveEnvironment ( workspaceEnv ) : undefined ;
173+ }
174+
122175function getDataToStore ( environmentPath : string | undefined , uri : Uri | undefined ) : string | undefined {
123176 if ( ! workspace . workspaceFolders ?. length ) {
124177 return environmentPath ;
0 commit comments