Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embedding IronPython, built-in help command, my CLR objects

I'm embedding IronPython (2.6.1) in a C# assembly and exposing several objects to scripts which are executed with PythonEngine.ExecuteFile. I expose them either with

scope.SetVariable("SomeObject", new SomeObject())

or

engine.Execute("from MyNamespace import SomeObject", scope)

depending on how the scripts use them. My application assembly is added to the engine with

engine.Runtime.LoadAssembly(Assembly.GetExecutingAssembly())

Now a script can execute help(SomeObject) and dump the nice little help info(*), however it's incomplete. None of the object's events or properties (public of course) show up and many of the 'built-in' members are missing as well.

Here's the odd part; If I fire up ipy.exe and execute the following:

import sys
sys.path.append('<location of my app>')
import clr
clr.AddReferenceToFile('myapp.exe')
from MyNamespace import SomeObject
help(SomeObject)

I get a different dump, complete with all the missing members!

Why do the two differ?

Bonus question: Assuming I get it working correctly, is it possible to add descriptive text on my CLR objects to the output of help()? Like you can from within the script, on your python-native types? My first guess was the DescriptionAttribute, but that didn't work.

(*) Obviously a final, working script wouldn't do this but it is exceedingly helpful while writing/testing the script.

Answered

Here is a complete console program that illustrates how to import the site which replaces the usless internal help() with the standard python library help().

using System;
using System.Collections.Generic;
using System.Reflection;
using IronPython.Hosting;
using IronPython.Runtime;
using Microsoft.Scripting.Hosting.Providers;

namespace MyApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Work around issue w/ pydoc - piping to more doesn't work so instead indicate that we're a dumb terminal
            if (Environment.GetEnvironmentVariable("TERM") == null)
                Environment.SetEnvironmentVariable("TERM", "dumb");

            var engine = Python.CreateEngine();

            // Add standard Python library path (is there a better way to do this??)
            PythonContext context = HostingHelpers.GetLanguageContext(engine) as PythonContext;
            ICollection<string> paths = context.GetSearchPaths();
            paths.Add(@"C:\Program Files (x86)\IronPython 2.6\Lib");
            context.SetSearchPaths(paths);

            // Import site module
            engine.ImportModule("site");

            engine.Runtime.LoadAssembly(Assembly.GetEntryAssembly());

            var scope = engine.CreateScope();
            scope.SetVariable("SomeObject", new SomeObject());
            engine.Execute("help(SomeObject)", scope);
        }
    }

    /// <summary>
    /// Description of SomeObject.
    /// </summary>
    public class SomeObject
    {
        /// <summary>
        /// Description of SomeProperty.
        /// </summary>
        public int SomeProperty { get; set; }
        /// <summary>
        /// Description of SomeMethod.
        /// </summary>
        public void SomeMethod() { }
        /// <summary>
        /// Description of SomeEvent.
        /// </summary>
        public event EventHandler SomeEvent;
    }
}
like image 444
Tergiver Avatar asked Jan 08 '11 19:01

Tergiver


People also ask

How IronPython works?

IronPython works as an extension to the . NET Framework, but it can also be used by . NET projects to take advantage of Python's scripting power. Other than that, since IronPython is a real implementation of Python itself, there's no need to learn a new language or extra features if you already know Python.

How do I import modules into IronPython?

If you have installed IronPython from NuGet packages and you want modules from the CPython Standard Library then the best way to do it is by installing the IronPython. StdLib NuGet package which is from the same authors of IronPython .

What is import CLR in Python?

Project descriptionNET Common Language Runtime (CLR) and provides a powerful application scripting tool for . NET developers. It allows Python code to interact with the CLR, and may also be used to embed Python into a . NET application.


1 Answers

My guess is that in your app you're not importing the standard library. IronPython includes a built-in help function and the standard library includes a help function which gets installed by site.py. If you make sure the standard library is available when you host and then import site.py when you create the engine then you should get the standard library help. That being said it's probably a bug or missing feature that the built-in help isn't documenting events and properties.

Regarding the documentation - yes, you just need to use C#'s doc comments and build with the /doc:MyAssemblyName.xml option. If the XML file is in the same directory as the assembly IronPython will read the doc strings and provide them for doc attributes which help() then reads.

like image 183
Dino Viehland Avatar answered Oct 19 '22 16:10

Dino Viehland