[IronPython] New clr.ImportExtensions (LINQ) Syntax

Dave Wald davew252 at tx.rr.com
Sat Apr 9 05:04:37 CEST 2011


Hi all - I've been experimenting with with the new extension method 
import facility and so far it is working well, more or less as I 
expected, except that I'm getting an error message when I try to chain 
Linq method calls. I don't know whether this should be considered a bug 
or not. It seems the dynamic code cannot pass the intermediate 
enumerable (iterator/generator?) object between method calls. I have to 
wrap it in a list(...) call for it to work. And I would have thought 
.ToList() would work, but it blows too.
I don't know enough about the internals to judge whether it's even 
possible for the DLR to do this. The exception seems to be coming from 
DLR code.
Would be nice if the chained syntax could be made to work, tho. But even 
as it is, it still allows much cleaner code style than my homebrew 
module did.
Ideas? Enlightenment?

Thanks

Here's the code:

import clr
clr.AddReference("System.Core")
import System
from System import Linq

clr.ImportExtensions(Linq)

class Product(object):
     def __init__(self, cat, id, qtyOnHand ):
         self.Cat = cat
         self.ID = id
         self.QtyOnHand = qtyOnHand
         self.Q = self.QtyOnHand

def runit():
     products = [Product(prod[0], prod[1], prod[2]) for prod in
         ('DrillRod', 'DR123', 45), ('Flange', 'F423', 12), ('Gizmo', 
'G9872', 214), ('Sprocket', 'S534', 42)]

     # pd = products.Where(lambda prod: prod.Q < 40).Select(lambda prod: 
(prod.Cat, prod.ID) )
     # blows: "Type System.Collections.Generic.IEnumerable`1[TSource] 
contains generic parameters"

     # pd = products.Where(lambda prod: prod.Q < 
40).AsEnumerable().Select(lambda prod: (prod.Cat, prod.ID) )
     #blows, same exception

     pd = products.Where(lambda prod: prod.Q < 40)               #ok
     for prod in pd: print prod.Cat, prod.ID, prod.Q                     
#==> Flange F423 12

     # pd2 = pd.Select(lambda prod: (prod.Cat, prod.ID) )        #blows, 
same exception - note source (pd) is not a list at this point - it's a 
...+WhereEnumerator... object

     pd2 = products.Select(lambda prod: (prod.Cat, prod.ID) )    #ok
     for prod in pd2: print "Cat: {0}, ID: {1}".format(prod[0], prod[1]) 
         #==> Cat: DrillRod, ID: DR123 ...

     pd2 = list(pd).Select(lambda prod: (prod.Cat, prod.ID) )    #ok    
             Wrapping it in a list
     for prod in pd2: print "Cat: {0}, ID: {1}".format(prod[0], prod[1]) 
         #==> Cat: Flange, ID: F423

     # pd = products.Where(lambda prod: prod.Q < 30).ToList()    #blows, 
same exception

     pd = list( products.Where(lambda prod: prod.Q < 30) )       #ok
     for prod in pd2: print "Cat: {0}, ID: {1}".format(prod[0], 
prod[1])         #==> Cat: Flange, ID: F423

     # ok
     pd = list( products.Where(lambda prod: prod.Q < 40) ).Select(lambda 
prod: "Cat: {0}, ID: {1}, Qty: {2}".format(prod.Cat, prod.ID, prod.Q))
     for prod in pd: print prod      #==> Cat: Flange, ID: F423, Qty: 12

     # ok
     pd = ( list(products.Where(lambda prod: prod.Q < 40))
             .Select(lambda prod: "Cat: {0}, ID: {1}, Qty: 
{2}".format(prod.Cat, prod.ID, prod.Q)) )
     for prod in pd: print prod      #==> Cat: Flange, ID: F423, Qty: 12

if __name__ == "__main__":
     runit()
-------------------------------------------------------------------------------------------------------------------------

Here's the barf:

System.ArgumentException was unhandled by user code
   Message=Type System.Collections.Generic.IEnumerable`1[TSource] 
contains generic parameters
   Source=System.Core
   StackTrace:
        at System.Dynamic.Utils.TypeUtils.ValidateType(Type type)
        at System.Linq.Expressions.Expression.Convert(Expression 
expression, Type type, MethodInfo method)
        at Microsoft.Scripting.Ast.Utils.Convert(Expression expression, 
Type type)
        at 
IronPython.Runtime.Binding.MetaBuiltinFunction.GetInstance(Expression 
instance, Type testType)
        at 
IronPython.Runtime.Binding.MetaBuiltinFunction.MakeSelfCall(DynamicMetaObjectBinder 
call, Expression codeContext, DynamicMetaObject[] args)
        at 
IronPython.Runtime.Binding.MetaBuiltinFunction.InvokeWorker(DynamicMetaObjectBinder 
call, Expression codeContext, DynamicMetaObject[] args)
        at 
IronPython.Runtime.Binding.MetaBuiltinFunction.Invoke(PythonInvokeBinder 
pythonInvoke, Expression codeContext, DynamicMetaObject target, 
DynamicMetaObject[] args)
        at 
IronPython.Runtime.Binding.PythonInvokeBinder.BindWorker(DynamicMetaObject 
context, DynamicMetaObject target, DynamicMetaObject[] args)
        at 
IronPython.Runtime.Binding.PythonInvokeBinder.Bind(DynamicMetaObject 
target, DynamicMetaObject[] args)
        at 
Microsoft.Scripting.Utils.DynamicUtils.GenericInterpretedBinder`1.Bind(DynamicMetaObjectBinder 
binder, Int32 compilationThreshold, Object[] args)
        at 
Microsoft.Scripting.Utils.DynamicUtils.LightBind[T](DynamicMetaObjectBinder 
binder, Object[] args, Int32 compilationThreshold)
        at 
IronPython.Runtime.Types.BuiltinFunction.IronPython.Runtime.Binding.IFastInvokable.MakeInvokeBinding[T](CallSite`1 
site, PythonInvokeBinder binder, CodeContext state, Object[] args)
        at 
IronPython.Runtime.Binding.PythonInvokeBinder.BindDelegate[T](CallSite`1 
site, Object[] args)
        at 
System.Runtime.CompilerServices.CallSiteBinder.BindCore[T](CallSite`1 
site, Object[] args)
        at 
System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite 
site, T0 arg0, T1 arg1, T2 arg2)
        at Test_CLR_ImportExtensions$2.runit$80(PythonFunction 
$function) in 
C:\IPy27_Projects\IPy_LINQ1\IPy_LINQ1\Test_CLR_ImportExtensions.py:line 131
        at 
IronPython.Runtime.PythonFunction.FunctionCaller.Call0(CallSite site, 
CodeContext context, Object func)
        at 
System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite 
site, T0 arg0, T1 arg1)
        at __main__$1.__main__(FunctionCode $functionCode) in 
C:\IPy27_Projects\IPy_LINQ1\IPy_LINQ1\Main.py:line 21
        at IronPython.Compiler.RuntimeScriptCode.InvokeTarget(Scope scope)
        at IronPython.Compiler.RuntimeScriptCode.Run(Scope scope)
        at IronPython.Hosting.PythonCommandLine.RunFileWorker(String 
fileName)
        at IronPython.Hosting.PythonCommandLine.RunFile(String fileName)
   InnerException:  (nothing after this)






-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/ironpython-users/attachments/20110408/2a53f9b2/attachment.html>


More information about the Ironpython-users mailing list