jupyterpack 0.5.1 → 0.5.3
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/pythonServer/baseServer.d.ts +3 -7
- package/lib/pythonServer/baseServer.js +36 -2
- package/lib/pythonServer/dash/dashServer.d.ts +2 -5
- package/lib/pythonServer/dash/dashServer.js +6 -1
- package/lib/pythonServer/dash/deps.d.ts +2 -0
- package/lib/pythonServer/dash/deps.js +4 -0
- package/lib/pythonServer/shiny/deps.d.ts +2 -0
- package/lib/pythonServer/shiny/deps.js +4 -0
- package/lib/pythonServer/shiny/shinyServer.d.ts +2 -6
- package/lib/pythonServer/shiny/shinyServer.js +6 -1
- 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 -8
- package/lib/pythonServer/streamlit/streamlitServer.js +9 -4
- package/lib/pythonWidget/pythonWidgetModel.js +2 -0
- package/lib/type.d.ts +15 -6
- package/package.json +1 -1
- package/src/pythonServer/baseServer.ts +54 -14
- package/src/pythonServer/dash/dashServer.ts +9 -7
- package/src/pythonServer/dash/deps.ts +6 -0
- package/src/pythonServer/shiny/deps.ts +6 -0
- package/src/pythonServer/shiny/shinyServer.ts +9 -8
- package/src/pythonServer/streamlit/deps.ts +12 -0
- package/src/pythonServer/streamlit/streamlitServer.ts +12 -11
- package/src/pythonWidget/pythonWidgetModel.ts +3 -0
- package/src/type.ts +17 -6
package/README.md
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
## Features
|
|
9
9
|
|
|
10
|
-
- **Python Web Apps**: Serve Python web applications directly in the browser using JupyterLite's in-browser Python kernel. `jupyterpack` currently supports Dash and
|
|
10
|
+
- **Python Web Apps**: Serve Python web applications directly in the browser using JupyterLite's in-browser Python kernel. `jupyterpack` currently supports Dash, Streamlit and Shiny for Python. You can also use `jupyterpack` to serve any `asgi` or `wsgi` Python web application.
|
|
11
|
+
.
|
|
11
12
|
- **JavaScript Web Apps**: Bundle and serve JavaScript web applications using in-browser bundlers.
|
|
12
13
|
|
|
13
14
|

|
|
@@ -46,7 +47,90 @@ the `app.spk` is the entry point of your React app, it should contain the follow
|
|
|
46
47
|
}
|
|
47
48
|
```
|
|
48
49
|
|
|
49
|
-
Double
|
|
50
|
+
Double-clicking the `spk` file to open the web app as a tab of JupyterLab.
|
|
51
|
+
|
|
52
|
+
## `.spk` — Jupyter Pack File Format
|
|
53
|
+
|
|
54
|
+
A **`.spk`** file describes how an application should be loaded, executed, and rendered in JupyterLite and JupyterLab.
|
|
55
|
+
It defines the **entry point**, **framework**, optional **dependencies**, and runtime **metadata**, allowing reproducible execution across environments.
|
|
56
|
+
|
|
57
|
+
The file is expressed in **JSON**.
|
|
58
|
+
|
|
59
|
+
### Basic Structure
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
interface IJupyterPackFileFormat {
|
|
63
|
+
entry: string;
|
|
64
|
+
framework: JupyterPackFramework;
|
|
65
|
+
name?: string;
|
|
66
|
+
metadata?: {
|
|
67
|
+
autoreload?: boolean;
|
|
68
|
+
};
|
|
69
|
+
rootUrl?: string;
|
|
70
|
+
dependencies?: IDependencies;
|
|
71
|
+
disableDependencies?: boolean;
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
- `entry` (required): Path to the main entry file of the application. For examples:
|
|
76
|
+
- _"app.py"_
|
|
77
|
+
- _"/index.html"_
|
|
78
|
+
- _"dashboard/index.py"_
|
|
79
|
+
|
|
80
|
+
The path is resolved relative to the .spk file location.
|
|
81
|
+
|
|
82
|
+
- `framework` (required): The framework used to run the application. Supported frameworks are:
|
|
83
|
+
|
|
84
|
+
| Value | Description |
|
|
85
|
+
| ----------- | -------------------------------- |
|
|
86
|
+
| `react` | React-based frontend application |
|
|
87
|
+
| `dash` | Plotly Dash application |
|
|
88
|
+
| `streamlit` | Streamlit application |
|
|
89
|
+
| `tornado` | Tornado web application |
|
|
90
|
+
| `shiny` | Shiny application (Python) |
|
|
91
|
+
| `starlette` | Starlette ASGI application |
|
|
92
|
+
|
|
93
|
+
- `name` (optional): The name of the application. If not provided, the name will be the name of the .spk file.
|
|
94
|
+
|
|
95
|
+
- `metadata` (optional): Additional metadata for the application.
|
|
96
|
+
- `autoreload`: Enables automatic reload when source files change.
|
|
97
|
+
|
|
98
|
+
- `rootUrl` (optional): The root URL of the web application. Default is `/`
|
|
99
|
+
|
|
100
|
+
- `dependencies` (optional): The dependencies of the web application. It will be merged with the default dependencies of the selected framework
|
|
101
|
+
- `mamba`: Emscripten-forge packages
|
|
102
|
+
- `pip`: PYPI packages
|
|
103
|
+
Example:
|
|
104
|
+
```typescript
|
|
105
|
+
dependencies: {
|
|
106
|
+
mamba: ['numpy, scipy'];
|
|
107
|
+
pip: ['plotly'];
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
You only need to specify the dependencies of the application, the required dependencies of the framework will be automatically added.
|
|
112
|
+
|
|
113
|
+
- `disableDependencies` (optional): Disable entirely the dependency installation. This is useful when dependencies are already provided by the environment. Default is `false`.
|
|
114
|
+
|
|
115
|
+
### Full example
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"name": "Sales Dashboard",
|
|
120
|
+
"entry": "app.py",
|
|
121
|
+
"framework": "streamlit",
|
|
122
|
+
"rootUrl": "/",
|
|
123
|
+
"metadata": {
|
|
124
|
+
"autoreload": true
|
|
125
|
+
},
|
|
126
|
+
"dependencies": {
|
|
127
|
+
"mamba": ["numpy", "pandas"],
|
|
128
|
+
"pip": []
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Framework-specific configurations
|
|
50
134
|
|
|
51
135
|
### Dash application
|
|
52
136
|
|
|
@@ -68,7 +152,27 @@ the `app.spk` is the entry point of your Dash app, it should contain the followi
|
|
|
68
152
|
}
|
|
69
153
|
```
|
|
70
154
|
|
|
71
|
-
For
|
|
155
|
+
For Dash applications, you must define your Dash instance as a variable named `app`.
|
|
156
|
+
Do **not** call `app.run_server()` yourself — `jupyterpack` is responsible for starting and managing the server lifecycle.
|
|
157
|
+
|
|
158
|
+
As with React applications, double-clicking the `.spk` file will open the Dash app in a new JupyterLab tab.
|
|
159
|
+
|
|
160
|
+
### Streamlit application
|
|
161
|
+
|
|
162
|
+
Streamlit applications follow a similar structure to Dash apps.
|
|
163
|
+
Write your code as a standard Streamlit application and do **not** start the server manually — `jupyterpack` will handle execution and serving automatically.
|
|
164
|
+
|
|
165
|
+
Opening the `.spk` file will launch the Streamlit app in a new JupyterLab tab.
|
|
166
|
+
|
|
167
|
+
### Shiny application
|
|
168
|
+
|
|
169
|
+
Shiny applications also follow a structure similar to Dash apps.
|
|
170
|
+
`jupyterpack` supports both **Shiny Express** and **Shiny Core** applications.
|
|
171
|
+
|
|
172
|
+
- **Shiny Express**: no special requirements.
|
|
173
|
+
- **Shiny Core**: the application instance must be assigned to a variable named `app`.
|
|
174
|
+
|
|
175
|
+
In both cases, the server is managed by `jupyterpack`, and opening the `.spk` file will launch the app in JupyterLab.
|
|
72
176
|
|
|
73
177
|
## Try it online!
|
|
74
178
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { IBasePythonServer, IDependencies, IDict, IKernelExecutor, IPythonServerInitOptions, JupyterPackFramework } from '../type';
|
|
1
2
|
import { KernelExecutor } from './kernelExecutor';
|
|
2
|
-
import { IDict, IBasePythonServer, IKernelExecutor, JupyterPackFramework } from '../type';
|
|
3
3
|
export declare abstract class BasePythonServer implements IBasePythonServer {
|
|
4
4
|
constructor(options: KernelExecutor.IOptions);
|
|
5
5
|
abstract reloadPythonServer(options: {
|
|
@@ -9,12 +9,7 @@ export declare abstract class BasePythonServer implements IBasePythonServer {
|
|
|
9
9
|
get isDisposed(): boolean;
|
|
10
10
|
get kernelExecutor(): IKernelExecutor;
|
|
11
11
|
dispose(): void;
|
|
12
|
-
init(options:
|
|
13
|
-
entryPath?: string;
|
|
14
|
-
initCode?: string;
|
|
15
|
-
instanceId: string;
|
|
16
|
-
kernelClientId: string;
|
|
17
|
-
}): Promise<void>;
|
|
12
|
+
init(options: IPythonServerInitOptions): Promise<void>;
|
|
18
13
|
disposePythonServer(): Promise<void>;
|
|
19
14
|
getResponseFunctionFactory(options: {
|
|
20
15
|
urlPath: string;
|
|
@@ -69,6 +64,7 @@ export declare abstract class BasePythonServer implements IBasePythonServer {
|
|
|
69
64
|
kernelClientId: string;
|
|
70
65
|
framework: JupyterPackFramework;
|
|
71
66
|
}): string;
|
|
67
|
+
protected mergeDependencies(spkDeps?: IDependencies, defaultDeps?: IDependencies): IDependencies | undefined;
|
|
72
68
|
protected _baseUrl: string | undefined;
|
|
73
69
|
protected readonly _openedWebsockets: {
|
|
74
70
|
instanceId: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { KernelExecutor } from './kernelExecutor';
|
|
2
|
-
import websocketPatch from '../websocket/websocket.js?raw';
|
|
3
1
|
import { PageConfig, URLExt } from '@jupyterlab/coreutils';
|
|
4
2
|
import { arrayBufferToBase64, base64ToArrayBuffer, base64ToString, isBinaryContentType, stringOrNone } from '../tools';
|
|
3
|
+
import websocketPatch from '../websocket/websocket.js?raw';
|
|
4
|
+
import { KernelExecutor } from './kernelExecutor';
|
|
5
5
|
export class BasePythonServer {
|
|
6
6
|
constructor(options) {
|
|
7
7
|
this._openedWebsockets = [];
|
|
@@ -33,6 +33,27 @@ export class BasePythonServer {
|
|
|
33
33
|
patch_all()
|
|
34
34
|
`;
|
|
35
35
|
await this._kernelExecutor.executeCode({ code: patchCode });
|
|
36
|
+
if (!options.disableDependencies) {
|
|
37
|
+
const { dependencies } = options;
|
|
38
|
+
if (dependencies === null || dependencies === void 0 ? void 0 : dependencies.mamba) {
|
|
39
|
+
const mambaDeps = `
|
|
40
|
+
%mamba install ${dependencies.mamba.join(' ')}
|
|
41
|
+
True
|
|
42
|
+
`;
|
|
43
|
+
await this.kernelExecutor.executeCode({
|
|
44
|
+
code: mambaDeps
|
|
45
|
+
}, true);
|
|
46
|
+
}
|
|
47
|
+
if (dependencies === null || dependencies === void 0 ? void 0 : dependencies.pip) {
|
|
48
|
+
const pipDeps = `
|
|
49
|
+
%pip install ${dependencies.pip.join(' ')}
|
|
50
|
+
True
|
|
51
|
+
`;
|
|
52
|
+
await this.kernelExecutor.executeCode({
|
|
53
|
+
code: pipDeps
|
|
54
|
+
}, true);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
36
57
|
}
|
|
37
58
|
async disposePythonServer() {
|
|
38
59
|
await this.kernelExecutor.executeCode({
|
|
@@ -138,4 +159,17 @@ export class BasePythonServer {
|
|
|
138
159
|
this._baseUrl = baseURL;
|
|
139
160
|
return baseURL;
|
|
140
161
|
}
|
|
162
|
+
mergeDependencies(spkDeps, defaultDeps) {
|
|
163
|
+
var _a, _b, _c, _d;
|
|
164
|
+
if (!spkDeps) {
|
|
165
|
+
return defaultDeps;
|
|
166
|
+
}
|
|
167
|
+
if (!defaultDeps) {
|
|
168
|
+
return spkDeps;
|
|
169
|
+
}
|
|
170
|
+
const merged = {};
|
|
171
|
+
merged.mamba = [...((_a = spkDeps.mamba) !== null && _a !== void 0 ? _a : []), ...((_b = defaultDeps.mamba) !== null && _b !== void 0 ? _b : [])];
|
|
172
|
+
merged.pip = [...((_c = spkDeps.pip) !== null && _c !== void 0 ? _c : []), ...((_d = defaultDeps.pip) !== null && _d !== void 0 ? _d : [])];
|
|
173
|
+
return merged;
|
|
174
|
+
}
|
|
141
175
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
+
import { IPythonServerInitOptions } from '../../type';
|
|
1
2
|
import { BasePythonServer } from '../baseServer';
|
|
2
3
|
export declare class DashServer extends BasePythonServer {
|
|
3
|
-
init(options:
|
|
4
|
-
initCode?: string;
|
|
5
|
-
instanceId: string;
|
|
6
|
-
kernelClientId: string;
|
|
7
|
-
}): Promise<void>;
|
|
4
|
+
init(options: IPythonServerInitOptions): Promise<void>;
|
|
8
5
|
reloadPythonServer(options: {
|
|
9
6
|
entryPath?: string;
|
|
10
7
|
initCode?: string;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { JupyterPackFramework } from '../../type';
|
|
2
2
|
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
import { DEPENDENCIES } from './deps';
|
|
3
4
|
export class DashServer extends BasePythonServer {
|
|
4
5
|
async init(options) {
|
|
5
|
-
|
|
6
|
+
const mergedOptions = {
|
|
7
|
+
...options,
|
|
8
|
+
dependencies: this.mergeDependencies(options.dependencies, DEPENDENCIES)
|
|
9
|
+
};
|
|
10
|
+
await super.init(mergedOptions);
|
|
6
11
|
const { initCode, instanceId, kernelClientId } = options;
|
|
7
12
|
const baseURL = this.buildBaseURL({
|
|
8
13
|
instanceId,
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
+
import { IPythonServerInitOptions } from '../../type';
|
|
1
2
|
import { BasePythonServer } from '../baseServer';
|
|
2
3
|
export declare class ShinyServer extends BasePythonServer {
|
|
3
|
-
init(options:
|
|
4
|
-
entryPath?: string;
|
|
5
|
-
initCode?: string;
|
|
6
|
-
instanceId: string;
|
|
7
|
-
kernelClientId: string;
|
|
8
|
-
}): Promise<void>;
|
|
4
|
+
init(options: IPythonServerInitOptions): Promise<void>;
|
|
9
5
|
disposePythonServer(): Promise<void>;
|
|
10
6
|
reloadPythonServer(options: {
|
|
11
7
|
entryPath?: string;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { JupyterPackFramework } from '../../type';
|
|
2
2
|
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
import { DEPENDENCIES } from './deps';
|
|
3
4
|
export class ShinyServer extends BasePythonServer {
|
|
4
5
|
async init(options) {
|
|
5
|
-
|
|
6
|
+
const mergedOptions = {
|
|
7
|
+
...options,
|
|
8
|
+
dependencies: this.mergeDependencies(options.dependencies, DEPENDENCIES)
|
|
9
|
+
};
|
|
10
|
+
await super.init(mergedOptions);
|
|
6
11
|
const { instanceId, kernelClientId, entryPath } = options;
|
|
7
12
|
const baseURL = this.buildBaseURL({
|
|
8
13
|
instanceId,
|
|
@@ -1,11 +1,7 @@
|
|
|
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;
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { JupyterPackFramework } from '../../type';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
import { DEPENDENCIES } from './deps';
|
|
4
|
+
export class StreamlitServer extends BasePythonServer {
|
|
4
5
|
async init(options) {
|
|
6
|
+
const mergedOptions = {
|
|
7
|
+
...options,
|
|
8
|
+
dependencies: this.mergeDependencies(options.dependencies, DEPENDENCIES)
|
|
9
|
+
};
|
|
10
|
+
await super.init(mergedOptions);
|
|
5
11
|
const { instanceId, kernelClientId, entryPath } = options;
|
|
6
12
|
if (!entryPath) {
|
|
7
13
|
throw new Error('Missing streamlit entry path, please check your SPK file');
|
|
@@ -12,8 +18,7 @@ export class StreamlitServer extends TornadoServer {
|
|
|
12
18
|
framework: JupyterPackFramework.STREAMLIT
|
|
13
19
|
});
|
|
14
20
|
const patchCode = `
|
|
15
|
-
from jupyterpack.common import set_base_url_env, patch_tornado
|
|
16
|
-
patch_all()
|
|
21
|
+
from jupyterpack.common import set_base_url_env, patch_tornado
|
|
17
22
|
patch_tornado()
|
|
18
23
|
set_base_url_env("${baseURL}")
|
|
19
24
|
`;
|
|
@@ -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();
|
package/lib/type.d.ts
CHANGED
|
@@ -28,6 +28,8 @@ export interface IJupyterPackFileFormat {
|
|
|
28
28
|
autoreload?: boolean;
|
|
29
29
|
};
|
|
30
30
|
rootUrl?: string;
|
|
31
|
+
dependencies?: IDependencies;
|
|
32
|
+
disableDependencies?: boolean;
|
|
31
33
|
}
|
|
32
34
|
export declare enum MessageAction {
|
|
33
35
|
INIT = "INIT"
|
|
@@ -61,12 +63,7 @@ export interface IBasePythonServer extends IDisposable {
|
|
|
61
63
|
wsUrl: string;
|
|
62
64
|
message: string;
|
|
63
65
|
}): Promise<void>;
|
|
64
|
-
init(options:
|
|
65
|
-
entryPath?: string;
|
|
66
|
-
initCode?: string;
|
|
67
|
-
instanceId: string;
|
|
68
|
-
kernelClientId: string;
|
|
69
|
-
}): Promise<void>;
|
|
66
|
+
init(options: IPythonServerInitOptions): Promise<void>;
|
|
70
67
|
disposePythonServer(): Promise<void>;
|
|
71
68
|
reloadPythonServer(options: {
|
|
72
69
|
entryPath?: string;
|
|
@@ -106,3 +103,15 @@ export interface IPythonWidgetModel extends IDisposable {
|
|
|
106
103
|
error: string;
|
|
107
104
|
}>;
|
|
108
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/package.json
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
import { KernelExecutor } from './kernelExecutor';
|
|
2
|
-
import websocketPatch from '../websocket/websocket.js?raw';
|
|
3
|
-
import {
|
|
4
|
-
IDict,
|
|
5
|
-
IBasePythonServer,
|
|
6
|
-
IKernelExecutor,
|
|
7
|
-
JupyterPackFramework
|
|
8
|
-
} from '../type';
|
|
9
1
|
import { PageConfig, URLExt } from '@jupyterlab/coreutils';
|
|
2
|
+
|
|
10
3
|
import {
|
|
11
4
|
arrayBufferToBase64,
|
|
12
5
|
base64ToArrayBuffer,
|
|
@@ -14,6 +7,16 @@ import {
|
|
|
14
7
|
isBinaryContentType,
|
|
15
8
|
stringOrNone
|
|
16
9
|
} from '../tools';
|
|
10
|
+
import {
|
|
11
|
+
IBasePythonServer,
|
|
12
|
+
IDependencies,
|
|
13
|
+
IDict,
|
|
14
|
+
IKernelExecutor,
|
|
15
|
+
IPythonServerInitOptions,
|
|
16
|
+
JupyterPackFramework
|
|
17
|
+
} from '../type';
|
|
18
|
+
import websocketPatch from '../websocket/websocket.js?raw';
|
|
19
|
+
import { KernelExecutor } from './kernelExecutor';
|
|
17
20
|
|
|
18
21
|
export abstract class BasePythonServer implements IBasePythonServer {
|
|
19
22
|
constructor(options: KernelExecutor.IOptions) {
|
|
@@ -45,17 +48,39 @@ export abstract class BasePythonServer implements IBasePythonServer {
|
|
|
45
48
|
})
|
|
46
49
|
.catch(console.error);
|
|
47
50
|
}
|
|
48
|
-
async init(options: {
|
|
49
|
-
entryPath?: string;
|
|
50
|
-
initCode?: string;
|
|
51
|
-
instanceId: string;
|
|
52
|
-
kernelClientId: string;
|
|
53
|
-
}): Promise<void> {
|
|
51
|
+
async init(options: IPythonServerInitOptions): Promise<void> {
|
|
54
52
|
const patchCode = `
|
|
55
53
|
from jupyterpack.common import patch_all
|
|
56
54
|
patch_all()
|
|
57
55
|
`;
|
|
58
56
|
await this._kernelExecutor.executeCode({ code: patchCode });
|
|
57
|
+
if (!options.disableDependencies) {
|
|
58
|
+
const { dependencies } = options;
|
|
59
|
+
if (dependencies?.mamba) {
|
|
60
|
+
const mambaDeps = `
|
|
61
|
+
%mamba install ${dependencies.mamba.join(' ')}
|
|
62
|
+
True
|
|
63
|
+
`;
|
|
64
|
+
await this.kernelExecutor.executeCode(
|
|
65
|
+
{
|
|
66
|
+
code: mambaDeps
|
|
67
|
+
},
|
|
68
|
+
true
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
if (dependencies?.pip) {
|
|
72
|
+
const pipDeps = `
|
|
73
|
+
%pip install ${dependencies.pip.join(' ')}
|
|
74
|
+
True
|
|
75
|
+
`;
|
|
76
|
+
await this.kernelExecutor.executeCode(
|
|
77
|
+
{
|
|
78
|
+
code: pipDeps
|
|
79
|
+
},
|
|
80
|
+
true
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
59
84
|
}
|
|
60
85
|
|
|
61
86
|
async disposePythonServer(): Promise<void> {
|
|
@@ -230,6 +255,21 @@ export abstract class BasePythonServer implements IBasePythonServer {
|
|
|
230
255
|
|
|
231
256
|
return baseURL;
|
|
232
257
|
}
|
|
258
|
+
protected mergeDependencies(
|
|
259
|
+
spkDeps?: IDependencies,
|
|
260
|
+
defaultDeps?: IDependencies
|
|
261
|
+
): IDependencies | undefined {
|
|
262
|
+
if (!spkDeps) {
|
|
263
|
+
return defaultDeps;
|
|
264
|
+
}
|
|
265
|
+
if (!defaultDeps) {
|
|
266
|
+
return spkDeps;
|
|
267
|
+
}
|
|
268
|
+
const merged: IDependencies = {};
|
|
269
|
+
merged.mamba = [...(spkDeps.mamba ?? []), ...(defaultDeps.mamba ?? [])];
|
|
270
|
+
merged.pip = [...(spkDeps.pip ?? []), ...(defaultDeps.pip ?? [])];
|
|
271
|
+
return merged;
|
|
272
|
+
}
|
|
233
273
|
|
|
234
274
|
protected _baseUrl: string | undefined;
|
|
235
275
|
protected readonly _openedWebsockets: {
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { JupyterPackFramework } from '../../type';
|
|
1
|
+
import { IPythonServerInitOptions, JupyterPackFramework } from '../../type';
|
|
2
2
|
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
import { DEPENDENCIES } from './deps';
|
|
3
4
|
|
|
4
5
|
export class DashServer extends BasePythonServer {
|
|
5
|
-
async init(options: {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
await super.init(
|
|
6
|
+
async init(options: IPythonServerInitOptions) {
|
|
7
|
+
const mergedOptions: IPythonServerInitOptions = {
|
|
8
|
+
...options,
|
|
9
|
+
dependencies: this.mergeDependencies(options.dependencies, DEPENDENCIES)
|
|
10
|
+
};
|
|
11
|
+
await super.init(mergedOptions);
|
|
12
|
+
|
|
11
13
|
const { initCode, instanceId, kernelClientId } = options;
|
|
12
14
|
|
|
13
15
|
const baseURL = this.buildBaseURL({
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { JupyterPackFramework } from '../../type';
|
|
1
|
+
import { IPythonServerInitOptions, JupyterPackFramework } from '../../type';
|
|
2
2
|
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
import { DEPENDENCIES } from './deps';
|
|
3
4
|
|
|
4
5
|
export class ShinyServer extends BasePythonServer {
|
|
5
|
-
async init(options: {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
async init(options: IPythonServerInitOptions) {
|
|
7
|
+
const mergedOptions: IPythonServerInitOptions = {
|
|
8
|
+
...options,
|
|
9
|
+
dependencies: this.mergeDependencies(options.dependencies, DEPENDENCIES)
|
|
10
|
+
};
|
|
11
|
+
await super.init(mergedOptions);
|
|
12
|
+
|
|
12
13
|
const { instanceId, kernelClientId, entryPath } = options;
|
|
13
14
|
const baseURL = this.buildBaseURL({
|
|
14
15
|
instanceId,
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { JupyterPackFramework } from '../../type';
|
|
2
|
-
import {
|
|
1
|
+
import { IPythonServerInitOptions, JupyterPackFramework } from '../../type';
|
|
2
|
+
import { BasePythonServer } from '../baseServer';
|
|
3
|
+
import { DEPENDENCIES } from './deps';
|
|
4
|
+
|
|
5
|
+
export class StreamlitServer extends BasePythonServer {
|
|
6
|
+
async init(options: IPythonServerInitOptions) {
|
|
7
|
+
const mergedOptions: IPythonServerInitOptions = {
|
|
8
|
+
...options,
|
|
9
|
+
dependencies: this.mergeDependencies(options.dependencies, DEPENDENCIES)
|
|
10
|
+
};
|
|
11
|
+
await super.init(mergedOptions);
|
|
3
12
|
|
|
4
|
-
export class StreamlitServer extends TornadoServer {
|
|
5
|
-
async init(options: {
|
|
6
|
-
entryPath?: string;
|
|
7
|
-
initCode?: string;
|
|
8
|
-
instanceId: string;
|
|
9
|
-
kernelClientId: string;
|
|
10
|
-
}) {
|
|
11
13
|
const { instanceId, kernelClientId, entryPath } = options;
|
|
12
14
|
if (!entryPath) {
|
|
13
15
|
throw new Error(
|
|
@@ -21,8 +23,7 @@ export class StreamlitServer extends TornadoServer {
|
|
|
21
23
|
});
|
|
22
24
|
|
|
23
25
|
const patchCode = `
|
|
24
|
-
from jupyterpack.common import set_base_url_env, patch_tornado
|
|
25
|
-
patch_all()
|
|
26
|
+
from jupyterpack.common import set_base_url_env, patch_tornado
|
|
26
27
|
patch_tornado()
|
|
27
28
|
set_base_url_env("${baseURL}")
|
|
28
29
|
`;
|
|
@@ -135,9 +135,12 @@ export class PythonWidgetModel implements IPythonWidgetModel {
|
|
|
135
135
|
sessionConnection: this._sessionConnection
|
|
136
136
|
}));
|
|
137
137
|
const data = await this._connectionManager.registerConnection(executor);
|
|
138
|
+
|
|
138
139
|
await executor.init({
|
|
139
140
|
initCode: entryContent.content,
|
|
140
141
|
entryPath: spkContent.entry,
|
|
142
|
+
dependencies: spkContent.dependencies,
|
|
143
|
+
disableDependencies: spkContent.disableDependencies,
|
|
141
144
|
...data
|
|
142
145
|
});
|
|
143
146
|
const finish = new PromiseDelegate<void>();
|
package/src/type.ts
CHANGED
|
@@ -38,6 +38,8 @@ export interface IJupyterPackFileFormat {
|
|
|
38
38
|
autoreload?: boolean;
|
|
39
39
|
};
|
|
40
40
|
rootUrl?: string;
|
|
41
|
+
dependencies?: IDependencies;
|
|
42
|
+
disableDependencies?: boolean;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
export enum MessageAction {
|
|
@@ -78,12 +80,7 @@ export interface IBasePythonServer extends IDisposable {
|
|
|
78
80
|
wsUrl: string;
|
|
79
81
|
message: string;
|
|
80
82
|
}): Promise<void>;
|
|
81
|
-
init(options:
|
|
82
|
-
entryPath?: string;
|
|
83
|
-
initCode?: string;
|
|
84
|
-
instanceId: string;
|
|
85
|
-
kernelClientId: string;
|
|
86
|
-
}): Promise<void>;
|
|
83
|
+
init(options: IPythonServerInitOptions): Promise<void>;
|
|
87
84
|
disposePythonServer(): Promise<void>;
|
|
88
85
|
reloadPythonServer(options: {
|
|
89
86
|
entryPath?: string;
|
|
@@ -125,3 +122,17 @@ export interface IPythonWidgetModel extends IDisposable {
|
|
|
125
122
|
| { success: false; error: string }
|
|
126
123
|
>;
|
|
127
124
|
}
|
|
125
|
+
|
|
126
|
+
export interface IDependencies {
|
|
127
|
+
mamba?: string[];
|
|
128
|
+
pip?: string[];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface IPythonServerInitOptions {
|
|
132
|
+
entryPath?: string;
|
|
133
|
+
initCode?: string;
|
|
134
|
+
instanceId: string;
|
|
135
|
+
kernelClientId: string;
|
|
136
|
+
dependencies?: IDependencies;
|
|
137
|
+
disableDependencies?: boolean;
|
|
138
|
+
}
|