jupyterpack 0.3.0 → 0.5.1
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/README.md +1 -1
- 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 +14 -6
- package/lib/index.d.ts +1 -1
- package/lib/pythonServer/baseServer.d.ts +82 -0
- package/lib/pythonServer/baseServer.js +141 -0
- package/lib/pythonServer/dash/dashServer.d.ts +5 -17
- package/lib/pythonServer/dash/dashServer.js +19 -24
- package/lib/pythonServer/index.d.ts +3 -3
- package/lib/pythonServer/index.js +5 -1
- package/lib/pythonServer/kernelExecutor.d.ts +2 -53
- package/lib/pythonServer/kernelExecutor.js +5 -70
- package/lib/pythonServer/shiny/shinyServer.d.ts +14 -0
- package/lib/pythonServer/shiny/shinyServer.js +49 -0
- package/lib/pythonServer/starlette/starletteServer.d.ts +13 -0
- package/lib/pythonServer/starlette/starletteServer.js +49 -0
- package/lib/pythonServer/streamlit/streamlitServer.d.ts +6 -26
- package/lib/pythonServer/streamlit/streamlitServer.js +33 -41
- package/lib/pythonServer/tornado/tornadoServer.d.ts +6 -26
- package/lib/pythonServer/tornado/tornadoServer.js +28 -36
- 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/swConnection/mainConnectionManager.d.ts +4 -4
- package/lib/swConnection/mainConnectionManager.js +23 -12
- package/lib/token.d.ts +2 -1
- package/lib/token.js +1 -0
- package/lib/tools.d.ts +6 -0
- package/lib/tools.js +25 -0
- package/lib/type.d.ts +39 -4
- package/lib/type.js +2 -0
- package/lib/websocket/websocket.js +5 -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 +16 -6
- package/src/global.d.ts +5 -0
- package/src/pythonServer/baseServer.ts +245 -0
- package/src/pythonServer/dash/dashServer.ts +25 -35
- package/src/pythonServer/index.ts +9 -5
- package/src/pythonServer/kernelExecutor.ts +8 -147
- package/src/pythonServer/shiny/shinyServer.ts +62 -0
- package/src/pythonServer/starlette/starletteServer.ts +59 -0
- package/src/pythonServer/streamlit/streamlitServer.ts +40 -62
- package/src/pythonServer/tornado/tornadoServer.ts +33 -60
- package/src/pythonWidget/comm.ts +65 -0
- package/src/pythonWidget/pythonWidget.ts +19 -1
- package/src/pythonWidget/pythonWidgetModel.ts +107 -20
- package/src/sandpackWidget/sandpackFilesModel.ts +17 -3
- package/src/sandpackWidget/sandpackPanel.ts +45 -4
- package/src/swConnection/mainConnectionManager.ts +28 -20
- package/src/token.ts +5 -1
- package/src/tools.ts +31 -0
- package/src/type.ts +46 -7
- package/src/websocket/websocket.ts +9 -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
|
@@ -1,74 +1,12 @@
|
|
|
1
|
-
import { PageConfig, URLExt } from '@jupyterlab/coreutils';
|
|
2
1
|
import stripAnsi from 'strip-ansi';
|
|
3
|
-
import { arrayBufferToBase64, base64ToArrayBuffer, base64ToString, isBinaryContentType } from '../tools';
|
|
4
|
-
import websocketPatch from '../websocket/websocket.js?raw';
|
|
5
|
-
import { patch } from './common/generatedPythonFiles';
|
|
6
2
|
export class KernelExecutor {
|
|
7
3
|
constructor(options) {
|
|
8
4
|
this._isDisposed = false;
|
|
9
5
|
this._sessionConnection = options.sessionConnection;
|
|
10
|
-
this._wsPatch = websocketPatch.replaceAll('"use strict";', '');
|
|
11
6
|
}
|
|
12
7
|
get isDisposed() {
|
|
13
8
|
return this._isDisposed;
|
|
14
9
|
}
|
|
15
|
-
async init(options) {
|
|
16
|
-
await this.executeCode({ code: patch });
|
|
17
|
-
}
|
|
18
|
-
openWebsocketFunctionFactory(options) {
|
|
19
|
-
return undefined;
|
|
20
|
-
}
|
|
21
|
-
sendWebsocketMessageFunctionFactory(options) {
|
|
22
|
-
return undefined;
|
|
23
|
-
}
|
|
24
|
-
async openWebsocket(options) {
|
|
25
|
-
const code = this.openWebsocketFunctionFactory(options);
|
|
26
|
-
if (code) {
|
|
27
|
-
await this.executeCode({ code });
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
async sendWebsocketMessage(options) {
|
|
31
|
-
const code = this.sendWebsocketMessageFunctionFactory(options);
|
|
32
|
-
if (code) {
|
|
33
|
-
await this.executeCode({ code });
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
async getResponse(options) {
|
|
37
|
-
var _a;
|
|
38
|
-
const { method, urlPath, requestBody, params, headers } = options;
|
|
39
|
-
const content = requestBody ? arrayBufferToBase64(requestBody) : undefined;
|
|
40
|
-
const code = this.getResponseFunctionFactory({
|
|
41
|
-
method,
|
|
42
|
-
urlPath,
|
|
43
|
-
headers,
|
|
44
|
-
params,
|
|
45
|
-
content
|
|
46
|
-
});
|
|
47
|
-
const raw = await this.executeCode({ code }, true);
|
|
48
|
-
if (!raw) {
|
|
49
|
-
throw new Error(`Missing response for ${urlPath}`);
|
|
50
|
-
}
|
|
51
|
-
const jsonStr = raw.replaceAll("'", '');
|
|
52
|
-
const obj = JSON.parse(jsonStr);
|
|
53
|
-
const responseHeaders = JSON.parse(atob(obj.headers));
|
|
54
|
-
const contentType = (_a = responseHeaders === null || responseHeaders === void 0 ? void 0 : responseHeaders['Content-Type']) !== null && _a !== void 0 ? _a : responseHeaders === null || responseHeaders === void 0 ? void 0 : responseHeaders['content-type'];
|
|
55
|
-
let responseContent;
|
|
56
|
-
if (isBinaryContentType(contentType)) {
|
|
57
|
-
responseContent = base64ToArrayBuffer(obj.content);
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
responseContent = base64ToString(obj.content);
|
|
61
|
-
}
|
|
62
|
-
if (contentType && contentType.toLowerCase() === 'text/html') {
|
|
63
|
-
responseContent = responseContent.replace('<head>', `<head>\n<script>\n${this._wsPatch}\n</script>\n`);
|
|
64
|
-
}
|
|
65
|
-
const decodedObj = {
|
|
66
|
-
status_code: obj.status_code,
|
|
67
|
-
headers: responseHeaders,
|
|
68
|
-
content: responseContent
|
|
69
|
-
};
|
|
70
|
-
return decodedObj;
|
|
71
|
-
}
|
|
72
10
|
async executeCode(code, waitForResult) {
|
|
73
11
|
var _a;
|
|
74
12
|
const kernel = (_a = this._sessionConnection) === null || _a === void 0 ? void 0 : _a.kernel;
|
|
@@ -92,11 +30,14 @@ export class KernelExecutor {
|
|
|
92
30
|
}
|
|
93
31
|
case 'stream': {
|
|
94
32
|
const content = msg.content;
|
|
33
|
+
if (content.text.length === 0) {
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
95
36
|
if (content.name === 'stderr') {
|
|
96
|
-
console.error('Kernel stream', content.text);
|
|
37
|
+
console.error('Kernel stream:', content.text);
|
|
97
38
|
}
|
|
98
39
|
else {
|
|
99
|
-
console.log('Kernel stream', content.text);
|
|
40
|
+
console.log('Kernel stream:', content.text);
|
|
100
41
|
}
|
|
101
42
|
break;
|
|
102
43
|
}
|
|
@@ -124,10 +65,4 @@ export class KernelExecutor {
|
|
|
124
65
|
this._isDisposed = true;
|
|
125
66
|
this._sessionConnection.dispose();
|
|
126
67
|
}
|
|
127
|
-
buildBaseURL(options) {
|
|
128
|
-
const { instanceId, kernelClientId, framework } = options;
|
|
129
|
-
const labBaseUrl = PageConfig.getOption('baseUrl');
|
|
130
|
-
const baseURL = URLExt.join(labBaseUrl, 'extensions/jupyterpack/static', instanceId, framework, kernelClientId, '/');
|
|
131
|
-
return baseURL;
|
|
132
|
-
}
|
|
133
68
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BasePythonServer } from '../baseServer';
|
|
2
|
+
export declare class ShinyServer extends BasePythonServer {
|
|
3
|
+
init(options: {
|
|
4
|
+
entryPath?: string;
|
|
5
|
+
initCode?: string;
|
|
6
|
+
instanceId: string;
|
|
7
|
+
kernelClientId: string;
|
|
8
|
+
}): Promise<void>;
|
|
9
|
+
disposePythonServer(): Promise<void>;
|
|
10
|
+
reloadPythonServer(options: {
|
|
11
|
+
entryPath?: string;
|
|
12
|
+
initCode?: string;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { JupyterPackFramework } from '../../type';
|
|
2
|
+
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
export class ShinyServer extends BasePythonServer {
|
|
4
|
+
async init(options) {
|
|
5
|
+
await super.init(options);
|
|
6
|
+
const { instanceId, kernelClientId, entryPath } = options;
|
|
7
|
+
const baseURL = this.buildBaseURL({
|
|
8
|
+
instanceId,
|
|
9
|
+
kernelClientId,
|
|
10
|
+
framework: JupyterPackFramework.SHINY
|
|
11
|
+
});
|
|
12
|
+
const bootstrapCode = `
|
|
13
|
+
from jupyterpack.common import set_base_url_env
|
|
14
|
+
set_base_url_env("${baseURL}")
|
|
15
|
+
from jupyterpack.shiny import patch_shiny
|
|
16
|
+
patch_shiny()
|
|
17
|
+
`;
|
|
18
|
+
await this.kernelExecutor.executeCode({ code: bootstrapCode });
|
|
19
|
+
if (entryPath) {
|
|
20
|
+
const loaderCode = `
|
|
21
|
+
from jupyterpack.shiny import ShinyServer, get_shiny_app
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
${this._server_var} = ShinyServer(get_shiny_app("${entryPath}"), "${baseURL}")
|
|
25
|
+
`;
|
|
26
|
+
await this.kernelExecutor.executeCode({ code: loaderCode });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async disposePythonServer() {
|
|
30
|
+
await this.kernelExecutor.executeCode({
|
|
31
|
+
code: `${this._server_var}.dispose()`
|
|
32
|
+
});
|
|
33
|
+
for (const element of this._openedWebsockets) {
|
|
34
|
+
await this.closeWebsocket(element);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async reloadPythonServer(options) {
|
|
38
|
+
const { entryPath } = options;
|
|
39
|
+
if (entryPath) {
|
|
40
|
+
const reloadCode = `
|
|
41
|
+
from jupyterpack.shiny import get_shiny_app
|
|
42
|
+
|
|
43
|
+
await ${this._server_var}.dispose()
|
|
44
|
+
${this._server_var}.reload(get_shiny_app("${entryPath}"))
|
|
45
|
+
`;
|
|
46
|
+
await this.kernelExecutor.executeCode({ code: reloadCode }, true);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BasePythonServer } from '../baseServer';
|
|
2
|
+
export declare class StarletteServer extends BasePythonServer {
|
|
3
|
+
init(options: {
|
|
4
|
+
initCode?: string;
|
|
5
|
+
instanceId: string;
|
|
6
|
+
kernelClientId: string;
|
|
7
|
+
}): Promise<void>;
|
|
8
|
+
disposePythonServer(): Promise<void>;
|
|
9
|
+
reloadPythonServer(options: {
|
|
10
|
+
entryPath?: string;
|
|
11
|
+
initCode?: string;
|
|
12
|
+
}): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { JupyterPackFramework } from '../../type';
|
|
2
|
+
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
export class StarletteServer extends BasePythonServer {
|
|
4
|
+
async init(options) {
|
|
5
|
+
await super.init(options);
|
|
6
|
+
const { initCode, instanceId, kernelClientId } = options;
|
|
7
|
+
const baseURL = this.buildBaseURL({
|
|
8
|
+
instanceId,
|
|
9
|
+
kernelClientId,
|
|
10
|
+
framework: JupyterPackFramework.STARLETTE
|
|
11
|
+
});
|
|
12
|
+
const bootstrapCode = `
|
|
13
|
+
from jupyterpack.common import set_base_url_env
|
|
14
|
+
set_base_url_env("${baseURL}")
|
|
15
|
+
`;
|
|
16
|
+
await this.kernelExecutor.executeCode({ code: bootstrapCode });
|
|
17
|
+
if (initCode) {
|
|
18
|
+
const initCodeWithUrl = initCode.replaceAll('{{base_url}}', baseURL);
|
|
19
|
+
await this.kernelExecutor.executeCode({ code: initCodeWithUrl });
|
|
20
|
+
const loaderCode = `
|
|
21
|
+
from jupyterpack.asgi import AsgiServer
|
|
22
|
+
${this._server_var} = AsgiServer(app, "${baseURL}")
|
|
23
|
+
`;
|
|
24
|
+
await this.kernelExecutor.executeCode({ code: loaderCode });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async disposePythonServer() {
|
|
28
|
+
await this.kernelExecutor.executeCode({
|
|
29
|
+
code: `${this._server_var}.dispose()`
|
|
30
|
+
});
|
|
31
|
+
for (const element of this._openedWebsockets) {
|
|
32
|
+
await this.closeWebsocket(element);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async reloadPythonServer(options) {
|
|
36
|
+
var _a;
|
|
37
|
+
const { initCode } = options;
|
|
38
|
+
if (initCode) {
|
|
39
|
+
await this.kernelExecutor.executeCode({
|
|
40
|
+
code: initCode.replaceAll('{{base_url}}', (_a = this._baseUrl) !== null && _a !== void 0 ? _a : '')
|
|
41
|
+
});
|
|
42
|
+
const reloadCode = `
|
|
43
|
+
await ${this._server_var}.dispose()
|
|
44
|
+
${this._server_var}.reload(app)
|
|
45
|
+
`;
|
|
46
|
+
await this.kernelExecutor.executeCode({ code: reloadCode }, true);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -1,33 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export declare class StreamlitServer extends KernelExecutor {
|
|
1
|
+
import { TornadoServer } from '../tornado/tornadoServer';
|
|
2
|
+
export declare class StreamlitServer extends TornadoServer {
|
|
4
3
|
init(options: {
|
|
5
4
|
entryPath?: string;
|
|
6
5
|
initCode?: string;
|
|
7
6
|
instanceId: string;
|
|
8
7
|
kernelClientId: string;
|
|
9
8
|
}): Promise<void>;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
params?: string;
|
|
15
|
-
content?: string;
|
|
16
|
-
}): string;
|
|
17
|
-
openWebsocketFunctionFactory(options: {
|
|
18
|
-
instanceId: string;
|
|
19
|
-
kernelId: string;
|
|
20
|
-
wsUrl: string;
|
|
21
|
-
protocol?: string;
|
|
22
|
-
}): string;
|
|
23
|
-
sendWebsocketMessageFunctionFactory(options: {
|
|
24
|
-
instanceId: string;
|
|
25
|
-
kernelId: string;
|
|
26
|
-
wsUrl: string;
|
|
27
|
-
message: string;
|
|
28
|
-
}): string;
|
|
29
|
-
disposePythonServer(): Promise<void>;
|
|
30
|
-
private _GET_RESPONSE_FUNCTION;
|
|
31
|
-
private _OPEN_WEBSOCKET_FUNCTION;
|
|
32
|
-
private _SEND_WEBSOCKET_FUNCTION;
|
|
9
|
+
reloadPythonServer(options: {
|
|
10
|
+
entryPath?: string;
|
|
11
|
+
initCode?: string;
|
|
12
|
+
}): Promise<void>;
|
|
33
13
|
}
|
|
@@ -1,18 +1,7 @@
|
|
|
1
|
-
import { stringOrNone } from '../../tools';
|
|
2
1
|
import { JupyterPackFramework } from '../../type';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { bootstrap as tornadoBootstrap, tornadoBridge } from '../tornado/generatedPythonFiles';
|
|
6
|
-
import { bootstrap, streamlitLoader } from './generatedPythonFiles';
|
|
7
|
-
export class StreamlitServer extends KernelExecutor {
|
|
8
|
-
constructor() {
|
|
9
|
-
super(...arguments);
|
|
10
|
-
this._GET_RESPONSE_FUNCTION = '__jupyterpack_streamlit_get_response';
|
|
11
|
-
this._OPEN_WEBSOCKET_FUNCTION = '__jupyterpack_streamlit_open_ws';
|
|
12
|
-
this._SEND_WEBSOCKET_FUNCTION = '__jupyterpack_streamlit_receive_ws_message';
|
|
13
|
-
}
|
|
2
|
+
import { TornadoServer } from '../tornado/tornadoServer';
|
|
3
|
+
export class StreamlitServer extends TornadoServer {
|
|
14
4
|
async init(options) {
|
|
15
|
-
await super.init(options);
|
|
16
5
|
const { instanceId, kernelClientId, entryPath } = options;
|
|
17
6
|
if (!entryPath) {
|
|
18
7
|
throw new Error('Missing streamlit entry path, please check your SPK file');
|
|
@@ -22,34 +11,37 @@ export class StreamlitServer extends KernelExecutor {
|
|
|
22
11
|
kernelClientId,
|
|
23
12
|
framework: JupyterPackFramework.STREAMLIT
|
|
24
13
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return code;
|
|
14
|
+
const patchCode = `
|
|
15
|
+
from jupyterpack.common import set_base_url_env, patch_tornado, patch_all
|
|
16
|
+
patch_all()
|
|
17
|
+
patch_tornado()
|
|
18
|
+
set_base_url_env("${baseURL}")
|
|
19
|
+
`;
|
|
20
|
+
await this.kernelExecutor.executeCode({ code: patchCode });
|
|
21
|
+
const bootstrapCode = `
|
|
22
|
+
from jupyterpack.streamlit import patch_streamlit
|
|
23
|
+
patch_streamlit()
|
|
24
|
+
`;
|
|
25
|
+
await this.kernelExecutor.executeCode({ code: bootstrapCode });
|
|
26
|
+
const stCode = `
|
|
27
|
+
from jupyterpack.streamlit import StreamlitServer, create_streamlit_app
|
|
28
|
+
__jupyterpack_st_server, __jupyterpack_tor_app = await create_streamlit_app("${entryPath}", "${baseURL}")
|
|
29
|
+
${this._server_var} = StreamlitServer(__jupyterpack_tor_app, "${baseURL}", __jupyterpack_st_server)
|
|
30
|
+
`;
|
|
31
|
+
await this.kernelExecutor.executeCode({ code: stCode });
|
|
44
32
|
}
|
|
45
|
-
|
|
46
|
-
const {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
33
|
+
async reloadPythonServer(options) {
|
|
34
|
+
const { entryPath } = options;
|
|
35
|
+
if (!entryPath || !this._baseUrl) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const reloadCode = `
|
|
39
|
+
${this._server_var}.dispose()
|
|
40
|
+
__jupyterpack_st_server, __jupyterpack_tor_app = await create_streamlit_app("${entryPath}", "${this._baseUrl}")
|
|
41
|
+
${this._server_var}.reload(__jupyterpack_tor_app, __jupyterpack_st_server)
|
|
42
|
+
`;
|
|
43
|
+
await this.kernelExecutor.executeCode({
|
|
44
|
+
code: reloadCode
|
|
45
|
+
}, true);
|
|
54
46
|
}
|
|
55
47
|
}
|
|
@@ -1,32 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export declare class TornadoServer extends KernelExecutor {
|
|
1
|
+
import { BasePythonServer } from '../baseServer';
|
|
2
|
+
export declare class TornadoServer extends BasePythonServer {
|
|
4
3
|
init(options: {
|
|
5
4
|
initCode?: string;
|
|
6
5
|
instanceId: string;
|
|
7
6
|
kernelClientId: string;
|
|
8
7
|
}): Promise<void>;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
params?: string;
|
|
14
|
-
content?: string;
|
|
15
|
-
}): string;
|
|
16
|
-
openWebsocketFunctionFactory(options: {
|
|
17
|
-
instanceId: string;
|
|
18
|
-
kernelId: string;
|
|
19
|
-
wsUrl: string;
|
|
20
|
-
protocol?: string;
|
|
21
|
-
}): string;
|
|
22
|
-
sendWebsocketMessageFunctionFactory(options: {
|
|
23
|
-
instanceId: string;
|
|
24
|
-
kernelId: string;
|
|
25
|
-
wsUrl: string;
|
|
26
|
-
message: string;
|
|
27
|
-
}): string;
|
|
28
|
-
disposePythonServer(): Promise<void>;
|
|
29
|
-
private _GET_RESPONSE_FUNCTION;
|
|
30
|
-
private _OPEN_WEBSOCKET_FUNCTION;
|
|
31
|
-
private _SEND_WEBSOCKET_FUNCTION;
|
|
8
|
+
reloadPythonServer(options: {
|
|
9
|
+
entryPath?: string;
|
|
10
|
+
initCode?: string;
|
|
11
|
+
}): Promise<void>;
|
|
32
12
|
}
|
|
@@ -1,15 +1,6 @@
|
|
|
1
|
-
import { stringOrNone } from '../../tools';
|
|
2
1
|
import { JupyterPackFramework } from '../../type';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { bootstrap, tornadoBridge, tornadoLoader } from './generatedPythonFiles';
|
|
6
|
-
export class TornadoServer extends KernelExecutor {
|
|
7
|
-
constructor() {
|
|
8
|
-
super(...arguments);
|
|
9
|
-
this._GET_RESPONSE_FUNCTION = '__jupyterpack_tornado_get_response';
|
|
10
|
-
this._OPEN_WEBSOCKET_FUNCTION = '__jupyterpack_tornado_open_ws';
|
|
11
|
-
this._SEND_WEBSOCKET_FUNCTION = '__jupyterpack_tornado_receive_ws_message';
|
|
12
|
-
}
|
|
2
|
+
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
export class TornadoServer extends BasePythonServer {
|
|
13
4
|
async init(options) {
|
|
14
5
|
await super.init(options);
|
|
15
6
|
const { initCode, instanceId, kernelClientId } = options;
|
|
@@ -18,34 +9,35 @@ export class TornadoServer extends KernelExecutor {
|
|
|
18
9
|
kernelClientId,
|
|
19
10
|
framework: JupyterPackFramework.TORNADO
|
|
20
11
|
});
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
const bootstrapCode = `
|
|
13
|
+
from jupyterpack.common import set_base_url_env, patch_tornado
|
|
14
|
+
set_base_url_env("${baseURL}")
|
|
15
|
+
patch_tornado()
|
|
16
|
+
|
|
17
|
+
`;
|
|
18
|
+
await this.kernelExecutor.executeCode({ code: bootstrapCode });
|
|
24
19
|
if (initCode) {
|
|
25
20
|
const initCodeWithUrl = initCode.replaceAll('{{base_url}}', baseURL);
|
|
26
|
-
await this.executeCode({ code: initCodeWithUrl });
|
|
27
|
-
const
|
|
28
|
-
|
|
21
|
+
await this.kernelExecutor.executeCode({ code: initCodeWithUrl });
|
|
22
|
+
const loaderCode = `
|
|
23
|
+
from jupyterpack.tornado import TornadoServer
|
|
24
|
+
${this._server_var} = TornadoServer(app, "${baseURL}")
|
|
25
|
+
`;
|
|
26
|
+
await this.kernelExecutor.executeCode({ code: loaderCode });
|
|
29
27
|
}
|
|
30
28
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return code;
|
|
45
|
-
}
|
|
46
|
-
async disposePythonServer() {
|
|
47
|
-
await this.executeCode({
|
|
48
|
-
code: '__jupyterpack_tornado_dispose()'
|
|
49
|
-
});
|
|
29
|
+
async reloadPythonServer(options) {
|
|
30
|
+
var _a;
|
|
31
|
+
const { initCode } = options;
|
|
32
|
+
if (initCode) {
|
|
33
|
+
await this.kernelExecutor.executeCode({
|
|
34
|
+
code: initCode.replaceAll('{{base_url}}', (_a = this._baseUrl) !== null && _a !== void 0 ? _a : '')
|
|
35
|
+
});
|
|
36
|
+
const reloadCode = `
|
|
37
|
+
${this._server_var}.dispose()
|
|
38
|
+
${this._server_var}.reload(app)
|
|
39
|
+
`;
|
|
40
|
+
await this.kernelExecutor.executeCode({ code: reloadCode }, true);
|
|
41
|
+
}
|
|
50
42
|
}
|
|
51
43
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Kernel } from '@jupyterlab/services';
|
|
2
|
+
export declare class CommBroadcastManager {
|
|
3
|
+
constructor();
|
|
4
|
+
registerKernel(kernel: Kernel.IKernelConnection): void;
|
|
5
|
+
unregisterKernel(kernelId?: string): void;
|
|
6
|
+
private _handle_comm_open;
|
|
7
|
+
dispose(): void;
|
|
8
|
+
private _kernels;
|
|
9
|
+
private _comms;
|
|
10
|
+
private _broadcastChannels;
|
|
11
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const COMM_NAME = 'jupyterpack:broadcast:comm';
|
|
2
|
+
export class CommBroadcastManager {
|
|
3
|
+
constructor() {
|
|
4
|
+
this._handle_comm_open = async (comm, msg, kernelId) => {
|
|
5
|
+
var _a;
|
|
6
|
+
if (this._comms.has(kernelId)) {
|
|
7
|
+
(_a = this._comms.get(kernelId)) === null || _a === void 0 ? void 0 : _a.push(comm);
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
this._comms.set(kernelId, [comm]);
|
|
11
|
+
}
|
|
12
|
+
const channelName = msg.metadata.channel_name;
|
|
13
|
+
if (!channelName) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (!this._broadcastChannels.has(channelName)) {
|
|
17
|
+
this._broadcastChannels.set(channelName, new BroadcastChannel(channelName));
|
|
18
|
+
}
|
|
19
|
+
const broadcastChannel = this._broadcastChannels.get(channelName);
|
|
20
|
+
comm.onMsg = commMsg => {
|
|
21
|
+
const { data } = commMsg.content;
|
|
22
|
+
broadcastChannel.postMessage(data);
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
this._kernels = new Map();
|
|
26
|
+
this._comms = new Map();
|
|
27
|
+
this._broadcastChannels = new Map();
|
|
28
|
+
this._kernels = new Map();
|
|
29
|
+
this._comms = new Map();
|
|
30
|
+
}
|
|
31
|
+
registerKernel(kernel) {
|
|
32
|
+
this._kernels.set(kernel.id, kernel);
|
|
33
|
+
kernel.registerCommTarget(COMM_NAME, (comm, msg) => this._handle_comm_open(comm, msg, kernel.id));
|
|
34
|
+
}
|
|
35
|
+
unregisterKernel(kernelId) {
|
|
36
|
+
var _a;
|
|
37
|
+
if (kernelId) {
|
|
38
|
+
this._kernels.delete(kernelId);
|
|
39
|
+
const comms = (_a = this._comms.get(kernelId)) !== null && _a !== void 0 ? _a : [];
|
|
40
|
+
comms.forEach(comm => comm.dispose());
|
|
41
|
+
this._comms.delete(kernelId);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
dispose() {
|
|
45
|
+
this._kernels.clear();
|
|
46
|
+
this._comms.clear();
|
|
47
|
+
this._broadcastChannels.forEach(it => {
|
|
48
|
+
it.close();
|
|
49
|
+
});
|
|
50
|
+
this._broadcastChannels.clear();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -2,9 +2,14 @@ import { PythonWidgetModel } from './pythonWidgetModel';
|
|
|
2
2
|
import { IFramePanel } from '../document/iframePanel';
|
|
3
3
|
export declare class PythonWidget extends IFramePanel {
|
|
4
4
|
constructor(options: PythonWidget.IOptions);
|
|
5
|
+
get autoreload(): boolean;
|
|
6
|
+
set autoreload(value: boolean);
|
|
7
|
+
get isReady(): Promise<void>;
|
|
5
8
|
get model(): PythonWidgetModel;
|
|
9
|
+
reload(): Promise<void>;
|
|
6
10
|
dispose(): void;
|
|
7
11
|
private _model;
|
|
12
|
+
private _isReady;
|
|
8
13
|
}
|
|
9
14
|
export declare namespace PythonWidget {
|
|
10
15
|
interface IOptions {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { PageConfig, URLExt } from '@jupyterlab/coreutils';
|
|
2
2
|
import { IFramePanel } from '../document/iframePanel';
|
|
3
|
+
import { PromiseDelegate } from '@lumino/coreutils';
|
|
3
4
|
export class PythonWidget extends IFramePanel {
|
|
4
5
|
constructor(options) {
|
|
5
6
|
super();
|
|
7
|
+
this._isReady = new PromiseDelegate();
|
|
6
8
|
this._model = options.model;
|
|
7
9
|
this._model.initialize().then(connectionData => {
|
|
8
10
|
if (!connectionData.success) {
|
|
@@ -10,6 +12,7 @@ export class PythonWidget extends IFramePanel {
|
|
|
10
12
|
this._iframe.contentDocument.body.innerText = `Failed to start server: ${connectionData.error}`;
|
|
11
13
|
return;
|
|
12
14
|
}
|
|
15
|
+
this._isReady.resolve();
|
|
13
16
|
const iframe = this._iframe;
|
|
14
17
|
const fullLabextensionsUrl = PageConfig.getOption('fullLabextensionsUrl');
|
|
15
18
|
const iframeUrl = URLExt.join(fullLabextensionsUrl, 'jupyterpack/static', connectionData.instanceId, connectionData.framework, connectionData.kernelClientId, connectionData.rootUrl);
|
|
@@ -17,11 +20,27 @@ export class PythonWidget extends IFramePanel {
|
|
|
17
20
|
iframe.addEventListener('load', () => {
|
|
18
21
|
this.toggleSpinner(false);
|
|
19
22
|
});
|
|
23
|
+
this._model.serverReloaded.connect(() => {
|
|
24
|
+
var _a, _b, _c;
|
|
25
|
+
(_c = (_b = (_a = this._iframe) === null || _a === void 0 ? void 0 : _a.contentWindow) === null || _b === void 0 ? void 0 : _b.location) === null || _c === void 0 ? void 0 : _c.reload();
|
|
26
|
+
});
|
|
20
27
|
});
|
|
21
28
|
}
|
|
29
|
+
get autoreload() {
|
|
30
|
+
return this._model.autoreload;
|
|
31
|
+
}
|
|
32
|
+
set autoreload(value) {
|
|
33
|
+
this._model.autoreload = value;
|
|
34
|
+
}
|
|
35
|
+
get isReady() {
|
|
36
|
+
return this._isReady.promise;
|
|
37
|
+
}
|
|
22
38
|
get model() {
|
|
23
39
|
return this._model;
|
|
24
40
|
}
|
|
41
|
+
async reload() {
|
|
42
|
+
await this._model.reload();
|
|
43
|
+
}
|
|
25
44
|
dispose() {
|
|
26
45
|
this._model.dispose();
|
|
27
46
|
}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { DocumentRegistry } from '@jupyterlab/docregistry';
|
|
2
2
|
import { Contents, ServiceManager } from '@jupyterlab/services';
|
|
3
|
-
import {
|
|
4
|
-
import { IConnectionManager, IJupyterPackFileFormat, JupyterPackFramework } from '../type';
|
|
5
|
-
export declare class PythonWidgetModel implements
|
|
3
|
+
import { Signal } from '@lumino/signaling';
|
|
4
|
+
import { IConnectionManager, IJupyterPackFileFormat, IPythonWidgetModel, JupyterPackFramework } from '../type';
|
|
5
|
+
export declare class PythonWidgetModel implements IPythonWidgetModel {
|
|
6
6
|
constructor(options: PythonWidgetModel.IOptions);
|
|
7
|
+
get autoreload(): boolean;
|
|
8
|
+
set autoreload(val: boolean);
|
|
7
9
|
get isDisposed(): boolean;
|
|
8
10
|
get connectionManager(): IConnectionManager;
|
|
11
|
+
get serverReloaded(): Signal<IPythonWidgetModel, void>;
|
|
12
|
+
get kernelStatusChanged(): Signal<IPythonWidgetModel, "started" | "stopped">;
|
|
13
|
+
reload(): Promise<void>;
|
|
9
14
|
initialize(): Promise<{
|
|
10
15
|
success: true;
|
|
11
16
|
instanceId: string;
|
|
@@ -16,7 +21,10 @@ export declare class PythonWidgetModel implements IDisposable {
|
|
|
16
21
|
success: false;
|
|
17
22
|
error: string;
|
|
18
23
|
}>;
|
|
19
|
-
dispose(): void
|
|
24
|
+
dispose(): Promise<void>;
|
|
25
|
+
private _loadData;
|
|
26
|
+
private _onFileChanged;
|
|
27
|
+
private _commBroadcastManager;
|
|
20
28
|
private _isDisposed;
|
|
21
29
|
private _kernelStarted;
|
|
22
30
|
private _sessionConnection;
|
|
@@ -26,6 +34,10 @@ export declare class PythonWidgetModel implements IDisposable {
|
|
|
26
34
|
private _contentsManager;
|
|
27
35
|
private _jpackModel;
|
|
28
36
|
private _executor?;
|
|
37
|
+
private _localPath;
|
|
38
|
+
private _serverReloaded;
|
|
39
|
+
private _kernelStatusChanged;
|
|
40
|
+
private _autoreload;
|
|
29
41
|
}
|
|
30
42
|
export declare namespace PythonWidgetModel {
|
|
31
43
|
interface IOptions {
|