Skip to content

How to support IronPython 2.7 and 3.4 in one app? #1798

Closed

Description

@andyste1

We have a large desktop application that uses v2.7. It's a scientific data processing app that allows users to write their own .py scripts (as well as many "system" scripts) which the app can execute and interact with, and is in use at many customer sites.

We'd like to start using v3.4 but it's vital that the app can still run all those v2.7 scripts that are out there at customer sites. I'll therefore need to reference both versions of IronPython, and (somehow) use either the 2.7 or 3.4 script engine etc, depending on which version of the script it is.
The main issue I see is that the assembly DLLs have the same name in both versions (and I'm guessing the types will also have the same names), so does anyone have a suggestion as to how I can reference/use both versions of IronPython in the same app? Releasing a new version of our app that only support v3.4, and leaving existing customers on the older version with 2.7 isn't an option.

Activity

  1. slozier commented on May 3, 2024

    @slozier
    Contributor

    I store the IronPython specific assemblies in separate (IronPython2/IronPython3) folders. I have an assembly resolver which is used to load the appropriate assemblies from their respective folders. Then, using a common DLR I create engines for each. Something like this:

    public sealed class PythonEngine
    {
        static PythonEngine()
        {
            AppDomain.CurrentDomain.AssemblyResolve += IronPythonResolver;
        }
    
        private static readonly Version Ipy2Version = new Version(2, 7, 12, 0);
        private static readonly Version Ipy3Version = new Version(3, 4, 1, 0);
    
        private static LanguageSetup GetLanguageSetup(int version)
        {
            if (version == 3)
            {
                return new LanguageSetup(
                    $"IronPython.Runtime.PythonContext, IronPython, Version={Ipy3Version}, Culture=neutral, PublicKeyToken=7f709c5b713576e1",
                    "IronPython 3",
                    new[] { "IronPython3" },
                    new[] { ".py" }
                );
            }
            else
            {
                return new LanguageSetup(
                    $"IronPython.Runtime.PythonContext, IronPython, Version={Ipy2Version}, Culture=neutral, PublicKeyToken=7f709c5b713576e1",
                    "IronPython 2",
                    new[] { "IronPython2" },
                    new[] { ".py" }
                );
            }
        }
    
        public static ScriptEngine Create(int version, IDictionary<string, object?>? options = null)
        {
            ScriptRuntimeSetup setup = new ScriptRuntimeSetup();
    
            var languageSetup = GetLanguageSetup(version);
    
            if (options != null)
            {
                foreach (var entry in options)
                {
                    setup.Options.Add(entry.Key, entry.Value);
                }
            }
    
            setup.LanguageSetups.Add(languageSetup);
            var runtime = new ScriptRuntime(setup);
            return runtime.GetEngine(languageSetup.Names[0]);
        }
    
        private static Assembly? IronPythonResolver(object? sender, ResolveEventArgs args)
        {
            if (args.Name is null) return null;
            var assemblyName = new AssemblyName(args.Name);
    
            if (assemblyName.Name != null && assemblyName.Version != null && (assemblyName.Name.StartsWith("Microsoft.Scripting", StringComparison.Ordinal) || assemblyName.Name == "Microsoft.Dynamic"))
            {
                var path = Path.Combine(Application.ProgramPath, assemblyName.Name + ".dll");
                return File.Exists(path) ? Assembly.LoadFile(path) : null;
            }
    
            if (assemblyName.Name != null && assemblyName.Version != null && assemblyName.Name.StartsWith("IronPython", StringComparison.Ordinal))
            {
                var path = Path.Combine(Application.ProgramPath, assemblyName.Version.Major == 3 ? "IronPython3" : "IronPython2", assemblyName.Name + ".dll");
                return File.Exists(path) ? Assembly.LoadFile(path) : null;
            }
    
            return null;
        }
    }
  2. locked and limited conversation to collaborators on May 3, 2024
  3. converted this issue into a discussion #1799 on May 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions