@@ -103,11 +103,13 @@ export class VenvManager implements EnvironmentManager {
103103 }
104104 }
105105
106+ /**
107+ * Returns configuration for quick create in the workspace root, undefined if no suitable Python 3 version is found.
108+ */
106109 quickCreateConfig ( ) : QuickCreateConfig | undefined {
107110 if ( ! this . globalEnv || ! this . globalEnv . version . startsWith ( '3.' ) ) {
108111 return undefined ;
109112 }
110-
111113 return {
112114 description : l10n . t ( 'Create a virtual environment in workspace root' ) ,
113115 detail : l10n . t (
@@ -217,6 +219,9 @@ export class VenvManager implements EnvironmentManager {
217219 }
218220 }
219221
222+ /**
223+ * Removes the specified Python environment, updates internal collections, and fires change events as needed.
224+ */
220225 async remove ( environment : PythonEnvironment ) : Promise < void > {
221226 try {
222227 this . skipWatcherRefresh = true ;
@@ -470,6 +475,9 @@ export class VenvManager implements EnvironmentManager {
470475 await this . loadGlobalEnv ( globals ) ;
471476 }
472477
478+ /**
479+ * Loads and sets the global Python environment from the provided list, resolving if necessary. O(g) where g = globals.length
480+ */
473481 private async loadGlobalEnv ( globals : PythonEnvironment [ ] ) {
474482 this . globalEnv = undefined ;
475483
@@ -502,30 +510,28 @@ export class VenvManager implements EnvironmentManager {
502510 }
503511 }
504512
513+ /**
514+ * Loads and maps Python environments to their corresponding project paths in the workspace. about O(p × e) where p = projects.len and e = environments.len
515+ */
505516 private async loadEnvMap ( ) {
506517 const globals = await this . baseManager . getEnvironments ( 'global' ) ;
507518 await this . loadGlobalEnv ( globals ) ;
508519
509520 this . fsPathToEnv . clear ( ) ;
510521
511522 const sorted = sortEnvironments ( this . collection ) ;
512- const paths = this . api . getPythonProjects ( ) . map ( ( p ) => path . normalize ( p . uri . fsPath ) ) ;
523+ const projectPaths = this . api . getPythonProjects ( ) . map ( ( p ) => path . normalize ( p . uri . fsPath ) ) ;
513524 const events : ( ( ) => void ) [ ] = [ ] ;
514- for ( const p of paths ) {
525+ // Iterates through all workspace projects
526+ for ( const p of projectPaths ) {
515527 const env = await getVenvForWorkspace ( p ) ;
516-
517528 if ( env ) {
518- const found = this . findEnvironmentByPath ( env , sorted ) ?? this . findEnvironmentByPath ( env , globals ) ;
519- const previous = this . fsPathToEnv . get ( p ) ;
529+ // from env path find PythonEnvironment object in the collection.
530+ let foundEnv = this . findEnvironmentByPath ( env , sorted ) ?? this . findEnvironmentByPath ( env , globals ) ;
531+ const previousEnv = this . fsPathToEnv . get ( p ) ;
520532 const pw = this . api . getPythonProject ( Uri . file ( p ) ) ;
521- if ( found ) {
522- this . fsPathToEnv . set ( p , found ) ;
523- if ( pw && previous ?. envId . id !== found . envId . id ) {
524- events . push ( ( ) =>
525- this . _onDidChangeEnvironment . fire ( { uri : pw . uri , old : undefined , new : found } ) ,
526- ) ;
527- }
528- } else {
533+ if ( ! foundEnv ) {
534+ // attempt to resolve
529535 const resolved = await resolveVenvPythonEnvironmentPath (
530536 env ,
531537 this . nativeFinder ,
@@ -534,39 +540,39 @@ export class VenvManager implements EnvironmentManager {
534540 this . baseManager ,
535541 ) ;
536542 if ( resolved ) {
537- // If resolved add it to the collection
538- this . fsPathToEnv . set ( p , resolved ) ;
543+ // If resolved; add it to the venvManager collection
539544 this . addEnvironment ( resolved , false ) ;
540- if ( pw && previous ?. envId . id !== resolved . envId . id ) {
541- events . push ( ( ) =>
542- this . _onDidChangeEnvironment . fire ( { uri : pw . uri , old : undefined , new : resolved } ) ,
543- ) ;
544- }
545+ foundEnv = resolved ;
545546 } else {
546547 this . log . error ( `Failed to resolve python environment: ${ env } ` ) ;
548+ return ;
547549 }
548550 }
551+ // Given found env, add it to the map and fire the event if needed.
552+ this . fsPathToEnv . set ( p , foundEnv ) ;
553+ if ( pw && previousEnv ?. envId . id !== foundEnv . envId . id ) {
554+ events . push ( ( ) =>
555+ this . _onDidChangeEnvironment . fire ( { uri : pw . uri , old : undefined , new : foundEnv } ) ,
556+ ) ;
557+ }
549558 } else {
550- // There is NO selected venv, then try and choose the venv that is in the workspace.
551- if ( sorted . length === 1 ) {
552- this . fsPathToEnv . set ( p , sorted [ 0 ] ) ;
553- } else {
554- // These are sorted by version and by path length. The assumption is that the user would want to pick
555- // latest version and the one that is closest to the workspace.
556- const found = sorted . find ( ( e ) => {
557- const t = this . api . getPythonProject ( e . environmentPath ) ?. uri . fsPath ;
558- return t && path . normalize ( t ) === p ;
559- } ) ;
560- if ( found ) {
561- this . fsPathToEnv . set ( p , found ) ;
562- }
559+ // Search through all known environments (e) and check if any are associated with the current project path. If so, add that environment and path in the map.
560+ const found = sorted . find ( ( e ) => {
561+ const t = this . api . getPythonProject ( e . environmentPath ) ?. uri . fsPath ;
562+ return t && path . normalize ( t ) === p ;
563+ } ) ;
564+ if ( found ) {
565+ this . fsPathToEnv . set ( p , found ) ;
563566 }
564567 }
565568 }
566569
567570 events . forEach ( ( e ) => e ( ) ) ;
568571 }
569572
573+ /**
574+ * Finds a PythonEnvironment in the given collection (or all environments) that matches the provided file system path. O(e) where e = environments.len
575+ */
570576 private findEnvironmentByPath ( fsPath : string , collection ?: PythonEnvironment [ ] ) : PythonEnvironment | undefined {
571577 const normalized = path . normalize ( fsPath ) ;
572578 const envs = collection ?? this . collection ;
@@ -576,6 +582,10 @@ export class VenvManager implements EnvironmentManager {
576582 } ) ;
577583 }
578584
585+ /**
586+ * Returns all Python projects associated with the given environment.
587+ * O(p), where p is project.len
588+ */
579589 public getProjectsByEnvironment ( environment : PythonEnvironment ) : PythonProject [ ] {
580590 const projects : PythonProject [ ] = [ ] ;
581591 this . fsPathToEnv . forEach ( ( env , fsPath ) => {
0 commit comments