Skip to content

Commit

Permalink
Rework xeus output paths and URLs
Browse files Browse the repository at this point in the history
  • Loading branch information
martinRenou committed Jan 10, 2024
1 parent d6486c4 commit 3ec76eb
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 101 deletions.
27 changes: 11 additions & 16 deletions jupyterlite_xeus/add_on.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from traitlets import List, Unicode

from .create_conda_env import create_conda_env_from_yaml,create_conda_env_from_specs
from .constants import EXTENSION_NAME, STATIC_DIR
from .constants import EXTENSION_NAME

from empack.pack import DEFAULT_CONFIG_PATH, pack_env, pack_directory, add_tarfile_to_env_meta
from empack.file_patterns import pkg_file_filter_from_yaml
Expand Down Expand Up @@ -74,11 +74,10 @@ class XeusAddon(FederatedExtensionAddon):

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.static_dir = self.output_extensions / STATIC_DIR
self.xeus_output_dir = Path(self.manager.output_dir) / "xeus"
self.cwd = TemporaryDirectory()

def post_build(self, manager):

# check that either prefix or environment_file is set
if not self.prefix and not self.environment_file:
raise ValueError("Either prefix or environment_file must be set")
Expand All @@ -94,7 +93,6 @@ def post_build(self, manager):
yield from self.copy_jupyterlab_extensions_from_prefix(manager)

def create_prefix(self):

# read the environment file
root_prefix = Path(self.cwd.name) / "env"
env_name = "xeus-env"
Expand All @@ -118,13 +116,11 @@ def create_prefix(self):
)

def copy_kernels_from_prefix(self):

if not os.path.exists(self.prefix) or not os.path.isdir(self.prefix):
raise ValueError(f"Prefix {self.prefix} does not exist or is not a directory")

kernel_spec_path = Path(self.prefix) / "share" / "jupyter" / "kernels"


all_kernels = []
# find all folders in the kernelspec path
for kernel_dir in kernel_spec_path.iterdir():
Expand All @@ -139,10 +135,10 @@ def copy_kernels_from_prefix(self):
kernel_file = Path(self.cwd.name) / "kernels.json"
kernel_file.write_text(json.dumps(all_kernels), **UTF8)
yield dict(
name=f"copy:kernels.json",
name=f"copy:{kernel_file}",
actions=[
(
self.copy_one, [kernel_file, self.static_dir / "share"/"jupyter" / "kernels.json" ]
self.copy_one, [kernel_file, self.xeus_output_dir / "kernels.json"]
)
]
)
Expand All @@ -157,32 +153,31 @@ def copy_kernel(self, kernel_dir, kernel_wasm, kernel_js):
kernel_json = Path(self.cwd.name) / f"{kernel_dir.name}_kernel.json"
kernel_json.write_text(json.dumps(kernel_spec), **UTF8)


# copy the kernel binary files to the bin dir
yield dict(name=f"copy:{kernel_dir.name}:binaries", actions=[
(self.copy_one, [kernel_js, self.static_dir / "bin"/ kernel_js.name ]),
(self.copy_one, [kernel_wasm, self.static_dir / "bin"/ kernel_wasm.name ]),
(self.copy_one, [kernel_js, self.xeus_output_dir / "bin" / kernel_js.name ]),
(self.copy_one, [kernel_wasm, self.xeus_output_dir / "bin" / kernel_wasm.name ]),
])

# copy the kernel.json file
yield dict(
name=f"copy:{kernel_dir.name}:kernel.json",
actions=[(self.copy_one, [kernel_json, self.static_dir /"share"/"jupyter"/ "kernels"/ kernel_dir.name / "kernel.json" ])],
actions=[(self.copy_one, [kernel_json, self.xeus_output_dir / "kernels"/ kernel_dir.name / "kernel.json" ])],
)
# copy the logo files
yield dict(
name=f"copy:{kernel_dir.name}:logos",
actions=[
(self.copy_one, [kernel_dir / "logo-32x32.png", self.static_dir /"share"/ "jupyter"/ "kernels"/ kernel_dir.name / "logo-32x32.png" ]),
(self.copy_one, [kernel_dir / "logo-64x64.png", self.static_dir /"share"/ "jupyter"/ "kernels"/ kernel_dir.name / "logo-64x64.png" ])
(self.copy_one, [kernel_dir / "logo-32x32.png", self.xeus_output_dir / "kernels" / kernel_dir.name / "logo-32x32.png" ]),
(self.copy_one, [kernel_dir / "logo-64x64.png", self.xeus_output_dir / "kernels" / kernel_dir.name / "logo-64x64.png" ])
])

yield from self.pack_prefix(kernel_dir=kernel_dir)

def pack_prefix(self, kernel_dir):
kernel_name = kernel_dir.name
packages_dir = Path(self.static_dir) / "share" / "jupyter" / "kernel_packages"
full_kernel_dir = Path(self.static_dir) / "share"/ "jupyter"/"kernels"/ kernel_name
packages_dir = self.xeus_output_dir / "kernel_packages"
full_kernel_dir = self.xeus_output_dir / "kernels"/ kernel_name

out_path = Path(self.cwd.name) / "packed_env"
out_path.mkdir(parents=True, exist_ok=True)
Expand Down
98 changes: 39 additions & 59 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright (c) JupyterLite Contributors
// Distributed under the terms of the Modified BSD License.

import { PageConfig, URLExt } from '@jupyterlab/coreutils';
import {
IServiceWorkerManager,
JupyterLiteServer,
Expand All @@ -12,63 +13,45 @@ import { IKernel, IKernelSpecs } from '@jupyterlite/kernel';

import { WebWorkerKernel } from './web_worker_kernel';

const EXTENSION_NAME = 'xeus';
const EXTENSION_STATIC_DIR = `../extensions/@jupyterlite/${EXTENSION_NAME}/static/`;

// helper function to fetch json
function getPkgJson(url: string) {
const json_url = EXTENSION_STATIC_DIR + url;
const xhr = new XMLHttpRequest();
xhr.open('GET', json_url, false);
xhr.send(null);
return JSON.parse(xhr.responseText);
}
async function getJson(url: string) {
const json_url = URLExt.join(PageConfig.getBaseUrl(), url);

let kernel_dir: string[] = [];
try {
kernel_dir = getPkgJson('share/jupyter/kernels.json');
} catch (err) {
console.log(err);
console.log('could not fetch share/jupyter/kernels/kernels.json');
kernel_dir = [];
throw err;
const response = await fetch(json_url);
return JSON.parse(await response.text());
}

// fetch kernel spec for each kernel
const kernel_specs = kernel_dir.map(kernel_dir => {
const spec: any = getPkgJson(
'share/jupyter/kernels/' + kernel_dir + '/kernel.json'
);
spec.name = kernel_dir;
spec.dir = kernel_dir;
spec.resources = {
'logo-32x32':
EXTENSION_STATIC_DIR +
'share/jupyter/kernels/' +
kernel_dir +
'/logo-32x32.png',
'logo-64x64':
EXTENSION_STATIC_DIR +
'share/jupyter/kernels/' +
kernel_dir +
'/logo-64x64.png'
};
return spec;
});
const xeusKernelsPlugin: JupyterLiteServerPlugin<void> = {
id: '@jupyterlite/xeus:register-kernels',
autoStart: true,
requires: [IKernelSpecs],
optional: [IServiceWorkerManager, IBroadcastChannelWrapper],
activate: async (
app: JupyterLiteServer,
kernelspecs: IKernelSpecs,
serviceWorker?: IServiceWorkerManager,
broadcastChannel?: IBroadcastChannelWrapper
) => {
let kernel_dir: string[] = [];
try {
kernel_dir = await getJson('xeus/kernels.json');
} catch (err) {
console.log(`Could not fetch xeus/kernels.json: ${err}`);
throw err;
}

// Fetch kernel spec for each kernel
kernel_dir.map(async kernel_dir => {
const kernelspec = await getJson(
'xeus/kernels/' + kernel_dir + '/kernel.json'
);
kernelspec.name = kernel_dir;
kernelspec.dir = kernel_dir;
kernelspec.resources = {
'logo-32x32': 'xeus/kernels/' + kernel_dir + '/logo-32x32.png',
'logo-64x64': 'xeus/kernels/' + kernel_dir + '/logo-64x64.png'
};

const server_kernels = kernel_specs.map(kernelspec => {
const server_kernel: JupyterLiteServerPlugin<void> = {
// use name from spec
id: `@jupyterlite/${kernelspec.name}-extension:kernel`,
autoStart: true,
requires: [IKernelSpecs],
optional: [IServiceWorkerManager, IBroadcastChannelWrapper],
activate: (
app: JupyterLiteServer,
kernelspecs: IKernelSpecs,
serviceWorker?: IServiceWorkerManager,
broadcastChannel?: IBroadcastChannelWrapper
) => {
kernelspecs.register({
spec: kernelspec,
create: async (options: IKernel.IOptions): Promise<IKernel> => {
Expand All @@ -93,11 +76,8 @@ const server_kernels = kernel_specs.map(kernelspec => {
});
}
});
}
};
return server_kernel;
});

const plugins: JupyterLiteServerPlugin<any>[] = server_kernels;
});
}
};

export default plugins;
export default xeusKernelsPlugin;
16 changes: 0 additions & 16 deletions src/web_worker_kernel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,21 @@ export class WebWorkerKernel implements IKernel {
* @param options The instantiation options for a new WebWorkerKernel
*/
constructor(options: WebWorkerKernel.IOptions) {
console.log('constructing WebWorkerKernel kernel');
const { id, name, sendMessage, location } = options;
this._id = id;
this._name = name;
this._location = location;
this._kernelspec = options.kernelspec;
this._sendMessage = sendMessage;
console.log('constructing WebWorkerKernel worker');
this._worker = new Worker(new URL('./worker.js', import.meta.url), {
type: 'module'
});
console.log('constructing WebWorkerKernel done');

this._worker.onmessage = e => {
this._processWorkerMessage(e.data);
};

console.log('wrap');
this._remote = wrap(this._worker);
console.log('wrap done');

this._remote.processMessage({
msg: {
Expand All @@ -60,19 +55,13 @@ export class WebWorkerKernel implements IKernel {
}
});

console.log('init filesystem');
this.initFileSystem(options);

console.log('constructing WebWorkerKernel done2');
}

async handleMessage(msg: KernelMessage.IMessage): Promise<void> {
console.log('handleMessage', msg);
this._parent = msg;
this._parentHeader = msg.header;
console.log('send message to worker');
await this._sendMessageToWorker(msg);
console.log('send message to worker awaiting done');
}

private async _sendMessageToWorker(msg: any): Promise<void> {
Expand All @@ -81,11 +70,7 @@ export class WebWorkerKernel implements IKernel {
this._executeDelegate = new PromiseDelegate<void>();
}

console.log(' this._remote.processMessage({ msg, parent: this.parent });');
await this._remote.processMessage({ msg, parent: this.parent });
console.log(
' this._remote.processMessage({ msg, parent: this.parent }); done'
);
if (msg.header.msg_type !== 'input_reply') {
return await this._executeDelegate.promise;
}
Expand Down Expand Up @@ -120,7 +105,6 @@ export class WebWorkerKernel implements IKernel {
* @param msg The worker message to process.
*/
private _processWorkerMessage(msg: any): void {
console.log('processWorkerMessage', msg);
if (!msg.header) {
return;
}
Expand Down
21 changes: 11 additions & 10 deletions src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// Copyright (c) JupyterLite Contributors
// Distributed under the terms of the Modified BSD License.

console.log('worker loaded');

import { expose } from 'comlink';

import {
Expand All @@ -12,6 +10,7 @@ import {
IEmscriptenFSNode,
IStats
} from '@jupyterlite/contents';
import { PageConfig, URLExt } from '@jupyterlab/coreutils';

declare function createXeusModule(options: any): any;

Expand Down Expand Up @@ -96,7 +95,6 @@ async function get_stdin() {

class XeusKernel {
constructor(resolve: any) {
console.log('constructing kernel');
this._resolve = resolve;
}

Expand All @@ -105,7 +103,6 @@ class XeusKernel {
}

mount(driveName: string, mountpoint: string, baseUrl: string): void {
console.log('mounting drive');
const { FS, PATH, ERRNO_CODES } = globalThis.Module;

if (!FS) {
Expand Down Expand Up @@ -164,14 +161,14 @@ class XeusKernel {

private async initialize() {
// the location of the kernel on the server
// ie `share/jupyter/kernels/${dir}`
// ie `xeus/kernels/${dir}`
const dir = this._kernelspec.dir;

// location of the kernel binary on the server
const binary_js = this._kernelspec.argv[0];
const binary_wasm = binary_js.replace('.js', '.wasm');

importScripts(binary_js);
importScripts(URLExt.join(PageConfig.getBaseUrl(), binary_js));
globalThis.Module = await createXeusModule({
locateFile: (file: string) => {
if (file.endsWith('.wasm')) {
Expand All @@ -182,15 +179,20 @@ class XeusKernel {
});
try {
await this.waitRunDependency();
console.log(globalThis.Module);

// each kernel can have a `async_init` function
// which can do kernel specific **async** initialization
// This function is usually implemented in the pre/post.js
// in the emscripten build of that kernel
if (globalThis.Module['async_init'] !== undefined) {
const kernel_root_url = `share/jupyter/kernels/${dir}`;
const pkg_root_url = 'share/jupyter/kernel_packages';
const kernel_root_url = URLExt.join(
PageConfig.getBaseUrl(),
`xeus/kernels/${dir}`
);
const pkg_root_url = URLExt.join(
PageConfig.getBaseUrl(),
'xeus/kernel_packages'
);
const verbose = true;
await globalThis.Module['async_init'](
kernel_root_url,
Expand Down Expand Up @@ -244,6 +246,5 @@ class XeusKernel {
}

globalThis.ready = new Promise(resolve => {
console.log('expose(new XeusKernel(resolve));');
expose(new XeusKernel(resolve));
});

0 comments on commit 3ec76eb

Please sign in to comment.