@jupyter/docprovider 3.0.0-alpha.1 → 3.0.0-beta.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/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/notebookCellExecutor.d.ts +23 -0
- package/lib/notebookCellExecutor.js +108 -0
- package/lib/ydrive.d.ts +3 -1
- package/lib/ydrive.js +19 -1
- package/lib/yprovider.js +5 -2
- package/package.json +10 -5
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { INotebookCellExecutor } from '@jupyterlab/notebook';
|
|
2
|
+
import { ServerConnection } from '@jupyterlab/services';
|
|
3
|
+
/**
|
|
4
|
+
* Notebook cell executor posting a request to the server for execution.
|
|
5
|
+
*/
|
|
6
|
+
export declare class NotebookCellServerExecutor implements INotebookCellExecutor {
|
|
7
|
+
private _serverSettings;
|
|
8
|
+
/**
|
|
9
|
+
* Constructor
|
|
10
|
+
*
|
|
11
|
+
* @param options Constructor options; the contents manager, the collaborative drive and optionally the server settings.
|
|
12
|
+
*/
|
|
13
|
+
constructor(options: {
|
|
14
|
+
serverSettings?: ServerConnection.ISettings;
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Execute a given cell of the notebook.
|
|
18
|
+
*
|
|
19
|
+
* @param options Execution options
|
|
20
|
+
* @returns Execution success status
|
|
21
|
+
*/
|
|
22
|
+
runCell({ cell, notebook, notebookConfig, onCellExecuted, onCellExecutionScheduled, sessionContext, sessionDialogs, translator }: INotebookCellExecutor.IRunCellOptions): Promise<boolean>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/* -----------------------------------------------------------------------------
|
|
2
|
+
| Copyright (c) Jupyter Development Team.
|
|
3
|
+
| Distributed under the terms of the Modified BSD License.
|
|
4
|
+
|----------------------------------------------------------------------------*/
|
|
5
|
+
import { Dialog, showDialog } from '@jupyterlab/apputils';
|
|
6
|
+
import { URLExt } from '@jupyterlab/coreutils';
|
|
7
|
+
import { ServerConnection } from '@jupyterlab/services';
|
|
8
|
+
import { nullTranslator } from '@jupyterlab/translation';
|
|
9
|
+
/**
|
|
10
|
+
* Notebook cell executor posting a request to the server for execution.
|
|
11
|
+
*/
|
|
12
|
+
export class NotebookCellServerExecutor {
|
|
13
|
+
/**
|
|
14
|
+
* Constructor
|
|
15
|
+
*
|
|
16
|
+
* @param options Constructor options; the contents manager, the collaborative drive and optionally the server settings.
|
|
17
|
+
*/
|
|
18
|
+
constructor(options) {
|
|
19
|
+
var _a;
|
|
20
|
+
this._serverSettings =
|
|
21
|
+
(_a = options.serverSettings) !== null && _a !== void 0 ? _a : ServerConnection.makeSettings();
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Execute a given cell of the notebook.
|
|
25
|
+
*
|
|
26
|
+
* @param options Execution options
|
|
27
|
+
* @returns Execution success status
|
|
28
|
+
*/
|
|
29
|
+
async runCell({ cell, notebook, notebookConfig, onCellExecuted, onCellExecutionScheduled, sessionContext, sessionDialogs, translator }) {
|
|
30
|
+
var _a, _b, _c;
|
|
31
|
+
translator = translator !== null && translator !== void 0 ? translator : nullTranslator;
|
|
32
|
+
const trans = translator.load('jupyterlab');
|
|
33
|
+
switch (cell.model.type) {
|
|
34
|
+
case 'markdown':
|
|
35
|
+
cell.rendered = true;
|
|
36
|
+
cell.inputHidden = false;
|
|
37
|
+
onCellExecuted({ cell, success: true });
|
|
38
|
+
break;
|
|
39
|
+
case 'code':
|
|
40
|
+
if (sessionContext) {
|
|
41
|
+
if (sessionContext.isTerminating) {
|
|
42
|
+
await showDialog({
|
|
43
|
+
title: trans.__('Kernel Terminating'),
|
|
44
|
+
body: trans.__('The kernel for %1 appears to be terminating. You can not run any cell for now.', (_a = sessionContext.session) === null || _a === void 0 ? void 0 : _a.path),
|
|
45
|
+
buttons: [Dialog.okButton()]
|
|
46
|
+
});
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
if (sessionContext.pendingInput) {
|
|
50
|
+
await showDialog({
|
|
51
|
+
title: trans.__('Cell not executed due to pending input'),
|
|
52
|
+
body: trans.__('The cell has not been executed to avoid kernel deadlock as there is another pending input! Submit your pending input and try again.'),
|
|
53
|
+
buttons: [Dialog.okButton()]
|
|
54
|
+
});
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
if (sessionContext.hasNoKernel) {
|
|
58
|
+
const shouldSelect = await sessionContext.startKernel();
|
|
59
|
+
if (shouldSelect && sessionDialogs) {
|
|
60
|
+
await sessionDialogs.selectKernel(sessionContext);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (sessionContext.hasNoKernel) {
|
|
64
|
+
cell.model.sharedModel.transact(() => {
|
|
65
|
+
cell.model.clearExecution();
|
|
66
|
+
});
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
const kernelId = (_c = (_b = sessionContext === null || sessionContext === void 0 ? void 0 : sessionContext.session) === null || _b === void 0 ? void 0 : _b.kernel) === null || _c === void 0 ? void 0 : _c.id;
|
|
70
|
+
const apiURL = URLExt.join(this._serverSettings.baseUrl, `api/kernels/${kernelId}/execute`);
|
|
71
|
+
const cellId = cell.model.sharedModel.getId();
|
|
72
|
+
const documentId = notebook.sharedModel.getState('document_id');
|
|
73
|
+
const init = {
|
|
74
|
+
method: 'POST',
|
|
75
|
+
body: JSON.stringify({ cell_id: cellId, document_id: documentId })
|
|
76
|
+
};
|
|
77
|
+
onCellExecutionScheduled({ cell });
|
|
78
|
+
let success = false;
|
|
79
|
+
try {
|
|
80
|
+
// FIXME quid of deletedCells and timing record
|
|
81
|
+
const response = await ServerConnection.makeRequest(apiURL, init, this._serverSettings);
|
|
82
|
+
success = response.ok;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
onCellExecuted({
|
|
86
|
+
cell,
|
|
87
|
+
success: false
|
|
88
|
+
});
|
|
89
|
+
if (cell.isDisposed) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
onCellExecuted({ cell, success });
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
cell.model.sharedModel.transact(() => {
|
|
100
|
+
cell.model.clearExecution();
|
|
101
|
+
}, false);
|
|
102
|
+
break;
|
|
103
|
+
default:
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
return Promise.resolve(true);
|
|
107
|
+
}
|
|
108
|
+
}
|
package/lib/ydrive.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TranslationBundle } from '@jupyterlab/translation';
|
|
2
2
|
import { Contents, Drive, User } from '@jupyterlab/services';
|
|
3
3
|
import { ICollaborativeDrive, ISharedModelFactory } from './tokens';
|
|
4
|
+
import { Awareness } from 'y-protocols/awareness';
|
|
4
5
|
/**
|
|
5
6
|
* A Collaborative implementation for an `IDrive`, talking to the
|
|
6
7
|
* server using the Jupyter REST API and a WebSocket connection.
|
|
@@ -11,7 +12,7 @@ export declare class YDrive extends Drive implements ICollaborativeDrive {
|
|
|
11
12
|
*
|
|
12
13
|
* @param user - The user manager to add the identity to the awareness of documents.
|
|
13
14
|
*/
|
|
14
|
-
constructor(user: User.IManager, translator: TranslationBundle);
|
|
15
|
+
constructor(user: User.IManager, translator: TranslationBundle, globalAwareness: Awareness | null);
|
|
15
16
|
/**
|
|
16
17
|
* SharedModel factory for the YDrive.
|
|
17
18
|
*/
|
|
@@ -47,4 +48,5 @@ export declare class YDrive extends Drive implements ICollaborativeDrive {
|
|
|
47
48
|
private _user;
|
|
48
49
|
private _trans;
|
|
49
50
|
private _providers;
|
|
51
|
+
private _globalAwareness;
|
|
50
52
|
}
|
package/lib/ydrive.js
CHANGED
|
@@ -18,9 +18,10 @@ export class YDrive extends Drive {
|
|
|
18
18
|
*
|
|
19
19
|
* @param user - The user manager to add the identity to the awareness of documents.
|
|
20
20
|
*/
|
|
21
|
-
constructor(user, translator) {
|
|
21
|
+
constructor(user, translator, globalAwareness) {
|
|
22
22
|
super({ name: 'RTC' });
|
|
23
23
|
this._onCreate = (options, sharedModel) => {
|
|
24
|
+
var _a, _b;
|
|
24
25
|
if (typeof options.format !== 'string') {
|
|
25
26
|
return;
|
|
26
27
|
}
|
|
@@ -34,14 +35,30 @@ export class YDrive extends Drive {
|
|
|
34
35
|
user: this._user,
|
|
35
36
|
translator: this._trans
|
|
36
37
|
});
|
|
38
|
+
// Add the document path in the list of opened ones for this user.
|
|
39
|
+
const state = ((_a = this._globalAwareness) === null || _a === void 0 ? void 0 : _a.getLocalState()) || {};
|
|
40
|
+
const documents = state.documents || [];
|
|
41
|
+
if (!documents.includes(options.path)) {
|
|
42
|
+
documents.push(`${this.name}:${options.path}`);
|
|
43
|
+
(_b = this._globalAwareness) === null || _b === void 0 ? void 0 : _b.setLocalStateField('documents', documents);
|
|
44
|
+
}
|
|
37
45
|
const key = `${options.format}:${options.contentType}:${options.path}`;
|
|
38
46
|
this._providers.set(key, provider);
|
|
39
47
|
sharedModel.disposed.connect(() => {
|
|
48
|
+
var _a, _b;
|
|
40
49
|
const provider = this._providers.get(key);
|
|
41
50
|
if (provider) {
|
|
42
51
|
provider.dispose();
|
|
43
52
|
this._providers.delete(key);
|
|
44
53
|
}
|
|
54
|
+
// Remove the document path from the list of opened ones for this user.
|
|
55
|
+
const state = ((_a = this._globalAwareness) === null || _a === void 0 ? void 0 : _a.getLocalState()) || {};
|
|
56
|
+
const documents = state.documents || [];
|
|
57
|
+
const index = documents.indexOf(`${this.name}:${options.path}`);
|
|
58
|
+
if (index > -1) {
|
|
59
|
+
documents.splice(index, 1);
|
|
60
|
+
}
|
|
61
|
+
(_b = this._globalAwareness) === null || _b === void 0 ? void 0 : _b.setLocalStateField('documents', documents);
|
|
45
62
|
});
|
|
46
63
|
}
|
|
47
64
|
catch (error) {
|
|
@@ -52,6 +69,7 @@ export class YDrive extends Drive {
|
|
|
52
69
|
};
|
|
53
70
|
this._user = user;
|
|
54
71
|
this._trans = translator;
|
|
72
|
+
this._globalAwareness = globalAwareness;
|
|
55
73
|
this._providers = new Map();
|
|
56
74
|
this.sharedModelFactory = new SharedModelFactory(this._onCreate);
|
|
57
75
|
}
|
package/lib/yprovider.js
CHANGED
|
@@ -32,10 +32,13 @@ export class WebSocketProvider {
|
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
34
|
this._onSync = (isSynced) => {
|
|
35
|
-
var _a;
|
|
36
35
|
if (isSynced) {
|
|
36
|
+
if (this._yWebsocketProvider) {
|
|
37
|
+
this._yWebsocketProvider.off('sync', this._onSync);
|
|
38
|
+
const state = this._sharedModel.ydoc.getMap('state');
|
|
39
|
+
state.set('document_id', this._yWebsocketProvider.roomname);
|
|
40
|
+
}
|
|
37
41
|
this._ready.resolve();
|
|
38
|
-
(_a = this._yWebsocketProvider) === null || _a === void 0 ? void 0 : _a.off('sync', this._onSync);
|
|
39
42
|
}
|
|
40
43
|
};
|
|
41
44
|
this._ready = new PromiseDelegate();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyter/docprovider",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-beta.0",
|
|
4
4
|
"description": "JupyterLab - Document Provider",
|
|
5
5
|
"homepage": "https://github.com/jupyterlab/jupyter-collaboration",
|
|
6
6
|
"bugs": {
|
|
@@ -41,18 +41,23 @@
|
|
|
41
41
|
"watch": "tsc -b --watch"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@jupyter/ydoc": "^
|
|
45
|
-
"@jupyterlab/
|
|
46
|
-
"@jupyterlab/
|
|
44
|
+
"@jupyter/ydoc": "^2.0.0",
|
|
45
|
+
"@jupyterlab/apputils": "^4.2.0",
|
|
46
|
+
"@jupyterlab/cells": "^4.2.0",
|
|
47
|
+
"@jupyterlab/coreutils": "^6.2.0",
|
|
48
|
+
"@jupyterlab/notebook": "^4.2.0",
|
|
49
|
+
"@jupyterlab/services": "^7.2.0",
|
|
50
|
+
"@jupyterlab/translation": "^4.2.0",
|
|
47
51
|
"@lumino/coreutils": "^2.1.0",
|
|
48
52
|
"@lumino/disposable": "^2.1.0",
|
|
49
53
|
"@lumino/signaling": "^2.1.0",
|
|
54
|
+
"@lumino/widgets": "^2.2.0",
|
|
50
55
|
"y-protocols": "^1.0.5",
|
|
51
56
|
"y-websocket": "^1.3.15",
|
|
52
57
|
"yjs": "^13.5.40"
|
|
53
58
|
},
|
|
54
59
|
"devDependencies": {
|
|
55
|
-
"@jupyterlab/testing": "^4.0.
|
|
60
|
+
"@jupyterlab/testing": "^4.0.0",
|
|
56
61
|
"@types/jest": "^29.2.0",
|
|
57
62
|
"jest": "^29.5.0",
|
|
58
63
|
"rimraf": "^4.1.2",
|