Skip to content

Commit

Permalink
[1.x] Make server extension verification call during extension startu…
Browse files Browse the repository at this point in the history
…p non-blocking (#480) (#481)

* Make server extension verification call during extension startup non-blocking (#480)

* remove async call, make call sync, refactor into a separate function

* don't use abbreviations in the verifyServerExtension function or type naming

* Update src/index.tsx

Co-authored-by: david qiu <[email protected]>

* remove unused type

* add @jupyterlab/rendermime-interfaces as a dependency

* Remove async from activatePlugin function declaration (makes it not async)

* set @jupyterlab/rendermime-interfaces version to ^3.8.0 to support all JLab >= 4

---------

Co-authored-by: david qiu <[email protected]>

* Fix translator usage, remove @jupyterlab/rendermime-interfaces dependency (#483)

* update snapshots

* use lowercase "es" is "es2017" as is convention in Project Jupyter

* fix 1.x dependencies

* fix package manifest to be compatible with JL3

* Make ErrorBoundary return JSX.Element to avoid type conflicts

---------

Co-authored-by: david qiu <[email protected]>
  • Loading branch information
andrii-i and dlqqq committed Feb 16, 2024
1 parent 10d45a3 commit 72ce4ac
Show file tree
Hide file tree
Showing 8 changed files with 2,604 additions and 4,052 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ node_modules/
*.tsbuildinfo
jupyter_scheduler/labextension

# Yarn 3 cache
.yarn

# Integration tests
ui-tests/test-results/
ui-tests/playwright-report/
Expand Down
16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@
"@jupyterlab/docmanager-extension": "^3.4.2",
"@jupyterlab/filebrowser": "^3.4.1",
"@jupyterlab/launcher": "^3.4.4",
"@jupyterlab/rendermime-interfaces": "^3",
"@jupyterlab/services": "^6.4.2",
"@jupyterlab/translation": "^3.4.1",
"@jupyterlab/ui-components": "^3.4.2",
"@lumino/polling": "^1.9.0",
"@lumino/signaling": "^1.10.0",
"@lumino/coreutils": "^1.12.0",
"@lumino/widgets": "^1.32.0",
"@lumino/coreutils": "^1",
"@lumino/polling": "^1",
"@lumino/signaling": "^1",
"@lumino/widgets": "^1",
"@mui/icons-material": "^5.10.9",
"@mui/material": "^5.10.6",
"@mui/system": "^5.10.6",
"@types/react-dom": "^18.0.5",
"cronstrue": "^2.12.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
Expand All @@ -93,6 +93,8 @@
"mkdirp": "^1.0.3",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"@types/react": "^17.0.1",
"@types/react-dom": "^17.0.1",
"rimraf": "^3.0.2",
"stylelint": "^14.3.0",
"stylelint-config-prettier": "^9.0.3",
Expand All @@ -103,8 +105,8 @@
"typescript": "~4.1.3"
},
"resolutions": {
"@types/react": "^17.0.1",
"@types/react-dom": "^18.0.5"
"@lumino/coreutils": "^1",
"@jupyterlab/rendermime-interfaces": "3.0.0 - 3.6.7"
},
"sideEffects": [
"style/*.css",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dependencies = [
"jupyter_server>=1.6,<3",
"traitlets",
"nbconvert",
"pydantic",
"pydantic~=1.10",
"sqlalchemy<2",
"croniter",
"pytz",
Expand Down
4 changes: 2 additions & 2 deletions src/components/error-boundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class ErrorBoundary extends React.Component<
this.setState({ hasError: true, error });
}

render(): React.ReactNode {
render(): JSX.Element {
let errorDetail;
if (typeof this.state.error === 'string') {
errorDetail = this.state.error;
Expand All @@ -53,6 +53,6 @@ export class ErrorBoundary extends React.Component<
</div>
);
}
return this.props.children;
return <> {this.props.children} </>;
}
}
41 changes: 37 additions & 4 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import {
JupyterFrontEnd,
JupyterFrontEndPlugin
} from '@jupyterlab/application';
import { MainAreaWidget, WidgetTracker } from '@jupyterlab/apputils';
import {
Dialog,
MainAreaWidget,
showDialog,
WidgetTracker
} from '@jupyterlab/apputils';
import { FileBrowser, IFileBrowserFactory } from '@jupyterlab/filebrowser';
import { ILauncher } from '@jupyterlab/launcher';
import { INotebookTracker } from '@jupyterlab/notebook';
import { Contents } from '@jupyterlab/services';
import { Contents, ServerConnection } from '@jupyterlab/services';
import { ITranslator } from '@jupyterlab/translation';

import AdvancedOptions from './advanced-options';
Expand All @@ -20,6 +25,7 @@ import { SchedulerService } from './handler';
import { IJobsModel, emptyCreateJobModel, JobsView } from './model';
import { NotebookJobsPanel } from './notebook-jobs-panel';
import { Scheduler } from './tokens';
import { SERVER_EXTENSION_404_JSX } from './util/errors';
import { MakeNameValid } from './util/job-name-validation';

export namespace CommandIDs {
Expand All @@ -34,6 +40,32 @@ export namespace CommandIDs {
export const NotebookJobsPanelId = 'notebook-jobs-panel';
export { Scheduler } from './tokens';

/**
* Call API to verify that the server extension is actually installed.
*/
async function verifyServerExtension(props: {
api: SchedulerService;
translator: ITranslator;
}) {
const trans = props.translator.load('jupyterlab');
try {
await props.api.getJobs({ max_items: 0 });
} catch (e: unknown) {
// in case of 404, show missing server extension dialog and return
if (
e instanceof ServerConnection.ResponseError &&
e.response.status === 404
) {
showDialog({
title: trans.__('Jupyter Scheduler server extension not found'),
body: SERVER_EXTENSION_404_JSX,
buttons: [Dialog.okButton()]
}).catch(console.warn);
return;
}
}
}

/**
* Initialization data for the jupyterlab-scheduler extension.
*/
Expand Down Expand Up @@ -114,19 +146,20 @@ function getDirectoryFromPath(path: string | null): string | null {
return directories.join('/') + (directories.length > 0 ? '/' : '');
}

async function activatePlugin(
function activatePlugin(
app: JupyterFrontEnd,
browserFactory: IFileBrowserFactory,
notebookTracker: INotebookTracker,
translator: ITranslator,
restorer: ILayoutRestorer,
advancedOptions: Scheduler.IAdvancedOptions,
launcher: ILauncher | null
): Promise<void> {
): void {
const { commands } = app;
const trans = translator.load('jupyterlab');
const fileBrowserTracker = browserFactory.tracker;
const api = new SchedulerService({});
verifyServerExtension({ api, translator });
const widgetTracker = new WidgetTracker<MainAreaWidget<NotebookJobsPanel>>({
namespace: 'jupyterlab-scheduler'
});
Expand Down
28 changes: 28 additions & 0 deletions src/util/errors.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';

export const SERVER_EXTENSION_404_JSX = (
<div>
<p>
The Jupyter Scheduler extension is installed but it can't be activated. It
looks like the required Jupyter Server extension (
<code>jupyter_scheduler</code>) is not installed or not enabled in this
environment.
</p>
<h3>Why am I seeing this message?</h3>
<p>
If you installed the Jupyter Scheduler extension from the Extension
Manager in JupyterLab, you might have installed only the client extension
and not the server extension. You can install the server extension by
running <code>pip install jupyter_scheduler</code> in the same environment
in which you run JupyterLab.
</p>
<h3>How do I check if the extension is installed?</h3>
<p>
Please ensure that <code>jupyter server extension list</code> includes
jupyter_scheduler and that it is enabled. If it is enabled, please restart
JupyterLab. If the server extension is installed but not enabled, run{' '}
<code>jupyter server extension enable --user --py jupyter_scheduler</code>{' '}
and restart JupyterLab.
</p>
</div>
);
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"noUnusedLocals": true,
"preserveWatchOutput": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"outDir": "lib",
"rootDir": "src",
"strict": true,
Expand Down
Loading

0 comments on commit 72ce4ac

Please sign in to comment.