Ignore this entry - just trying to fix the code-formatting problems

    [Test]
public void ExtendingClass()
{
PythonEngine engine = new PythonEngine();

engine.Import("clr");
engine.LoadAssembly(GetType().Assembly);
engine.ExecuteToConsole("from IronPythonLib.Tests import *");

engine.Execute(@"class MyTransformer(IStringTransformer):
def Transform(self, input):
return input + "" is now transformed""");

IStringTransformer transformer = engine.EvaluateAs("MyTransformer()");
Assert.AreEqual("input is now transformed", transformer.Transform("input"));
}



hmmm?



edit: seems better now, swapped to a simpler layout though I doub't it will work well for people with lower resolutions... most people will (hopefully) read this via RSS at any rate.
Read More

The final solution (for generic IronPython delegates)...

Back once more...

I decided to spend ten minutes implementing a version of the last post which didn't require us to generate a function definition for a python method with a generic number of parameters... it's actually not too hard.



First off, the key to solving this problem is to generate a Type for our custom delegate - for performance reasons you would want to cache the results, but we won't do that here... Also I think it would be more apropriate for the first 0->9 parameters that we just return a generic Func delegate (generic Func & Proc delegates are going to be part of .Net 3.0, as mentioned here - At the moment I use something similar from the RhinoCommons library, have a look here)



So, first off we build a helper method for generating our delegate - just heavy use of emit here, based off an example on MSDN:


public Type CreateCustomDelegate(Type returnType, params Type[] parameterTypes)
{
AssemblyName assembly = new AssemblyName();
assembly.Name = "CreateCustomDelegateAssembly";

AssemblyBuilder assemblyBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly(assembly, AssemblyBuilderAccess.RunAndSave);

ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("TempModule");

TypeBuilder typeBuilder =
moduleBuilder.DefineType("TempDelegateType",

TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Class |

TypeAttributes.AnsiClass | TypeAttributes.AutoClass, typeof (MulticastDelegate));

ConstructorBuilder constructorBuilder =
typeBuilder.DefineConstructor(
MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public,
CallingConventions.Standard, new Type[] {typeof (object), typeof (int)});
constructorBuilder.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);

MethodBuilder methodBuilder =
typeBuilder.DefineMethod("Invoke",

MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot |

MethodAttributes.Virtual, returnType, parameterTypes);
methodBuilder.SetImplementationFlags(MethodImplAttributes.Managed | MethodImplAttributes.Runtime);

return typeBuilder.CreateType();
}



Basically it goes through the motions of building a delegate type, derived from MulticastDelegate with our selected output type and parameter types...



Now to put that type to use:


[Test]
public void WithCustomDelegate()
{
Dictionary context = new Dictionary();
context.Add("user", "alex");
context.Add("age", 26);

Proc testCore = delegate
{
List parameters = new List(context.Keys);
List values = new List(context.Values);

PythonEngine engine = new PythonEngine();

Type[] parameterTypes = new Type[context.Count];
for (int i = 0; i < parametertypes.length;="" i++)="" parametertypes[i]="typeof">

Type delegateType = CreateCustomDelegate(typeof (object), parameterTypes);

Type pythonEngine = typeof (PythonEngine);
MethodInfo genericMethod =
pythonEngine.GetMethod("CreateMethod", new Type[] {typeof (string), typeof (IList)});
MethodInfo method = genericMethod.MakeGenericMethod(delegateType);

object result =
method.Invoke(engine,

new object[] {"return user + ' is ' + str(age) + ' years old'", parameters});

Delegate myDelegate = (Delegate) result;
Assert.AreEqual("alex is 26 years old", myDelegate.DynamicInvoke(values.ToArray()));
};

// try it with our two keys in the dictionary

testCore();

// try it with another key in the dictionary

context.Add("monkey_colour", "brown");
testCore();
}



Our test creates our custom delegate type for the number of parameters we have, and then we use that when invoking the
PythonEngine.CreateMethodTDelegate>(string statements, IListstring> parameters) method.



Here we have to do a little reflection, simply because we cant directly use a local variable of type "Type" as a generic type
parameter, so we grab the generic method, set the parameter and then invoke it.



However in the end, as you can see we get a real Delegate, which we can use DynamicInvoke upon.



This is actually pretty handy, and it's certainly a lot more script-friendly, compared to the alternative of forcing users to
look up values from context by index ie.



    context['user'] + ' is ' + str(context['age']) +
' years old'



vs.



    user + ' is ' + str(age) + ' years old'



I know what I prefer ;o)
Read More

IronPython is your friend - Part 2 - More IronPython and delegates….

Part  2 - More IronPython and delegates...



So we have briefly covererd strongly typed delegates and event handlers... But they make the assumption that we know what our arguments are at compile time, what if we dont?



Say for instance you're expression engine has a bag of contextual values being passed around in a dictionary, like this:


Dictionary context = new Dictionary();
context.Add("user", "alex");
context.Add("age", 26);


What if we want to use python to evaluate expressions against that context?... Say something like writing out "my name is alex and my age is 25" - the expression in python is easy enough, we can go:


my name is' + name + ? and my age is ? + str(age)

But how do we marry all these together... lets start exploring... ever noticed that delegates have a DynamicInvoke method with a signature like this?


object DynamicInvoke(params object[] parameters)

Perhaps we can try and use this to our advantage... lets see shall we?

First Attempt

[Test]
[ExpectedException(typeof (ArgumentException), "T must be a concrete delegate, not MulticastDelegate or Delegate")]
public void LooseDelegateAndDynamicInvoke()
{
PythonEngine engine = new PythonEngine();

List parameters = new List(new string[] {"name", "age"});

Delegate func =
engine.CreateMethod("return ?my name is' + name + ? and my age is ? + str(age)", parameters);
string result = (string) func.DynamicInvoke("alex", 26);

Assert.AreEqual("my name is alex and my age is 25", result);
}



Sadly this doesn't work so well, seems the PythonEngine is looking for a concrete delegate... we could try giving it void delegate, but it does type checking on the number of parameters and their type, so we're a little stuck.



At this point I think the best answer is to actually build some code which generates the apropriate delegate type, based on the supplied dictionary, and then passing that onto the python engine, but there is another way... it's a little less elegant, but it's at least amusing:


Round 2

First of let's build a little helper method...


private static string GenerateFunction(string functionName, string[] parameters, string statements)
{
StringBuilder builder = new StringBuilder();

builder.AppendFormat("def {0}(", functionName);

for (int i = 0; i < parameters.length;="">
{
if (i > 0) builder.AppendFormat(", ");
builder.AppendFormat(parameters[i]);
}

builder.AppendFormat("):rn ");

builder.AppendFormat(statements.Replace("rn", "n").Replace("r", "n").Replace("n", "rn "));

return builder.ToString();
}



You can no doubt see where this is going - so given a statement like this:


GenerateFunction("func", new string[] { "user", "age" }, "return user + ' is ' + str(age) + ' years old'")


We'd end up with a string like this:



    def func(user, age):

        return user + ' is ' +
str(age) + ' years old'



And, moving on from there we build a test...
[Test]
public void GeneratingPythonFunction()
{
Dictionary context = new Dictionary();
context.Add("user", "alex");
context.Add("age", 26);

List parameters = new List(context.Keys);
List values = new List(context.Values);

PythonEngine engine = new PythonEngine();

engine.Execute(
GenerateFunction("func", parameters.ToArray(), "return user + ' is ' + str(age) + ' years old'"));

PythonFunction func1 = engine.EvaluateAs("func");

engine.Execute(
GenerateFunction("func", parameters.ToArray(),
"return user + ' is ' + str(age+1) + ' years old next year'"));

PythonFunction func2 = engine.EvaluateAs("func");

object result1 = func1.Call(values.ToArray());
Assert.AreEqual("alex is 26 years old", result1);

object result2 = func2.Call(values.ToArray());
Assert.AreEqual("alex is 27 years old next year", result2);
}

Are there problems with this?... well there's a few, unsurprisingly!

  • PythonFunction's are not delegates.
  • String manipulation is a bit clunky
  • Because these are named functions, you probably want to lock against some object when generating the function, to avoid cross-threading issues...

Back to delegates

Aside from the problems it works alright, but what we really want is a delegate... those PythonFunctions don't give you the flexibility to substitute IronRuby in the future now do they?

So first off, lets declare a delegate suitable for our purposes.

[ThereBeDragons("Only use as a last resort")]
public delegate object UntypedDelegate(params object[] parameters);


Aint she a beauty ;o) - full credit for the ThereBeDragons attribute goes to Ayende, though it's probably not really warranted in this situation - now, let's rework the last test to use a delegate instead, a simple anonymous delegate will do the dirty work:


[Test]
public void UntypedDelegateForPythonFunction()
{
Dictionary context = new Dictionary();
context.Add("user", "alex");
context.Add("age", 26);

List parameters = new List(context.Keys);
List values = new List(context.Values);

PythonEngine engine = new PythonEngine();

engine.Execute(GenerateFunction("func",parameters.ToArray(),"return user + ' is ' + str(age) + ' years old'"));

PythonFunction func1 = engine.EvaluateAs("func");

UntypedDelegate func1Delegate = delegate(object[] param)
{
return func1.Call(param);
};

object result1 = func1Delegate(values.ToArray());
Assert.AreEqual("alex is 26 years old", result1);
}



It's certainly better then passing around PythonFunction instances - though you need to be a little careful... there's a little quirk here, if we were to use:


object result1 = func1Delegate.DynamicInvoke(values.ToArray());


It's going to fail because the wrong number of arguments were supplied (it expects only 1, an array), so our delegate doesn't really behave like it has multiple parameters.. so to dynamically invoke this delegate we'd need to take special care, promoting the arguments into a second array like so:


object result1 = func1Delegate.DynamicInvoke(new object[] { values.ToArray()});


Next Time

When I get bored I'll write a version which doesn't require the clunky generator and post it up...



Next time I'll talk about writing classes which are python-friendly, riveting stuff eh? As you were.
Read More

IronPython is your friend - Part 1 - IronPython and delegates….

I felt like posting some code snippets... so I was looking around
and thought perhaps some IronPython might be interesting.... Some
of you may find this useful, possibly not.  I tend to
explore functionality using unit tests, so all my code will be
test cases - I might make this part of a small series on looking
at python code with a view to integrating it into an existing
system as a scripting engine.  Lets call the series
"IronPython is your friend"... because it really is.



Part 1 - IronPython and delegates....

So you have downloaded the IronPython runtime dll's, and you
would like to start integrating it into some project your working
on... first off lets create a python engine, and make sure it
goes....


[Test]
public void GetGoing()
{
PythonEngine engine = new PythonEngine();
engine.Execute("myString = 'hello'");
Assert.AreEqual("hello reader", engine.Evaluate("myString + ' reader'"));
}


That was pretty easy; we executed some python code to assign the
value hello to myString, and then evaluated the expression - sweet
you might say - no effort required.



Now, you could write your scripting engine so that it passed the
strings to the engine for evaluation every time you wanted to
evaluate them - but this strings malarkey isn't very pleasant...
what we really want is a decent god fearing .Net delegate, so we
can call this without having to think about the python engine....
Lets check out our first destination, method delegates.


Method Delegates

Given a converter delegate like this:



   
Converter
int,
string>



(Which by the way, if you haven't stumbled across the generic
ConverterTInput,TOutput> delegate yet,
effectively you end up with a delegate method of the
definition"TOutput Converter(TInput)" - pretty
handy actually)

 

We could do this:


[Test]
public void StatementsToStronglyTypedDelegate()
{
PythonEngine engine = new PythonEngine();
List parameters = new List(new string[] {"age"});
Converter converter =
engine.CreateMethod<>>("return str(age+1)", parameters);
Assert.AreEqual("11", converter(10));
}


Using a strongly typed overload for the engine's
CreateMethod method, we're able to evaluate statements using
our new delegate, which in turn uses our IronPython method we
created earlier... looks promising!


Events

Now delegates are cool,  but it's only half the story for
scripting in an application - depending on your model, you may be
aiming to produce results similar to a microsoft's VBA in
applications like Excel or Word - and for this we need to be able
to assign python code to events on our own classes... we can do
this using delegates of course, or we could let the python (user
code) do this itself, and save some time.... So lets have a look at
the latter:


[Test]
public void HookingToEvents()
{
PythonEngine engine = new PythonEngine();

ManualResetEvent waitHandle = new ManualResetEvent(false);
WebClient client = new WebClient();

List results = new List();

engine.Globals["client"] = client;
engine.Globals["results"] = results;

engine.Execute(
@"def storeResult(sender, e):
results.Add(e.Result)
e.UserState.Set()

# assign out storeResult function as an event handler for the client class
client.DownloadStringCompleted += storeResult
");

client.DownloadStringAsync(
new Uri(
"http://api.feedburner.com/awareness/1.0/GetFeedData?uri=http://feeds.feedburner.com/BitterCoder"),
waitHandle);

Assert.IsTrue(waitHandle.WaitOne(10000, false), "timeout occured after 10 seconds");

Assert.AreEqual(1, results.Count);

Assert.IsTrue(results[0].StartsWith("<>
}

     

This test is a bit clunky, but you get the idea... we are:
  • Creating a web client, for downloading some xml from a web
    site.
  • Set the client as a global variable for the default module in
    the python engine.
  • Execute some python, which creates a function, and assigns
    that function as a handle for the web client's
    DownloadStringCompleted event (take note at how concise the code
    is, this would be a lot uglier in C#)

  • start the async download
  • Make sure we got a response, and that the python code did
    what it should.

All in all, with a little finesse you can recreate a model
similar to VBA, driving your extension points from events - and
this certainly has some merit - obviously you want to create the
code in their own modules, as opposed to using the default module
for the python engine as we are.



We haven't quite finished with delegates yet though, I'll leave
that for part 2 - which I'll post shortly.


Read More