mirror of https://github.com/pyodide/pyodide.git
Add options to disable integrity check in pyodide.loadPackage (#3149)
This PR adds an option to disable integrity check in `pyodide.loadPackage` when it is loading packages registered in repodata.json.
This commit is contained in:
parent
d2fce73291
commit
825a01e3af
|
@ -74,6 +74,18 @@ substitutions:
|
|||
the method is called on.
|
||||
{pr}`3130`
|
||||
|
||||
- {{ Breaking }} The messageCallback and errorCallback argument to
|
||||
{any}`loadPackage <pyodide.loadPackage>` and
|
||||
{any}`loadPackagesFromImports <pyodide.loadPackagesFromImports>`
|
||||
is now passed as named arguments.
|
||||
The old usage still works with a deprecation warning.
|
||||
{pr}`3149`
|
||||
|
||||
- {{ Enhancement }} {any}`loadPackage <pyodide.loadPackage>` and
|
||||
{any}`loadPackagesFromImports <pyodide.loadPackagesFromImports>` now accepts
|
||||
a new option `checkIntegrity`. If set to False, integrity check for Python Packages
|
||||
will be disabled.
|
||||
|
||||
- {{ Fix }} Shared libraries with version suffix are now handled correctly.
|
||||
{pr}`3154`
|
||||
|
||||
|
|
|
@ -10,6 +10,11 @@ state, this list is subject to change and some features can be removed without
|
|||
deprecation warnings. More details about each item can often be found in the
|
||||
{ref}`changelog`.
|
||||
|
||||
## 0.24.0
|
||||
|
||||
- The `messageCallback` and `errorCallback` argument to `loadPackage` and `loadPackagesFromImports` will be passed as a
|
||||
named argument only.
|
||||
|
||||
## 0.23.0
|
||||
|
||||
Names that used to be in the root `pyodide` module and were moved to submodules
|
||||
|
|
|
@ -71,6 +71,7 @@ export function runPython(
|
|||
}
|
||||
API.runPython = runPython;
|
||||
|
||||
let loadPackagesFromImportsPositionalCallbackDeprecationWarned = false;
|
||||
/**
|
||||
* Inspect a Python code chunk and use :js:func:`pyodide.loadPackage` to install
|
||||
* any known packages that the code chunk imports. Uses the Python API
|
||||
|
@ -86,17 +87,39 @@ API.runPython = runPython;
|
|||
* ``pyodide.loadPackage(['numpy'])``.
|
||||
*
|
||||
* @param code The code to inspect.
|
||||
* @param messageCallback The ``messageCallback`` argument of
|
||||
* :any:`pyodide.loadPackage` (optional).
|
||||
* @param errorCallback The ``errorCallback`` argument of
|
||||
* :any:`pyodide.loadPackage` (optional).
|
||||
* @param options Options passed to :any:`pyodide.loadPackage`.
|
||||
* @param options.messageCallback A callback, called with progress messages
|
||||
* (optional)
|
||||
* @param options.errorCallback A callback, called with error/warning messages
|
||||
* (optional)
|
||||
* @param options.checkIntegrity If true, check the integrity of the downloaded
|
||||
* packages (default: true)
|
||||
* @async
|
||||
*/
|
||||
export async function loadPackagesFromImports(
|
||||
code: string,
|
||||
messageCallback?: (msg: string) => void,
|
||||
errorCallback?: (err: string) => void,
|
||||
options: {
|
||||
messageCallback?: (message: string) => void;
|
||||
errorCallback?: (message: string) => void;
|
||||
checkIntegrity?: boolean;
|
||||
} = {
|
||||
checkIntegrity: true,
|
||||
},
|
||||
errorCallbackDeprecated?: (message: string) => void,
|
||||
) {
|
||||
if (typeof options === "function") {
|
||||
if (!loadPackagesFromImportsPositionalCallbackDeprecationWarned) {
|
||||
console.warn(
|
||||
"Passing a messageCallback or errorCallback as the second or third argument to loadPackagesFromImports is deprecated and will be removed in v0.24. Instead use { messageCallback : callbackFunc }",
|
||||
);
|
||||
options = {
|
||||
messageCallback: options,
|
||||
errorCallback: errorCallbackDeprecated,
|
||||
};
|
||||
loadPackagesFromImportsPositionalCallbackDeprecationWarned = true;
|
||||
}
|
||||
}
|
||||
|
||||
let pyimports = API.pyodide_code.find_imports(code);
|
||||
let imports;
|
||||
try {
|
||||
|
@ -116,7 +139,7 @@ export async function loadPackagesFromImports(
|
|||
}
|
||||
}
|
||||
if (packages.size) {
|
||||
await loadPackage(Array.from(packages), messageCallback, errorCallback);
|
||||
await loadPackage(Array.from(packages), options);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -191,12 +191,15 @@ function recursiveDependencies(
|
|||
* @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.
|
||||
* @param checkIntegrity Whether to check the integrity of the downloaded
|
||||
* package.
|
||||
* @returns The binary data for the package
|
||||
* @private
|
||||
*/
|
||||
async function downloadPackage(
|
||||
name: string,
|
||||
channel: string,
|
||||
checkIntegrity: boolean = true,
|
||||
): Promise<Uint8Array> {
|
||||
let file_name, uri, file_sub_resource_hash;
|
||||
if (channel === DEFAULT_CHANNEL) {
|
||||
|
@ -212,6 +215,10 @@ async function downloadPackage(
|
|||
uri = channel;
|
||||
file_sub_resource_hash = undefined;
|
||||
}
|
||||
|
||||
if (!checkIntegrity) {
|
||||
file_sub_resource_hash = undefined;
|
||||
}
|
||||
try {
|
||||
return await loadBinaryFile(uri, file_sub_resource_hash);
|
||||
} catch (e) {
|
||||
|
@ -274,6 +281,8 @@ async function installPackage(
|
|||
* @param toLoad The map of package names to PackageLoadMetadata
|
||||
* @param loaded The set of loaded package names, this will be updated by this function.
|
||||
* @param failed The map of <failed package name, error message>, this will be updated by this function.
|
||||
* @param checkIntegrity Whether to check the integrity of the downloaded
|
||||
* package.
|
||||
* @private
|
||||
*/
|
||||
async function downloadAndInstall(
|
||||
|
@ -281,6 +290,7 @@ async function downloadAndInstall(
|
|||
toLoad: Map<string, PackageLoadMetadata>,
|
||||
loaded: Set<string>,
|
||||
failed: Map<string, Error>,
|
||||
checkIntegrity: boolean = true,
|
||||
) {
|
||||
if (loadedPackages[name] !== undefined) {
|
||||
return;
|
||||
|
@ -289,7 +299,7 @@ async function downloadAndInstall(
|
|||
const pkg = toLoad.get(name)!;
|
||||
|
||||
try {
|
||||
const buffer = await downloadPackage(pkg.name, pkg.channel);
|
||||
const buffer = await downloadPackage(pkg.name, pkg.channel, checkIntegrity);
|
||||
const installPromisDependencies = pkg.depends.map((dependency) => {
|
||||
return toLoad.has(dependency)
|
||||
? toLoad.get(dependency)!.done
|
||||
|
@ -422,6 +432,7 @@ API.loadDynlib = loadDynlib;
|
|||
|
||||
const acquirePackageLock = createLock();
|
||||
|
||||
let loadPackagePositionalCallbackDeprecationWarned = false;
|
||||
/**
|
||||
* Load a package or a list of packages over the network. This installs the
|
||||
* package in the virtual filesystem. The package needs to be imported from
|
||||
|
@ -433,19 +444,41 @@ const acquirePackageLock = createLock();
|
|||
* ``<package-name>.data`` in the same directory. The argument can be a
|
||||
* ``PyProxy`` of a list, in which case the list will be converted to JavaScript
|
||||
* and the ``PyProxy`` will be destroyed.
|
||||
* @param messageCallback A callback, called with progress messages
|
||||
* @param options
|
||||
* @param options.messageCallback A callback, called with progress messages
|
||||
* (optional)
|
||||
* @param errorCallback A callback, called with error/warning messages
|
||||
* @param options.errorCallback A callback, called with error/warning messages
|
||||
* (optional)
|
||||
* @param options.checkIntegrity If true, check the integrity of the downloaded
|
||||
* packages (default: true)
|
||||
* @async
|
||||
*/
|
||||
export async function loadPackage(
|
||||
names: string | PyProxy | Array<string>,
|
||||
messageCallback?: (msg: string) => void,
|
||||
errorCallback?: (msg: string) => void,
|
||||
options: {
|
||||
messageCallback?: (message: string) => void;
|
||||
errorCallback?: (message: string) => void;
|
||||
checkIntegrity?: boolean;
|
||||
} = {
|
||||
checkIntegrity: true,
|
||||
},
|
||||
errorCallbackDeprecated?: (message: string) => void,
|
||||
) {
|
||||
messageCallback = messageCallback || console.log;
|
||||
errorCallback = errorCallback || console.error;
|
||||
if (typeof options === "function") {
|
||||
if (!loadPackagePositionalCallbackDeprecationWarned) {
|
||||
console.warn(
|
||||
"Passing a messageCallback or errorCallback as the second or third argument to loadPackage is deprecated and will be removed in v0.24. Instead use { messageCallback : callbackFunc }",
|
||||
);
|
||||
options = {
|
||||
messageCallback: options,
|
||||
errorCallback: errorCallbackDeprecated,
|
||||
};
|
||||
loadPackagePositionalCallbackDeprecationWarned = true;
|
||||
}
|
||||
}
|
||||
|
||||
const messageCallback = options.messageCallback || console.log;
|
||||
const errorCallback = options.errorCallback || console.error;
|
||||
if (isPyProxy(names)) {
|
||||
names = names.toJs();
|
||||
}
|
||||
|
@ -503,6 +536,7 @@ export async function loadPackage(
|
|||
toLoad,
|
||||
loaded,
|
||||
failed,
|
||||
options.checkIntegrity,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,29 +49,29 @@ async function main() {
|
|||
|
||||
expectType<Promise<void>>(pyodide.loadPackagesFromImports("import some_pkg"));
|
||||
expectType<Promise<void>>(
|
||||
pyodide.loadPackagesFromImports("import some_pkg", (x: any) =>
|
||||
console.log(x),
|
||||
),
|
||||
pyodide.loadPackagesFromImports("import some_pkg", {
|
||||
messageCallback: (x: any) => console.log(x),
|
||||
}),
|
||||
);
|
||||
expectType<Promise<void>>(
|
||||
pyodide.loadPackagesFromImports(
|
||||
"import some_pkg",
|
||||
(x: any) => console.log(x),
|
||||
(x: any) => console.warn(x),
|
||||
),
|
||||
pyodide.loadPackagesFromImports("import some_pkg", {
|
||||
messageCallback: (x: any) => console.log(x),
|
||||
errorCallback: (x: any) => console.warn(x),
|
||||
}),
|
||||
);
|
||||
|
||||
expectType<Promise<void>>(pyodide.loadPackage("blah"));
|
||||
expectType<Promise<void>>(pyodide.loadPackage(["blah", "blah2"]));
|
||||
expectType<Promise<void>>(
|
||||
pyodide.loadPackage("blah", (x: any) => console.log(x)),
|
||||
pyodide.loadPackage("blah", {
|
||||
messageCallback: (x: any) => console.log(x),
|
||||
}),
|
||||
);
|
||||
expectType<Promise<void>>(
|
||||
pyodide.loadPackage(
|
||||
["blah", "blah2"],
|
||||
(x: any) => console.log(x),
|
||||
(x: any) => console.warn(x),
|
||||
),
|
||||
pyodide.loadPackage(["blah", "blah2"], {
|
||||
messageCallback: (x: any) => console.log(x),
|
||||
errorCallback: (x: any) => console.warn(x),
|
||||
}),
|
||||
);
|
||||
expectType<Promise<void>>(pyodide.loadPackage(px));
|
||||
|
||||
|
|
|
@ -1248,6 +1248,18 @@ def test_raises_jsexception(selenium):
|
|||
raise_jsexception(selenium)
|
||||
|
||||
|
||||
def test_deprecations(selenium_standalone):
|
||||
selenium = selenium_standalone
|
||||
selenium.run_js(
|
||||
"""
|
||||
pyodide.loadPackage("micropip", (x) => x);
|
||||
pyodide.loadPackagesFromImports("import micropip", (x) => x);
|
||||
"""
|
||||
)
|
||||
dep_msg = "Passing a messageCallback or errorCallback as the second or third argument to loadPackage is deprecated and will be removed in v0.24. Instead use { messageCallback : callbackFunc }"
|
||||
assert selenium.logs.count(dep_msg) == 1
|
||||
|
||||
|
||||
@run_in_pyodide(packages=["pytest"])
|
||||
def test_moved_deprecation_warnings(selenium_standalone):
|
||||
import pytest
|
||||
|
|
Loading…
Reference in New Issue