Skip to content

Commit 03d8c98

Browse files
trungleducjtpio
authored andcommitted
Use kernel id as keys of the map used to store widget manager (#2)
1 parent a66f79e commit 03d8c98

File tree

1 file changed

+138
-89
lines changed

1 file changed

+138
-89
lines changed

python/jupyterlab_widgets/src/plugin.ts

Lines changed: 138 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ import { ISettingRegistry } from '@jupyterlab/settingregistry';
55

66
import * as nbformat from '@jupyterlab/nbformat';
77

8-
import { IConsoleTracker, CodeConsole } from '@jupyterlab/console';
9-
10-
import { DocumentRegistry } from '@jupyterlab/docregistry';
8+
import {
9+
IConsoleTracker,
10+
CodeConsole,
11+
ConsolePanel,
12+
} from '@jupyterlab/console';
1113

1214
import {
13-
INotebookModel,
1415
INotebookTracker,
1516
Notebook,
1617
NotebookPanel,
@@ -33,8 +34,6 @@ import { toArray, filter } from '@lumino/algorithm';
3334

3435
import { DisposableDelegate } from '@lumino/disposable';
3536

36-
import { AttachedProperty } from '@lumino/properties';
37-
3837
import { WidgetRenderer } from './renderer';
3938

4039
import {
@@ -55,6 +54,7 @@ import '@jupyter-widgets/base/css/index.css';
5554
import '@jupyter-widgets/controls/css/widgets-base.css';
5655
import { KernelMessage } from '@jupyterlab/services';
5756
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
57+
import { ISessionContext } from '@jupyterlab/apputils';
5858

5959
const WIDGET_REGISTRY: base.IWidgetRegistryData[] = [];
6060

@@ -131,16 +131,69 @@ function* chain<T>(
131131
}
132132
}
133133

134-
export function registerWidgetManager(
135-
context: DocumentRegistry.IContext<INotebookModel>,
134+
/**
135+
* Get the kernel id of current notebook or console panel, this value
136+
* is used as key for `Private.widgetManagerProperty` to store the widget
137+
* manager of current notebook or console panel.
138+
*
139+
* @param {ISessionContext} sessionContext The session context of notebook or
140+
* console panel.
141+
*/
142+
async function getWidgetManagerOwner(
143+
sessionContext: ISessionContext
144+
): Promise<Private.IWidgetManagerOwner> {
145+
await sessionContext.ready;
146+
return sessionContext.session!.kernel!.id;
147+
}
148+
149+
/**
150+
* Common handler for registering both notebook and console
151+
* `WidgetManager`
152+
*
153+
* @param {(Notebook | CodeConsole)} content Context of panel.
154+
* @param {ISessionContext} sessionContext Session context of panel.
155+
* @param {IRenderMimeRegistry} rendermime Rendermime of panel.
156+
* @param {IterableIterator<WidgetRenderer>} renderers Iterator of
157+
* `WidgetRenderer` inside panel
158+
* @param {(() => WidgetManager | KernelWidgetManager)} widgetManagerFactory
159+
* function to create widget manager.
160+
*/
161+
async function registerWidgetHandler(
162+
content: Notebook | CodeConsole,
163+
sessionContext: ISessionContext,
136164
rendermime: IRenderMimeRegistry,
137-
renderers: IterableIterator<WidgetRenderer>
138-
): DisposableDelegate {
139-
let wManager = Private.widgetManagerProperty.get(context);
165+
renderers: IterableIterator<WidgetRenderer>,
166+
widgetManagerFactory: () => WidgetManager | KernelWidgetManager
167+
): Promise<DisposableDelegate> {
168+
const wManagerOwner = await getWidgetManagerOwner(sessionContext);
169+
let wManager = Private.widgetManagerProperty.get(wManagerOwner);
170+
let currentOwner: string;
171+
140172
if (!wManager) {
141-
wManager = new WidgetManager(context, rendermime, SETTINGS);
173+
wManager = widgetManagerFactory();
142174
WIDGET_REGISTRY.forEach((data) => wManager!.register(data));
143-
Private.widgetManagerProperty.set(context, wManager);
175+
Private.widgetManagerProperty.set(wManagerOwner, wManager);
176+
currentOwner = wManagerOwner;
177+
content.disposed.connect((_) => {
178+
const currentwManager = Private.widgetManagerProperty.get(currentOwner);
179+
if (currentwManager) {
180+
Private.widgetManagerProperty.delete(currentOwner);
181+
}
182+
});
183+
184+
sessionContext.kernelChanged.connect((_, args) => {
185+
const { newValue } = args;
186+
if (newValue) {
187+
const newKernelId = newValue.id;
188+
const oldwManager = Private.widgetManagerProperty.get(currentOwner);
189+
190+
if (oldwManager) {
191+
Private.widgetManagerProperty.delete(currentOwner);
192+
Private.widgetManagerProperty.set(newKernelId, oldwManager);
193+
}
194+
currentOwner = newKernelId;
195+
}
196+
});
144197
}
145198

146199
for (const r of renderers) {
@@ -167,43 +220,43 @@ export function registerWidgetManager(
167220
});
168221
}
169222

170-
export function registerConsoleWidgetManager(
171-
console: CodeConsole,
172-
rendermime: IRenderMimeRegistry,
223+
export async function registerWidgetManager(
224+
panel: NotebookPanel,
173225
renderers: IterableIterator<WidgetRenderer>
174-
): DisposableDelegate {
175-
let wManager = Private.widgetManagerProperty.get(console);
176-
if (!wManager) {
177-
wManager = new KernelWidgetManager(
178-
console.sessionContext.session?.kernel!,
179-
rendermime
180-
);
181-
WIDGET_REGISTRY.forEach((data) => wManager!.register(data));
182-
Private.widgetManagerProperty.set(console, wManager);
183-
}
184-
185-
for (const r of renderers) {
186-
r.manager = wManager;
187-
}
188-
189-
// Replace the placeholder widget renderer with one bound to this widget
190-
// manager.
191-
rendermime.removeMimeType(WIDGET_VIEW_MIMETYPE);
192-
rendermime.addFactory(
193-
{
194-
safe: false,
195-
mimeTypes: [WIDGET_VIEW_MIMETYPE],
196-
createRenderer: (options) => new WidgetRenderer(options, wManager),
197-
},
198-
0
226+
): Promise<DisposableDelegate> {
227+
const content = panel.content;
228+
const context = panel.context;
229+
const sessionContext = context.sessionContext;
230+
const rendermime = content.rendermime;
231+
const widgetManagerFactory = () =>
232+
new WidgetManager(context, rendermime, SETTINGS);
233+
234+
return registerWidgetHandler(
235+
content,
236+
sessionContext,
237+
rendermime,
238+
renderers,
239+
widgetManagerFactory
199240
);
241+
}
200242

201-
return new DisposableDelegate(() => {
202-
if (rendermime) {
203-
rendermime.removeMimeType(WIDGET_VIEW_MIMETYPE);
204-
}
205-
wManager!.dispose();
206-
});
243+
export async function registerConsoleWidgetManager(
244+
panel: ConsolePanel,
245+
renderers: IterableIterator<WidgetRenderer>
246+
): Promise<DisposableDelegate> {
247+
const content = panel.console;
248+
const sessionContext = content.sessionContext;
249+
const rendermime = content.rendermime;
250+
const widgetManagerFactory = () =>
251+
new KernelWidgetManager(sessionContext.session!.kernel!, rendermime);
252+
253+
return registerWidgetHandler(
254+
content,
255+
sessionContext,
256+
rendermime,
257+
renderers,
258+
widgetManagerFactory
259+
);
207260
}
208261

209262
/**
@@ -247,12 +300,17 @@ function activateWidgetExtension(
247300
const { commands } = app;
248301
const trans = (translator ?? nullTranslator).load('jupyterlab_widgets');
249302

250-
const bindUnhandledIOPubMessageSignal = (nb: NotebookPanel): void => {
303+
const bindUnhandledIOPubMessageSignal = async (
304+
nb: NotebookPanel
305+
): Promise<void> => {
251306
if (!loggerRegistry) {
252307
return;
253308
}
309+
const wManagerOwner = await getWidgetManagerOwner(
310+
nb.context.sessionContext
311+
);
312+
const wManager = Private.widgetManagerProperty.get(wManagerOwner);
254313

255-
const wManager = Private.widgetManagerProperty.get(nb.context);
256314
if (wManager) {
257315
wManager.onUnhandledIOPubMessage.connect(
258316
(
@@ -300,48 +358,30 @@ function activateWidgetExtension(
300358
);
301359

302360
if (tracker !== null) {
303-
tracker.forEach((panel) => {
304-
registerWidgetManager(
305-
panel.context,
306-
panel.content.rendermime,
307-
chain(
308-
notebookWidgetRenderers(panel.content),
309-
outputViews(app, panel.context.path)
310-
)
361+
const rendererIterator = (panel: NotebookPanel) =>
362+
chain(
363+
notebookWidgetRenderers(panel.content),
364+
outputViews(app, panel.context.path)
311365
);
312-
366+
tracker.forEach(async (panel) => {
367+
await registerWidgetManager(panel, rendererIterator(panel));
313368
bindUnhandledIOPubMessageSignal(panel);
314369
});
315-
tracker.widgetAdded.connect((sender, panel) => {
316-
registerWidgetManager(
317-
panel.context,
318-
panel.content.rendermime,
319-
chain(
320-
notebookWidgetRenderers(panel.content),
321-
outputViews(app, panel.context.path)
322-
)
323-
);
324-
370+
tracker.widgetAdded.connect(async (sender, panel) => {
371+
await registerWidgetManager(panel, rendererIterator(panel));
325372
bindUnhandledIOPubMessageSignal(panel);
326373
});
327374
}
328375

329376
if (consoleTracker !== null) {
377+
const rendererIterator = (panel: ConsolePanel) =>
378+
chain(consoleWidgetRenderers(panel.console));
379+
330380
consoleTracker.forEach(async (panel) => {
331-
await panel.sessionContext.ready;
332-
registerConsoleWidgetManager(
333-
panel.console,
334-
panel.console.rendermime,
335-
chain(consoleWidgetRenderers(panel.console))
336-
);
381+
await registerConsoleWidgetManager(panel, rendererIterator(panel));
337382
});
338383
consoleTracker.widgetAdded.connect(async (sender, panel) => {
339-
await panel.sessionContext.ready;
340-
registerConsoleWidgetManager(
341-
panel.console,
342-
panel.console.rendermime,
343-
chain(consoleWidgetRenderers(panel.console))
344-
);
384+
await registerConsoleWidgetManager(panel, rendererIterator(panel));
345385
});
346386
}
347387
if (settingRegistry !== null) {
@@ -415,14 +455,23 @@ function activateWidgetExtension(
415455

416456
namespace Private {
417457
/**
418-
* A private attached property for a widget manager.
458+
* A type alias for keys of `widgetManagerProperty` .
419459
*/
420-
export const widgetManagerProperty = new AttachedProperty<
421-
DocumentRegistry.Context | CodeConsole,
422-
WidgetManager | KernelWidgetManager | undefined
423-
>({
424-
name: 'widgetManager',
425-
create: (owner: DocumentRegistry.Context | CodeConsole): undefined =>
426-
undefined,
427-
});
460+
export type IWidgetManagerOwner = string;
461+
462+
/**
463+
* A type alias for values of `widgetManagerProperty` .
464+
*/
465+
export type IWidgetManagerValue =
466+
| WidgetManager
467+
| KernelWidgetManager
468+
| undefined;
469+
470+
/**
471+
* A private map for a widget manager.
472+
*/
473+
export const widgetManagerProperty = new Map<
474+
IWidgetManagerOwner,
475+
IWidgetManagerValue
476+
>();
428477
}

0 commit comments

Comments
 (0)