[Ironpython-users] instropection in an embedded engine

Hernán Foffani hfoffani at gmail.com
Tue Sep 27 19:50:13 CEST 2011


El 27/09/2011, a las 16:54, Keith Rome escribió:

> Just beware that if you use this same mechanism to introspect CLR objects, it can return member names for static and protected members in addition to the public instance members (and attempts to access those members might fail). To work around this, I first use reflection to get a list of static or protected CLR members and then exclude those member names from the list returned by Operations.GetMemberNames(). For Python objects, this doesn't seem to cause any complications, since reflection does not know anything about the dynamic members.

My use case is pure Python objects, and right now a couple of C# lines solved it.

> 
> Doing it that way allows the same code to operate correctly in a heterogeneous environment, where some objects might originate from a dynamic scope while others originate from a static managed scope.

Interesting. I might use it in case our users decided to extend our application by using IP and pure .NET dlls.
So far nobody did that, but who knows....

Thanks again,
-Hernán.

> 
> Example (I am sure there are ways to tighten this up, but it gets the job done):
> 
> IEnumerable<string> GetMemberNames(dynamic obj)
> {
>    // use reflection first so we can exclude anything that will just fail under the dynamic context
>    var objType = ((object)obj).GetType();
>    var staticMembers = objType.GetMembers(BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
>    var privateMembers = objType.GetMembers(BindingFlags.Instance | BindingFlags.NonPublic);
>    var excludedMembers = staticMembers.Union(privateMembers).Select(member => member.Name).OrderBy(name => name).Distinct();
> 
>    var langContext = HostingHelpers.GetLanguageContext(_scriptService.GetScriptEngine());
>    try
>    {
>        IList<string> members;
> 
>        try
>        {
>            members = langContext.Operations.GetMemberNames(obj);
>        }
>        catch (AmbiguousMatchException)
>        {
>            members = langContext.Operations.GetMemberNames((object)obj);
>        }
> 
>        members = members.Except(excludedMembers).ToList();
> 
>        // ... I do some more work here to filter out members that start with underbar
>        // character or that resolve to types that don't make sense for my purposes (events, etc)
> 
>        return members;
>    }
>    catch (Exception)
>    {
>        return new string[] { };
>    }
> }
> 
> 
> Keith Rome
> Senior Consultant and Architect
> MCPD-EAD, MCSD, MCDBA, MCTS-WPF, MCTS-TFS, MCTS-WSS
> Wintellect | 770.617.4016 | krome at wintellect.com
> www.wintellect.com
> 
> 
> -----Original Message-----
> From: ironpython-users-bounces+rome=wintellect.com at python.org [mailto:ironpython-users-bounces+rome=wintellect.com at python.org] On Behalf Of Hernán Foffani
> Sent: Tuesday, September 27, 2011 6:43 AM
> Cc: ironpython-users at python.org
> Subject: Re: [Ironpython-users] instropection in an embedded engine
> 
> You are right. It was the all the Operations thing what I was missing altogether, silly me.
> Now it all make sense.
> Thanks a lot.
> 
> El 26/09/2011, a las 19:57, Keith Rome escribió:
> 
>> If you are just trying to enumerate members of a python object, and possibly invoke them, then wouldn't a LanguageContext's DynamicOperations get the job done? Perhaps I am misunderstanding your objectives though.
>> 
>> HostingHelpers.GetLanguageContext(ScriptEngine) to get the LanguageContext, and then just use the Operations property from that. This gives you introspection methods for GetMemberNames() and a number of invocation mechanisms. All you need is a reference to an object to inspect and the language engine that owns it (or one that is compatible with it).
>> 
>> In my implementation of a Watches/Locals/Modules UI for a python debugger, I use that procedure as the basis for routines that populate the inspector grids. Basically, whenever the user reaches a breakpoint via my settrace() hook, I inspect the members of all variables in the current scope and refresh a visual tree (really a grid with indentation), and as they drill down into those objects I just walk down one step further into the data structure. It isn't the fastest thing in the world, but then again it doesn't have to be - the script is effectively paused until I allow the breakpoint to resume.
>> 
>> 
>> Keith Rome
>> Senior Consultant and Architect
>> MCPD-EAD, MCSD, MCDBA, MCTS-WPF, MCTS-TFS, MCTS-WSS Wintellect | 
>> 770.617.4016 | krome at wintellect.com www.wintellect.com
>> 
>> 
>> -----Original Message-----
>> From: ironpython-users-bounces+rome=wintellect.com at python.org 
>> [mailto:ironpython-users-bounces+rome=wintellect.com at python.org] On 
>> Behalf Of Hernán Foffani
>> Sent: Monday, September 26, 2011 1:36 PM
>> To: ironpython-users at python.org
>> Subject: Re: [Ironpython-users] instropection in an embedded engine
>> 
>> Thanks, I'm getting closer.
>> Now I'm trying to find how to get a (new? current?) CodeContext to, for instance, call DictProxy.keys(..) The public constructor of CodeContext signature (a PythonDictionary and a ModuleContext) doesn't match the examples I could find (ScriptScope, LanguageContext).
>> 
>> Does anyone know of any examples of introspection of a hosted IP scripting from C#?
>> Evidently there's a lot I'm missing here and would like to do the due homework first.
>> 
>> I'm using NET 4 and don't need 2.x compatibility.
>> 
>> Regards,
>> -Hernán
>> 
>> El 23/09/2011, a las 21:43, Dino Viehland escribió:
>> 
>>> __class__ exists on object in python and is then inherited by the 
>>> other types.  When accessing a member from C# you get its view of the world which doesn't include Python object members.  To get the Python type I suggest calling DynamicHelpers.GetPythonType.
>>> 
>>> Sent from my Windows Phone
>>> 
>>> -----Original Message-----
>>> From: Hernán Foffani
>>> Sent: Friday, September 23, 2011 9:12 AM
>>> To: ironpython-users at python.org
>>> Subject: [Ironpython-users] instropection in an embedded engine
>>> 
>>> 
>>> Having the following Python code:
>>> 
>>>  class Plugin:
>>>    def method(self):
>>>      pass
>>>  plugin = Plugin()
>>> 
>>> and an embedded ScriptScope instance in my .NET application, the 
>>> following C# works fine
>>> 
>>> dynamic plugin = pythonEngine.GetVariable("plugin");
>>> var attrs = plugin.__class__.__dict__;
>>> 
>>> if Plugin python class was defined as an old-style class, but fails 
>>> if Plugin inherits from object (__class__ non existent).
>>> 
>>> Under the VS debugger the dynamic object plugin shows as having three 
>>> attributes .class, .dict and .slots_and_weakref (with dots in their
>>> names) but no __class__ or __dict__.
>>> 
>>> I found that I could do something like 
>>> plugin.method.im_class.__dict__ but I'd rather stick with the common idiom.
>>> 
>>> Is it a known issue? Something related to the way I'm using the engine?
>>> 
>>> Thanks in advance,
>>> -Hernán.
>>> 
>>> _______________________________________________
>>> Ironpython-users mailing list
>>> Ironpython-users at python.org
>>> http://mail.python.org/mailman/listinfo/ironpython-users
>>> 
>> 
>> _______________________________________________
>> Ironpython-users mailing list
>> Ironpython-users at python.org
>> http://mail.python.org/mailman/listinfo/ironpython-users
>> 
>> 
> 
> _______________________________________________
> Ironpython-users mailing list
> Ironpython-users at python.org
> http://mail.python.org/mailman/listinfo/ironpython-users
> 
> 



More information about the Ironpython-users mailing list