Skip to content

Commit e3d34ab

Browse files
authored
Install jupyter instead of installing kernel spec (#10080)
* Install jupyter instead of installing kernel spec For #10071
1 parent c8e7e5e commit e3d34ab

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

news/2 Fixes/10071.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Re-install `Jupyter` instead of installing `kernelspec` if `kernelspec` cannot be found in the python environment.

src/client/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,8 @@ function sortProductsInOrderForInstallation(products: Product[]) {
5757
* @returns {string}
5858
*/
5959
export function getMessageForLibrariesNotInstalled(products: Product[], interpreterName?: string): string {
60+
// Even though kernelspec cannot be installed, display it so user knows what is missing.
6061
const names = products
61-
// Ignore kernelspec as it not something that can be installed.
62-
.filter(product => product !== Product.kernelspec)
6362
.map(product => ProductNames.get(product))
6463
.filter(name => !!name)
6564
.map(name => name as string);
@@ -131,15 +130,15 @@ export class JupyterInterpreterDependencyService {
131130
_error?: JupyterInstallError,
132131
token?: CancellationToken
133132
): Promise<JupyterInterpreterDependencyResponse> {
134-
const productsToInstall = await this.getDependenciesNotInstalled(interpreter, token);
133+
const missingProducts = await this.getDependenciesNotInstalled(interpreter, token);
135134
if (Cancellation.isCanceled(token)) {
136135
return JupyterInterpreterDependencyResponse.cancel;
137136
}
138-
if (productsToInstall.length === 0) {
137+
if (missingProducts.length === 0) {
139138
return JupyterInterpreterDependencyResponse.ok;
140139
}
141140

142-
const message = getMessageForLibrariesNotInstalled(productsToInstall, interpreter.displayName);
141+
const message = getMessageForLibrariesNotInstalled(missingProducts, interpreter.displayName);
143142

144143
sendTelemetryEvent(Telemetry.JupyterNotInstalledErrorShown);
145144
const selection = await this.applicationShell.showErrorMessage(
@@ -155,8 +154,15 @@ export class JupyterInterpreterDependencyService {
155154

156155
switch (selection) {
157156
case DataScience.jupyterInstall(): {
157+
// Ignore kernelspec as it not something that can be installed.
158+
// If kernelspec isn't available, then re-install `Jupyter`.
159+
if (missingProducts.includes(Product.kernelspec) && !missingProducts.includes(Product.jupyter)) {
160+
missingProducts.push(Product.jupyter);
161+
}
162+
const productsToInstall = missingProducts.filter(product => product !== Product.kernelspec);
158163
// Install jupyter, then notebook, then others in that order.
159164
sortProductsInOrderForInstallation(productsToInstall);
165+
160166
let productToInstall = productsToInstall.shift();
161167
const cancellatonPromise = createPromiseFromCancellation({
162168
cancelAction: 'resolve',

src/test/datascience/jupyter/interpreter/jupyterInterpreterDependencyService.unit.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,33 @@ suite('Data Science - Jupyter Interpreter Configuration', () => {
8484
test('Prompt to install if notebook is not installed', async () => testPromptIfModuleNotInstalled(true, false));
8585
test('Prompt to install if jupyter & notebook is not installed', async () =>
8686
testPromptIfModuleNotInstalled(false, false));
87+
test('Reinstall Jupyter if jupyter and notebook are installed but kernelspec is not found', async () => {
88+
when(installer.isInstalled(Product.jupyter, pythonInterpreter)).thenResolve(true);
89+
when(installer.isInstalled(Product.notebook, pythonInterpreter)).thenResolve(true);
90+
when(appShell.showErrorMessage(anything(), anything(), anything(), anything())).thenResolve(
91+
// tslint:disable-next-line: no-any
92+
DataScience.jupyterInstall() as any
93+
);
94+
when(pythonExecService.execModule('jupyter', deepEqual(['kernelspec', '--version']), anything())).thenReject(
95+
new Error('Not found')
96+
);
97+
when(installer.install(anything(), anything(), anything())).thenResolve(InstallerResponse.Installed);
98+
99+
const response = await configuration.installMissingDependencies(pythonInterpreter);
100+
101+
// Jupyter must be installed & not kernelspec or anything else.
102+
verify(installer.install(Product.jupyter, anything(), anything())).once();
103+
verify(installer.install(anything(), anything(), anything())).once();
104+
verify(
105+
appShell.showErrorMessage(
106+
anything(),
107+
DataScience.jupyterInstall(),
108+
DataScience.selectDifferentJupyterInterpreter(),
109+
anything()
110+
)
111+
).once();
112+
assert.equal(response, JupyterInterpreterDependencyResponse.cancel);
113+
});
87114

88115
async function testInstallationOfJupyter(
89116
installerResponse: InstallerResponse,

0 commit comments

Comments
 (0)