Skip to content

Commit 9b87bda

Browse files
committed
Allow to install extra packages from extra indexes from jupyter-lite.json<F48>
This is in progress, but the idea is to be able to point to dev wheels on rtd or similar without having to make a custom pyidide distribution. For example: ``` // jupyter-lite.json { "jupyter-config-data": { "litePluginSettings": { "extraPackagesAndIndexes": [ { "indexes": [ "https://cors.carreau.workers.dev/scientific-python-nightly-wheels/simple", "https://pypi.org/simple" ], "package": "xarray" } ] } } } ``` Package could also be a simple url to a whl (I need to check how it works if it's a local URL), and indexes can be ommited. WIP as I'm stuggling to have the typescript build process work.
1 parent 65f1ab2 commit 9b87bda

File tree

4 files changed

+38
-2
lines changed

4 files changed

+38
-2
lines changed

packages/pyodide-kernel-extension/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ const kernel: JupyterLiteServerPlugin<void> = {
5858
const pipliteUrls = rawPipUrls.map((pipUrl: string) => URLExt.parse(pipUrl).href);
5959
const disablePyPIFallback = !!config.disablePyPIFallback;
6060
const loadPyodideOptions = config.loadPyodideOptions || {};
61+
const extraPackagesAndIndexes = config.extraPackagesAndIndexes || [];
6162

6263
for (const [key, value] of Object.entries(loadPyodideOptions)) {
6364
if (key.endsWith('URL') && typeof value === 'string') {
@@ -99,6 +100,7 @@ const kernel: JupyterLiteServerPlugin<void> = {
99100
mountDrive,
100101
loadPyodideOptions,
101102
contentsManager,
103+
extraPackagesAndIndexes,
102104
});
103105
},
104106
});

packages/pyodide-kernel/src/kernel.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ export class PyodideKernel extends BaseKernel implements IKernel {
120120
location: this.location,
121121
mountDrive: options.mountDrive,
122122
loadPyodideOptions: options.loadPyodideOptions || {},
123+
extraPackagesAndIndexes: options.extraPackagesAndIndexes || [],
123124
};
124125
}
125126

@@ -394,5 +395,6 @@ export namespace PyodideKernel {
394395
* The Jupyterlite content manager
395396
*/
396397
contentsManager: Contents.IManager;
398+
extraPackagesAndIndexes: Array<{ package: string; indexes: string[] | null }>;
397399
}
398400
}

packages/pyodide-kernel/src/tokens.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ export namespace IPyodideWorkerKernel {
9090
*/
9191
mountDrive: boolean;
9292

93+
/**
94+
* List of extra url/wheel paths to load, and extra associated indexes urls (if not a wheel url)
95+
*/
96+
extraPackagesAndIndexes: Array<{ package: string; indexes: string[] | null }>;
97+
9398
/**
9499
* additional options to provide to `loadPyodide`
95100
* @see https://pyodide.org/en/stable/usage/api/js-api.html#globalThis.loadPyodide

packages/pyodide-kernel/src/worker.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,13 @@ export class PyodideRemoteKernel {
6565
throw new Error('Uninitialized');
6666
}
6767

68-
const { pipliteWheelUrl, disablePyPIFallback, pipliteUrls, loadPyodideOptions } =
69-
this._options;
68+
const {
69+
pipliteWheelUrl,
70+
disablePyPIFallback,
71+
pipliteUrls,
72+
loadPyodideOptions,
73+
extraPackagesAndIndexes,
74+
} = this._options;
7075

7176
const preloaded = (loadPyodideOptions || {}).packages || [];
7277

@@ -80,6 +85,28 @@ export class PyodideRemoteKernel {
8085
await micropip.install('${pipliteWheelUrl}', keep_going=True)
8186
`);
8287
}
88+
console.debug('extraPackagesAndIndexes', extraPackagesAndIndexes);
89+
90+
if (extraPackagesAndIndexes.length > 0) {
91+
// note that here pkg can be a package name or a wheel url
92+
for (let { package: pkg, indexes } of extraPackagesAndIndexes) {
93+
let installCmd: string;
94+
if (indexes === null) {
95+
installCmd = `import micropip\nawait micropip.install('${pkg}', keep_going=True)`;
96+
} else {
97+
installCmd = `import micropip\nawait micropip.install('${pkg}', index_urls=${JSON.stringify(indexes)}, keep_going=True)`;
98+
}
99+
console.info('installCmd', installCmd);
100+
try {
101+
await this._pyodide.runPythonAsync(installCmd);
102+
console.info(`Package ${pkg} Installed successfully`);
103+
} catch (e) {
104+
console.error('Error installing package', e);
105+
}
106+
}
107+
} else {
108+
console.info('no extra packages and indexes');
109+
}
83110

84111
// get piplite early enough to impact pyodide-kernel dependencies
85112
await this._pyodide.runPythonAsync(`

0 commit comments

Comments
 (0)