Invalidate Importlib's Module Cache on Writes to FS (#996)

* Add runtime.invalidate_module_path_cache() to clear importlib's cache of modules

* Clear cache after [[fetch]], after plugin files download, after plugins setup, and prior to py-script tag execution.
This commit is contained in:
Jeff Glass
2022-11-29 15:36:23 -06:00
committed by GitHub
parent 3e408b7baa
commit 4299a74e40
4 changed files with 25 additions and 0 deletions

View File

@@ -179,6 +179,8 @@ export class PyScriptApp {
// lifecycle (6.5)
this.plugins.afterSetup(runtime);
//Refresh module cache in case plugins have modified the filesystem
runtime.invalidate_module_path_cache()
this.logStatus('Executing <py-script> tags...');
this.executeScripts(runtime);
@@ -205,6 +207,8 @@ export class PyScriptApp {
// Save and load pyscript.py from FS
runtime.interpreter.FS.writeFile('pyscript.py', pyscript, { encoding: 'utf8' });
//Refresh the module cache so Python consistently finds pyscript module
runtime.invalidate_module_path_cache()
// inject `define_custom_element` it into the PyScript module scope
const pyscript_module = runtime.interpreter.pyimport('pyscript');
@@ -227,6 +231,8 @@ from pyscript import micropip, Element, console, document`);
await runtime.installPackage(this.config.packages);
await this.fetchPaths(runtime);
//This may be unnecessary - only useful if plugins try to import files fetch'd in fetchPaths()
runtime.invalidate_module_path_cache()
// Finally load plugins
await this.fetchPythonPlugins(runtime);
}
@@ -273,6 +279,10 @@ from pyscript import micropip, Element, console, document`);
// TODO: Would be probably be better to store plugins somewhere like /plugins/python/ or similar
const destPath = `./${filename}`;
await runtime.loadFromFile(destPath, singleFile);
//refresh module cache before trying to import module files into runtime
runtime.invalidate_module_path_cache()
const modulename = singleFile.replace(/^.*[\\/]/, '').replace('.py', '');
console.log(`importing ${modulename}`);

View File

@@ -118,4 +118,9 @@ export class PyodideRuntime extends Runtime {
this.interpreter.FS.write(stream, data, 0, data.length, 0);
this.interpreter.FS.close(stream);
}
invalidate_module_path_cache(): void {
const importlib = this.interpreter.pyimport("importlib")
importlib.invalidate_caches()
}
}

View File

@@ -100,4 +100,10 @@ export abstract class Runtime extends Object {
* underlying interpreter.
* */
abstract loadFromFile(path: string, fetch_path: string): Promise<void>;
/**
* delegates clearing importlib's module path
* caches to the underlying interpreter
*/
abstract invalidate_module_path_cache(): void;
}

View File

@@ -36,4 +36,8 @@ export class FakeRuntime extends Runtime {
async loadFromFile(path: string, fetch_path: string) {
throw new Error("not implemented");
}
invalidate_module_path_cache(): void {
throw new Error("not implemented");
}
}