Skip to content

Commit 3f54ff7

Browse files
committed
start nb7 support
1 parent 7360d84 commit 3f54ff7

File tree

8 files changed

+1117
-150
lines changed

8 files changed

+1117
-150
lines changed

.github/workflows/test.yaml

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,39 @@ on:
2424
workflow_dispatch:
2525

2626
jobs:
27+
build:
28+
runs-on: ubuntu-22.04
29+
defaults:
30+
run:
31+
shell: bash
32+
steps:
33+
- uses: actions/checkout@v4
34+
35+
- uses: actions/setup-python@v4
36+
with:
37+
python-version: "3.11"
38+
39+
- uses: actions/setup-node@v3
40+
with:
41+
cache: yarn
42+
node-version: 20.x
43+
registry-url: https://registry.npmjs.org
44+
cache-dependency-path: labextension/yarn.lock
45+
46+
- name: Update root build packages
47+
run: pip install --upgrade build
48+
49+
- name: Build Python package
50+
run: pyproject-build
51+
52+
- name: Upload built artifacts
53+
uses: actions/upload-artifact@v3
54+
with:
55+
name: dist-${{ github.run_number }}
56+
path: ./dist
57+
2758
test:
59+
needs: [build]
2860
timeout-minutes: 30
2961
strategy:
3062
fail-fast: false
@@ -37,11 +69,17 @@ jobs:
3769
- python-version: "3.11"
3870
jupyter_server-version: "2"
3971
jupyterlab-version: "3"
72+
notebook-version: "6"
4073
os: windows-2022
4174
- python-version: "3.11"
4275
jupyter_server-version: "2"
4376
jupyterlab-version: "4"
4477
os: windows-2022
78+
notebook-version: "7"
79+
- jupyterlab-version: "3"
80+
notebook-version: "6"
81+
- jupyterlab-version: "4"
82+
notebook-version: "7"
4583
exclude:
4684
- jupyter_server-version: "1"
4785
jupyterlab-version: "4"
@@ -52,34 +90,29 @@ jobs:
5290
shell: bash
5391

5492
steps:
55-
- uses: actions/checkout@v3
93+
94+
- uses: actions/checkout@v4
5695

5796
- uses: actions/setup-python@v4
5897
with:
5998
python-version: "${{ matrix.python-version }}"
6099

61-
- uses: actions/setup-node@v3
62-
with:
63-
cache: yarn
64-
node-version: 18.x
65-
registry-url: https://registry.npmjs.org
66-
cache-dependency-path: labextension/yarn.lock
67-
68100
- name: Update root build packages
69-
run: |
70-
pip install --upgrade build pip
101+
run: pip install --upgrade pip
71102

72-
- name: Build Python package
73-
run: |
74-
pyproject-build
103+
- name: Download built artifacts
104+
uses: actions/download-artifact@v3
105+
with:
106+
name: dist-${{ github.run_number }}
107+
path: ./dist
75108

76109
- name: Install Python package
77110
# NOTE: See CONTRIBUTING.md for a local development setup that differs
78111
# slightly from this.
79112
#
80113
# Pytest options are set in `pyproject.toml`.
81114
run: |
82-
pip install -vv $(ls ./dist/jupyter_server_proxy-*.whl)\[acceptance\] 'jupyterlab~=${{ matrix.jupyterlab-version }}.0' 'jupyter_server~=${{ matrix.jupyter_server-version }}.0'
115+
pip install -vv $(ls ./dist/*.whl)\[acceptance\] 'jupyterlab~=${{ matrix.jupyterlab-version }}.0' 'jupyter_server~=${{ matrix.jupyter_server-version }}.0' 'notebook~=${{ matrix.notebook-version }}.0'
83116
84117
- name: List Python packages
85118
run: |
@@ -101,6 +134,7 @@ jobs:
101134
./build/coverage
102135
103136
- name: Check the Notebook Server extension is installed
137+
if: matrix.jupyterlab-version != '4'
104138
run: |
105139
jupyter serverextension list
106140
jupyter serverextension list 2>&1 | grep -iE "jupyter_server_proxy.*OK" -

labextension/.yarnrc

Lines changed: 0 additions & 11 deletions
This file was deleted.

labextension/.yarnrc.yml

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,23 @@
1-
# jlpm in JupyterLab 4 is yarn 3, and this is a yarn 2+ compatible configuration
2-
# file.
3-
#
1+
# jlpm in JupyterLab 4 is yarn 3
42
# Config reference: https://yarnpkg.com/configuration/yarnrc
5-
#
3+
4+
enableInlineBuilds: false
5+
enableTelemetry: false
6+
httpTimeout: 60000
67
nodeLinker: node-modules
7-
httpTimeout: 300000
8-
npmRegistryServer: "https://registry.npmjs.org/"
8+
npmRegistryServer: https://registry.npmjs.org/
9+
installStatePath: ./build/.cache/yarn/install-state.gz
10+
cacheFolder: ./build/.cache/yarn/cache
11+
logFilters:
12+
- code: YN0006
13+
level: discard
14+
- code: YN0002
15+
level: discard
16+
- code: YN0007
17+
level: discard
18+
- code: YN0013
19+
level: discard
20+
- code: YN0019
21+
level: discard
22+
- code: YN0008
23+
level: discard

labextension/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@
4747
"@jupyterlab/launcher": "^2.0 || ^3.0 || ^4.0"
4848
},
4949
"devDependencies": {
50-
"@jupyterlab/builder": "^3.2.4 || ^4.0.0",
50+
"@jupyterlab/builder": "^4.0.6",
5151
"npm-run-all": "^4.1.5",
52-
"rimraf": "^3.0.2",
53-
"typescript": "~4.8.4",
54-
"yarn-deduplicate": "^6.0.0"
52+
"rimraf": "^5.0.1",
53+
"typescript": "~5.2.2",
54+
"yarn-berry-deduplicate": "^6.0.0"
5555
},
5656
"jupyterlab": {
5757
"extension": true,

labextension/src/index.ts

Lines changed: 70 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,40 @@ import {
22
JupyterFrontEnd,
33
JupyterFrontEndPlugin,
44
ILayoutRestorer,
5+
ILabShell,
56
} from "@jupyterlab/application";
7+
import { ReadonlyPartialJSONObject } from "@lumino/coreutils";
68
import { ILauncher } from "@jupyterlab/launcher";
79
import { PageConfig } from "@jupyterlab/coreutils";
810
import { IFrame, MainAreaWidget, WidgetTracker } from "@jupyterlab/apputils";
911

12+
/** An interface for the arguments to the open command. */
13+
export interface IOpenArgs extends ReadonlyPartialJSONObject {
14+
id: string;
15+
title: string;
16+
url: string;
17+
newBrowserTab: boolean;
18+
}
19+
20+
/** The JSON schema for the open command arguments.
21+
*
22+
* https://lumino.readthedocs.io/en/latest/api/interfaces/commands.CommandRegistry.ICommandOptions.html
23+
*/
24+
export const argSchema = {
25+
type: "object",
26+
properties: {
27+
id: { type: "string" },
28+
title: { type: "string" },
29+
url: { type: "string", format: "uri" },
30+
newBrowserTab: { type: "boolean" },
31+
},
32+
};
33+
34+
/** Create a new iframe widget. */
1035
function newServerProxyWidget(
1136
id: string,
1237
url: string,
13-
text: string,
38+
text: string
1439
): MainAreaWidget<IFrame> {
1540
const content = new IFrame({
1641
sandbox: [
@@ -40,27 +65,27 @@ function newServerProxyWidget(
4065
*/
4166
async function activate(
4267
app: JupyterFrontEnd,
43-
launcher: ILauncher,
44-
restorer: ILayoutRestorer,
68+
labShell: ILabShell | null,
69+
launcher: ILauncher | null,
70+
restorer: ILayoutRestorer | null
4571
): Promise<void> {
72+
const baseUrl = PageConfig.getBaseUrl();
4673
// Fetch configured server processes from {base_url}/server-proxy/servers-info
47-
const response = await fetch(
48-
PageConfig.getBaseUrl() + "server-proxy/servers-info",
49-
);
74+
const response = await fetch(`${baseUrl}server-proxy/servers-info`);
75+
5076
if (!response.ok) {
51-
console.log(
52-
"Could not fetch metadata about registered servers. Make sure jupyter-server-proxy is installed.",
77+
console.warn(
78+
"Could not fetch metadata about registered servers. Make sure jupyter-server-proxy is installed."
5379
);
54-
console.log(response);
80+
console.warn(response);
5581
return;
5682
}
83+
5784
const data = await response.json();
5885

5986
const namespace = "server-proxy";
60-
const tracker = new WidgetTracker<MainAreaWidget<IFrame>>({
61-
namespace,
62-
});
63-
const command = namespace + ":" + "open";
87+
const tracker = new WidgetTracker<MainAreaWidget<IFrame>>({ namespace });
88+
const command = `${namespace}:open`;
6489

6590
if (restorer) {
6691
void restorer.restore(tracker, {
@@ -76,20 +101,19 @@ async function activate(
76101
}
77102

78103
const { commands, shell } = app;
104+
79105
commands.addCommand(command, {
80-
label: (args) => args["title"] as string,
106+
label: (args) => (args as IOpenArgs).title,
107+
describedBy: async () => {
108+
return { args: argSchema };
109+
},
81110
execute: (args) => {
82-
const id = args["id"] as string;
83-
const title = args["title"] as string;
84-
const url = args["url"] as string;
85-
const newBrowserTab = args["newBrowserTab"] as boolean;
111+
const { id, title, url, newBrowserTab } = args as IOpenArgs;
86112
if (newBrowserTab) {
87113
window.open(url, "_blank");
88114
return;
89115
}
90-
let widget = tracker.find((widget) => {
91-
return widget.content.id == id;
92-
});
116+
let widget = tracker.find((widget) => widget.content.id === id);
93117
if (!widget) {
94118
widget = newServerProxyWidget(id, url, title);
95119
}
@@ -98,38 +122,38 @@ async function activate(
98122
}
99123
if (!widget.isAttached) {
100124
shell.add(widget);
101-
return widget;
102125
} else {
103126
shell.activateById(widget.id);
104127
}
128+
return widget;
105129
},
106130
});
107131

108-
for (let server_process of data.server_processes) {
109-
if (!server_process.launcher_entry.enabled) {
110-
continue;
111-
}
132+
if (launcher) {
133+
const baseUrl = PageConfig.getBaseUrl();
134+
for (let server_process of data.server_processes) {
135+
const { new_browser_tab, launcher_entry, name } = server_process;
112136

113-
const url =
114-
PageConfig.getBaseUrl() + server_process.launcher_entry.path_info;
115-
const title = server_process.launcher_entry.title;
116-
const newBrowserTab = server_process.new_browser_tab;
117-
const id = namespace + ":" + server_process.name;
118-
const launcher_item: ILauncher.IItemOptions = {
119-
command: command,
120-
args: {
121-
url: url,
122-
title: title + (newBrowserTab ? " [↗]" : ""),
123-
newBrowserTab: newBrowserTab,
124-
id: id,
125-
},
126-
category: "Notebook",
127-
};
128-
129-
if (server_process.launcher_entry.icon_url) {
130-
launcher_item.kernelIconUrl = server_process.launcher_entry.icon_url;
137+
if (!launcher_entry.enabled) {
138+
continue;
139+
}
140+
141+
launcher.add({
142+
command: command,
143+
args: {
144+
url: `${baseUrl}${launcher_entry.path_info}`,
145+
title: launcher_entry.title + (new_browser_tab ? " [↗]" : ""),
146+
newBrowserTab: new_browser_tab,
147+
id: `${namespace}:${name}`,
148+
},
149+
category: "Notebook",
150+
kernelIconUrl: launcher_entry.icon_url || void 0,
151+
});
131152
}
132-
launcher.add(launcher_item);
153+
}
154+
155+
if (!labShell) {
156+
console.warn("TODO: handle notebook 7");
133157
}
134158
}
135159

@@ -142,7 +166,7 @@ async function activate(
142166
const extension: JupyterFrontEndPlugin<void> = {
143167
id: "@jupyterhub/jupyter-server-proxy:add-launcher-entries",
144168
autoStart: true,
145-
requires: [ILauncher, ILayoutRestorer],
169+
optional: [ILabShell, ILauncher, ILayoutRestorer],
146170
activate: activate,
147171
};
148172

0 commit comments

Comments
 (0)