Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow customizing cache location for packages in Node #3967

Merged
merged 8 commits into from Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/project/changelog.md
Expand Up @@ -15,6 +15,9 @@ myst:

## Unreleased

- {{ Enhancement }} Allow customizing installation location for packages
{pr}`3967`

- {{ Enhancement }} ABI Break: Updated Emscripten to version 3.1.39
{pr}`3665`, {pr}`3659`, {pr}`3822`, {pr}`3889`, {pr}`3890`

Expand Down
17 changes: 14 additions & 3 deletions src/js/load-package.ts
Expand Up @@ -214,11 +214,11 @@ function recursiveDependencies(

/**
* Download a package. If `channel` is `DEFAULT_CHANNEL`, look up the wheel URL
* relative to indexURL from `pyodide-lock.json`, otherwise use the URL specified by
* relative to packageCacheDir (when IN_NODE), or indexURL from `pyodide-lock.json`, otherwise use the URL specified by
* `channel`.
* @param name The name of the package
* @param channel Either `DEFAULT_CHANNEL` or the absolute URL to the
* wheel or the path to the wheel relative to indexURL.
* wheel or the path to the wheel relative to packageCacheDir (when IN_NODE), or indexURL.
* @param checkIntegrity Whether to check the integrity of the downloaded
* package.
* @returns The binary data for the package
Expand All @@ -229,13 +229,24 @@ async function downloadPackage(
channel: string,
checkIntegrity: boolean = true,
): Promise<Uint8Array> {
let installBaseUrl: string;
if (IN_NODE) {
installBaseUrl = API.config.packageCacheDir;
// ensure that the directory exists before trying to download files into it
await nodeFsPromisesMod.mkdir(API.config.packageCacheDir, {
recursive: true,
});
} else {
installBaseUrl = API.config.indexURL;
}

let file_name, uri, file_sub_resource_hash;
if (channel === DEFAULT_CHANNEL) {
if (!(name in API.lockfile_packages)) {
throw new Error(`Internal error: no entry for package named ${name}`);
}
file_name = API.lockfile_packages[name].file_name;
uri = resolvePath(file_name, API.config.indexURL);
uri = resolvePath(file_name, installBaseUrl);
file_sub_resource_hash = API.package_loader.sub_resource_hash(
API.lockfile_packages[name].sha256,
);
Expand Down
12 changes: 12 additions & 0 deletions src/js/pyodide.ts
Expand Up @@ -177,6 +177,7 @@ function calculateIndexURL(): string {
*/
export type ConfigType = {
indexURL: string;
packageCacheDir: string;
lockFileURL: string;
homedir: string;
fullStdLib?: boolean;
Expand Down Expand Up @@ -209,6 +210,16 @@ export async function loadPyodide(
*/
indexURL?: string;

/**
* The file path where packages will be cached in `node.js`. If a package
* exists in `packageCacheDir` it is loaded from there, otherwise it is
* downloaded from the JsDelivr CDN and then cached into `packageCacheDir`.
* Only applies when running in node.js. Ignored in browsers.
*
* Default: same as indexURL
*/
packageCacheDir?: string;

/**
* The URL from which Pyodide will load the Pyodide ``pyodide-lock.json`` lock
* file. You can produce custom lock files with :py:func:`micropip.freeze`.
Expand Down Expand Up @@ -293,6 +304,7 @@ export async function loadPyodide(
args: [],
_node_mounts: [],
env: {},
packageCacheDir: indexURL,
};
const config = Object.assign(default_config, options) as ConfigType;
if (options.homedir) {
Expand Down