Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On Kernel Creation #323

Merged
merged 6 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -172,5 +172,6 @@ packages/react/.vscode/launch.json
!.storybook
!.vscode
!.licenserc.yaml
!packages/react/jupyter_react/static/README.md
!dev/notebooks/.datalayer
!docs/static/img
!packages/react/jupyter_react/static/README.md
6 changes: 4 additions & 2 deletions dev/config/jupyter_server_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,16 @@
}

#################
# Content
# Contents
#################

# c.FileContentsManager.delete_to_trash = False
content_dir = os.path.dirname(os.path.realpath(__file__)) + '/../notebooks'
c.ServerApp.root_dir = content_dir
c.ServerApp.preferred_dir = content_dir

# c.FileContentsManager.delete_to_trash = False
c.ContentsManager.allow_hidden = True

#################
# URLs
#################
Expand Down
185 changes: 185 additions & 0 deletions dev/notebooks/.datalayer/ping.ipynb

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions packages/react/public/index-local.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
"jupyterServerToken": "60c1661cc408f978c309d04157af55c9588ff9557c9380e4fb50785750703da6",
"runUrl": "https://oss.datalayer.run",
"token": "",
"cpuEnvironment": "python-simple-env",
"gpuEnvironment": "pytorch-cuda-env"
"cpuEnvironment": "python-cpu-env",
"gpuEnvironment": "pytorch-cuda-env",
"credits": 1
}
</script>
<script id="jupyter-config-data" type="application/json">
{
"appName": "Jupyter React",
"baseUrl": "http://localhost:8686/api/jupyter-server",
"wsUrl": "ws://localhost:8686/api/jupyter-server",
"token": "60c1661cc408f978c309d04157af55c9588ff9557c9380e4fb50785750703da6",
Expand Down
3 changes: 2 additions & 1 deletion packages/react/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
"jupyterServerToken": "60c1661cc408f978c309d04157af55c9588ff9557c9380e4fb50785750703da6",
"runUrl": "https://prod1.datalayer.run",
"token": "",
"cpuEnvironment": "python-simple-env",
"cpuEnvironment": "python-cpu-env",
"gpuEnvironment": "pytorch-cuda-env",
"credits": 1
}
</script>
<script id="jupyter-config-data" type="application/json">
{
"appName": "Jupyter React",
"baseUrl": "https://oss.datalayer.run/api/jupyter-server",
"wsUrl": "wss://oss.datalayer.run/api/jupyter-server",
"token": "60c1661cc408f978c309d04157af55c9588ff9557c9380e4fb50785750703da6",
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/components/cell/CellAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ export class CellAdapter {
this._sessionContext.kernelChanged.connect(
(_, arg: Session.ISessionConnection.IKernelChangedArgs) => {
const kernelConnection = arg.newValue;
console.log('Current Jupyter Kernel connection', kernelConnection);
console.log('Current Jupyter Kernel Connection', kernelConnection);
if (kernelConnection && !kernelConnection.handleComms) {
console.warn(
'Jupyter Kernel Connection does not handle Comms',
Expand Down
7 changes: 4 additions & 3 deletions packages/react/src/components/notebook/Notebook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { CellMetadataEditor } from './cell/metadata/CellMetadataEditor';
import { ICellSidebarProps } from './cell/sidebar/CellSidebarWidget';
import { INotebookToolbarProps } from './toolbar/NotebookToolbar';
import { newUuid } from '../../utils';
import { OnKernelConnection } from '../../state';
import { useNotebookStore } from './NotebookState';
import { NotebookAdapter } from './NotebookAdapter';

Expand All @@ -43,14 +44,15 @@ export type INotebookProps = {
maxHeight?: string;
nbformat?: INotebookContent;
nbgrader: boolean;
onKernelConnection?: OnKernelConnection;
path?: string;
readonly: boolean;
renderers: IRenderMime.IRendererFactory[];
serverless: boolean,
serviceManager?: ServiceManager.IManager,
url?: string;
/**
* The Kernel Id to use, as defined in the Kernel API
* The Kernel Id to use, as defined in the Kernel API.
*/
useRunningKernelId?: string;
/**
Expand Down Expand Up @@ -91,7 +93,7 @@ export const Notebook = (props: INotebookProps) => {
const kernel = props.kernel ?? defaultKernel;
const notebookStore = useNotebookStore();
const portals = notebookStore.selectNotebookPortals(id);
//
// Bootstrap the Notebook Adapter.
const bootstrapAdapter = (serviceManager?: ServiceManager.IManager, kernel?: Kernel) => {
const adapter = new NotebookAdapter({
...props,
Expand All @@ -100,7 +102,6 @@ export const Notebook = (props: INotebookProps) => {
kernel,
serviceManager,
});
console.log('Notebook Adapter is bootstraping...', adapter.serviceManager);
// Update the local state.
setAdapter(adapter);
// Update the global state.
Expand Down
145 changes: 90 additions & 55 deletions packages/react/src/components/notebook/NotebookAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,23 @@ import { find } from '@lumino/algorithm';
import { CommandRegistry } from '@lumino/commands';
import { BoxPanel, Widget } from '@lumino/widgets';
import { IChangedArgs } from '@jupyterlab/coreutils';
import { Cell, ICellModel, MarkdownCell } from '@jupyterlab/cells';
import { Contents, ServiceManager, Kernel as JupyterKernel, SessionManager } from '@jupyterlab/services';
import { DocumentRegistry, Context } from '@jupyterlab/docregistry';
import { IRenderMime } from '@jupyterlab/rendermime-interfaces';
import { standardRendererFactories, RenderMimeRegistry } from '@jupyterlab/rendermime';
import { rendererFactory as jsonRendererFactory } from '@jupyterlab/json-extension';
import { rendererFactory as javascriptRendererFactory } from '@jupyterlab/javascript-extension';
import { Notebook, NotebookPanel, NotebookWidgetFactory, NotebookTracker, INotebookModel } from '@jupyterlab/notebook';
import { ybinding, CodeMirrorEditorFactory, CodeMirrorMimeTypeService, EditorLanguageRegistry, EditorExtensionRegistry, EditorThemeRegistry } from '@jupyterlab/codemirror';
import { IEditorServices } from '@jupyterlab/codeeditor';
import { standardRendererFactories, RenderMimeRegistry } from '@jupyterlab/rendermime';
import { IRenderMime } from '@jupyterlab/rendermime-interfaces';
import { ISharedAttachmentsCell, IYText } from '@jupyter/ydoc';
import { INotebookContent, CellType, IAttachments } from '@jupyterlab/nbformat';
import { Completer, CompleterModel, CompletionHandler, ProviderReconciliator, KernelCompleterProvider } from '@jupyterlab/completer';
import { Notebook, NotebookPanel, NotebookWidgetFactory, NotebookTracker, INotebookModel } from '@jupyterlab/notebook';
import { Cell, ICellModel, MarkdownCell } from '@jupyterlab/cells';
import { rendererFactory as jsonRendererFactory } from '@jupyterlab/json-extension';
import { rendererFactory as javascriptRendererFactory } from '@jupyterlab/javascript-extension';
import { MathJaxTypesetter } from '@jupyterlab/mathjax-extension';
import { INotebookContent, CellType, IAttachments } from '@jupyterlab/nbformat';
import { ISharedAttachmentsCell, IYText } from '@jupyter/ydoc';
import { WIDGET_MIMETYPE } from '@jupyter-widgets/html-manager/lib/output_renderers';
import { Lite, Kernel, WidgetManager, WidgetLabRenderer } from '../../jupyter';
import { OnKernelConnection } from '../../state';
import { ICellSidebarProps } from './cell/sidebar/CellSidebarWidget';
import { JupyterReactContentFactory } from './content/JupyterReactContentFactory';
import { JupyterReactNotebookModelFactory } from './model/JupyterReactNotebookModelFactory';
Expand All @@ -48,17 +49,22 @@ export class NotebookAdapter {
private _nbgrader: boolean;
private _notebookModelFactory?: JupyterReactNotebookModelFactory;
private _notebookPanel?: NotebookPanel;
private _url?: string;
private _onKernelConnection?: OnKernelConnection;
private _path?: string;
private _readonly: boolean;
private _renderers: IRenderMime.IRendererFactory[];
private _rendermime?: RenderMimeRegistry;
private _serverless: boolean;
private _serviceManager: ServiceManager.IManager;
private _tracker?: NotebookTracker;
private _url?: string;

constructor(props: INotebookProps) {

console.log('A new Notebook Adapter is being created...');

this._CellSidebar = props.CellSidebar;

this._id = props.id;
this._kernel = props.kernel;
this._lite = props.lite;
Expand All @@ -71,6 +77,8 @@ export class NotebookAdapter {
this._serviceManager = props.serviceManager!;
this._url = props.url;

this._onKernelConnection = props.onKernelConnection;

this._boxPanel = new BoxPanel();
this._boxPanel.addClass('dla-Jupyter-Notebook');
this._boxPanel.spacing = 0;
Expand Down Expand Up @@ -149,6 +157,8 @@ export class NotebookAdapter {

initializeContext() {

const isNbFormat = this._path !== undefined && this._path !== '' ? false : true;

this._context = new Context({
manager: this._serviceManager,
factory: this._notebookModelFactory!,
Expand Down Expand Up @@ -177,10 +187,7 @@ export class NotebookAdapter {
},
1
);
*/
/*
// This code block was causing https://github.com/datalayer/jupyter-ui/issues/195
// TODO Double check there is not side effect.
// This code block is causing https://github.com/datalayer/jupyter-ui/issues/195
this._context?.sessionContext
.changeKernel({id: this._kernel.id })
.then(() => {
Expand All @@ -189,53 +196,56 @@ export class NotebookAdapter {
);
});
*/

// These are fixes to have more control on the kernel launch.
(this._context.sessionContext as any)._initialize =
async (): Promise<boolean> => {
const manager = (this._context!.sessionContext as any)
.sessionManager as SessionManager;
await manager.ready;
await manager.refreshRunning();
const model = find(manager.running(), model => {
return model.kernel?.id === this._kernel?.id;
});
if (model) {
try {
const session = manager.connectTo({
model: {
...model,
path: this._path ?? model.path,
name: this._path ?? model.name,
},
kernelConnectionOptions: {
handleComms: true,
},
});
(this._context!.sessionContext as any)._handleNewSession(session);
} catch (err) {
void (this._context!.sessionContext as any)._handleSessionError(
err
);
return Promise.reject(err);
}
(this._context.sessionContext as any)._initialize = async (): Promise<boolean> => {
const manager = (this._context!.sessionContext as any).sessionManager as SessionManager;
await manager.ready;
await manager.refreshRunning();
const model = find(manager.running(), model => {
return model.kernel?.id === this._kernel?.id;
});
if (model) {
try {
const session = manager.connectTo({
model: {
...model,
path: this._path ?? model.path,
name: this._path ?? model.name,
},
kernelConnectionOptions: {
handleComms: true,
},
});
(this._context!.sessionContext as any)._handleNewSession(session);
} catch (err) {
void (this._context!.sessionContext as any)._handleSessionError(
err
);
return Promise.reject(err);
}
return await (this._context!.sessionContext as any)._startIfNecessary();
};
}
return await (this._context!.sessionContext as any)._startIfNecessary();
};

this._context.sessionContext.ready.then(() => {
if (this._onKernelConnection) {
const kernelConnection = this._context?.sessionContext.session?.kernel;
this._onKernelConnection(kernelConnection);
}
});

this._context.sessionContext.kernelChanged.connect((_, args) => {
console.log('Previous Jupyter Kernel connection', args.oldValue);
console.log('Previous Jupyter Kernel Connection.', args.oldValue);
const kernelConnection = args.newValue;
console.log('Current Jupyter Kernel connection', kernelConnection);
console.log('Current Jupyter Kernel Connection.', kernelConnection);
if (kernelConnection && !kernelConnection.handleComms) {
console.warn(
'The current Kernel Connection does not handle Comms',
kernelConnection.id
);
console.warn('The current Kernel Connection does not handle Comms...', kernelConnection.id);
(kernelConnection as any).handleComms = true;
console.log(
'The current Kernel Connection is updated to enforce Comms support',
kernelConnection.handleComms
);
console.log('The current Kernel Connection is updated to enforce Comms support!', kernelConnection.handleComms);
}
if (this._onKernelConnection) {
this._onKernelConnection(kernelConnection);
}
});

Expand Down Expand Up @@ -302,10 +312,35 @@ export class NotebookAdapter {
this._notebookPanel?.update();
});

const isNbFormat = (this._path !== undefined && this._path !== '') ? false : true;

if (isNbFormat) {
// If nbformat is provided and we don't want to interact with the content manager.
(this._context as any)._populate = async (): Promise<void> => {
(this._context as any)._isPopulated = true;
(this._context as any)._isReady = true;
(this._context as any)._populatedPromise.resolve(void 0);
// Add a checkpoint if none exists and the file is writable.
// Force skip this step for nbformat notebooks.
// await (this._context as any)._maybeCheckpoint(false);
if ((this._context as any).isDisposed) {
return;
}
// Update the kernel preference.
const name = (this._context as any)._model.defaultKernelName ||
(this._context as any).sessionContext.kernelPreference.name;
(this._context as any).sessionContext.kernelPreference = {
...(this._context as any).sessionContext.kernelPreference,
name,
language: (this._context as any)._model.defaultKernelLanguage
};
// Note: we don't wait on the session to initialize
// so that the user can be shown the content before
// any kernel has started.
void (this._context as any).sessionContext.initialize().then((shouldSelect: boolean) => {
if (shouldSelect) {
void (this._context as any)._dialogs.selectKernel((this._context!.sessionContext as any).sessionContext);
}
});
};
(this._context as any).initialize = async (isNew: boolean): Promise<void> => {
(this._context as Context<INotebookModel>).model.dirty = false;
const now = new Date().toISOString();
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/components/viewer/Viewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ export const Viewer = (props: IViewerProps) => {
return response.text();
})
.then(nbformat => {
// const nbformat = nb.replaceAll('\\n', '');
// const nbformat = nb.replaceAll('\\n', '');
setModel(JSON.parse(nbformat));
});
}
}, [nbformat]);
}, [nbformat, nbformatUrl]);
return (
<>
{model?.cells.map(cell => {
Expand Down
6 changes: 3 additions & 3 deletions packages/react/src/examples/JupyterLabApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { createRoot } from 'react-dom/client';
import { NotebookPanel } from '@jupyterlab/notebook';
import { Jupyter } from '../jupyter/Jupyter';
import { JupyterReactTheme } from '../theme';
import { JupyterLabApp, JupyterLabAppAdapter } from '../components/jupyterlab';

import * as lightThemePlugins from '@jupyterlab/theme-light-extension';
Expand Down Expand Up @@ -48,8 +48,8 @@ document.body.appendChild(div);
const root = createRoot(div);

root.render(
<Jupyter startDefaultKernel={false} disableCssLoading>
<JupyterReactTheme>
<h1>JupyterLab Application</h1>
<JupyterLabAppExample />
</Jupyter>
</JupyterReactTheme>
);
10 changes: 3 additions & 7 deletions packages/react/src/examples/JupyterLabAppHeadless.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { Box, Text, ToggleSwitch, ThemeProvider, useTheme } from '@primer/react'
import { BoxPanel } from '@lumino/widgets';
import { ThemeManager } from '@jupyterlab/apputils';
// import { NotebookTracker } from '@jupyterlab/notebook';
import { Jupyter } from '../jupyter/Jupyter';
import { JupyterReactTheme } from '../theme';
import Lumino from '../components/lumino/Lumino';
import { Colormode } from '../theme/JupyterLabColormode';
import JupyterLabApp from '../components/jupyterlab/JupyterLabApp';
Expand Down Expand Up @@ -63,11 +63,7 @@ const JupyterLabAppHeadless = () => {
};
return (
<>
<Jupyter
startDefaultKernel={false}
disableCssLoading
colormode="light"
>
<JupyterReactTheme colormode="light">
<ThemeProvider
colorMode={theme === 'light' ? 'day' : 'night'}
dayScheme="light"
Expand Down Expand Up @@ -135,7 +131,7 @@ const JupyterLabAppHeadless = () => {
PluginType={ThemeManager}
onPlugin={onPlugin}
/>
</Jupyter>
</JupyterReactTheme>
</>
);
};
Expand Down
Loading
Loading