@@ -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 (
@@ -214,6 +216,9 @@ export class VenvManager implements EnvironmentManager {
214216 }
215217 }
216218
219+ /**
220+ * Removes the specified Python environment, updates internal collections, and fires change events as needed.
221+ */
217222 async remove ( environment : PythonEnvironment ) : Promise < void > {
218223 try {
219224 this . skipWatcherRefresh = true ;
@@ -467,6 +472,9 @@ export class VenvManager implements EnvironmentManager {
467472 await this . loadGlobalEnv ( globals ) ;
468473 }
469474
475+ /**
476+ * Loads and sets the global Python environment from the provided list, resolving if necessary. O(g) where g = globals.length
477+ */
470478 private async loadGlobalEnv ( globals : PythonEnvironment [ ] ) {
471479 this . globalEnv = undefined ;
472480
@@ -499,30 +507,28 @@ export class VenvManager implements EnvironmentManager {
499507 }
500508 }
501509
510+ /**
511+ * 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
512+ */
502513 private async loadEnvMap ( ) {
503514 const globals = await this . baseManager . getEnvironments ( 'global' ) ;
504515 await this . loadGlobalEnv ( globals ) ;
505516
506517 this . fsPathToEnv . clear ( ) ;
507518
508519 const sorted = sortEnvironments ( this . collection ) ;
509- const paths = this . api . getPythonProjects ( ) . map ( ( p ) => path . normalize ( p . uri . fsPath ) ) ;
520+ const projectPaths = this . api . getPythonProjects ( ) . map ( ( p ) => path . normalize ( p . uri . fsPath ) ) ;
510521 const events : ( ( ) => void ) [ ] = [ ] ;
511- for ( const p of paths ) {
522+ // Iterates through all workspace projects
523+ for ( const p of projectPaths ) {
512524 const env = await getVenvForWorkspace ( p ) ;
513-
514525 if ( env ) {
515- const found = this . findEnvironmentByPath ( env , sorted ) ?? this . findEnvironmentByPath ( env , globals ) ;
516- const previous = this . fsPathToEnv . get ( p ) ;
526+ // from env path find PythonEnvironment object in the collection.
527+ let foundEnv = this . findEnvironmentByPath ( env , sorted ) ?? this . findEnvironmentByPath ( env , globals ) ;
528+ const previousEnv = this . fsPathToEnv . get ( p ) ;
517529 const pw = this . api . getPythonProject ( Uri . file ( p ) ) ;
518- if ( found ) {
519- this . fsPathToEnv . set ( p , found ) ;
520- if ( pw && previous ?. envId . id !== found . envId . id ) {
521- events . push ( ( ) =>
522- this . _onDidChangeEnvironment . fire ( { uri : pw . uri , old : undefined , new : found } ) ,
523- ) ;
524- }
525- } else {
530+ if ( ! foundEnv ) {
531+ // attempt to resolve
526532 const resolved = await resolveVenvPythonEnvironmentPath (
527533 env ,
528534 this . nativeFinder ,
@@ -531,39 +537,39 @@ export class VenvManager implements EnvironmentManager {
531537 this . baseManager ,
532538 ) ;
533539 if ( resolved ) {
534- // If resolved add it to the collection
535- this . fsPathToEnv . set ( p , resolved ) ;
540+ // If resolved; add it to the venvManager collection
536541 this . addEnvironment ( resolved , false ) ;
537- if ( pw && previous ?. envId . id !== resolved . envId . id ) {
538- events . push ( ( ) =>
539- this . _onDidChangeEnvironment . fire ( { uri : pw . uri , old : undefined , new : resolved } ) ,
540- ) ;
541- }
542+ foundEnv = resolved ;
542543 } else {
543544 this . log . error ( `Failed to resolve python environment: ${ env } ` ) ;
545+ return ;
544546 }
545547 }
548+ // Given found env, add it to the map and fire the event if needed.
549+ this . fsPathToEnv . set ( p , foundEnv ) ;
550+ if ( pw && previousEnv ?. envId . id !== foundEnv . envId . id ) {
551+ events . push ( ( ) =>
552+ this . _onDidChangeEnvironment . fire ( { uri : pw . uri , old : undefined , new : foundEnv } ) ,
553+ ) ;
554+ }
546555 } else {
547- // There is NO selected venv, then try and choose the venv that is in the workspace.
548- if ( sorted . length === 1 ) {
549- this . fsPathToEnv . set ( p , sorted [ 0 ] ) ;
550- } else {
551- // These are sorted by version and by path length. The assumption is that the user would want to pick
552- // latest version and the one that is closest to the workspace.
553- const found = sorted . find ( ( e ) => {
554- const t = this . api . getPythonProject ( e . environmentPath ) ?. uri . fsPath ;
555- return t && path . normalize ( t ) === p ;
556- } ) ;
557- if ( found ) {
558- this . fsPathToEnv . set ( p , found ) ;
559- }
556+ // 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.
557+ const found = sorted . find ( ( e ) => {
558+ const t = this . api . getPythonProject ( e . environmentPath ) ?. uri . fsPath ;
559+ return t && path . normalize ( t ) === p ;
560+ } ) ;
561+ if ( found ) {
562+ this . fsPathToEnv . set ( p , found ) ;
560563 }
561564 }
562565 }
563566
564567 events . forEach ( ( e ) => e ( ) ) ;
565568 }
566569
570+ /**
571+ * Finds a PythonEnvironment in the given collection (or all environments) that matches the provided file system path. O(e) where e = environments.len
572+ */
567573 private findEnvironmentByPath ( fsPath : string , collection ?: PythonEnvironment [ ] ) : PythonEnvironment | undefined {
568574 const normalized = path . normalize ( fsPath ) ;
569575 const envs = collection ?? this . collection ;
@@ -573,6 +579,10 @@ export class VenvManager implements EnvironmentManager {
573579 } ) ;
574580 }
575581
582+ /**
583+ * Returns all Python projects associated with the given environment.
584+ * O(p), where p is project.len
585+ */
576586 public getProjectsByEnvironment ( environment : PythonEnvironment ) : PythonProject [ ] {
577587 const projects : PythonProject [ ] = [ ] ;
578588 this . fsPathToEnv . forEach ( ( env , fsPath ) => {
0 commit comments