jupyterpack 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/document/commands.d.ts +8 -0
- package/lib/document/commands.js +76 -0
- package/lib/document/iframePanel.d.ts +4 -1
- package/lib/document/plugin.d.ts +2 -1
- package/lib/document/plugin.js +22 -4
- package/lib/document/toolbar.d.ts +9 -0
- package/lib/document/toolbar.js +20 -0
- package/lib/document/widgetFactory.d.ts +2 -1
- package/lib/document/widgetFactory.js +11 -5
- package/lib/index.d.ts +1 -1
- package/lib/pythonServer/dash/dashServer.d.ts +4 -6
- package/lib/pythonServer/dash/dashServer.js +18 -10
- package/lib/pythonServer/kernelExecutor.d.ts +5 -0
- package/lib/pythonServer/kernelExecutor.js +13 -6
- package/lib/pythonServer/streamlit/streamlitServer.d.ts +7 -26
- package/lib/pythonServer/streamlit/streamlitServer.js +32 -36
- package/lib/pythonServer/tornado/tornadoServer.d.ts +5 -3
- package/lib/pythonServer/tornado/tornadoServer.js +31 -14
- package/lib/pythonWidget/comm.d.ts +11 -0
- package/lib/pythonWidget/comm.js +52 -0
- package/lib/pythonWidget/pythonWidget.d.ts +5 -0
- package/lib/pythonWidget/pythonWidget.js +19 -0
- package/lib/pythonWidget/pythonWidgetModel.d.ts +16 -4
- package/lib/pythonWidget/pythonWidgetModel.js +77 -13
- package/lib/sandpackWidget/sandpackFilesModel.d.ts +6 -2
- package/lib/sandpackWidget/sandpackFilesModel.js +13 -2
- package/lib/sandpackWidget/sandpackPanel.d.ts +10 -1
- package/lib/sandpackWidget/sandpackPanel.js +38 -3
- package/lib/token.d.ts +2 -1
- package/lib/token.js +1 -0
- package/lib/tools.d.ts +5 -0
- package/lib/tools.js +17 -0
- package/lib/type.d.ts +27 -1
- package/package.json +6 -6
- package/src/document/commands.ts +91 -0
- package/src/document/iframePanel.ts +4 -1
- package/src/document/plugin.ts +28 -7
- package/src/document/toolbar.ts +39 -0
- package/src/document/widgetFactory.ts +13 -5
- package/src/global.d.ts +5 -0
- package/src/pythonServer/dash/dashServer.ts +23 -14
- package/src/pythonServer/kernelExecutor.ts +21 -7
- package/src/pythonServer/streamlit/streamlitServer.ts +41 -61
- package/src/pythonServer/tornado/tornadoServer.ts +35 -18
- package/src/pythonWidget/comm.ts +65 -0
- package/src/pythonWidget/pythonWidget.ts +19 -1
- package/src/pythonWidget/pythonWidgetModel.ts +105 -18
- package/src/sandpackWidget/sandpackFilesModel.ts +17 -3
- package/src/sandpackWidget/sandpackPanel.ts +45 -4
- package/src/token.ts +5 -1
- package/src/tools.ts +22 -0
- package/src/type.ts +29 -1
- package/style/base.css +7 -0
- package/style/icons/autoreload.svg +16 -0
- package/style/icons/box.svg +12 -0
- package/style/icons/externallink.svg +10 -0
- package/lib/pythonServer/common/generatedPythonFiles.d.ts +0 -2
- package/lib/pythonServer/common/generatedPythonFiles.js +0 -72
- package/lib/pythonServer/dash/generatedPythonFiles.d.ts +0 -2
- package/lib/pythonServer/dash/generatedPythonFiles.js +0 -31
- package/lib/pythonServer/streamlit/generatedPythonFiles.d.ts +0 -2
- package/lib/pythonServer/streamlit/generatedPythonFiles.js +0 -147
- package/lib/pythonServer/tornado/generatedPythonFiles.d.ts +0 -3
- package/lib/pythonServer/tornado/generatedPythonFiles.js +0 -456
- package/src/pythonServer/common/generatedPythonFiles.ts +0 -73
- package/src/pythonServer/dash/generatedPythonFiles.ts +0 -32
- package/src/pythonServer/streamlit/generatedPythonFiles.ts +0 -148
- package/src/pythonServer/tornado/generatedPythonFiles.ts +0 -457
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { refreshIcon } from '@jupyterlab/ui-components';
|
|
2
|
+
import { CommandRegistry } from '@lumino/commands';
|
|
3
|
+
import { Panel } from '@lumino/widgets';
|
|
4
|
+
|
|
5
|
+
import { autoReloadIcon, linkIcon } from '../tools';
|
|
6
|
+
import { IJupyterpackDocTracker } from '../type';
|
|
7
|
+
import { IFramePanel } from './iframePanel';
|
|
8
|
+
import { PageConfig, URLExt } from '@jupyterlab/coreutils';
|
|
9
|
+
|
|
10
|
+
export const CommandIDs = {
|
|
11
|
+
RELOAD: 'jupyterpack:reload',
|
|
12
|
+
TOGGLE_AUTORELOAD: 'jupyterpack:toggleAutoreload',
|
|
13
|
+
OPEN_SPECTA: 'jupyterpack:openInSpecta'
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const labBaseUrl = PageConfig.getOption('baseUrl');
|
|
17
|
+
|
|
18
|
+
function getCurrentIframPanel(
|
|
19
|
+
tracker: IJupyterpackDocTracker
|
|
20
|
+
): IFramePanel | undefined {
|
|
21
|
+
const current = tracker.currentWidget?.content as Panel | undefined;
|
|
22
|
+
if (!current) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const widget = current.widgets[0] as IFramePanel | undefined;
|
|
26
|
+
if (!widget) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
return widget;
|
|
30
|
+
}
|
|
31
|
+
export function addCommands(
|
|
32
|
+
commands: CommandRegistry,
|
|
33
|
+
tracker: IJupyterpackDocTracker
|
|
34
|
+
) {
|
|
35
|
+
commands.addCommand(CommandIDs.RELOAD, {
|
|
36
|
+
caption: 'Reload',
|
|
37
|
+
isEnabled: () => {
|
|
38
|
+
return tracker.currentWidget !== null;
|
|
39
|
+
},
|
|
40
|
+
icon: refreshIcon,
|
|
41
|
+
execute: async () => {
|
|
42
|
+
const widget = getCurrentIframPanel(tracker);
|
|
43
|
+
if (widget) {
|
|
44
|
+
await widget.reload();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
const commandState = { toggled: false };
|
|
49
|
+
commands.addCommand(CommandIDs.TOGGLE_AUTORELOAD, {
|
|
50
|
+
isEnabled: () => {
|
|
51
|
+
return tracker.currentWidget !== null;
|
|
52
|
+
},
|
|
53
|
+
isToggled: () => {
|
|
54
|
+
const widget = getCurrentIframPanel(tracker);
|
|
55
|
+
return Boolean(widget?.autoreload);
|
|
56
|
+
},
|
|
57
|
+
icon: autoReloadIcon,
|
|
58
|
+
caption: e => {
|
|
59
|
+
return commandState.toggled
|
|
60
|
+
? 'Auto-reload enabled'
|
|
61
|
+
: 'Auto-reload disabled';
|
|
62
|
+
},
|
|
63
|
+
execute: async () => {
|
|
64
|
+
const widget = getCurrentIframPanel(tracker);
|
|
65
|
+
if (widget) {
|
|
66
|
+
widget.autoreload = !widget?.autoreload;
|
|
67
|
+
|
|
68
|
+
commands.notifyCommandChanged(CommandIDs.TOGGLE_AUTORELOAD);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
commands.addCommand(CommandIDs.OPEN_SPECTA, {
|
|
73
|
+
caption: 'Open in Specta',
|
|
74
|
+
isEnabled: () => {
|
|
75
|
+
return tracker.currentWidget !== null;
|
|
76
|
+
},
|
|
77
|
+
icon: linkIcon,
|
|
78
|
+
execute: async () => {
|
|
79
|
+
const context = tracker.currentWidget?.context;
|
|
80
|
+
if (!context) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const spectaUrl = new URL(
|
|
84
|
+
URLExt.join(labBaseUrl, 'specta'),
|
|
85
|
+
window.location.origin
|
|
86
|
+
);
|
|
87
|
+
spectaUrl.searchParams.set('path', context.path);
|
|
88
|
+
window.open(spectaUrl.toString(), '_blank');
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Widget } from '@lumino/widgets';
|
|
2
2
|
|
|
3
|
-
export class IFramePanel extends Widget {
|
|
3
|
+
export abstract class IFramePanel extends Widget {
|
|
4
4
|
constructor() {
|
|
5
5
|
super();
|
|
6
6
|
this.addClass('jupyterpack-iframe-panel');
|
|
@@ -20,6 +20,9 @@ export class IFramePanel extends Widget {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
abstract reload(): Promise<void>;
|
|
24
|
+
abstract autoreload: boolean;
|
|
25
|
+
abstract isReady: Promise<void>;
|
|
23
26
|
protected _iframe: HTMLIFrameElement;
|
|
24
27
|
protected _spinner: HTMLDivElement;
|
|
25
28
|
}
|
package/src/document/plugin.ts
CHANGED
|
@@ -4,20 +4,29 @@ import {
|
|
|
4
4
|
} from '@jupyterlab/application';
|
|
5
5
|
|
|
6
6
|
import { JupyterPackWidgetFactory } from './widgetFactory';
|
|
7
|
-
import { IConnectionManager } from '../type';
|
|
8
|
-
import { IConnectionManagerToken } from '../token';
|
|
7
|
+
import { IConnectionManager, IJupyterpackDocTracker } from '../type';
|
|
8
|
+
import { IConnectionManagerToken, IJupyterpackDocTrackerToken } from '../token';
|
|
9
|
+
import { WidgetTracker } from '@jupyterlab/apputils';
|
|
10
|
+
import { DocumentWidget } from '@jupyterlab/docregistry';
|
|
11
|
+
import { logoIcon } from '../tools';
|
|
12
|
+
import { addCommands } from './commands';
|
|
9
13
|
|
|
10
14
|
const FACTORY = 'jupyterpack';
|
|
11
15
|
const CONTENT_TYPE = 'jupyterpack';
|
|
12
16
|
|
|
13
|
-
export const spkPlugin: JupyterFrontEndPlugin<
|
|
17
|
+
export const spkPlugin: JupyterFrontEndPlugin<IJupyterpackDocTracker> = {
|
|
14
18
|
id: 'jupyterpack:spkplugin',
|
|
15
19
|
requires: [IConnectionManagerToken],
|
|
16
20
|
autoStart: true,
|
|
21
|
+
provides: IJupyterpackDocTrackerToken,
|
|
17
22
|
activate: (
|
|
18
23
|
app: JupyterFrontEnd,
|
|
19
24
|
connectionManager: IConnectionManager
|
|
20
|
-
):
|
|
25
|
+
): IJupyterpackDocTracker => {
|
|
26
|
+
const tracker = new WidgetTracker<DocumentWidget>({
|
|
27
|
+
namespace: FACTORY
|
|
28
|
+
});
|
|
29
|
+
addCommands(app.commands, tracker);
|
|
21
30
|
const widgetFactory = new JupyterPackWidgetFactory({
|
|
22
31
|
name: FACTORY,
|
|
23
32
|
modelName: 'text',
|
|
@@ -25,7 +34,8 @@ export const spkPlugin: JupyterFrontEndPlugin<void> = {
|
|
|
25
34
|
defaultFor: [CONTENT_TYPE],
|
|
26
35
|
commands: app.commands,
|
|
27
36
|
manager: app.serviceManager,
|
|
28
|
-
connectionManager
|
|
37
|
+
connectionManager,
|
|
38
|
+
tracker
|
|
29
39
|
});
|
|
30
40
|
|
|
31
41
|
// Registering the widget factory
|
|
@@ -35,10 +45,21 @@ export const spkPlugin: JupyterFrontEndPlugin<void> = {
|
|
|
35
45
|
app.docRegistry.addFileType({
|
|
36
46
|
name: CONTENT_TYPE,
|
|
37
47
|
displayName: 'SPK',
|
|
38
|
-
mimeTypes: ['
|
|
48
|
+
mimeTypes: ['application/json'],
|
|
39
49
|
extensions: ['.spk', '.SPK'],
|
|
40
50
|
fileFormat: 'json',
|
|
41
|
-
contentType: CONTENT_TYPE
|
|
51
|
+
contentType: CONTENT_TYPE,
|
|
52
|
+
icon: logoIcon
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
widgetFactory.widgetCreated.connect((_, widget) => {
|
|
56
|
+
widget.title.icon = logoIcon;
|
|
57
|
+
widget.context.pathChanged.connect(() => {
|
|
58
|
+
tracker.save(widget);
|
|
59
|
+
});
|
|
60
|
+
tracker.add(widget);
|
|
42
61
|
});
|
|
62
|
+
|
|
63
|
+
return tracker;
|
|
43
64
|
}
|
|
44
65
|
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CommandToolbarButton,
|
|
3
|
+
ReactiveToolbar
|
|
4
|
+
} from '@jupyterlab/ui-components';
|
|
5
|
+
import { CommandRegistry } from '@lumino/commands';
|
|
6
|
+
|
|
7
|
+
import { IJupyterpackDocTracker } from '../type';
|
|
8
|
+
import { CommandIDs } from './commands';
|
|
9
|
+
|
|
10
|
+
export class ToolbarWidget extends ReactiveToolbar {
|
|
11
|
+
constructor(options: {
|
|
12
|
+
tracker: IJupyterpackDocTracker;
|
|
13
|
+
commands: CommandRegistry;
|
|
14
|
+
}) {
|
|
15
|
+
super();
|
|
16
|
+
this.addClass('jupyterpack-toolbar');
|
|
17
|
+
this.addItem(
|
|
18
|
+
'Reload',
|
|
19
|
+
new CommandToolbarButton({
|
|
20
|
+
commands: options.commands,
|
|
21
|
+
id: CommandIDs.RELOAD
|
|
22
|
+
})
|
|
23
|
+
);
|
|
24
|
+
this.addItem(
|
|
25
|
+
'Toggle Auto Reload',
|
|
26
|
+
new CommandToolbarButton({
|
|
27
|
+
id: CommandIDs.TOGGLE_AUTORELOAD,
|
|
28
|
+
commands: options.commands
|
|
29
|
+
})
|
|
30
|
+
);
|
|
31
|
+
this.addItem(
|
|
32
|
+
'Open Specta',
|
|
33
|
+
new CommandToolbarButton({
|
|
34
|
+
id: CommandIDs.OPEN_SPECTA,
|
|
35
|
+
commands: options.commands
|
|
36
|
+
})
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
import { ABCWidgetFactory, DocumentRegistry } from '@jupyterlab/docregistry';
|
|
2
2
|
import { Contents, ServiceManager } from '@jupyterlab/services';
|
|
3
3
|
import { CommandRegistry } from '@lumino/commands';
|
|
4
|
+
import { UUID } from '@lumino/coreutils';
|
|
4
5
|
import { Panel } from '@lumino/widgets';
|
|
5
6
|
|
|
7
|
+
import { PythonWidget } from '../pythonWidget/pythonWidget';
|
|
8
|
+
import { PythonWidgetModel } from '../pythonWidget/pythonWidgetModel';
|
|
9
|
+
import { SandpackPanel } from '../sandpackWidget/sandpackPanel';
|
|
6
10
|
import {
|
|
7
11
|
IConnectionManager,
|
|
12
|
+
IJupyterpackDocTracker,
|
|
8
13
|
IJupyterPackFileFormat,
|
|
9
14
|
JupyterPackFramework
|
|
10
15
|
} from '../type';
|
|
11
|
-
import { SandpackPanel } from '../sandpackWidget/sandpackPanel';
|
|
12
16
|
import { JupyterPackDocWidget } from './jupyterpackDocWidget';
|
|
13
|
-
import {
|
|
14
|
-
import { UUID } from '@lumino/coreutils';
|
|
15
|
-
import { PythonWidget } from '../pythonWidget/pythonWidget';
|
|
17
|
+
import { ToolbarWidget } from './toolbar';
|
|
16
18
|
|
|
17
19
|
interface IOptions extends DocumentRegistry.IWidgetFactoryOptions {
|
|
18
20
|
commands: CommandRegistry;
|
|
19
21
|
manager: ServiceManager.IManager;
|
|
20
22
|
connectionManager: IConnectionManager;
|
|
23
|
+
tracker: IJupyterpackDocTracker;
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
export class JupyterPackWidgetFactory extends ABCWidgetFactory<JupyterPackDocWidget> {
|
|
@@ -72,9 +75,14 @@ export class JupyterPackWidgetFactory extends ABCWidgetFactory<JupyterPackDocWid
|
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
77
|
});
|
|
78
|
+
const toolbar = new ToolbarWidget({
|
|
79
|
+
tracker: this.options.tracker,
|
|
80
|
+
commands: this.options.commands
|
|
81
|
+
});
|
|
75
82
|
return new JupyterPackDocWidget({
|
|
76
83
|
context,
|
|
77
|
-
content
|
|
84
|
+
content,
|
|
85
|
+
toolbar
|
|
78
86
|
});
|
|
79
87
|
}
|
|
80
88
|
|
package/src/global.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { stringOrNone } from '../../tools';
|
|
2
2
|
import { IDict, JupyterPackFramework } from '../../type';
|
|
3
|
-
import { patch } from '../common/generatedPythonFiles';
|
|
4
3
|
import { KernelExecutor } from '../kernelExecutor';
|
|
5
|
-
import { bootstrap, dashLoader } from './generatedPythonFiles';
|
|
6
4
|
|
|
7
5
|
export class DashServer extends KernelExecutor {
|
|
8
6
|
async init(options: {
|
|
@@ -18,14 +16,20 @@ export class DashServer extends KernelExecutor {
|
|
|
18
16
|
kernelClientId,
|
|
19
17
|
framework: JupyterPackFramework.DASH
|
|
20
18
|
});
|
|
21
|
-
await this.executeCode({ code: patch });
|
|
22
19
|
await this.executeCode({
|
|
23
|
-
code:
|
|
20
|
+
code: `
|
|
21
|
+
import os
|
|
22
|
+
os.environ["DASH_URL_BASE_PATHNAME"] = "${baseURL}"
|
|
23
|
+
`
|
|
24
24
|
});
|
|
25
25
|
if (initCode) {
|
|
26
26
|
await this.executeCode({ code: initCode });
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
const loaderCode = `
|
|
29
|
+
from jupyterpack.dash import DashServer
|
|
30
|
+
${this._DASH_SERVER_VAR} = DashServer(app, "${baseURL}")
|
|
31
|
+
`;
|
|
32
|
+
await this.executeCode({ code: loaderCode });
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
getResponseFunctionFactory(options: {
|
|
@@ -36,22 +40,27 @@ export class DashServer extends KernelExecutor {
|
|
|
36
40
|
content?: string;
|
|
37
41
|
}) {
|
|
38
42
|
const { method, urlPath, headers, params, content } = options;
|
|
39
|
-
const code = `${this.
|
|
43
|
+
const code = `${this._DASH_SERVER_VAR}.get_response("${method}", "${urlPath}", headers=${JSON.stringify(headers)} , content=${stringOrNone(content)}, params=${stringOrNone(params)})`;
|
|
40
44
|
return code;
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
async disposePythonServer(): Promise<void> {
|
|
44
|
-
|
|
48
|
+
await this.executeCode({ code: `${this._DASH_SERVER_VAR}.dispose()` });
|
|
45
49
|
}
|
|
46
50
|
|
|
47
|
-
async
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
wsUrl: string;
|
|
51
|
-
protocol?: string;
|
|
51
|
+
async reloadPythonServer(options: {
|
|
52
|
+
entryPath?: string;
|
|
53
|
+
initCode?: string;
|
|
52
54
|
}): Promise<void> {
|
|
53
|
-
|
|
55
|
+
const { initCode } = options;
|
|
56
|
+
if (initCode) {
|
|
57
|
+
await this.executeCode({ code: initCode });
|
|
58
|
+
}
|
|
59
|
+
await this.executeCode(
|
|
60
|
+
{ code: `${this._DASH_SERVER_VAR}.reload(app)` },
|
|
61
|
+
true
|
|
62
|
+
);
|
|
54
63
|
}
|
|
55
64
|
|
|
56
|
-
private
|
|
65
|
+
private _DASH_SERVER_VAR = '__jupyterpack_dash_server';
|
|
57
66
|
}
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
} from '../tools';
|
|
10
10
|
import { IDict, IKernelExecutor, JupyterPackFramework } from '../type';
|
|
11
11
|
import websocketPatch from '../websocket/websocket.js?raw';
|
|
12
|
-
import { patch } from './common/generatedPythonFiles';
|
|
13
12
|
|
|
14
13
|
export abstract class KernelExecutor implements IKernelExecutor {
|
|
15
14
|
constructor(options: KernelExecutor.IOptions) {
|
|
@@ -22,6 +21,10 @@ export abstract class KernelExecutor implements IKernelExecutor {
|
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
abstract disposePythonServer(): Promise<void>;
|
|
24
|
+
abstract reloadPythonServer(options: {
|
|
25
|
+
entryPath?: string;
|
|
26
|
+
initCode?: string;
|
|
27
|
+
}): Promise<void>;
|
|
25
28
|
|
|
26
29
|
abstract getResponseFunctionFactory(options: {
|
|
27
30
|
urlPath: string;
|
|
@@ -37,7 +40,11 @@ export abstract class KernelExecutor implements IKernelExecutor {
|
|
|
37
40
|
instanceId: string;
|
|
38
41
|
kernelClientId: string;
|
|
39
42
|
}): Promise<void> {
|
|
40
|
-
|
|
43
|
+
const patchCode = `
|
|
44
|
+
from jupyterpack.common import patch_all
|
|
45
|
+
patch_all()
|
|
46
|
+
`;
|
|
47
|
+
await this.executeCode({ code: patchCode });
|
|
41
48
|
}
|
|
42
49
|
|
|
43
50
|
openWebsocketFunctionFactory(options: {
|
|
@@ -160,10 +167,13 @@ export abstract class KernelExecutor implements IKernelExecutor {
|
|
|
160
167
|
}
|
|
161
168
|
case 'stream': {
|
|
162
169
|
const content = (msg as KernelMessage.IStreamMsg).content;
|
|
170
|
+
if (content.text.length === 0) {
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
163
173
|
if (content.name === 'stderr') {
|
|
164
|
-
console.error('Kernel stream', content.text);
|
|
174
|
+
console.error('Kernel stream:', content.text);
|
|
165
175
|
} else {
|
|
166
|
-
console.log('Kernel stream', content.text);
|
|
176
|
+
console.log('Kernel stream:', content.text);
|
|
167
177
|
}
|
|
168
178
|
break;
|
|
169
179
|
}
|
|
@@ -204,19 +214,23 @@ export abstract class KernelExecutor implements IKernelExecutor {
|
|
|
204
214
|
framework: JupyterPackFramework;
|
|
205
215
|
}) {
|
|
206
216
|
const { instanceId, kernelClientId, framework } = options;
|
|
207
|
-
const
|
|
217
|
+
const fullLabextensionsUrl = PageConfig.getOption('fullLabextensionsUrl');
|
|
218
|
+
|
|
208
219
|
const baseURL = URLExt.join(
|
|
209
|
-
|
|
210
|
-
'
|
|
220
|
+
fullLabextensionsUrl,
|
|
221
|
+
'jupyterpack/static',
|
|
211
222
|
instanceId,
|
|
212
223
|
framework,
|
|
213
224
|
kernelClientId,
|
|
214
225
|
'/'
|
|
215
226
|
);
|
|
227
|
+
this._baseUrl = baseURL;
|
|
216
228
|
|
|
217
229
|
return baseURL;
|
|
218
230
|
}
|
|
219
231
|
|
|
232
|
+
protected _baseUrl: string | undefined;
|
|
233
|
+
|
|
220
234
|
private _isDisposed: boolean = false;
|
|
221
235
|
private _sessionConnection: Session.ISessionConnection;
|
|
222
236
|
private _wsPatch: string;
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { patch, tools } from '../common/generatedPythonFiles';
|
|
4
|
-
import { KernelExecutor } from '../kernelExecutor';
|
|
5
|
-
import {
|
|
6
|
-
bootstrap as tornadoBootstrap,
|
|
7
|
-
tornadoBridge
|
|
8
|
-
} from '../tornado/generatedPythonFiles';
|
|
9
|
-
import { bootstrap, streamlitLoader } from './generatedPythonFiles';
|
|
1
|
+
import { JupyterPackFramework } from '../../type';
|
|
2
|
+
import { TornadoServer } from '../tornado/tornadoServer';
|
|
10
3
|
|
|
11
|
-
export class StreamlitServer extends
|
|
4
|
+
export class StreamlitServer extends TornadoServer {
|
|
12
5
|
async init(options: {
|
|
13
6
|
entryPath?: string;
|
|
14
7
|
initCode?: string;
|
|
15
8
|
instanceId: string;
|
|
16
9
|
kernelClientId: string;
|
|
17
10
|
}) {
|
|
18
|
-
await super.init(options);
|
|
19
11
|
const { instanceId, kernelClientId, entryPath } = options;
|
|
20
12
|
if (!entryPath) {
|
|
21
13
|
throw new Error(
|
|
@@ -27,61 +19,49 @@ export class StreamlitServer extends KernelExecutor {
|
|
|
27
19
|
kernelClientId,
|
|
28
20
|
framework: JupyterPackFramework.STREAMLIT
|
|
29
21
|
});
|
|
30
|
-
await this.executeCode({ code: patch });
|
|
31
|
-
await this.executeCode({ code: tools.replaceAll('{{base_url}}', baseURL) });
|
|
32
|
-
await this.executeCode({ code: tornadoBootstrap });
|
|
33
|
-
await this.executeCode({ code: tornadoBridge });
|
|
34
|
-
await this.executeCode({ code: bootstrap });
|
|
35
22
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
urlPath: string;
|
|
44
|
-
method: string;
|
|
45
|
-
headers: IDict;
|
|
46
|
-
params?: string;
|
|
47
|
-
content?: string;
|
|
48
|
-
}) {
|
|
49
|
-
const { method, urlPath, headers, params, content } = options;
|
|
50
|
-
const code = `await ${this._GET_RESPONSE_FUNCTION}("${method}", "${urlPath}", headers=${JSON.stringify(headers)} , content=${stringOrNone(content)}, params=${stringOrNone(params)})`;
|
|
51
|
-
return code;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
openWebsocketFunctionFactory(options: {
|
|
55
|
-
instanceId: string;
|
|
56
|
-
kernelId: string;
|
|
57
|
-
wsUrl: string;
|
|
58
|
-
protocol?: string;
|
|
59
|
-
}): string {
|
|
60
|
-
const { instanceId, kernelId, wsUrl, protocol } = options;
|
|
23
|
+
const patchCode = `
|
|
24
|
+
from jupyterpack.common import set_base_url_env, patch_tornado, patch_all
|
|
25
|
+
patch_all()
|
|
26
|
+
patch_tornado()
|
|
27
|
+
set_base_url_env("${baseURL}")
|
|
28
|
+
`;
|
|
29
|
+
await this.executeCode({ code: patchCode });
|
|
61
30
|
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
31
|
+
const bootstrapCode = `
|
|
32
|
+
from jupyterpack.streamlit import patch_streamlit
|
|
33
|
+
patch_streamlit()
|
|
34
|
+
`;
|
|
35
|
+
await this.executeCode({ code: bootstrapCode });
|
|
65
36
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const { instanceId, kernelId, wsUrl, message } = options;
|
|
73
|
-
const code = `await ${this._SEND_WEBSOCKET_FUNCTION}("${instanceId}", "${kernelId}", "${wsUrl}", '''${message}''')`;
|
|
74
|
-
return code;
|
|
37
|
+
const stCode = `
|
|
38
|
+
from jupyterpack.streamlit import StreamlitServer, create_streamlit_app
|
|
39
|
+
__jupyterpack_st_server, __jupyterpack_tor_app = await create_streamlit_app("${entryPath}", "${baseURL}")
|
|
40
|
+
${this._SERVER_VAR} = StreamlitServer(__jupyterpack_tor_app, "${baseURL}", __jupyterpack_st_server)
|
|
41
|
+
`;
|
|
42
|
+
await this.executeCode({ code: stCode });
|
|
75
43
|
}
|
|
76
44
|
|
|
77
|
-
async
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
45
|
+
async reloadPythonServer(options: {
|
|
46
|
+
entryPath?: string;
|
|
47
|
+
initCode?: string;
|
|
48
|
+
}): Promise<void> {
|
|
49
|
+
const { entryPath } = options;
|
|
50
|
+
if (!entryPath || !this._baseUrl) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const reloadCode = `
|
|
54
|
+
${this._SERVER_VAR}.dispose()
|
|
55
|
+
__jupyterpack_st_server, __jupyterpack_tor_app = await create_streamlit_app("${entryPath}", "${this._baseUrl}")
|
|
56
|
+
${this._SERVER_VAR}.reload(__jupyterpack_tor_app, __jupyterpack_st_server)
|
|
57
|
+
`;
|
|
58
|
+
await this.executeCode(
|
|
59
|
+
{
|
|
60
|
+
code: reloadCode
|
|
61
|
+
},
|
|
62
|
+
true
|
|
63
|
+
);
|
|
81
64
|
}
|
|
82
65
|
|
|
83
|
-
|
|
84
|
-
private _OPEN_WEBSOCKET_FUNCTION = '__jupyterpack_streamlit_open_ws';
|
|
85
|
-
private _SEND_WEBSOCKET_FUNCTION =
|
|
86
|
-
'__jupyterpack_streamlit_receive_ws_message';
|
|
66
|
+
protected _SERVER_VAR = '__jupyterpack_streamlit_server';
|
|
87
67
|
}
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { stringOrNone } from '../../tools';
|
|
2
2
|
import { IDict, JupyterPackFramework } from '../../type';
|
|
3
|
-
import { tools } from '../common/generatedPythonFiles';
|
|
4
3
|
import { KernelExecutor } from '../kernelExecutor';
|
|
5
|
-
|
|
6
|
-
bootstrap,
|
|
7
|
-
tornadoBridge,
|
|
8
|
-
tornadoLoader
|
|
9
|
-
} from './generatedPythonFiles';
|
|
4
|
+
|
|
10
5
|
export class TornadoServer extends KernelExecutor {
|
|
11
6
|
async init(options: {
|
|
12
7
|
initCode?: string;
|
|
@@ -21,14 +16,22 @@ export class TornadoServer extends KernelExecutor {
|
|
|
21
16
|
kernelClientId,
|
|
22
17
|
framework: JupyterPackFramework.TORNADO
|
|
23
18
|
});
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
const bootstrapCode = `
|
|
20
|
+
from jupyterpack.common import set_base_url_env, patch_tornado
|
|
21
|
+
set_base_url_env("${baseURL}")
|
|
22
|
+
patch_tornado()
|
|
23
|
+
|
|
24
|
+
`;
|
|
25
|
+
await this.executeCode({ code: bootstrapCode });
|
|
27
26
|
if (initCode) {
|
|
28
27
|
const initCodeWithUrl = initCode.replaceAll('{{base_url}}', baseURL);
|
|
29
28
|
await this.executeCode({ code: initCodeWithUrl });
|
|
30
|
-
const
|
|
31
|
-
|
|
29
|
+
const loaderCode = `
|
|
30
|
+
from jupyterpack.tornado import TornadoServer
|
|
31
|
+
${this._SERVER_VAR} = TornadoServer(app, "${baseURL}")
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
await this.executeCode({ code: loaderCode });
|
|
32
35
|
}
|
|
33
36
|
}
|
|
34
37
|
|
|
@@ -40,7 +43,7 @@ export class TornadoServer extends KernelExecutor {
|
|
|
40
43
|
content?: string;
|
|
41
44
|
}) {
|
|
42
45
|
const { method, urlPath, headers, params, content } = options;
|
|
43
|
-
const code = `await ${this.
|
|
46
|
+
const code = `await ${this._SERVER_VAR}.get_response("${method}", "${urlPath}", headers=${JSON.stringify(headers)} , content=${stringOrNone(content)}, params=${stringOrNone(params)})`;
|
|
44
47
|
return code;
|
|
45
48
|
}
|
|
46
49
|
|
|
@@ -52,7 +55,7 @@ export class TornadoServer extends KernelExecutor {
|
|
|
52
55
|
}): string {
|
|
53
56
|
const { instanceId, kernelId, wsUrl, protocol } = options;
|
|
54
57
|
|
|
55
|
-
const code = `await ${this.
|
|
58
|
+
const code = `await ${this._SERVER_VAR}.open_ws("${instanceId}", "${kernelId}", "${wsUrl}", ${stringOrNone(protocol)})`;
|
|
56
59
|
return code;
|
|
57
60
|
}
|
|
58
61
|
|
|
@@ -63,18 +66,32 @@ export class TornadoServer extends KernelExecutor {
|
|
|
63
66
|
message: string;
|
|
64
67
|
}): string {
|
|
65
68
|
const { instanceId, kernelId, wsUrl, message } = options;
|
|
66
|
-
const code = `await ${this.
|
|
69
|
+
const code = `await ${this._SERVER_VAR}.receive_ws_message("${instanceId}", "${kernelId}", "${wsUrl}", '''${message}''')`;
|
|
67
70
|
return code;
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
async disposePythonServer(): Promise<void> {
|
|
71
74
|
await this.executeCode({
|
|
72
|
-
code:
|
|
75
|
+
code: `${this._SERVER_VAR}.dispose()`
|
|
73
76
|
});
|
|
74
77
|
}
|
|
75
78
|
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
async reloadPythonServer(options: {
|
|
80
|
+
entryPath?: string;
|
|
81
|
+
initCode?: string;
|
|
82
|
+
}): Promise<void> {
|
|
83
|
+
const { initCode } = options;
|
|
84
|
+
if (initCode) {
|
|
85
|
+
await this.executeCode({
|
|
86
|
+
code: initCode.replaceAll('{{base_url}}', this._baseUrl ?? '')
|
|
87
|
+
});
|
|
88
|
+
const reloadCode = `
|
|
89
|
+
${this._SERVER_VAR}.dispose()
|
|
90
|
+
${this._SERVER_VAR}.reload(app)
|
|
91
|
+
`;
|
|
92
|
+
await this.executeCode({ code: reloadCode }, true);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
78
95
|
|
|
79
|
-
|
|
96
|
+
protected _SERVER_VAR = '__jupyterpack_tornado_server';
|
|
80
97
|
}
|