user862319
user862319

Reputation:

IronPython Override Builtin Method

I am trying to override the default __import__ method provided by IronPython to handle database imports. I have already run through the example provided here: https://stackoverflow.com/a/4127766/862319

Everything is working so far, but there is a minor issue related to namespace resolution within CLR types. I am able to import using the syntax import ClrAssembly.Type but the syntax from ClrAssembly import Type does not work. This is a minor inconvenience, but I would like to get it resolved. My suspicion is that there are two method signatures tied to the __import__method in IronPython:

Screenshot of import variable

But, the SO link above results in only a single method being applied with the 5 parameter signature. Here is the __import__ variable after being set:

enter image description here

How would I go about constructing a custom IronPython.Runtime.Types.BuiltinFunction that maps to 2 method signatures (5 param and 2 param version of DoDatabaseImport) and assign it back to the __import__ variable?

Upvotes: 4

Views: 755

Answers (2)

bwd
bwd

Reputation: 70

Hopefully this answer helps someone who is looking at this old question.

Looking at the source for IronPython 2.7.7 specifically the builtin.cs file from https://github.com/IronLanguages/main/blob/3d9c336e1b6f0a86914a89ece171a22f48b0cc6e/Languages/IronPython/IronPython/Modules/Builtin.cs

you can see that the 2 parameter function calls the 5 parameter overload with default values.

public static object __import__(CodeContext/*!*/ context, string name) {
    return __import__(context, name, null, null, null, -1);
}

To replicate this I used a delegate with similar default values.

delegate object ImportDelegate(CodeContext context, string moduleName, object globals = null, object locals = null, object fromlist = null, int level = -1);

protected object ImportOverride(CodeContext context, string moduleName, object globals = null, object locals = null, object fromlist = null, int level = -1)
{
    // do custom import logic here

    return IronPython.Modules.Builtin.__import__(context, moduleName, globals, locals, fromlist, level);
}

Overriding the builtin import function is shown below

private ScriptEngine pyengine;
private ScriptingEngine()
{
    Dictionary<string, object> options = new Dictionary<string, object>();
    options["Debug"] = true;
    pyengine = Python.CreateEngine(options);
    var builtinscope = Python.GetBuiltinModule(pyengine);
    builtinscope.SetVariable("__import__", new ImportDelegate(ImportOverride));
}

Upvotes: 2

BendEg
BendEg

Reputation: 21088

I had the same problem. My solution was, to search for all clr types and store them in a HashSet. If IronPython tries to import some thing from the clr, i ingored my own set of rules and called the built-in importer from IronPython. This is working pretty well for a while now.

Hope this helps.

Upvotes: 0

Related Questions