Skip to content
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

Run kernel on cell execution when no kernel #12858

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
797bb81
Run kernel on cell execute when no kernel
a3626a Jul 26, 2022
17a267c
Keep public getDefaultKernel's old behaviour
a3626a Oct 28, 2022
bab2141
Negate shouldStart condition (fix)
a3626a Oct 28, 2022
1d173ab
Update startKernel to call Private.getDefaultKernel
a3626a Oct 28, 2022
5e36c9b
Add selectPrefferedKernel setting
a3626a Dec 30, 2022
90c14c8
Fix missing replacement
a3626a Dec 30, 2022
267cc8d
Add missing select preffered kernel
a3626a Dec 30, 2022
47f22cc
Fix missing selectPreferredKernel setter
a3626a Dec 30, 2022
b71de65
Implement SessionContextDialogs class
a3626a Jan 19, 2023
72b9ed1
Remove test code
a3626a Jan 19, 2023
f4c1c2c
Add dialogs to session context and solve dependency issues
a3626a Jan 19, 2023
861d3fc
Fix missing old default dialog accesses
a3626a Jan 19, 2023
a353733
Update packages/apputils/src/sessioncontext.tsx
a3626a Feb 14, 2023
72fb36b
Update packages/apputils/src/sessioncontext.tsx
a3626a Feb 14, 2023
db09fbe
Remove dialogs from `SessionContext`
fcollonval Feb 22, 2023
b30fad4
Pass autoStartDefault
aditya211935 Jul 11, 2022
4ce05c3
Revert "Pass autoStartDefault"
fcollonval Feb 23, 2023
d5c212c
Fixing passing by the sessiondialogs
fcollonval Feb 23, 2023
c260703
Use notebook settings only for notebook selection
fcollonval Feb 23, 2023
000899e
Use existing `autoStartDefault` instead of `selectPreferredKernel`
fcollonval Feb 24, 2023
ed5f26a
Fix examples
fcollonval Feb 24, 2023
33df946
Add migration notes
fcollonval Feb 24, 2023
c4c1038
Fix tests
fcollonval Feb 24, 2023
fba07a6
Fix starting notebook with kernel defined
fcollonval Feb 27, 2023
2fcb956
Fix starting Console when kernel is defined
fcollonval Feb 27, 2023
fb38785
Remove unused variables
fcollonval Feb 27, 2023
2b0d3a0
More test fix
fcollonval Feb 27, 2023
a13397b
Lint the code
fcollonval Feb 27, 2023
2561d82
Apply suggestions to be more tolerant on requirements
fcollonval Mar 3, 2023
eaf4664
Update migration note to align with later state
fcollonval Mar 8, 2023
557dbb9
avoid `!` operator
fcollonval Mar 8, 2023
ef395c2
Make session dialogs and translator tokens optional
fcollonval Mar 8, 2023
c9dc745
Fix plugin activation
fcollonval Mar 9, 2023
14ff3cc
NotebookActions.run make sessionContext optional
fcollonval Mar 14, 2023
99ee80d
Add more integration tests
fcollonval Mar 15, 2023
4b1654f
Wait for notebook to close
fcollonval Mar 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/source/extension/extension_migration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ bumped their major version (following semver convention). We want to point out p
* Rename ``IToolbarWidgetRegistry.registerFactory`` to ``IToolbarWidgetRegistry.addFactory``
* ``ISanitizer`` and ``ISanitizer.IOptions`` are deprecated in favor of ``IRenderMime.ISanitizer`` and
``IRenderMime.ISanitizerOptions`` in ``@jupyterlab/rendermime-interfaces``.
* Global ``sessionContextDialogs`` is removed; you should request the token ``ISessionContextDialogs`` (from ``@jupyterlab/apputils``).
- ``@jupyterlab/attachments`` from 3.x to 4.x
Removed ``modelDB`` from ``IAttachmentsModel.IOptions``.
- ``@jupyterlab/buildutils`` from 3.x to 4.x
Expand Down Expand Up @@ -196,6 +197,7 @@ bumped their major version (following semver convention). We want to point out p
* ``IMainMenu.addMenu`` signature changed from ``addMenu(menu: Menu, options?: IMainMenu.IAddOptions): void``
to ``addMenu(menu: Menu, update?: boolean, options?: IMainMenu.IAddOptions): void``
- ``@jupyterlab/notebook`` from 3.x to 4.x
* ``NotebookWidgetFactory.IOptions`` has no ``sessionDialogs`` option any more.
* The ``NotebookPanel._onSave`` method is now ``private``.
* ``NotebookActions.collapseAll`` method renamed to ``NotebookActions.collapseAllHeadings``.
* Command ``Collapsible_Headings:Toggle_Collapse`` renamed to ``notebook:toggle-heading-collapse``.
Expand Down
38 changes: 33 additions & 5 deletions examples/cell/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,17 @@ import '@jupyterlab/theme-light-extension/style/theme.css';
import '@jupyterlab/completer/style/index.css';
import '../index.css';

import { Toolbar as AppToolbar, SessionContext } from '@jupyterlab/apputils';
import { Toolbar } from '@jupyterlab/ui-components';
import {
Toolbar as AppToolbar,
SessionContext,
SessionContextDialogs
} from '@jupyterlab/apputils';
import {
refreshIcon,
stopIcon,
Toolbar,
ToolbarButton
} from '@jupyterlab/ui-components';

import { Cell, CodeCell, CodeCellModel } from '@jupyterlab/cells';

Expand Down Expand Up @@ -138,10 +147,29 @@ function main(): void {
toolbar.addItem('spacer', Toolbar.createSpacerItem());
toolbar.addItem(
'interrupt',
AppToolbar.createInterruptButton(sessionContext)
new ToolbarButton({
icon: stopIcon,
onClick: () => {
void sessionContext.session?.kernel?.interrupt();
},
tooltip: 'Interrupt the kernel'
})
);
const dialogs = new SessionContextDialogs();
toolbar.addItem(
'restart',
new ToolbarButton({
icon: refreshIcon,
onClick: () => {
void dialogs.restart(sessionContext);
},
tooltip: 'Restart the kernel'
})
);
toolbar.addItem(
'name',
AppToolbar.createKernelNameItem(sessionContext, dialogs)
);
toolbar.addItem('restart', AppToolbar.createRestartButton(sessionContext));
toolbar.addItem('name', AppToolbar.createKernelNameItem(sessionContext));
toolbar.addItem('status', AppToolbar.createKernelStatusItem(sessionContext));

// Lay out the widgets.
Expand Down
9 changes: 6 additions & 3 deletions examples/notebook/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/**
* Set up keyboard shortcuts & commands for notebook
*/
import { sessionContextDialogs } from '@jupyterlab/apputils';
import { SessionContextDialogs } from '@jupyterlab/apputils';
import { CompletionHandler } from '@jupyterlab/completer';
import {
SearchDocumentModel,
Expand Down Expand Up @@ -163,6 +163,7 @@ export const SetupCommands = (
execute: async () =>
nbWidget.context.sessionContext.session?.kernel?.interrupt()
});
const sessionContextDialogs = new SessionContextDialogs();
commands.addCommand(cmdIds.restart, {
label: 'Restart Kernel',
execute: () =>
Expand All @@ -178,7 +179,8 @@ export const SetupCommands = (
execute: () => {
return NotebookActions.runAndAdvance(
nbWidget.content,
nbWidget.context.sessionContext
nbWidget.context.sessionContext,
sessionContextDialogs
);
}
});
Expand All @@ -187,7 +189,8 @@ export const SetupCommands = (
execute: () => {
return NotebookActions.run(
nbWidget.content,
nbWidget.context.sessionContext
nbWidget.context.sessionContext,
sessionContextDialogs
);
}
});
Expand Down
140 changes: 140 additions & 0 deletions galata/test/jupyterlab/kernel.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.

import { expect, test } from '@jupyterlab/galata';

test.describe('Kernel', () => {
test.describe('Notebook', () => {
test('Should not ask kernel when creating notebook from launcher', async ({
page
}) => {
await Promise.all([
page
.getByRole('tabpanel', { name: 'Launcher' })
.waitFor({ state: 'detached' }),
page.getByTitle('Python 3 (ipykernel)').nth(1).click()
]);

await expect.soft(page.locator('.jp-Dialog')).toHaveCount(0);

await expect(page.getByTitle('Switch kernel')).toHaveText(
'Python 3 (ipykernel)'
);
});

test('Should remember kernel auto start for notebook', async ({ page }) => {
await page.menu.clickMenuItem('File>New>Notebook');

// Open a notebook without selecting a kernel
await page
.locator('.jp-Dialog')
.getByRole('button', { name: 'No Kernel' })
.click();

await expect
.soft(page.getByTitle('Switch kernel'))
.toHaveText('No Kernel');

await Promise.all([
page
.getByRole('tab', { name: 'Untitled.ipynb' })
.waitFor({ state: 'detached' }),
page.menu.clickMenuItem('File>Close Tab')
]);

// Open the same notebook selecting and turning on auto start
await page.filebrowser.open('Untitled.ipynb');

await page
.locator('.jp-Dialog')
.getByText('Always start the preferred kernel')
.click();
await page
.locator('.jp-Dialog')
.getByRole('button', { name: 'Select' })
.click();

await expect
.soft(page.getByTitle('Switch kernel'))
.toHaveText('Python 3 (ipykernel)');

await page.menu.clickMenuItem('File>Close and Shut Down Notebook');

await Promise.all([
page
.getByRole('tab', { name: 'Untitled.ipynb' })
.waitFor({ state: 'detached' }),
page.locator('.jp-Dialog').getByRole('button', { name: 'Ok' }).click()
]);

// Open the same notebook and check it turns on the kernel
await page.filebrowser.open('Untitled.ipynb');

await expect(page.getByTitle('Switch kernel')).toHaveText(
'Python 3 (ipykernel)'
);
});

test('Should request kernel selection when executing a cell for notebook without kernel', async ({
page
}) => {
await page.menu.clickMenuItem('File>New>Notebook');

// Open a notebook without selecting a kernel
await page
.locator('.jp-Dialog')
.getByRole('button', { name: 'No Kernel' })
.click();

await expect
.soft(page.getByTitle('Switch kernel'))
.toHaveText('No Kernel');

// Request cell execution
await page.menu.clickMenuItem('Run>Run Selected Cell');

await page
.locator('.jp-Dialog')
.getByRole('button', { name: 'Select' })
.click();

await expect(page.getByTitle('Switch kernel')).toHaveText(
'Python 3 (ipykernel)'
);
});
});

test.describe('Console', () => {
test('Should not ask kernel when creating console from launcher', async ({
page
}) => {
await Promise.all([
page
.getByRole('tabpanel', { name: 'Launcher' })
.waitFor({ state: 'detached' }),
page.getByTitle('Python 3 (ipykernel)').nth(2).click()
]);

await expect.soft(page.locator('.jp-Dialog')).toHaveCount(0);

await expect(page.getByTitle('Change kernel for Console 1')).toHaveText(
'Python 3 (ipykernel) | Idle'
);
});

test('Should ask for kernel when creating console from menu', async ({
page
}) => {
await page.menu.clickMenuItem('File>New>Console');

await page
.locator('.jp-Dialog')
.getByRole('button', { name: 'Select' })
.click();

await expect(page.getByTitle('Change kernel for Console 1')).toHaveText(
'Python 3 (ipykernel) | Idle'
);
});
});
});
11 changes: 7 additions & 4 deletions packages/apputils-extension/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ import {
MainAreaWidget,
Printing,
Sanitizer,
sessionContextDialogs,
SessionContextDialogs,
WindowResolver
} from '@jupyterlab/apputils';
import { PageConfig, PathExt, URLExt } from '@jupyterlab/coreutils';
import { ISettingRegistry } from '@jupyterlab/settingregistry';
import { IStateDB, StateDB } from '@jupyterlab/statedb';
import { ITranslator } from '@jupyterlab/translation';
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
import { jupyterFaviconIcon } from '@jupyterlab/ui-components';
import { PromiseDelegate } from '@lumino/coreutils';
import { DisposableDelegate } from '@lumino/disposable';
Expand Down Expand Up @@ -555,9 +555,12 @@ const state: JupyterFrontEndPlugin<IStateDB> = {
const sessionDialogs: JupyterFrontEndPlugin<ISessionContextDialogs> = {
id: '@jupyterlab/apputils-extension:sessionDialogs',
provides: ISessionContextDialogs,
optional: [ITranslator],
autoStart: true,
activate: () => {
return sessionContextDialogs;
activate: async (app: JupyterFrontEnd, translator: ITranslator | null) => {
return new SessionContextDialogs({
translator: translator ?? nullTranslator
});
}
};

Expand Down
20 changes: 10 additions & 10 deletions packages/apputils-extension/src/statusbarplugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import {
ISessionContextDialogs,
KernelStatus,
RunningSessions,
sessionContextDialogs
SessionContextDialogs
} from '@jupyterlab/apputils';
import { IStatusBar } from '@jupyterlab/statusbar';
import { ITranslator } from '@jupyterlab/translation';
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
import { Title, Widget } from '@lumino/widgets';

/**
Expand All @@ -26,26 +26,26 @@ import { Title, Widget } from '@lumino/widgets';
export const kernelStatus: JupyterFrontEndPlugin<IKernelStatusModel> = {
id: '@jupyterlab/apputils-extension:kernel-status',
autoStart: true,
requires: [IStatusBar, ITranslator],
requires: [IStatusBar],
provides: IKernelStatusModel,
optional: [ISessionContextDialogs, ILabShell],
optional: [ISessionContextDialogs, ITranslator, ILabShell],
activate: (
app: JupyterFrontEnd,
statusBar: IStatusBar,
translator: ITranslator,
sessionDialogs: ISessionContextDialogs | null,
sessionDialogs_: ISessionContextDialogs | null,
translator_: ITranslator | null,
labShell: ILabShell | null
): IKernelStatusModel => {
const translator = translator_ ?? nullTranslator;
const sessionDialogs =
sessionDialogs_ ?? new SessionContextDialogs({ translator });
// When the status item is clicked, launch the kernel
// selection dialog for the current session.
const changeKernel = async () => {
if (!item.model.sessionContext) {
return;
}
await (sessionDialogs ?? sessionContextDialogs).selectKernel(
item.model.sessionContext,
translator
);
await sessionDialogs.selectKernel(item.model.sessionContext);
};

// Create the status item.
Expand Down