Skip to content

Commit

Permalink
Add XeusAddon.package_url_factory config
Browse files Browse the repository at this point in the history
  • Loading branch information
trungleduc committed Oct 15, 2024
1 parent f061568 commit 0c68668
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 69 deletions.
13 changes: 11 additions & 2 deletions jupyterlite_xeus/add_on.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""a JupyterLite addon for creating the env for xeus kernels"""

import json
import os
from pathlib import Path
Expand All @@ -18,7 +19,7 @@
SHARE_LABEXTENSIONS,
UTF8,
)
from traitlets import Bool, List, Unicode
from traitlets import Bool, Callable, List, Unicode

from .create_conda_env import (
create_conda_env_from_env_file,
Expand Down Expand Up @@ -102,6 +103,13 @@ class XeusAddon(FederatedExtensionAddon):
description="A comma-separated list of mount points, in the form <host_path>:<mount_path> to mount in the wasm prefix",
)

package_url_factory = Callable(
None,
allow_none=True,
config=True,
description="Factory to generate package download URL from package metadata. This is used to load python packages from external host",
)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.xeus_output_dir = Path(self.manager.output_dir) / "xeus"
Expand Down Expand Up @@ -290,6 +298,7 @@ def pack_prefix(self, kernel_dir):
relocate_prefix="/",
outdir=out_path,
use_cache=False,
package_url_factory=self.package_url_factory,
**pack_kwargs,
)

Expand Down Expand Up @@ -430,4 +439,4 @@ def dedupe_federated_extensions(self, config):
if os.path.exists(self.output_extensions / ext["name"] / ext["load"]):
named[ext["name"]] = ext

config[FEDERATED_EXTENSIONS] = sorted(named.values(), key=lambda x: x["name"])
config[FEDERATED_EXTENSIONS] = sorted(named.values(), key=lambda x: x["name"])
126 changes: 67 additions & 59 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,78 +30,86 @@ try {
throw err;
}

const plugins = kernel_list.map((kernel): JupyterLiteServerPlugin<void| IEmpackEnvMetaFile> => {
return {
id: `@jupyterlite/xeus-${kernel}:register`,
autoStart: true,
requires: [IKernelSpecs],
optional: [IServiceWorkerManager, IBroadcastChannelWrapper, IEmpackEnvMetaFile],
activate: (
app: JupyterLiteServer,
kernelspecs: IKernelSpecs,
serviceWorker?: IServiceWorkerManager,
broadcastChannel?: IBroadcastChannelWrapper,
empackEnvMetaFile?: IEmpackEnvMetaFile
) => {
// Fetch kernel spec
const kernelspec = getJson('xeus/kernels/' + kernel + '/kernel.json');
kernelspec.name = kernel;
kernelspec.dir = kernel;
for (const [key, value] of Object.entries(kernelspec.resources)) {
kernelspec.resources[key] = URLExt.join(
PageConfig.getBaseUrl(),
value as string
);
}

const contentsManager = app.serviceManager.contents;
kernelspecs.register({
spec: kernelspec,
create: async (options: IKernel.IOptions): Promise<IKernel> => {
const mountDrive = !!(
(serviceWorker?.enabled && broadcastChannel?.enabled) ||
crossOriginIsolated
const plugins = kernel_list.map(
(kernel): JupyterLiteServerPlugin<void | IEmpackEnvMetaFile> => {
return {
id: `@jupyterlite/xeus-${kernel}:register`,
autoStart: true,
requires: [IKernelSpecs],
optional: [
IServiceWorkerManager,
IBroadcastChannelWrapper,
IEmpackEnvMetaFile
],
activate: (
app: JupyterLiteServer,
kernelspecs: IKernelSpecs,
serviceWorker?: IServiceWorkerManager,
broadcastChannel?: IBroadcastChannelWrapper,
empackEnvMetaFile?: IEmpackEnvMetaFile
) => {
// Fetch kernel spec
const kernelspec = getJson('xeus/kernels/' + kernel + '/kernel.json');
kernelspec.name = kernel;
kernelspec.dir = kernel;
for (const [key, value] of Object.entries(kernelspec.resources)) {
kernelspec.resources[key] = URLExt.join(
PageConfig.getBaseUrl(),
value as string
);
}

if (mountDrive) {
console.info(
`${kernelspec.name} contents will be synced with Jupyter Contents`
const contentsManager = app.serviceManager.contents;
kernelspecs.register({
spec: kernelspec,
create: async (options: IKernel.IOptions): Promise<IKernel> => {
const mountDrive = !!(
(serviceWorker?.enabled && broadcastChannel?.enabled) ||
crossOriginIsolated
);
} else {
console.warn(
`${kernelspec.name} contents will NOT be synced with Jupyter Contents`
);
}
const link = empackEnvMetaFile ? await empackEnvMetaFile.getLink(kernelspec.dir): '';

return new WebWorkerKernel({
...options,
contentsManager,
mountDrive,
kernelSpec: kernelspec,
empackEnvMetaLink: link
});
}
});
}
};
});
if (mountDrive) {
console.info(
`${kernelspec.name} contents will be synced with Jupyter Contents`
);
} else {
console.warn(
`${kernelspec.name} contents will NOT be synced with Jupyter Contents`
);
}
const link = empackEnvMetaFile
? await empackEnvMetaFile.getLink(kernelspec.dir)
: '';

return new WebWorkerKernel({
...options,
contentsManager,
mountDrive,
kernelSpec: kernelspec,
empackEnvMetaLink: link
});
}
});
}
};
}
);

const empackEnvMetaPlugin: JupyterLiteServerPlugin<IEmpackEnvMetaFile> = {
id: `@jupyterlite/xeus-python:empack-env-meta`,
id: '@jupyterlite/xeus-python:empack-env-meta',
autoStart: true,
provides: IEmpackEnvMetaFile,
activate: (): IEmpackEnvMetaFile => {
return {
getLink: async (kernel?: string) => {
const kernel_root_url = URLExt.join(
PageConfig.getBaseUrl(),
`xeus/kernels/${kernel}`
);
return `${kernel_root_url}`;
const kernel_root_url = URLExt.join(
PageConfig.getBaseUrl(),
`xeus/kernels/${kernel}`
);
return `${kernel_root_url}`;
}
};
},
}
};

plugins.push(empackEnvMetaPlugin);
Expand Down
4 changes: 3 additions & 1 deletion src/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,6 @@ export interface IEmpackEnvMetaFile {
getLink: (kernel?: string) => Promise<string>;
}

export const IEmpackEnvMetaFile = new Token<IEmpackEnvMetaFile>('@jupyterlite/xeus-python:IEmpackEnvMetaFile');
export const IEmpackEnvMetaFile = new Token<IEmpackEnvMetaFile>(
'@jupyterlite/xeus-python:IEmpackEnvMetaFile'
);
13 changes: 10 additions & 3 deletions src/web_worker_kernel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,15 @@ export class WebWorkerKernel implements IKernel {
* @param options The instantiation options for a new WebWorkerKernel
*/
constructor(options: WebWorkerKernel.IOptions) {
const { id, name, sendMessage, location, kernelSpec, contentsManager, empackEnvMetaLink } =
options;
const {
id,
name,
sendMessage,
location,
kernelSpec,
contentsManager,
empackEnvMetaLink
} = options;
this._id = id;
this._name = name;
this._location = location;
Expand Down Expand Up @@ -105,7 +112,7 @@ export class WebWorkerKernel implements IKernel {
kernelSpec: this._kernelSpec,
baseUrl: PageConfig.getBaseUrl(),
mountDrive: options.mountDrive,
empackEnvMetaLink: this._empackEnvMetaLink,
empackEnvMetaLink: this._empackEnvMetaLink
})
.then(this._ready.resolve.bind(this._ready));

Expand Down
7 changes: 3 additions & 4 deletions src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,9 @@ export class XeusRemoteKernel {
// 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 = empackEnvMetaLink ? empackEnvMetaLink : URLExt.join(
baseUrl,
`xeus/kernels/${kernelSpec.dir}`
);
const kernel_root_url = empackEnvMetaLink
? empackEnvMetaLink
: URLExt.join(baseUrl, `xeus/kernels/${kernelSpec.dir}`);
const pkg_root_url = URLExt.join(baseUrl, 'xeus/kernel_packages');
const verbose = true;
await globalThis.Module['async_init'](
Expand Down

0 comments on commit 0c68668

Please sign in to comment.