-
Notifications
You must be signed in to change notification settings - Fork 331
Prevent unnecessary activation of the Python extension #5199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
357940f
5ffce0b
2842edc
03e727c
366b7f1
4b0ba93
fbda68b
4a3a46d
bf350bc
b605e19
0430769
e0ce172
ace02bb
555e1ea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Prevent unnecessary activation of the Python extension. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,13 +49,33 @@ import { | |
@injectable() | ||
export class PythonApiProvider implements IPythonApiProvider { | ||
private readonly api = createDeferred<PythonApi>(); | ||
private readonly didActivatePython = new EventEmitter<void>(); | ||
public get onDidActivatePythonExtension() { | ||
return this.didActivatePython.event; | ||
} | ||
|
||
private initialized?: boolean; | ||
private hooksRegistered?: boolean; | ||
|
||
constructor( | ||
@inject(IExtensions) private readonly extensions: IExtensions, | ||
@inject(IDisposableRegistry) private readonly disposables: IDisposableRegistry, | ||
@inject(IPythonExtensionChecker) private extensionChecker: IPythonExtensionChecker | ||
) {} | ||
) { | ||
const previouslyInstalled = this.extensionChecker.isPythonExtensionInstalled; | ||
if (!previouslyInstalled) { | ||
this.extensions.onDidChange( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the extension is subsequently installed, then register the hooks |
||
async () => { | ||
if (this.extensionChecker.isPythonExtensionInstalled) { | ||
await this.registerHooks(); | ||
} | ||
}, | ||
this, | ||
this.disposables | ||
); | ||
} | ||
this.disposables.push(this.didActivatePython); | ||
} | ||
|
||
public getApi(): Promise<PythonApi> { | ||
this.init().catch(noop); | ||
|
@@ -78,11 +98,23 @@ export class PythonApiProvider implements IPythonApiProvider { | |
if (!pythonExtension) { | ||
await this.extensionChecker.showPythonExtensionInstallRequiredPrompt(); | ||
} else { | ||
if (!pythonExtension.isActive) { | ||
await pythonExtension.activate(); | ||
} | ||
pythonExtension.exports.jupyter.registerHooks(); | ||
await this.registerHooks(); | ||
} | ||
} | ||
private async registerHooks() { | ||
if (this.hooksRegistered) { | ||
return; | ||
} | ||
const pythonExtension = this.extensions.getExtension<{ jupyter: { registerHooks(): void } }>(PythonExtension); | ||
if (!pythonExtension) { | ||
return; | ||
} | ||
this.hooksRegistered = true; | ||
if (!pythonExtension.isActive) { | ||
await pythonExtension.activate(); | ||
this.didActivatePython.fire(); | ||
} | ||
pythonExtension.exports.jupyter.registerHooks(); | ||
} | ||
} | ||
|
||
|
@@ -106,6 +138,9 @@ export class PythonExtensionChecker implements IPythonExtensionChecker { | |
public get isPythonExtensionInstalled() { | ||
return this.extensions.getExtension(this.pythonExtensionId) !== undefined; | ||
} | ||
public get isPythonExtensionActive() { | ||
return this.extensions.getExtension(this.pythonExtensionId)?.isActive === true; | ||
} | ||
|
||
public async showPythonExtensionInstallRequiredPrompt(): Promise<void> { | ||
if (this.waitingOnInstallPrompt) { | ||
|
@@ -292,24 +327,17 @@ export class InterpreterService implements IInterpreterService { | |
) {} | ||
|
||
public get onDidChangeInterpreter(): Event<void> { | ||
if (this.extensionChecker.isPythonExtensionInstalled && !this.eventHandlerAdded) { | ||
this.apiProvider | ||
.getApi() | ||
.then((api) => { | ||
if (!this.eventHandlerAdded) { | ||
this.eventHandlerAdded = true; | ||
api.onDidChangeInterpreter( | ||
() => { | ||
// Clear our cache of active interpreters. | ||
this.workspaceCachedActiveInterpreter.clear(); | ||
this.didChangeInterpreter.fire(); | ||
}, | ||
this, | ||
this.disposables | ||
); | ||
} | ||
}) | ||
.catch(noop); | ||
if (this.extensionChecker.isPythonExtensionInstalled) { | ||
if (this.extensionChecker.isPythonExtensionActive && !this.eventHandlerAdded) { | ||
this.hookupOnDidChangeInterpreterEvent(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add event handlers only if extension has been activated, and add it later once python loads. |
||
} | ||
if (!this.extensionChecker.isPythonExtensionActive) { | ||
this.apiProvider.onDidActivatePythonExtension( | ||
this.hookupOnDidChangeInterpreterEvent, | ||
this, | ||
this.disposables | ||
); | ||
} | ||
} | ||
return this.didChangeInterpreter.event; | ||
} | ||
|
@@ -345,4 +373,18 @@ export class InterpreterService implements IInterpreterService { | |
return undefined; | ||
} | ||
} | ||
private hookupOnDidChangeInterpreterEvent() { | ||
if (this.eventHandlerAdded) { | ||
return; | ||
} | ||
this.apiProvider | ||
.getApi() | ||
.then((api) => { | ||
if (!this.eventHandlerAdded) { | ||
this.eventHandlerAdded = true; | ||
api.onDidChangeInterpreter(() => this.didChangeInterpreter.fire(), this, this.disposables); | ||
} | ||
}) | ||
.catch(noop); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,12 +19,14 @@ export interface ILanguageServer extends Disposable { | |
|
||
export const IPythonApiProvider = Symbol('IPythonApi'); | ||
export interface IPythonApiProvider { | ||
onDidActivatePythonExtension: Event<void>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not fully sure if I'm suggesting this. But does this seem to you like it should be on IPythonExtensionChecker? That has everything relevant to checking if the extension is installed or active. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No can do, its the PythonApiProvider that activates the Python extension. So only PythonAPIProvider knows if the python extension was activated or not. |
||
getApi(): Promise<PythonApi>; | ||
setApi(api: PythonApi): void; | ||
} | ||
export const IPythonExtensionChecker = Symbol('IPythonExtensionChecker'); | ||
export interface IPythonExtensionChecker { | ||
readonly isPythonExtensionInstalled: boolean; | ||
readonly isPythonExtensionActive: boolean; | ||
showPythonExtensionInstallRequiredPrompt(): Promise<void>; | ||
showPythonExtensionInstallRecommendedPrompt(): Promise<void>; | ||
} | ||
|
Uh oh!
There was an error while loading. Please reload this page.