-
Notifications
You must be signed in to change notification settings - Fork 290
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Separate Kernel Specs & Python envs in kernel pick (#11926)
* Separate Kernel Specs & Python envs in kernel pick * oops * oops
- Loading branch information
1 parent
60a9c28
commit d561d93
Showing
11 changed files
with
782 additions
and
135 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
130 changes: 70 additions & 60 deletions
130
...raw/finder/localKernelFinder.unit.test.ts → .../contributedKerneFinder.node.unit.test.ts
Large diffs are not rendered by default.
Oops, something went wrong.
151 changes: 151 additions & 0 deletions
151
src/kernels/raw/finder/contributedLocalKernelSpecFinder.node.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
'use strict'; | ||
|
||
import { inject, injectable } from 'inversify'; | ||
import { Event, EventEmitter } from 'vscode'; | ||
import { IKernelFinder, LocalKernelSpecConnectionMetadata } from '../../types'; | ||
import { LocalPythonAndRelatedNonPythonKernelSpecFinder } from './localPythonAndRelatedNonPythonKernelSpecFinder.node'; | ||
import { LocalKnownPathKernelSpecFinder } from './localKnownPathKernelSpecFinder.node'; | ||
import { traceInfo, traceDecoratorError, traceError, traceVerbose } from '../../../platform/logging'; | ||
import { IDisposableRegistry, IExtensions } from '../../../platform/common/types'; | ||
import { capturePerfTelemetry, Telemetry } from '../../../telemetry'; | ||
import { areObjectsWithUrisTheSame, noop } from '../../../platform/common/utils/misc'; | ||
import { KernelFinder } from '../../kernelFinder'; | ||
import { IExtensionSyncActivationService } from '../../../platform/activation/types'; | ||
import { DataScience } from '../../../platform/common/utils/localize'; | ||
import { IPythonExtensionChecker } from '../../../platform/api/types'; | ||
import { IInterpreterService } from '../../../platform/interpreter/contracts'; | ||
import { ContributedKernelFinderKind, IContributedKernelFinder } from '../../internalTypes'; | ||
import { PYTHON_LANGUAGE } from '../../../platform/common/constants'; | ||
|
||
// This class searches for local kernels. | ||
// First it searches on a global persistent state, then on the installed python interpreters, | ||
// and finally on the default locations that jupyter installs kernels on. | ||
@injectable() | ||
export class ContributedLocalKernelSpecFinder | ||
implements IContributedKernelFinder<LocalKernelSpecConnectionMetadata>, IExtensionSyncActivationService | ||
{ | ||
kind = ContributedKernelFinderKind.LocalKernelSpec; | ||
id: string = ContributedKernelFinderKind.LocalKernelSpec; | ||
displayName: string = DataScience.localKernelSpecs(); | ||
|
||
private _onDidChangeKernels = new EventEmitter<void>(); | ||
onDidChangeKernels: Event<void> = this._onDidChangeKernels.event; | ||
|
||
private wasPythonInstalledWhenFetchingControllers = false; | ||
|
||
private cache: LocalKernelSpecConnectionMetadata[] = []; | ||
|
||
constructor( | ||
@inject(LocalKnownPathKernelSpecFinder) private readonly nonPythonKernelFinder: LocalKnownPathKernelSpecFinder, | ||
@inject(LocalPythonAndRelatedNonPythonKernelSpecFinder) | ||
private readonly pythonKernelFinder: LocalPythonAndRelatedNonPythonKernelSpecFinder, | ||
@inject(IKernelFinder) kernelFinder: KernelFinder, | ||
@inject(IDisposableRegistry) private readonly disposables: IDisposableRegistry, | ||
@inject(IPythonExtensionChecker) private readonly extensionChecker: IPythonExtensionChecker, | ||
@inject(IInterpreterService) private readonly interpreters: IInterpreterService, | ||
@inject(IExtensions) private readonly extensions: IExtensions | ||
) { | ||
kernelFinder.registerKernelFinder(this); | ||
} | ||
|
||
activate() { | ||
this.loadInitialState().then(noop, noop); | ||
|
||
this.interpreters.onDidChangeInterpreters( | ||
async () => this.updateCache().then(noop, noop), | ||
this, | ||
this.disposables | ||
); | ||
this.extensions.onDidChange( | ||
() => { | ||
// If we just installed the Python extension and we fetched the controllers, then fetch it again. | ||
if ( | ||
!this.wasPythonInstalledWhenFetchingControllers && | ||
this.extensionChecker.isPythonExtensionInstalled | ||
) { | ||
this.updateCache().then(noop, noop); | ||
} | ||
}, | ||
this, | ||
this.disposables | ||
); | ||
this.nonPythonKernelFinder.onDidChangeKernels( | ||
() => this.updateCache().then(noop, noop), | ||
this, | ||
this.disposables | ||
); | ||
this.pythonKernelFinder.onDidChangeKernels(() => this.updateCache().then(noop, noop), this, this.disposables); | ||
this.wasPythonInstalledWhenFetchingControllers = this.extensionChecker.isPythonExtensionInstalled; | ||
} | ||
|
||
private async loadInitialState() { | ||
traceVerbose('LocalKernelFinder: load initial set of kernels'); | ||
await this.updateCache(); | ||
traceVerbose('LocalKernelFinder: loaded initial set of kernels'); | ||
} | ||
|
||
@traceDecoratorError('List kernels failed') | ||
@capturePerfTelemetry(Telemetry.KernelListingPerf, { kind: 'localKernelSpec' }) | ||
private async updateCache() { | ||
try { | ||
let kernels: LocalKernelSpecConnectionMetadata[] = []; | ||
// Exclude python kernel specs (we'll get that from the pythonKernelFinder) | ||
const kernelSpecs = this.nonPythonKernelFinder.kernels.filter((item) => { | ||
if (this.extensionChecker.isPythonExtensionInstalled) { | ||
return item.kernelSpec.language !== PYTHON_LANGUAGE; | ||
} | ||
return true; | ||
}); | ||
const kernelSpecsFromPythonKernelFinder = this.pythonKernelFinder.kernels.filter( | ||
(item) => item.kind === 'startUsingLocalKernelSpec' | ||
) as LocalKernelSpecConnectionMetadata[]; | ||
kernels = kernels.concat(kernelSpecs).concat(kernelSpecsFromPythonKernelFinder); | ||
await this.writeToCache(kernels); | ||
} catch (ex) { | ||
traceError('Exception Saving loaded kernels', ex); | ||
} | ||
} | ||
|
||
public get kernels(): LocalKernelSpecConnectionMetadata[] { | ||
return this.cache; | ||
} | ||
private filterKernels(kernels: LocalKernelSpecConnectionMetadata[]) { | ||
return kernels.filter(({ kernelSpec }) => { | ||
if (!kernelSpec) { | ||
return true; | ||
} | ||
// Disable xeus python for now. | ||
if (kernelSpec.argv[0].toLowerCase().endsWith('xpython')) { | ||
traceInfo(`Hiding xeus kernelspec`); | ||
return false; | ||
} | ||
|
||
return true; | ||
}); | ||
} | ||
|
||
private async writeToCache(values: LocalKernelSpecConnectionMetadata[]) { | ||
try { | ||
const oldValues = this.cache; | ||
const uniqueIds = new Set<string>(); | ||
const uniqueKernels = values.filter((item) => { | ||
if (uniqueIds.has(item.id)) { | ||
return false; | ||
} | ||
uniqueIds.add(item.id); | ||
return true; | ||
}); | ||
this.cache = this.filterKernels(uniqueKernels); | ||
if (areObjectsWithUrisTheSame(oldValues, this.cache)) { | ||
return; | ||
} | ||
|
||
this._onDidChangeKernels.fire(); | ||
} catch (ex) { | ||
traceError('LocalKernelFinder: Failed to write to cache', ex); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.