I am loading an IronPython script from a database and executing it. This works fine for simple scripts, but imports are a problem. How can I intercept these import calls a
After a great deal of trial and error, I arrived at a solution. I never managed to get the PlatformAdaptationLayer approach to work correctly. It never called back to the PAL when attempting to load the modules.
So what I decided to do was replace the built-in import function by using the SetVariable method as shown below (Engine and Scope are protected members exposing the ScriptEngine and ScriptScope for the parent script):
delegate object ImportDelegate(CodeContext context, string moduleName, PythonDictionary globals, PythonDictionary locals, PythonTuple tuple);
protected void OverrideImport()
{
ScriptScope scope = IronPython.Hosting.Python.GetBuiltinModule(Engine);
scope.SetVariable("__import__", new ImportDelegate(DoDatabaseImport));
}
protected object DoDatabaseImport(CodeContext context, string moduleName, PythonDictionary globals, PythonDictionary locals, PythonTuple tuple)
{
if (ScriptExistsInDb(moduleName))
{
string rawScript = GetScriptFromDb(moduleName);
ScriptSource source = Engine.CreateScriptSourceFromString(rawScript);
ScriptScope scope = Engine.CreateScope();
Engine.Execute(rawScript, scope);
Microsoft.Scripting.Runtime.Scope ret = Microsoft.Scripting.Hosting.Providers.HostingHelpers.GetScope(scope);
Scope.SetVariable(moduleName, ret);
return ret;
}
else
{ // fall back on the built-in method
return IronPython.Modules.Builtin.__import__(context, moduleName);
}
}
Hope this helps someone!