Skip to content

Commit

Permalink
Revert "passive thebe manager (#756)"
Browse files Browse the repository at this point in the history
This reverts commit 30f569e.
  • Loading branch information
stevejpurves committed Sep 5, 2024
1 parent 3f07f0e commit ea4f077
Show file tree
Hide file tree
Showing 18 changed files with 1,104 additions and 652 deletions.
1 change: 0 additions & 1 deletion apps/demo-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"@types/node": "^16.18.14",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"classnames": "^2.5.1",
"localforage": "^1.10.0",
"match-sorter": "^6.3.1",
"react": "^18.2.0",
Expand Down
1,416 changes: 1,053 additions & 363 deletions apps/demo-react/public/widget-test.ipynb

Large diffs are not rendered by default.

27 changes: 8 additions & 19 deletions apps/demo-react/src/NotebookPage.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,23 @@
import {
ThebeSessionProvider,
ThebeRenderMimeRegistryProvider,
useThebeServer,
useThebeLoader,
} from 'thebe-react';
import { ThebeSessionProvider, ThebeRenderMimeRegistryProvider, useThebeServer } from 'thebe-react';
import { ConnectionStatusTray } from './ConnectionStatusTray';
import { ConnectionErrorTray } from './ConnectionErrorTray';
import { NotebookStatusTray } from './NotebookStatusTray';
import { NotebookErrorTray } from './NotebookErrorTray';
import { AdminPanel } from './AdminPanel';

export function NotebookPage({ children }: React.PropsWithChildren) {
const { core } = useThebeLoader();
const { connecting, config, ready, error } = useThebeServer();

if (!core) return null;
const { connecting, ready, config, error } = useThebeServer();

if (!connecting && !ready && !error) return null;
return (
<ThebeRenderMimeRegistryProvider>
<ThebeSessionProvider start path={config?.kernels.path}>
<>
{(connecting || ready || error) && (
<>
<ConnectionStatusTray />
<ConnectionErrorTray />
<NotebookStatusTray />
<NotebookErrorTray />
<AdminPanel />
</>
)}
<ConnectionStatusTray />
<ConnectionErrorTray />
<NotebookStatusTray />
<NotebookErrorTray />
<AdminPanel />
{children}
</>
</ThebeSessionProvider>
Expand Down
17 changes: 3 additions & 14 deletions apps/demo-react/src/WidgetsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { useNotebook } from 'thebe-react';
import JupyterOutputDecoration from './JupyterOutputDecoration';
import { useParams } from 'react-router-dom';
import classNames from 'classnames';

export function WidgetsPage() {
const { notebookName } = useParams<{ notebookName: string }>();
const { ready, executing, executeAll, cellRefs, cellIds, errors } = useNotebook(
const { ready, executing, executeAll, cellRefs, cellIds } = useNotebook(
notebookName ?? 'widget-test',
async (n) => {
const url = `/${n}.ipynb`;
Expand All @@ -28,22 +27,12 @@ export function WidgetsPage() {
<h4 className="text-sm">
notebook: <code>{notebookName}.ipynb</code>
</h4>
<div
className={classNames(
'inline-block px-4 py-2 mt-3 text-sm font-bold text-white rounded-full',
{ 'bg-gray-500': !ready, 'bg-green-500': ready },
)}
>
<div className="inline-block px-4 py-2 mt-3 text-sm font-bold text-white bg-green-500 rounded-full">
{ready ? 'ready' : 'not ready'}
</div>
<div className="mt-4">
{!executing && (
<button
className={classNames('button', {
'text-gray-400 bg-gray-100 border-gray-300 cursor-not-allowed': !ready || errors,
})}
onClick={clickExecute}
>
<button className="button" onClick={clickExecute}>
run all
</button>
)}
Expand Down
6 changes: 0 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions packages/core/src/cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,32 @@ import { ensureString, shortId } from './utils';

class ThebeCodeCell extends PassiveCellRenderer implements IThebeCell {
kind: CellKind;
notebookId: string;
source: string;
metadata: JsonObject;
session?: ThebeSession;
executionCount: number | null;
protected initialOutputs: IOutput[];
readonly notebookId: string;
protected busy: boolean;
protected events: EventEmitter;

constructor(
id: string,
notebookId: string,
source: string,
outputs: IOutput[],
config: Config,
metadata: JsonObject,
rendermime: IRenderMimeRegistry,
) {
super(id, outputs, rendermime);
super(id, rendermime);
this.kind = 'code';
this.events = new EventEmitter(id, config, EventSubject.cell, this);
this.notebookId = notebookId;
this.source = source;
this.metadata = metadata;
this.busy = false;
this.executionCount = null;
this.initialOutputs = [];
console.debug('thebe:cell constructor', this);
}

Expand All @@ -48,7 +49,6 @@ class ThebeCodeCell extends PassiveCellRenderer implements IThebeCell {
icc.id ?? shortId(),
notebookId,
ensureString(icc.source),
icc.outputs ?? [],
config,
icc.metadata,
rendermime,
Expand Down
1 change: 0 additions & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export * from './thebe/api';
export * from './thebe/entrypoint';
export * from './utils';
export * from './manager';
export * from './passiveManager';
export * from './rendermime';
export * from './types';
export * from './config';
Expand Down
27 changes: 16 additions & 11 deletions packages/core/src/manager.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
import type { IRenderMimeRegistry } from '@jupyterlab/rendermime';
import type { Widget } from '@lumino/widgets';

import * as LuminoWidget from '@lumino/widgets';
import { MessageLoop } from '@lumino/messaging';

import { KernelWidgetManager, WidgetRenderer, output } from '@jupyter-widgets/jupyterlab-manager';

export const WIDGET_MIMETYPE = 'application/vnd.jupyter.widget-view+json';

import * as base from '@jupyter-widgets/base';
import * as controls from '@jupyter-widgets/controls';
import { shortId } from './utils';
import { RequireJsLoader } from './requireJsLoader';
import { requireLoader } from './loader';
import type { Kernel } from '@jupyterlab/services';

export const WIDGET_STATE_MIMETYPE = 'application/vnd.jupyter.widget-state+json';
export const WIDGET_VIEW_MIMETYPE = 'application/vnd.jupyter.widget-view+json';

/**
* @deprecated use WIDGET_VIEW_MIMETYPE
*/
export const WIDGET_MIMETYPE = WIDGET_VIEW_MIMETYPE;

/**
* A Widget Manager class for Thebe using the context-free KernelWidgetManager from
* the JupyterLab Manager and inspierd by the implementation in Voila here:
Expand All @@ -35,17 +32,25 @@ export class ThebeManager extends KernelWidgetManager {
/** ensure this registry always gets the widget renderer.
* This is essential for cases where widgets are rendered heirarchically
*/
this.addWidgetFactories();

this._registerWidgets();
this._loader = new RequireJsLoader();
}

addWidgetFactories() {
this.rendermime.addFactory(
{
safe: false,
mimeTypes: [WIDGET_VIEW_MIMETYPE],
mimeTypes: [WIDGET_MIMETYPE],
createRenderer: (options) => new WidgetRenderer(options, this as any),
},
1,
);
}

this._registerWidgets();
this._loader = new RequireJsLoader();
removeWidgetFactories() {
this.rendermime.removeMimeType(WIDGET_MIMETYPE);
}

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import PassiveCellRenderer from './passive';
import type ThebeSession from './session';
import type { CellKind, IThebeCell, IThebeCellExecuteReturn, JsonObject } from './types';
import { ensureString, shortId } from './utils';
import type ThebeNotebook from './notebook';

/**
* A Thebe cell that is exepected to contain markdown (or raw) source.
Expand All @@ -29,7 +28,7 @@ export default class ThebeMarkdownCell extends PassiveCellRenderer implements IT
metadata: JsonObject,
rendermime: IRenderMimeRegistry,
) {
super(id, [], rendermime);
super(id, rendermime);
this.kind = 'markdown';
this.id = id;
this.notebookId = notebookId;
Expand Down
30 changes: 3 additions & 27 deletions packages/core/src/notebook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,19 @@ export interface CodeBlock {
[x: string]: any;
}

function coerceToObject(maybe: any): Record<string, any> {
if (typeof maybe === 'object') return maybe;
if (Array.isArray(maybe)) return Object.fromEntries(maybe.map((v, k) => [k, v]));
return {};
}

class ThebeNotebook {
readonly id: string;
readonly rendermime: IRenderMimeRegistry;
cells: IThebeCell[];
metadata: INotebookMetadata;
widgetState: Record<string, any>;
session?: ThebeSession;
protected events: EventEmitter;

constructor(
id: string,
config: Config,
rendermime: IRenderMimeRegistry,
metadata?: INotebookMetadata,
) {
constructor(id: string, config: Config, rendermime: IRenderMimeRegistry) {
this.id = id;
this.events = new EventEmitter(id, config, EventSubject.notebook, this);
this.cells = [];
this.metadata = metadata ?? {};
this.widgetState = coerceToObject(metadata?.widgets);
this.metadata = {};
this.rendermime = rendermime;
console.debug('thebe:notebook constructor', this);
}
Expand All @@ -50,15 +37,7 @@ class ThebeNotebook {
const notebook = new ThebeNotebook(id, config, rendermime);
notebook.cells = blocks.map((c) => {
const metadata = {};
const cell = new ThebeCodeCell(
c.id,
notebook.id,
c.source,
c.outputs ?? [],
config,
metadata,
notebook.rendermime,
);
const cell = new ThebeCodeCell(c.id, id, c.source, config, metadata, notebook.rendermime);
console.debug(`thebe:notebook:fromCodeBlocks Initializing cell ${c.id}`);
return cell;
});
Expand Down Expand Up @@ -92,9 +71,6 @@ class ThebeNotebook {
return p;
}

/**
@deprecated
*/
get widgets() {
return this.findCells('widget') ?? [];
}
Expand Down
19 changes: 4 additions & 15 deletions packages/core/src/passive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,17 @@ import { MessageLoop } from '@lumino/messaging';
class PassiveCellRenderer implements IPassiveCell {
readonly id: string;
readonly rendermime: IRenderMimeRegistry;
initialOutputs: nbformat.IOutput[];

protected model: OutputAreaModel;
protected area: OutputArea;

constructor(
id: string,
initialOutputs?: nbformat.IOutput[],
rendermime?: IRenderMimeRegistry,
mathjax?: MathjaxOptions,
) {
constructor(id: string, rendermime?: IRenderMimeRegistry, mathjax?: MathjaxOptions) {
this.id = id;
this.rendermime = rendermime ?? makeRenderMimeRegistry(mathjax ?? makeMathjaxOptions());
this.model = new OutputAreaModel({ trusted: true });
this.area = new OutputArea({
model: this.model,
rendermime: this.rendermime,
});
this.initialOutputs = initialOutputs ?? [];
}

/**
Expand All @@ -42,10 +34,7 @@ class PassiveCellRenderer implements IPassiveCell {
return this.area.isAttached;
}

attachToDOM(
el?: HTMLElement,
opts: { strict?: boolean; appendExisting?: boolean } = { strict: false, appendExisting: true },
) {
attachToDOM(el?: HTMLElement, strict = false) {
if (!this.area || !el) {
console.error(
`thebe:renderer:attachToDOM - could not attach to DOM - area: ${this.area}, el: ${el}`,
Expand All @@ -55,11 +44,11 @@ class PassiveCellRenderer implements IPassiveCell {
if (this.area.isAttached) {
// TODO should we detach and reattach?
console.debug(`thebe:renderer:attachToDOM - already attached`);
if (opts.strict) return;
if (strict) return;
} else {
// if the target element has contents, preserve it but wrap it in our output area
console.debug(`thebe:renderer:attachToDOM ${this.id} - appending existing contents`);
if (opts.appendExisting && el.innerHTML) {
if (el.innerHTML) {
this.area.model.add({
output_type: 'display_data',
data: {
Expand Down
Loading

0 comments on commit ea4f077

Please sign in to comment.