Skip to content

Commit

Permalink
Port perspective-jupyterlab to TypeScript
Browse files Browse the repository at this point in the history
Partly undoes 2d6e400

This change includes a restriction on the ipywidgets versions
perspective declares that it supports.  The plugin probably didn't work
with ipywidgets <= 7 anyhow, since it calls `processLuminoMessage`,
which in those earlier versions of ipywidgets was named
`processPhosphorMessage`.

see https://ipywidgets.readthedocs.io/en/8.0.7/migration_guides.html#phosphor-lumino

and

https://ipywidgets.readthedocs.io/en/8.0.7/migration_guides.html#updating-package-json

if we want to support older ipywidgets, we should do something like
ipywidgets docs describe
  • Loading branch information
tomjakubowski committed Aug 3, 2023
1 parent 37e3df3 commit 53f81a4
Show file tree
Hide file tree
Showing 21 changed files with 486 additions and 239 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,8 @@
"fix": "node tools/perspective-scripts/fix.mjs",
"version": "node tools/perspective-scripts/version.mjs",
"jlab_link": "pip3 install ./python/perspective --no-build-isolation"
},
"resolutions": {
"@lumino/widgets": "1.37.2"
}
}
31 changes: 31 additions & 0 deletions packages/perspective-jupyterlab/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,34 @@ jupyter labextension install @finos/perspective-jupyterlab
```bash
pip install perspective-python
```

## Cheat sheet

### frontend development

```
# from the project root:
# Focus JS, perspective-viewer (if necessary), perspective-jupyterlab, then build
yarn setup
yarn build
# Focus Python project, build it
yarn setup
yarn build
# Set up a jupyter lab (>=3.6) environment. This is out of scope.
jupyter lab &
# jlab_link installs the python extension (including the frontend changes) to a place
# where jupyterlab will find it
yarn run jlab_link
# verify @finos/perspective is installed
jupyter labextension list
# To iterate:
# Focus JS, perspective-jupyterlab (and/or anything else you're rebuilding)
yarn setup
# build frontend
yarn build
# install to jupyter
yarn run jlab_link
```
12 changes: 8 additions & 4 deletions packages/perspective-jupyterlab/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ const NBEXTENSION_PATH = path.resolve(
);

const TEST_BUILD = {
entryPoints: ["src/js/psp_widget.js"],
entryPoints: ["src/ts/psp_widget.ts"],
define: {
global: "window",
},
plugins: [WasmPlugin(true), WorkerPlugin({ inline: true })],
globalName: "PerspectiveLumino",
format: "esm",
loader: {
".ts": "ts",
".html": "text",
".ttf": "file",
".css": "text",
Expand All @@ -45,14 +46,15 @@ const TEST_BUILD = {
};

const LAB_BUILD = {
entryPoints: ["src/js/index.js"],
entryPoints: ["src/ts/index.ts"],
define: {
global: "window",
},
plugins: [WasmPlugin(true), WorkerPlugin({ inline: true })],
external: ["@jupyter*", "@lumino*"],
format: "esm",
loader: {
".ts": "ts",
".css": "text",
".html": "text",
".ttf": "file",
Expand All @@ -62,7 +64,7 @@ const LAB_BUILD = {

const NB_BUILDS = [
{
entryPoints: ["src/js/notebook/extension.js"],
entryPoints: ["src/ts/notebook/extension.js"],
define: {
global: "window",
},
Expand All @@ -72,6 +74,7 @@ const NB_BUILDS = [
AMDLoader([]),
],
loader: {
".ts": "ts",
".ttf": "file",
".css": "text",
},
Expand All @@ -80,7 +83,7 @@ const NB_BUILDS = [
outfile: path.join(NBEXTENSION_PATH, "extension.js"),
},
{
entryPoints: ["src/js/notebook/index.js"],
entryPoints: ["src/ts/notebook/index.js"],
define: {
global: "window",
},
Expand All @@ -92,6 +95,7 @@ const NB_BUILDS = [
external: ["@jupyter*"],
format: "cjs",
loader: {
".ts": "ts",
".ttf": "file",
".css": "text",
},
Expand Down
2 changes: 1 addition & 1 deletion packages/perspective-jupyterlab/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@finos/perspective-viewer-d3fc": "^2.3.2",
"@finos/perspective-viewer-datagrid": "^2.3.2",
"@finos/perspective-viewer-openlayers": "^2.3.2",
"@jupyter-widgets/base": "^2 || ^3 || ^4 || ^5 || ^6",
"@jupyter-widgets/base": "^6",
"@jupyterlab/application": "^3.6.1",
"@lumino/application": "^1.27.0",
"@lumino/widgets": "^1.37.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,17 @@
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

import { Client } from "@finos/perspective/src/js/api/client.js";
import { Client } from "@finos/perspective/api/client";
import { DOMWidgetView } from "@jupyter-widgets/base";

/**
* The schema for a message passed to and from `PerspectiveJupyterClient`.
*/
export interface PerspectiveJupyterMessage {
id: number;
type: string;
data: any;
}

/**
* `PerspectiveJupyterClient` acts as a message bus between the frontend and
Expand All @@ -22,14 +32,16 @@ import { Client } from "@finos/perspective/src/js/api/client.js";
* `@finos/perspective/api`.
*/
export class PerspectiveJupyterClient extends Client {
view: DOMWidgetView;

/**
* Create a new instance of the client.
*
* @param view {DOMWidgetView} the plugin view that can send messages to the
* Python backend.
*/

constructor(view) {
constructor(view: DOMWidgetView) {
super();
this.view = view;
}
Expand All @@ -43,7 +55,7 @@ export class PerspectiveJupyterClient extends Client {
* @param msg {any} the message to pass to the `PerspectiveManager`.
*/

send(msg) {
send(msg: any) {
// Handle calls to `update` with a binary by setting `binary_length`
// to true, so the kernel knows to handle the arraybuffer properly.
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ import "@finos/perspective-viewer-openlayers";
// NOTE: only expose the widget here
import { PerspectiveJupyterPlugin } from "./plugin";

declare global {
interface Window {
_JUPYTERLAB?: boolean;
}
}

let plugins = [PerspectiveJupyterPlugin];

// Conditionally import renderers if running in jupyterlab only
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ import { PERSPECTIVE_VERSION } from "./version";
* TODO: document
*/
export class PerspectiveModel extends DOMWidgetModel {
static model_name: string;
static model_module: string;
static model_module_version: string;
static view_name: string;
static view_module: string;
static view_module_version: string;

defaults() {
return {
...super.defaults(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { IJupyterWidgetRegistry } from "@jupyter-widgets/base";
import { PerspectiveModel } from "./model";
import { PerspectiveView } from "./view";
import { PERSPECTIVE_VERSION } from "./version";
import { JupyterFrontEnd } from "@jupyterlab/application";
const EXTENSION_ID = "@finos/perspective-jupyterlab";

/**
Expand All @@ -24,7 +25,7 @@ export const PerspectiveJupyterPlugin = {
id: EXTENSION_ID,
// @ts-ignore
requires: [IJupyterWidgetRegistry],
activate: (app, registry) => {
activate: (app: JupyterFrontEnd, registry: IJupyterWidgetRegistry) => {
registry.registerWidget({
name: EXTENSION_ID,
version: PERSPECTIVE_VERSION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

import "@finos/perspective-viewer";
import {
HTMLPerspectiveViewerElement,
PerspectiveViewerConfig,
} from "@finos/perspective-viewer";

import { Widget } from "@lumino/widgets";
import { Table, TableData } from "@finos/perspective";
import { Message } from "@lumino/messaging";
import { MIME_TYPE, PSP_CLASS, PSP_CONTAINER_CLASS } from "./utils";

let _increment = 0;
Expand All @@ -22,7 +29,17 @@ let _increment = 0;
* @class PerspectiveWidget (name) TODO: document
*/
export class PerspectiveWidget extends Widget {
constructor(name = "Perspective", bindto, server, client) {
public server?: boolean;
public client?: boolean;
public _load_complete?: boolean;
private _viewer: HTMLPerspectiveViewerElement;

constructor(
name = "Perspective",
bindto?: HTMLElement,
server?: boolean,
client?: boolean
) {
super({
node: bindto || document.createElement("div"),
});
Expand All @@ -44,12 +61,12 @@ export class PerspectiveWidget extends Widget {
*
*/

onAfterShow(msg) {
onAfterShow(msg: Message) {
this.viewer.notifyResize(true);
super.onAfterShow(msg);
}

onActivateRequest(msg) {
onActivateRequest(msg: Message) {
if (this.isAttached) {
this.viewer.focus();
}
Expand All @@ -64,7 +81,7 @@ export class PerspectiveWidget extends Widget {
return await this.viewer.save();
}

async restore(config) {
async restore(config: PerspectiveViewerConfig) {
return await this.viewer.restore(config);
}

Expand All @@ -74,7 +91,7 @@ export class PerspectiveWidget extends Widget {
* @param table A `perspective.table` object.
*/

async load(table) {
async load(table: Promise<Table>) {
await this.viewer.load(table);
this._load_complete = true;
}
Expand All @@ -85,7 +102,7 @@ export class PerspectiveWidget extends Widget {
* @param data
*/

async _update(data) {
async _update(data: TableData) {
const table = await this.viewer.getTable(true);
await table.update(data);
}
Expand All @@ -106,7 +123,7 @@ export class PerspectiveWidget extends Widget {
* @param data
*/

async replace(data) {
async replace(data: TableData) {
const table = await this.viewer.getTable(true);
await table.replace(data);
}
Expand Down Expand Up @@ -171,7 +188,7 @@ export class PerspectiveWidget extends Widget {
}
}

static createNode(node) {
static createNode(node: HTMLElement) {
node.classList.add("p-Widget");
node.classList.add(PSP_CONTAINER_CLASS);
const viewer = document.createElement("perspective-viewer");
Expand Down
Loading

0 comments on commit 53f81a4

Please sign in to comment.