@@ -111,6 +111,7 @@ export interface EnvironmentManagers extends Disposable {
111111 */
112112 onDidChangeActiveEnvironment : Event < DidChangeEnvironmentEventArgs > ;
113113 onDidChangePackages : Event < InternalDidChangePackagesEventArgs > ;
114+ onDidChangePackageProviderPackages : Event < DidChangePackagesEventArgs > ;
114115
115116 onDidChangeEnvironmentManager : Event < DidChangeEnvironmentManagerEventArgs > ;
116117 onDidChangePackageManager : Event < DidChangePackageManagerEventArgs > ;
@@ -171,6 +172,11 @@ function generateId(name: string, extensionId?: string): string {
171172export class PythonEnvironmentManagers implements EnvironmentManagers {
172173 private _environmentManagers : Map < string , InternalEnvironmentManager > = new Map ( ) ;
173174 private _packageManagers : Map < string , InternalPackageManager > = new Map ( ) ;
175+ private _projectPackageManagers : Map < string , InternalPackageManager > = new Map ( ) ;
176+ private readonly _packageManagerEventSubscriptions = new Map <
177+ string ,
178+ Map < Event < DidChangePackagesEventArgs > , Disposable >
179+ > ( ) ;
174180 private readonly subscriptions : Disposable [ ] = [ ] ;
175181
176182 /**
@@ -198,6 +204,7 @@ export class PythonEnvironmentManagers implements EnvironmentManagers {
198204 /** Fires when the active (selected) environment for a scope actually changes. */
199205 private _onDidChangeActiveEnvironment = new EventEmitter < DidChangeEnvironmentEventArgs > ( ) ;
200206 private _onDidChangePackages = new EventEmitter < InternalDidChangePackagesEventArgs > ( ) ;
207+ private _onDidChangePackageProviderPackages = new EventEmitter < DidChangePackagesEventArgs > ( ) ;
201208
202209 public onDidChangeEnvironmentManager : Event < DidChangeEnvironmentManagerEventArgs > =
203210 this . _onDidChangeEnvironmentManager . event ;
@@ -208,6 +215,8 @@ export class PythonEnvironmentManagers implements EnvironmentManagers {
208215 public onDidChangeManagerEnvironment : Event < DidChangeEnvironmentEventArgs > =
209216 this . _onDidChangeManagerEnvironment . event ;
210217 public onDidChangePackages : Event < InternalDidChangePackagesEventArgs > = this . _onDidChangePackages . event ;
218+ public onDidChangePackageProviderPackages : Event < DidChangePackagesEventArgs > =
219+ this . _onDidChangePackageProviderPackages . event ;
211220
212221 /** Fires only when the *selected* manager's environment for a scope actually changes. */
213222 public onDidChangeActiveEnvironment : Event < DidChangeEnvironmentEventArgs > =
@@ -301,20 +310,9 @@ export class PythonEnvironmentManagers implements EnvironmentManagers {
301310 traceError ( ex ) ;
302311 throw ex ;
303312 }
304- const disposables : Disposable [ ] = [ ] ;
305313 const mgr = new InternalPackageManager ( managerId , manager ) ;
306314
307- disposables . push (
308- mgr . onDidChangePackages ( ( e : DidChangePackagesEventArgs ) => {
309- setImmediate ( ( ) =>
310- this . _onDidChangePackages . fire ( {
311- environment : e . environment ,
312- manager : mgr ,
313- changes : e . changes ,
314- } ) ,
315- ) ;
316- } ) ,
317- ) ;
315+ this . subscribeToPackageManagerEvents ( mgr , mgr ) ;
318316
319317 this . _packageManagers . set ( managerId , mgr ) ;
320318 this . _onDidChangePackageManager . fire ( { kind : 'registered' , manager : mgr } ) ;
@@ -327,14 +325,23 @@ export class PythonEnvironmentManagers implements EnvironmentManagers {
327325
328326 return new Disposable ( ( ) => {
329327 this . _packageManagers . delete ( managerId ) ;
330- disposables . forEach ( ( d ) => d . dispose ( ) ) ;
328+ for ( const [ key , scopedManager ] of this . _projectPackageManagers ) {
329+ if ( scopedManager . id === managerId ) {
330+ this . _projectPackageManagers . delete ( key ) ;
331+ }
332+ }
333+ this . disposePackageManagerEventSubscriptions ( managerId ) ;
331334 setImmediate ( ( ) => this . _onDidChangePackageManager . fire ( { kind : 'unregistered' , manager : mgr } ) ) ;
332335 } ) ;
333336 }
334337
335338 public dispose ( ) {
336339 this . _environmentManagers . clear ( ) ;
337340 this . _packageManagers . clear ( ) ;
341+ this . _projectPackageManagers . clear ( ) ;
342+ for ( const managerId of this . _packageManagerEventSubscriptions . keys ( ) ) {
343+ this . disposePackageManagerEventSubscriptions ( managerId ) ;
344+ }
338345 this . _inlineRoutingOverrides . clear ( ) ;
339346 this . subscriptions . forEach ( ( subscription ) => subscription . dispose ( ) ) ;
340347 this . _onDidChangeEnvironmentManager . dispose ( ) ;
@@ -343,6 +350,7 @@ export class PythonEnvironmentManagers implements EnvironmentManagers {
343350 this . _onDidChangeManagerEnvironment . dispose ( ) ;
344351 this . _onDidChangeActiveEnvironment . dispose ( ) ;
345352 this . _onDidChangePackages . dispose ( ) ;
353+ this . _onDidChangePackageProviderPackages . dispose ( ) ;
346354 }
347355
348356 /**
@@ -407,17 +415,21 @@ export class PythonEnvironmentManagers implements EnvironmentManagers {
407415 }
408416
409417 if ( context === undefined || context instanceof Uri ) {
418+ const project = context ? this . pm . get ( context ) : undefined ;
410419 const defaultPkgManagerId = getDefaultPkgManagerSetting ( this . pm , context ) ;
411420 const defaultEnvManagerId = getDefaultEnvManagerSetting ( this . pm , context ) ;
412421 if ( defaultPkgManagerId ) {
413- return this . _packageManagers . get ( defaultPkgManagerId ) ;
422+ return this . getProjectPackageManager ( this . _packageManagers . get ( defaultPkgManagerId ) , project ) ;
414423 }
415424
416425 if ( defaultEnvManagerId ) {
417426 const preferredPkgManagerId =
418427 this . _environmentManagers . get ( defaultEnvManagerId ) ?. preferredPackageManagerId ;
419428 if ( preferredPkgManagerId ) {
420- return this . _packageManagers . get ( preferredPkgManagerId ) ;
429+ return this . getProjectPackageManager (
430+ this . _packageManagers . get ( preferredPkgManagerId ) ,
431+ project ,
432+ ) ;
421433 }
422434 }
423435 return undefined ;
@@ -439,6 +451,69 @@ export class PythonEnvironmentManagers implements EnvironmentManagers {
439451 return undefined ;
440452 }
441453
454+ private getProjectPackageManager (
455+ manager : InternalPackageManager | undefined ,
456+ project : PythonProject | undefined ,
457+ ) : InternalPackageManager | undefined {
458+ if ( ! manager || ! project ) {
459+ return manager ;
460+ }
461+
462+ const key = `${ manager . id } :${ normalizePath ( project . uri . fsPath ) } ` ;
463+ let scopedManager = this . _projectPackageManagers . get ( key ) ;
464+ if ( ! scopedManager ) {
465+ scopedManager = manager . createProjectScopedManager ( project ) ;
466+ if ( scopedManager ) {
467+ this . _projectPackageManagers . set ( key , scopedManager ) ;
468+ this . subscribeToPackageManagerEvents ( manager , scopedManager ) ;
469+ }
470+ }
471+ return scopedManager ?? manager ;
472+ }
473+
474+ private subscribeToPackageManagerEvents (
475+ provider : InternalPackageManager ,
476+ manager : InternalPackageManager ,
477+ ) : void {
478+ const event = manager . packageChangeEvent ;
479+ if ( ! event ) {
480+ return ;
481+ }
482+
483+ let subscriptions = this . _packageManagerEventSubscriptions . get ( provider . id ) ;
484+ if ( ! subscriptions ) {
485+ subscriptions = new Map ( ) ;
486+ this . _packageManagerEventSubscriptions . set ( provider . id , subscriptions ) ;
487+ }
488+ if ( subscriptions . has ( event ) ) {
489+ return ;
490+ }
491+
492+ subscriptions . set (
493+ event ,
494+ event ( ( e ) => {
495+ this . _onDidChangePackageProviderPackages . fire ( e ) ;
496+ const eventManager =
497+ Array . from ( this . _projectPackageManagers . values ( ) ) . find (
498+ ( candidate ) => candidate . id === provider . id && candidate . wraps ( e . manager ) ,
499+ ) ?? provider ;
500+ setImmediate ( ( ) =>
501+ this . _onDidChangePackages . fire ( {
502+ environment : e . environment ,
503+ manager : eventManager ,
504+ changes : e . changes ,
505+ } ) ,
506+ ) ;
507+ } ) ,
508+ ) ;
509+ }
510+
511+ private disposePackageManagerEventSubscriptions ( managerId : string ) : void {
512+ const subscriptions = this . _packageManagerEventSubscriptions . get ( managerId ) ;
513+ subscriptions ?. forEach ( ( subscription ) => subscription . dispose ( ) ) ;
514+ this . _packageManagerEventSubscriptions . delete ( managerId ) ;
515+ }
516+
442517 public get managers ( ) : InternalEnvironmentManager [ ] {
443518 return Array . from ( this . _environmentManagers . values ( ) ) ;
444519 }
0 commit comments