jupyterpack 0.4.0 → 0.5.2
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 +107 -3
- package/lib/document/widgetFactory.js +3 -1
- package/lib/pythonServer/baseServer.d.ts +78 -0
- package/lib/pythonServer/baseServer.js +175 -0
- package/lib/pythonServer/dash/dashServer.d.ts +4 -17
- package/lib/pythonServer/dash/dashServer.js +14 -22
- package/lib/pythonServer/dash/deps.d.ts +2 -0
- package/lib/pythonServer/dash/deps.js +4 -0
- package/lib/pythonServer/index.d.ts +3 -3
- package/lib/pythonServer/index.js +5 -1
- package/lib/pythonServer/kernelExecutor.d.ts +2 -58
- package/lib/pythonServer/kernelExecutor.js +0 -72
- package/lib/pythonServer/shiny/deps.d.ts +2 -0
- package/lib/pythonServer/shiny/deps.js +4 -0
- package/lib/pythonServer/shiny/shinyServer.d.ts +10 -0
- package/lib/pythonServer/shiny/shinyServer.js +54 -0
- package/lib/pythonServer/starlette/starletteServer.d.ts +13 -0
- package/lib/pythonServer/starlette/starletteServer.js +49 -0
- package/lib/pythonServer/streamlit/deps.d.ts +2 -0
- package/lib/pythonServer/streamlit/deps.js +10 -0
- package/lib/pythonServer/streamlit/streamlitServer.d.ts +4 -9
- package/lib/pythonServer/streamlit/streamlitServer.js +16 -15
- package/lib/pythonServer/tornado/tornadoServer.d.ts +2 -24
- package/lib/pythonServer/tornado/tornadoServer.js +10 -35
- package/lib/pythonWidget/pythonWidgetModel.js +2 -0
- package/lib/swConnection/mainConnectionManager.d.ts +4 -4
- package/lib/swConnection/mainConnectionManager.js +23 -12
- package/lib/tools.d.ts +1 -0
- package/lib/tools.js +8 -0
- package/lib/type.d.ts +27 -9
- package/lib/type.js +2 -0
- package/lib/websocket/websocket.js +5 -1
- package/package.json +1 -1
- package/src/document/widgetFactory.ts +3 -1
- package/src/pythonServer/baseServer.ts +285 -0
- package/src/pythonServer/dash/dashServer.ts +18 -35
- package/src/pythonServer/dash/deps.ts +6 -0
- package/src/pythonServer/index.ts +9 -5
- package/src/pythonServer/kernelExecutor.ts +3 -156
- package/src/pythonServer/shiny/deps.ts +6 -0
- package/src/pythonServer/shiny/shinyServer.ts +63 -0
- package/src/pythonServer/starlette/starletteServer.ts +59 -0
- package/src/pythonServer/streamlit/deps.ts +12 -0
- package/src/pythonServer/streamlit/streamlitServer.ts +19 -20
- package/src/pythonServer/tornado/tornadoServer.ts +11 -55
- package/src/pythonWidget/pythonWidgetModel.ts +5 -2
- package/src/swConnection/mainConnectionManager.ts +28 -20
- package/src/tools.ts +9 -0
- package/src/type.ts +34 -12
- package/src/websocket/websocket.ts +9 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IPythonServerInitOptions } from '../../type';
|
|
2
|
+
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
export declare class ShinyServer extends BasePythonServer {
|
|
4
|
+
init(options: IPythonServerInitOptions): Promise<void>;
|
|
5
|
+
disposePythonServer(): Promise<void>;
|
|
6
|
+
reloadPythonServer(options: {
|
|
7
|
+
entryPath?: string;
|
|
8
|
+
initCode?: string;
|
|
9
|
+
}): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { JupyterPackFramework } from '../../type';
|
|
2
|
+
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
import { DEPENDENCIES } from './deps';
|
|
4
|
+
export class ShinyServer extends BasePythonServer {
|
|
5
|
+
async init(options) {
|
|
6
|
+
const mergedOptions = {
|
|
7
|
+
...options,
|
|
8
|
+
dependencies: this.mergeDependencies(options.dependencies, DEPENDENCIES)
|
|
9
|
+
};
|
|
10
|
+
await super.init(mergedOptions);
|
|
11
|
+
const { instanceId, kernelClientId, entryPath } = options;
|
|
12
|
+
const baseURL = this.buildBaseURL({
|
|
13
|
+
instanceId,
|
|
14
|
+
kernelClientId,
|
|
15
|
+
framework: JupyterPackFramework.SHINY
|
|
16
|
+
});
|
|
17
|
+
const bootstrapCode = `
|
|
18
|
+
from jupyterpack.common import set_base_url_env
|
|
19
|
+
set_base_url_env("${baseURL}")
|
|
20
|
+
from jupyterpack.shiny import patch_shiny
|
|
21
|
+
patch_shiny()
|
|
22
|
+
`;
|
|
23
|
+
await this.kernelExecutor.executeCode({ code: bootstrapCode });
|
|
24
|
+
if (entryPath) {
|
|
25
|
+
const loaderCode = `
|
|
26
|
+
from jupyterpack.shiny import ShinyServer, get_shiny_app
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
${this._server_var} = ShinyServer(get_shiny_app("${entryPath}"), "${baseURL}")
|
|
30
|
+
`;
|
|
31
|
+
await this.kernelExecutor.executeCode({ code: loaderCode });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async disposePythonServer() {
|
|
35
|
+
await this.kernelExecutor.executeCode({
|
|
36
|
+
code: `${this._server_var}.dispose()`
|
|
37
|
+
});
|
|
38
|
+
for (const element of this._openedWebsockets) {
|
|
39
|
+
await this.closeWebsocket(element);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async reloadPythonServer(options) {
|
|
43
|
+
const { entryPath } = options;
|
|
44
|
+
if (entryPath) {
|
|
45
|
+
const reloadCode = `
|
|
46
|
+
from jupyterpack.shiny import get_shiny_app
|
|
47
|
+
|
|
48
|
+
await ${this._server_var}.dispose()
|
|
49
|
+
${this._server_var}.reload(get_shiny_app("${entryPath}"))
|
|
50
|
+
`;
|
|
51
|
+
await this.kernelExecutor.executeCode({ code: reloadCode }, true);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -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,14 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
initCode?: string;
|
|
6
|
-
instanceId: string;
|
|
7
|
-
kernelClientId: string;
|
|
8
|
-
}): Promise<void>;
|
|
1
|
+
import { IPythonServerInitOptions } from '../../type';
|
|
2
|
+
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
export declare class StreamlitServer extends BasePythonServer {
|
|
4
|
+
init(options: IPythonServerInitOptions): Promise<void>;
|
|
9
5
|
reloadPythonServer(options: {
|
|
10
6
|
entryPath?: string;
|
|
11
7
|
initCode?: string;
|
|
12
8
|
}): Promise<void>;
|
|
13
|
-
protected _SERVER_VAR: string;
|
|
14
9
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { JupyterPackFramework } from '../../type';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
super(...arguments);
|
|
6
|
-
this._SERVER_VAR = '__jupyterpack_streamlit_server';
|
|
7
|
-
}
|
|
2
|
+
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
import { DEPENDENCIES } from './deps';
|
|
4
|
+
export class StreamlitServer extends BasePythonServer {
|
|
8
5
|
async init(options) {
|
|
6
|
+
const mergedOptions = {
|
|
7
|
+
...options,
|
|
8
|
+
dependencies: this.mergeDependencies(options.dependencies, DEPENDENCIES)
|
|
9
|
+
};
|
|
10
|
+
await super.init(mergedOptions);
|
|
9
11
|
const { instanceId, kernelClientId, entryPath } = options;
|
|
10
12
|
if (!entryPath) {
|
|
11
13
|
throw new Error('Missing streamlit entry path, please check your SPK file');
|
|
@@ -16,23 +18,22 @@ export class StreamlitServer extends TornadoServer {
|
|
|
16
18
|
framework: JupyterPackFramework.STREAMLIT
|
|
17
19
|
});
|
|
18
20
|
const patchCode = `
|
|
19
|
-
from jupyterpack.common import set_base_url_env, patch_tornado
|
|
20
|
-
patch_all()
|
|
21
|
+
from jupyterpack.common import set_base_url_env, patch_tornado
|
|
21
22
|
patch_tornado()
|
|
22
23
|
set_base_url_env("${baseURL}")
|
|
23
24
|
`;
|
|
24
|
-
await this.executeCode({ code: patchCode });
|
|
25
|
+
await this.kernelExecutor.executeCode({ code: patchCode });
|
|
25
26
|
const bootstrapCode = `
|
|
26
27
|
from jupyterpack.streamlit import patch_streamlit
|
|
27
28
|
patch_streamlit()
|
|
28
29
|
`;
|
|
29
|
-
await this.executeCode({ code: bootstrapCode });
|
|
30
|
+
await this.kernelExecutor.executeCode({ code: bootstrapCode });
|
|
30
31
|
const stCode = `
|
|
31
32
|
from jupyterpack.streamlit import StreamlitServer, create_streamlit_app
|
|
32
33
|
__jupyterpack_st_server, __jupyterpack_tor_app = await create_streamlit_app("${entryPath}", "${baseURL}")
|
|
33
|
-
${this.
|
|
34
|
+
${this._server_var} = StreamlitServer(__jupyterpack_tor_app, "${baseURL}", __jupyterpack_st_server)
|
|
34
35
|
`;
|
|
35
|
-
await this.executeCode({ code: stCode });
|
|
36
|
+
await this.kernelExecutor.executeCode({ code: stCode });
|
|
36
37
|
}
|
|
37
38
|
async reloadPythonServer(options) {
|
|
38
39
|
const { entryPath } = options;
|
|
@@ -40,11 +41,11 @@ export class StreamlitServer extends TornadoServer {
|
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
42
43
|
const reloadCode = `
|
|
43
|
-
${this.
|
|
44
|
+
${this._server_var}.dispose()
|
|
44
45
|
__jupyterpack_st_server, __jupyterpack_tor_app = await create_streamlit_app("${entryPath}", "${this._baseUrl}")
|
|
45
|
-
${this.
|
|
46
|
+
${this._server_var}.reload(__jupyterpack_tor_app, __jupyterpack_st_server)
|
|
46
47
|
`;
|
|
47
|
-
await this.executeCode({
|
|
48
|
+
await this.kernelExecutor.executeCode({
|
|
48
49
|
code: reloadCode
|
|
49
50
|
}, true);
|
|
50
51
|
}
|
|
@@ -1,34 +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
|
-
getResponseFunctionFactory(options: {
|
|
10
|
-
urlPath: string;
|
|
11
|
-
method: string;
|
|
12
|
-
headers: IDict;
|
|
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
8
|
reloadPythonServer(options: {
|
|
30
9
|
entryPath?: string;
|
|
31
10
|
initCode?: string;
|
|
32
11
|
}): Promise<void>;
|
|
33
|
-
protected _SERVER_VAR: string;
|
|
34
12
|
}
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import { stringOrNone } from '../../tools';
|
|
2
1
|
import { JupyterPackFramework } from '../../type';
|
|
3
|
-
import {
|
|
4
|
-
export class TornadoServer extends
|
|
5
|
-
constructor() {
|
|
6
|
-
super(...arguments);
|
|
7
|
-
this._SERVER_VAR = '__jupyterpack_tornado_server';
|
|
8
|
-
}
|
|
2
|
+
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
export class TornadoServer extends BasePythonServer {
|
|
9
4
|
async init(options) {
|
|
10
5
|
await super.init(options);
|
|
11
6
|
const { initCode, instanceId, kernelClientId } = options;
|
|
@@ -20,49 +15,29 @@ export class TornadoServer extends KernelExecutor {
|
|
|
20
15
|
patch_tornado()
|
|
21
16
|
|
|
22
17
|
`;
|
|
23
|
-
await this.executeCode({ code: bootstrapCode });
|
|
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 });
|
|
21
|
+
await this.kernelExecutor.executeCode({ code: initCodeWithUrl });
|
|
27
22
|
const loaderCode = `
|
|
28
23
|
from jupyterpack.tornado import TornadoServer
|
|
29
|
-
${this.
|
|
24
|
+
${this._server_var} = TornadoServer(app, "${baseURL}")
|
|
30
25
|
`;
|
|
31
|
-
await this.executeCode({ code: loaderCode });
|
|
26
|
+
await this.kernelExecutor.executeCode({ code: loaderCode });
|
|
32
27
|
}
|
|
33
28
|
}
|
|
34
|
-
getResponseFunctionFactory(options) {
|
|
35
|
-
const { method, urlPath, headers, params, content } = options;
|
|
36
|
-
const code = `await ${this._SERVER_VAR}.get_response("${method}", "${urlPath}", headers=${JSON.stringify(headers)} , content=${stringOrNone(content)}, params=${stringOrNone(params)})`;
|
|
37
|
-
return code;
|
|
38
|
-
}
|
|
39
|
-
openWebsocketFunctionFactory(options) {
|
|
40
|
-
const { instanceId, kernelId, wsUrl, protocol } = options;
|
|
41
|
-
const code = `await ${this._SERVER_VAR}.open_ws("${instanceId}", "${kernelId}", "${wsUrl}", ${stringOrNone(protocol)})`;
|
|
42
|
-
return code;
|
|
43
|
-
}
|
|
44
|
-
sendWebsocketMessageFunctionFactory(options) {
|
|
45
|
-
const { instanceId, kernelId, wsUrl, message } = options;
|
|
46
|
-
const code = `await ${this._SERVER_VAR}.receive_ws_message("${instanceId}", "${kernelId}", "${wsUrl}", '''${message}''')`;
|
|
47
|
-
return code;
|
|
48
|
-
}
|
|
49
|
-
async disposePythonServer() {
|
|
50
|
-
await this.executeCode({
|
|
51
|
-
code: `${this._SERVER_VAR}.dispose()`
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
29
|
async reloadPythonServer(options) {
|
|
55
30
|
var _a;
|
|
56
31
|
const { initCode } = options;
|
|
57
32
|
if (initCode) {
|
|
58
|
-
await this.executeCode({
|
|
33
|
+
await this.kernelExecutor.executeCode({
|
|
59
34
|
code: initCode.replaceAll('{{base_url}}', (_a = this._baseUrl) !== null && _a !== void 0 ? _a : '')
|
|
60
35
|
});
|
|
61
36
|
const reloadCode = `
|
|
62
|
-
${this.
|
|
63
|
-
${this.
|
|
37
|
+
${this._server_var}.dispose()
|
|
38
|
+
${this._server_var}.reload(app)
|
|
64
39
|
`;
|
|
65
|
-
await this.executeCode({ code: reloadCode }, true);
|
|
40
|
+
await this.kernelExecutor.executeCode({ code: reloadCode }, true);
|
|
66
41
|
}
|
|
67
42
|
}
|
|
68
43
|
}
|
|
@@ -109,6 +109,8 @@ export class PythonWidgetModel {
|
|
|
109
109
|
await executor.init({
|
|
110
110
|
initCode: entryContent.content,
|
|
111
111
|
entryPath: spkContent.entry,
|
|
112
|
+
dependencies: spkContent.dependencies,
|
|
113
|
+
disableDependencies: spkContent.disableDependencies,
|
|
112
114
|
...data
|
|
113
115
|
});
|
|
114
116
|
const finish = new PromiseDelegate();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IConnectionManager, IDict
|
|
1
|
+
import { IBasePythonServer, IConnectionManager, IDict } from '../type';
|
|
2
2
|
/**
|
|
3
3
|
* Manages connections between clients and kernel executors.
|
|
4
4
|
* This class handles the registration of kernel executors and the generation of responses
|
|
@@ -10,7 +10,7 @@ import { IConnectionManager, IDict, IKernelExecutor } from '../type';
|
|
|
10
10
|
export declare class ConnectionManager implements IConnectionManager {
|
|
11
11
|
instanceId: string;
|
|
12
12
|
constructor(instanceId: string);
|
|
13
|
-
registerConnection(
|
|
13
|
+
registerConnection(pythonServer: IBasePythonServer): Promise<{
|
|
14
14
|
instanceId: string;
|
|
15
15
|
kernelClientId: string;
|
|
16
16
|
}>;
|
|
@@ -23,6 +23,6 @@ export declare class ConnectionManager implements IConnectionManager {
|
|
|
23
23
|
params?: string;
|
|
24
24
|
}): Promise<IDict | null>;
|
|
25
25
|
private _initWsChannel;
|
|
26
|
-
private
|
|
27
|
-
private
|
|
26
|
+
private _pythonServers;
|
|
27
|
+
private _wsBroadcastChannelMap;
|
|
28
28
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { arrayBufferToBase64 } from '../tools';
|
|
1
|
+
import { arrayBufferToBase64, stringToBase64 } from '../tools';
|
|
2
2
|
import { UUID } from '@lumino/coreutils';
|
|
3
3
|
/**
|
|
4
4
|
* Manages connections between clients and kernel executors.
|
|
@@ -11,18 +11,20 @@ import { UUID } from '@lumino/coreutils';
|
|
|
11
11
|
export class ConnectionManager {
|
|
12
12
|
constructor(instanceId) {
|
|
13
13
|
this.instanceId = instanceId;
|
|
14
|
-
this.
|
|
15
|
-
this.
|
|
16
|
-
this._initWsChannel();
|
|
14
|
+
this._pythonServers = new Map();
|
|
15
|
+
this._wsBroadcastChannelMap = new Map();
|
|
17
16
|
}
|
|
18
|
-
async registerConnection(
|
|
17
|
+
async registerConnection(pythonServer) {
|
|
19
18
|
const uuid = UUID.uuid4();
|
|
20
|
-
this.
|
|
19
|
+
this._pythonServers.set(uuid, pythonServer);
|
|
20
|
+
const wsbc = new BroadcastChannel(`/jupyterpack/ws/${this.instanceId}/${uuid}`);
|
|
21
|
+
this._initWsChannel(wsbc);
|
|
22
|
+
this._wsBroadcastChannelMap.set(`${this.instanceId}/${uuid}`, wsbc);
|
|
21
23
|
return { instanceId: this.instanceId, kernelClientId: uuid };
|
|
22
24
|
}
|
|
23
25
|
async generateResponse(options) {
|
|
24
26
|
const { urlPath, kernelClientId, method, params, requestBody, headers } = options;
|
|
25
|
-
const executor = this.
|
|
27
|
+
const executor = this._pythonServers.get(kernelClientId);
|
|
26
28
|
if (!executor) {
|
|
27
29
|
return null;
|
|
28
30
|
}
|
|
@@ -35,8 +37,8 @@ export class ConnectionManager {
|
|
|
35
37
|
});
|
|
36
38
|
return response;
|
|
37
39
|
}
|
|
38
|
-
_initWsChannel() {
|
|
39
|
-
|
|
40
|
+
_initWsChannel(broadcastChannel) {
|
|
41
|
+
broadcastChannel.onmessage = event => {
|
|
40
42
|
const rawData = event.data;
|
|
41
43
|
let data;
|
|
42
44
|
if (typeof rawData === 'string') {
|
|
@@ -46,9 +48,9 @@ export class ConnectionManager {
|
|
|
46
48
|
data = rawData;
|
|
47
49
|
}
|
|
48
50
|
const { action, dest, wsUrl, payload } = data;
|
|
49
|
-
const executor = this.
|
|
51
|
+
const executor = this._pythonServers.get(dest);
|
|
50
52
|
if (!executor) {
|
|
51
|
-
console.error('Missing kernel handle for message', data, dest, this.
|
|
53
|
+
console.error('Missing kernel handle for message', data, dest, this._pythonServers);
|
|
52
54
|
return;
|
|
53
55
|
}
|
|
54
56
|
switch (action) {
|
|
@@ -61,6 +63,14 @@ export class ConnectionManager {
|
|
|
61
63
|
});
|
|
62
64
|
break;
|
|
63
65
|
}
|
|
66
|
+
case 'close': {
|
|
67
|
+
executor.closeWebsocket({
|
|
68
|
+
instanceId: this.instanceId,
|
|
69
|
+
kernelId: dest,
|
|
70
|
+
wsUrl
|
|
71
|
+
});
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
64
74
|
case 'send': {
|
|
65
75
|
let serializedData;
|
|
66
76
|
let isBinary;
|
|
@@ -70,7 +80,8 @@ export class ConnectionManager {
|
|
|
70
80
|
isBinary = true;
|
|
71
81
|
}
|
|
72
82
|
else if (typeof payload === 'string') {
|
|
73
|
-
|
|
83
|
+
// convert string to base64 string to avoid encoding problem
|
|
84
|
+
serializedData = stringToBase64(payload);
|
|
74
85
|
isBinary = false;
|
|
75
86
|
}
|
|
76
87
|
else {
|
package/lib/tools.d.ts
CHANGED
|
@@ -7,5 +7,6 @@ export declare function removePrefix(path: string, prefix: string): string;
|
|
|
7
7
|
export declare function arrayBufferToBase64(buffer: ArrayBuffer): string;
|
|
8
8
|
export declare function base64ToArrayBuffer(base64: string): Uint8Array;
|
|
9
9
|
export declare function base64ToString(base64: string): string;
|
|
10
|
+
export declare function stringToBase64(str: string): string;
|
|
10
11
|
export declare function stringOrNone(content?: string): string;
|
|
11
12
|
export declare function isBinaryContentType(contentType?: string): boolean;
|
package/lib/tools.js
CHANGED
|
@@ -44,6 +44,14 @@ export function base64ToString(base64) {
|
|
|
44
44
|
const bytes = base64ToArrayBuffer(base64);
|
|
45
45
|
return new TextDecoder('utf-8').decode(bytes);
|
|
46
46
|
}
|
|
47
|
+
export function stringToBase64(str) {
|
|
48
|
+
const bytes = new TextEncoder().encode(str);
|
|
49
|
+
let binary = '';
|
|
50
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
51
|
+
binary += String.fromCharCode(bytes[i]);
|
|
52
|
+
}
|
|
53
|
+
return window.btoa(binary);
|
|
54
|
+
}
|
|
47
55
|
export function stringOrNone(content) {
|
|
48
56
|
return content ? `"${content}"` : 'None';
|
|
49
57
|
}
|
package/lib/type.d.ts
CHANGED
|
@@ -16,7 +16,9 @@ export declare enum JupyterPackFramework {
|
|
|
16
16
|
REACT = "react",
|
|
17
17
|
DASH = "dash",
|
|
18
18
|
STREAMLIT = "streamlit",
|
|
19
|
-
TORNADO = "tornado"
|
|
19
|
+
TORNADO = "tornado",
|
|
20
|
+
SHINY = "shiny",
|
|
21
|
+
STARLETTE = "starlette"
|
|
20
22
|
}
|
|
21
23
|
export interface IJupyterPackFileFormat {
|
|
22
24
|
entry: string;
|
|
@@ -26,6 +28,8 @@ export interface IJupyterPackFileFormat {
|
|
|
26
28
|
autoreload?: boolean;
|
|
27
29
|
};
|
|
28
30
|
rootUrl?: string;
|
|
31
|
+
dependencies?: IDependencies;
|
|
32
|
+
disableDependencies?: boolean;
|
|
29
33
|
}
|
|
30
34
|
export declare enum MessageAction {
|
|
31
35
|
INIT = "INIT"
|
|
@@ -38,6 +42,9 @@ export interface IKernelExecutorParams {
|
|
|
38
42
|
requestBody?: ArrayBuffer;
|
|
39
43
|
}
|
|
40
44
|
export interface IKernelExecutor extends IDisposable {
|
|
45
|
+
executeCode(code: KernelMessage.IExecuteRequestMsg['content'], waitForResult?: boolean): Promise<string | null>;
|
|
46
|
+
}
|
|
47
|
+
export interface IBasePythonServer extends IDisposable {
|
|
41
48
|
getResponse(options: IKernelExecutorParams): Promise<IDict>;
|
|
42
49
|
openWebsocket(options: {
|
|
43
50
|
instanceId: string;
|
|
@@ -45,19 +52,18 @@ export interface IKernelExecutor extends IDisposable {
|
|
|
45
52
|
wsUrl: string;
|
|
46
53
|
protocol?: string;
|
|
47
54
|
}): Promise<void>;
|
|
48
|
-
|
|
55
|
+
closeWebsocket(options: {
|
|
49
56
|
instanceId: string;
|
|
50
57
|
kernelId: string;
|
|
51
58
|
wsUrl: string;
|
|
52
|
-
message: string;
|
|
53
59
|
}): Promise<void>;
|
|
54
|
-
|
|
55
|
-
init(options: {
|
|
56
|
-
entryPath?: string;
|
|
57
|
-
initCode?: string;
|
|
60
|
+
sendWebsocketMessage(options: {
|
|
58
61
|
instanceId: string;
|
|
59
|
-
|
|
62
|
+
kernelId: string;
|
|
63
|
+
wsUrl: string;
|
|
64
|
+
message: string;
|
|
60
65
|
}): Promise<void>;
|
|
66
|
+
init(options: IPythonServerInitOptions): Promise<void>;
|
|
61
67
|
disposePythonServer(): Promise<void>;
|
|
62
68
|
reloadPythonServer(options: {
|
|
63
69
|
entryPath?: string;
|
|
@@ -72,7 +78,7 @@ export interface IKernelExecutor extends IDisposable {
|
|
|
72
78
|
}): string;
|
|
73
79
|
}
|
|
74
80
|
export interface IConnectionManager {
|
|
75
|
-
registerConnection(kernelExecutor:
|
|
81
|
+
registerConnection(kernelExecutor: IBasePythonServer): Promise<{
|
|
76
82
|
instanceId: string;
|
|
77
83
|
kernelClientId: string;
|
|
78
84
|
}>;
|
|
@@ -97,3 +103,15 @@ export interface IPythonWidgetModel extends IDisposable {
|
|
|
97
103
|
error: string;
|
|
98
104
|
}>;
|
|
99
105
|
}
|
|
106
|
+
export interface IDependencies {
|
|
107
|
+
mamba?: string[];
|
|
108
|
+
pip?: string[];
|
|
109
|
+
}
|
|
110
|
+
export interface IPythonServerInitOptions {
|
|
111
|
+
entryPath?: string;
|
|
112
|
+
initCode?: string;
|
|
113
|
+
instanceId: string;
|
|
114
|
+
kernelClientId: string;
|
|
115
|
+
dependencies?: IDependencies;
|
|
116
|
+
disableDependencies?: boolean;
|
|
117
|
+
}
|
package/lib/type.js
CHANGED
|
@@ -4,6 +4,8 @@ export var JupyterPackFramework;
|
|
|
4
4
|
JupyterPackFramework["DASH"] = "dash";
|
|
5
5
|
JupyterPackFramework["STREAMLIT"] = "streamlit";
|
|
6
6
|
JupyterPackFramework["TORNADO"] = "tornado";
|
|
7
|
+
JupyterPackFramework["SHINY"] = "shiny";
|
|
8
|
+
JupyterPackFramework["STARLETTE"] = "starlette";
|
|
7
9
|
})(JupyterPackFramework || (JupyterPackFramework = {}));
|
|
8
10
|
export var MessageAction;
|
|
9
11
|
(function (MessageAction) {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
}
|
|
37
37
|
return data;
|
|
38
38
|
};
|
|
39
|
-
const bcWsChannel = new BroadcastChannel(`/jupyterpack/ws/${instanceId}`);
|
|
39
|
+
const bcWsChannel = new BroadcastChannel(`/jupyterpack/ws/${instanceId}/${kernelClientId}`);
|
|
40
40
|
class BroadcastChannelWebSocket {
|
|
41
41
|
constructor(url, protocols) {
|
|
42
42
|
this.onclose = () => {
|
|
@@ -128,6 +128,10 @@
|
|
|
128
128
|
cb();
|
|
129
129
|
}
|
|
130
130
|
this._eventHandlers['close'] = [];
|
|
131
|
+
sendTypedMessage({
|
|
132
|
+
action: 'close',
|
|
133
|
+
wsUrl: this.url
|
|
134
|
+
});
|
|
131
135
|
bcWsChannel.removeEventListener('message', this._bcMessageHandler);
|
|
132
136
|
this.readyState = this.CLOSED;
|
|
133
137
|
}
|
package/package.json
CHANGED
|
@@ -54,7 +54,9 @@ export class JupyterPackWidgetFactory extends ABCWidgetFactory<JupyterPackDocWid
|
|
|
54
54
|
}
|
|
55
55
|
case JupyterPackFramework.DASH:
|
|
56
56
|
case JupyterPackFramework.STREAMLIT:
|
|
57
|
-
case JupyterPackFramework.TORNADO:
|
|
57
|
+
case JupyterPackFramework.TORNADO:
|
|
58
|
+
case JupyterPackFramework.STARLETTE:
|
|
59
|
+
case JupyterPackFramework.SHINY: {
|
|
58
60
|
const model = new PythonWidgetModel({
|
|
59
61
|
jpackModel,
|
|
60
62
|
context,
|