private IPythonInterpreterFactory CreateFactory(PythonInterpreterInformation info)
 {
     return(InterpreterFactoryCreator.CreateInterpreterFactory(
                info.Configuration,
                new InterpreterFactoryCreationOptions {
         WatchFileSystem = true,
     }
                ));
 }
예제 #2
0
 protected override void CreateFactory()
 {
     _factory = InterpreterFactoryCreator.CreateInterpreterFactory(
         Config,
         new InterpreterFactoryCreationOptions {
         WatchFileSystem = true,
     }
         );
 }
 private IPythonInterpreterFactory CreateFactory(PythonInterpreterInformation info)
 {
     return(InterpreterFactoryCreator.CreateInterpreterFactory(
                info.Configuration,
                new InterpreterFactoryCreationOptions {
         PackageManager = BuiltInPackageManagers.Conda,
         WatchFileSystem = true,
         NoDatabase = ExperimentalOptions.NoDatabaseFactory,
         DatabasePath = ExperimentalOptions.NoDatabaseFactory ?
                        DatabasePathSelector.CalculateVSLocalDatabasePath(_site, info.Configuration, 1) :
                        DatabasePathSelector.CalculateGlobalDatabasePath(info.Configuration, PythonTypeDatabase.FormatVersion)
     }
                ));
 }
예제 #4
0
            protected override void CreateFactory()
            {
                var dbPath = PathUtils.GetAbsoluteDirectoryPath(
                    Config.PrefixPath,
                    ".ptvs"
                    );

                _factory = InterpreterFactoryCreator.CreateInterpreterFactory(
                    Config,
                    new InterpreterFactoryCreationOptions {
                    PackageManager = new PipPackageManager(),
                    DatabasePath   = dbPath
                }
                    );
            }
            protected override void CreateFactory()
            {
                var dbPath = PathUtils.GetAbsoluteDirectoryPath(
                    Config.PrefixPath,
                    ".ptvs"
                    );

                _factory = InterpreterFactoryCreator.CreateInterpreterFactory(
                    Config,
                    new InterpreterFactoryCreationOptions {
                    PackageManager  = new PipPackageManager(),
                    DatabasePath    = dbPath,
                    WatchFileSystem = true,
                    NoDatabase      = PythonInterpreterInformation._experimentalFactory.Value
                }
                    );
            }
예제 #6
0
 public IPythonInterpreterFactory EnsureFactory()
 {
     if (Factory == null)
     {
         lock (this) {
             if (Factory == null)
             {
                 Factory = InterpreterFactoryCreator.CreateInterpreterFactory(
                     Configuration,
                     new InterpreterFactoryCreationOptions()
                 {
                     WatchLibraryForNewModules = true
                 }
                     );
             }
         }
     }
     return(Factory);
 }
            protected override void CreateFactory()
            {
                var dbPath = PathUtils.GetAbsoluteDirectoryPath(
                    Config.PrefixPath,
                    ".ptvs"
                    );

                _factory = InterpreterFactoryCreator.CreateInterpreterFactory(
                    Config,
                    new InterpreterFactoryCreationOptions {
                    PackageManager  = new PipPackageManager(),
                    WatchFileSystem = true,
                    NoDatabase      = ExperimentalOptions.NoDatabaseFactory,
                    DatabasePath    = ExperimentalOptions.NoDatabaseFactory ?
                                      DatabasePathSelector.CalculateProjectLocalDatabasePath(_factoryProvider._site, Config, 1) :
                                      DatabasePathSelector.CalculateProjectLocalDatabasePath(_factoryProvider._site, Config, 0)
                }
                    );
            }
예제 #8
0
 public IPythonInterpreterFactory EnsureFactory()
 {
     if (Factory == null)
     {
         lock (this) {
             if (Factory == null)
             {
                 Factory = InterpreterFactoryCreator.CreateInterpreterFactory(
                     Configuration,
                     new InterpreterFactoryCreationOptions {
                     PackageManager  = new PipPackageManager(),
                     WatchFileSystem = true,
                     NoDatabase      = _experimentalFactory.Value
                 }
                     );
             }
         }
     }
     return(Factory);
 }
        private PythonInterpreterFactoryWithDatabase LoadUserDefinedInterpreter(SettingsStore store, string guid)
        {
            // PythonInterpreters\
            //      Id\
            //          Description
            //          InterpreterPath
            //          WindowsInterpreterPath
            //          Architecture
            //          Version
            //          PathEnvironmentVariable

            Guid   id;
            string collection;

            if (Guid.TryParse(guid, out id) && store.CollectionExists((collection = PythonInterpreterKey + "\\" + id.ToString("B"))))
            {
                var path        = store.GetString(collection, PathKey, string.Empty);
                var winPath     = store.GetString(collection, WindowsPathKey, string.Empty);
                var libPath     = store.GetString(collection, LibraryPathKey, string.Empty);
                var arch        = store.GetString(collection, ArchitectureKey, string.Empty);
                var version     = store.GetString(collection, VersionKey, string.Empty);
                var pathEnvVar  = store.GetString(collection, PathEnvVarKey, string.Empty);
                var description = store.GetString(collection, DescriptionKey, string.Empty);

                return(InterpreterFactoryCreator.CreateInterpreterFactory(
                           new InterpreterFactoryCreationOptions {
                    LanguageVersionString = version,
                    Id = id,
                    Description = description,
                    InterpreterPath = path,
                    WindowInterpreterPath = winPath,
                    LibraryPath = libPath,
                    PathEnvironmentVariableName = pathEnvVar,
                    ArchitectureString = arch,
                    WatchLibraryForNewModules = true
                }
                           ));
            }
            return(null);
        }
예제 #10
0
 protected override void CreateFactory()
 {
     if (!ExperimentalOptions.NoDatabaseFactory)
     {
         _factory = new LegacyDB.CPythonInterpreterFactory(
             Config,
             new InterpreterFactoryCreationOptions {
             WatchFileSystem = true,
             DatabasePath    = DatabasePathSelector.CalculateProjectLocalDatabasePath(_factoryProvider._site, Config, 0)
         }
             );
     }
     else
     {
         _factory = InterpreterFactoryCreator.CreateInterpreterFactory(
             Config,
             new InterpreterFactoryCreationOptions {
             WatchFileSystem = true,
             DatabasePath    = DatabasePathSelector.CalculateProjectLocalDatabasePath(_factoryProvider._site, Config, 1)
         }
             );
     }
 }
        private IPythonInterpreterFactory CreateFactory(PythonInterpreterInformation info)
        {
            if (!ExperimentalOptions.NoDatabaseFactory)
            {
                // Use the database-backed factory
                var fact = new LegacyDB.CPythonInterpreterFactory(
                    info.Configuration,
                    new InterpreterFactoryCreationOptions {
                    WatchFileSystem = true,
                    DatabasePath    = DatabasePathSelector.CalculateGlobalDatabasePath(info.Configuration, LegacyDB.PythonTypeDatabase.FormatVersion)
                }
                    );
                fact.BeginRefreshIsCurrent();
                return(fact);
            }

            return(InterpreterFactoryCreator.CreateInterpreterFactory(
                       info.Configuration,
                       new InterpreterFactoryCreationOptions {
                WatchFileSystem = true,
                DatabasePath = DatabasePathSelector.CalculateVSLocalDatabasePath(_site, info.Configuration, 1)
            }
                       ));
        }
        private bool RegisterInterpreters(HashSet <string> registeredPaths, RegistryKey python, ProcessorArchitecture?arch)
        {
            bool anyAdded = false;

            string[] subKeyNames = null;
            for (int retries = 5; subKeyNames == null && retries > 0; --retries)
            {
                try {
                    subKeyNames = python.GetSubKeyNames();
                } catch (IOException) {
                    // Registry changed while enumerating subkeys. Give it a
                    // short period to settle down and try again.
                    // We are almost certainly being called from a background
                    // thread, so sleeping here is fine.
                    Thread.Sleep(100);
                }
            }
            if (subKeyNames == null)
            {
                return(false);
            }

            foreach (var key in subKeyNames)
            {
                Version version;
                ProcessorArchitecture?arch2;
                if (TryParsePythonVersion(key, out version, out arch2))
                {
                    if (version.Major == 2 && version.Minor <= 4)
                    {
                        // 2.4 and below not supported.
                        continue;
                    }

                    var installPath = python.OpenSubKey(key + "\\InstallPath");
                    if (installPath != null)
                    {
                        var basePathObj = installPath.GetValue("");
                        if (basePathObj == null)
                        {
                            // http://pytools.codeplex.com/discussions/301384
                            // messed up install, we don't know where it lives, we can't use it.
                            continue;
                        }
                        string basePath = basePathObj.ToString();
                        if (!PathUtils.IsValidPath(basePath))
                        {
                            // Invalid path in registry
                            continue;
                        }
                        if (!registeredPaths.Add(basePath))
                        {
                            // registered in both HCKU and HKLM
                            continue;
                        }

                        var actualArch = arch ?? arch2;
                        if (!actualArch.HasValue)
                        {
                            actualArch = NativeMethods.GetBinaryType(Path.Combine(basePath, CPythonInterpreterFactoryConstants.ConsoleExecutable));
                        }

                        var id          = CPythonInterpreterFactoryConstants.Guid32;
                        var description = CPythonInterpreterFactoryConstants.Description32;
                        if (actualArch == ProcessorArchitecture.Amd64)
                        {
                            id          = CPythonInterpreterFactoryConstants.Guid64;
                            description = CPythonInterpreterFactoryConstants.Description64;
                        }

                        if (!_interpreters.Any(f => f.Id == id && f.Configuration.Version == version))
                        {
                            IPythonInterpreterFactory fact;
                            try {
                                fact = InterpreterFactoryCreator.CreateInterpreterFactory(
                                    new InterpreterFactoryCreationOptions {
                                    LanguageVersion = version,
                                    Id                          = id,
                                    Description                 = string.Format("{0} {1}", description, version),
                                    InterpreterPath             = Path.Combine(basePath, CPythonInterpreterFactoryConstants.ConsoleExecutable),
                                    WindowInterpreterPath       = Path.Combine(basePath, CPythonInterpreterFactoryConstants.WindowsExecutable),
                                    LibraryPath                 = Path.Combine(basePath, CPythonInterpreterFactoryConstants.LibrarySubPath),
                                    PathEnvironmentVariableName = CPythonInterpreterFactoryConstants.PathEnvironmentVariableName,
                                    Architecture                = actualArch ?? ProcessorArchitecture.None,
                                    WatchLibraryForNewModules   = true
                                }
                                    );
                            } catch (ArgumentException) {
                                continue;
                            }

                            _interpreters.Add(fact);
                            anyAdded = true;
                        }
                    }
                }
            }

            return(anyAdded);
        }
예제 #13
0
 internal static PythonTypeDatabase CreateDefaultTypeDatabase(Version languageVersion)
 {
     return(new PythonTypeDatabase(InterpreterFactoryCreator.CreateAnalysisInterpreterFactory(languageVersion),
                                   BaselineDatabasePath, isDefaultDatabase: true));
 }
예제 #14
0
        private bool RegisterInterpreters(HashSet <string> registeredPaths, RegistryKey python, ProcessorArchitecture?arch)
        {
            bool anyAdded = false;

            foreach (var key in python.GetSubKeyNames())
            {
                Version version;
                ProcessorArchitecture?arch2;
                if (TryParsePythonVersion(key, out version, out arch2))
                {
                    if (version.Major == 2 && version.Minor <= 4)
                    {
                        // 2.4 and below not supported.
                        continue;
                    }

                    var installPath = python.OpenSubKey(key + "\\InstallPath");
                    if (installPath != null)
                    {
                        var basePathObj = installPath.GetValue("");
                        if (basePathObj == null)
                        {
                            // http://pytools.codeplex.com/discussions/301384
                            // messed up install, we don't know where it lives, we can't use it.
                            continue;
                        }
                        string basePath = basePathObj.ToString();
                        if (!CommonUtils.IsValidPath(basePath))
                        {
                            // Invalid path in registry
                            continue;
                        }
                        if (!registeredPaths.Add(basePath))
                        {
                            // registered in both HCKU and HKLM
                            continue;
                        }

                        var actualArch = arch ?? arch2;
                        if (!actualArch.HasValue)
                        {
                            actualArch = NativeMethods.GetBinaryType(Path.Combine(basePath, CPythonInterpreterFactoryConstants.ConsoleExecutable));
                        }

                        var id          = CPythonInterpreterFactoryConstants.Guid32;
                        var description = CPythonInterpreterFactoryConstants.Description32;
                        if (actualArch == ProcessorArchitecture.Amd64)
                        {
                            id          = CPythonInterpreterFactoryConstants.Guid64;
                            description = CPythonInterpreterFactoryConstants.Description64;
                        }

                        if (!_interpreters.Any(f => f.Id == id && f.Configuration.Version == version))
                        {
                            _interpreters.Add(InterpreterFactoryCreator.CreateInterpreterFactory(
                                                  new InterpreterFactoryCreationOptions {
                                LanguageVersion = version,
                                Id                          = id,
                                Description                 = string.Format("{0} {1}", description, version),
                                InterpreterPath             = Path.Combine(basePath, CPythonInterpreterFactoryConstants.ConsoleExecutable),
                                WindowInterpreterPath       = Path.Combine(basePath, CPythonInterpreterFactoryConstants.WindowsExecutable),
                                LibraryPath                 = Path.Combine(basePath, CPythonInterpreterFactoryConstants.LibrarySubPath),
                                PathEnvironmentVariableName = CPythonInterpreterFactoryConstants.PathEnvironmentVariableName,
                                Architecture                = actualArch ?? ProcessorArchitecture.None,
                                WatchLibraryForNewModules   = true
                            }
                                                  ));
                            anyAdded = true;
                        }
                    }
                }
            }

            return(anyAdded);
        }
예제 #15
0
        /// <summary>
        /// Call to find interpreters in the associated project. Separated from
        /// the constructor to allow exceptions to be handled without causing
        /// the project node to be invalid.
        /// </summary>
        /// <exception cref="InvalidDataException">
        /// One or more interpreters failed to load. The error message should be
        /// presented to the user, but can otherwise be ignored.
        /// </exception>
        public void DiscoverInterpreters()
        {
            // <Interpreter Include="InterpreterDirectory">
            //   <Id>guid</Id>
            //   <BaseInterpreter>guid</BaseInterpreter>
            //   <Version>...</Version>
            //   <InterpreterPath>...</InterpreterPath>
            //   <WindowsInterpreterPath>...</WindowsInterpreterPath>
            //   <LibraryPath>...</LibraryPath>
            //   <PathEnvironmentVariable>...</PathEnvironmentVariable>
            //   <Description>...</Description>
            // </Interpreter>

            var errors = new StringBuilder();

            errors.AppendLine("Some project interpreters failed to load:");
            bool anyChange = false, anyError = false;

            var projectHome = CommonUtils.GetAbsoluteDirectoryPath(_project.DirectoryPath, _project.GetPropertyValue("ProjectHome"));
            var factories   = new Dictionary <IPythonInterpreterFactory, FactoryInfo>();

            foreach (var item in _project.GetItems(InterpreterItem))
            {
                IPythonInterpreterFactory fact;
                Guid id, baseId;

                // Errors in these options are fatal, so we set anyError and
                // continue with the next entry.
                var dir = item.EvaluatedInclude;
                if (!CommonUtils.IsValidPath(dir))
                {
                    errors.AppendLine(string.Format("Interpreter has invalid path: {0}", dir ?? "(null)"));
                    anyError = true;
                    continue;
                }
                dir = CommonUtils.GetAbsoluteDirectoryPath(projectHome, dir);

                var value = item.GetMetadataValue(IdKey);
                if (string.IsNullOrEmpty(value) || !Guid.TryParse(value, out id))
                {
                    errors.AppendLine(string.Format("Interpreter {0} has invalid value for '{1}': {2}", dir, IdKey, value));
                    anyError = true;
                    continue;
                }
                if (factories.Keys.Any(f => f.Id == id))
                {
                    errors.AppendLine(string.Format("Interpreter {0} has a non-unique id: {1}", dir, id));
                    continue;
                }

                var     verStr = item.GetMetadataValue(VersionKey);
                Version ver;
                if (string.IsNullOrEmpty(verStr) || !Version.TryParse(verStr, out ver))
                {
                    errors.AppendLine(string.Format("Interpreter {0} has invalid value for '{1}': {2}", dir, VersionKey, verStr));
                    anyError = true;
                    continue;
                }

                // The rest of the options are non-fatal. We create an instance
                // of NotFoundError with an amended description, which will
                // allow the user to remove the entry from the project file
                // later.
                bool hasError = false;

                var description = item.GetMetadataValue(DescriptionKey);
                if (string.IsNullOrEmpty(description))
                {
                    description = CommonUtils.CreateFriendlyDirectoryPath(projectHome, dir);
                }

                value = item.GetMetadataValue(BaseInterpreterKey);
                PythonInterpreterFactoryWithDatabase baseInterp = null;
                if (!string.IsNullOrEmpty(value) && Guid.TryParse(value, out baseId))
                {
                    // It's a valid GUID, so find a suitable base. If we
                    // don't find one now, we'll try and figure it out from
                    // the pyvenv.cfg/orig-prefix.txt files later.
                    // Using an empty GUID will always go straight to the
                    // later lookup.
                    if (baseId != Guid.Empty)
                    {
                        baseInterp = _service.FindInterpreter(baseId, ver) as PythonInterpreterFactoryWithDatabase;
                    }
                }

                var path = item.GetMetadataValue(InterpreterPathKey);
                if (!CommonUtils.IsValidPath(path))
                {
                    errors.AppendLine(string.Format("Interpreter {0} has invalid value for '{1}': {2}", dir, InterpreterPathKey, path));
                    hasError = true;
                }
                else if (!hasError)
                {
                    path = CommonUtils.GetAbsoluteFilePath(dir, path);
                }

                var winPath = item.GetMetadataValue(WindowsPathKey);
                if (!CommonUtils.IsValidPath(winPath))
                {
                    errors.AppendLine(string.Format("Interpreter {0} has invalid value for '{1}': {2}", dir, WindowsPathKey, winPath));
                    hasError = true;
                }
                else if (!hasError)
                {
                    winPath = CommonUtils.GetAbsoluteFilePath(dir, winPath);
                }

                var libPath = item.GetMetadataValue(LibraryPathKey);
                if (string.IsNullOrEmpty(libPath))
                {
                    libPath = "lib";
                }
                if (!CommonUtils.IsValidPath(libPath))
                {
                    errors.AppendLine(string.Format("Interpreter {0} has invalid value for '{1}': {2}", dir, LibraryPathKey, libPath));
                    hasError = true;
                }
                else if (!hasError)
                {
                    libPath = CommonUtils.GetAbsoluteDirectoryPath(dir, libPath);
                }

                var pathVar = item.GetMetadataValue(PathEnvVarKey);
                if (string.IsNullOrEmpty(pathVar))
                {
                    if (baseInterp != null)
                    {
                        pathVar = baseInterp.Configuration.PathEnvironmentVariable;
                    }
                    else
                    {
                        pathVar = "PYTHONPATH";
                    }
                }

                string arch = null;
                if (baseInterp == null)
                {
                    arch = item.GetMetadataValue(ArchitectureKey);
                    if (string.IsNullOrEmpty(arch))
                    {
                        arch = "x86";
                    }
                }

                if (baseInterp == null && !hasError)
                {
                    // Only thing missing is the base interpreter, so let's try
                    // to find it using paths
                    baseInterp = DerivedInterpreterFactory.FindBaseInterpreterFromVirtualEnv(dir, libPath, _service) as
                                 PythonInterpreterFactoryWithDatabase;

                    if (baseInterp == null)
                    {
                        errors.AppendLine(string.Format("Interpreter {0} has invalid value for '{1}': {2}", dir, BaseInterpreterKey, value ?? "(null)"));
                        hasError = true;
                    }
                }

                if (hasError)
                {
                    fact = new NotFoundInterpreterFactory(
                        id,
                        ver,
                        string.Format("{0} (unavailable)", description),
                        Directory.Exists(dir) ? dir : null
                        );
                }
                else if (baseInterp != null)
                {
                    MigrateOldDerivedInterpreterFactoryDatabase(id, baseInterp.Configuration.Version, dir);
                    fact = new DerivedInterpreterFactory(
                        baseInterp,
                        new InterpreterFactoryCreationOptions {
                        LanguageVersion = baseInterp.Configuration.Version,
                        Id                          = id,
                        Description                 = description,
                        InterpreterPath             = path,
                        WindowInterpreterPath       = winPath,
                        LibraryPath                 = libPath,
                        PrefixPath                  = dir,
                        PathEnvironmentVariableName = pathVar,
                        Architecture                = baseInterp.Configuration.Architecture,
                        WatchLibraryForNewModules   = true
                    }
                        );
                }
                else
                {
                    fact = InterpreterFactoryCreator.CreateInterpreterFactory(new InterpreterFactoryCreationOptions {
                        LanguageVersion = ver,
                        Id                          = id,
                        Description                 = description,
                        InterpreterPath             = path,
                        WindowInterpreterPath       = winPath,
                        LibraryPath                 = libPath,
                        PrefixPath                  = dir,
                        PathEnvironmentVariableName = pathVar,
                        ArchitectureString          = arch,
                        WatchLibraryForNewModules   = true
                    });
                }
                var existing = FindInterpreter(id, ver);
                if (existing != null && existing.IsEqual(fact))
                {
                    factories[existing] = new FactoryInfo(item, factories[existing].Owned);
                    var disposable = fact as IDisposable;
                    if (disposable != null)
                    {
                        disposable.Dispose();
                    }
                }
                else
                {
                    _rootPaths[id]  = dir;
                    factories[fact] = new FactoryInfo(item, true);
                    anyChange       = true;
                }
            }

            // <InterpreterReference Include="{guid};{version}" />
            foreach (var item in _project.GetItems(InterpreterReferenceItem))
            {
                var match = InterpreterReferencePath.Match(item.EvaluatedInclude);
                if (match == null || !match.Success || !match.Groups.Cast <Group>().All(g => g.Success))
                {
                    errors.AppendLine(string.Format("Interpreter reference has invalid path: {0}", item.EvaluatedInclude));
                    anyError = true;
                    continue;
                }
                Guid id;
                var  value = match.Groups["id"];
                if (string.IsNullOrEmpty(value.Value) || !Guid.TryParse(value.Value, out id))
                {
                    errors.AppendLine(string.Format("Interpreter reference has invalid id: {0}", value.Value ?? "(null)"));
                    anyError = true;
                    continue;
                }
                Version ver;
                value = match.Groups["version"];
                if (string.IsNullOrEmpty(value.Value) || !Version.TryParse(value.Value, out ver))
                {
                    errors.AppendLine(string.Format("Interpreter reference has invalid version: {0}", value.Value ?? "(null)"));
                    anyError = true;
                    continue;
                }

                bool owned = false;
                var  fact  = _service.FindInterpreter(id, ver);
                if (fact == null)
                {
                    owned = true;
                    fact  = new NotFoundInterpreterFactory(id, ver);
                }

                var existing = FindInterpreter(id, ver);
                if (existing != null)
                {
                    factories[existing] = new FactoryInfo(item, factories[existing].Owned);
                    if (owned)
                    {
                        ((PythonInterpreterFactoryWithDatabase)fact).Dispose();
                    }
                }
                else
                {
                    factories[fact] = new FactoryInfo(item, owned);
                    anyChange       = true;
                }
            }

            if (anyChange || _factories == null || factories.Count != _factories.Count)
            {
                // Lock here mainly to ensure that any searches complete before
                // we trigger the changed event.
                lock (_factoriesLock) {
                    _factories = factories;
                }
                OnInterpreterFactoriesChanged();
                UpdateActiveInterpreter();
            }

            if (anyError)
            {
                throw new InvalidDataException(errors.ToString());
            }
        }
예제 #16
0
        /// <summary>
        /// Creates a derived interpreter factory from the specified set of
        /// options. This function will modify the project, raise the
        /// <see cref="InterpreterFactoriesChanged"/> event and potentially
        /// display UI.
        /// </summary>
        /// <param name="options">
        /// <para>The options for the new interpreter:</para>
        /// <para>Guid: ID of the base interpreter.</para>
        /// <para>Version: Version of the base interpreter. This will also be
        /// the version of the new interpreter.</para>
        /// <para>PythonPath: Either the path to the root of the virtual
        /// environment, or directly to the interpreter executable. If no file
        /// exists at the provided path, the name of the interpreter specified
        /// for the base interpreter is tried. If that is not found, "scripts"
        /// is added as the last directory. If that is not found, an exception
        /// is raised.</para>
        /// <para>PythonWindowsPath [optional]: The path to the interpreter
        /// executable for windowed applications. If omitted, an executable with
        /// the same name as the base interpreter's will be used if it exists.
        /// Otherwise, this will be set to the same as PythonPath.</para>
        /// <para>PathEnvVar [optional]: The name of the environment variable to
        /// set for search paths. If omitted, the value from the base
        /// interpreter will be used.</para>
        /// <para>Description [optional]: The user-friendly name of the
        /// interpreter. If omitted, the relative path from the project home to
        /// the directory containing the interpreter is used. If this path ends
        /// in "\\Scripts", the last segment is also removed.</para>
        /// </param>
        /// <returns>The ID of the created interpreter.</returns>
        public Guid CreateInterpreterFactory(InterpreterFactoryCreationOptions options)
        {
            var projectHome = CommonUtils.GetAbsoluteDirectoryPath(_project.DirectoryPath, _project.GetPropertyValue("ProjectHome"));
            var rootPath    = CommonUtils.GetAbsoluteDirectoryPath(projectHome, options.PrefixPath);

            IPythonInterpreterFactory fact;
            var id         = Guid.NewGuid();
            var baseInterp = _service.FindInterpreter(options.Id, options.LanguageVersion)
                             as PythonInterpreterFactoryWithDatabase;

            if (baseInterp != null)
            {
                var pathVar = options.PathEnvironmentVariableName;
                if (string.IsNullOrEmpty(pathVar))
                {
                    pathVar = baseInterp.Configuration.PathEnvironmentVariable;
                }

                var description = options.Description;
                if (string.IsNullOrEmpty(description))
                {
                    description = CommonUtils.CreateFriendlyDirectoryPath(projectHome, rootPath);
                    int i = description.LastIndexOf("\\scripts", StringComparison.OrdinalIgnoreCase);
                    if (i > 0)
                    {
                        description = description.Remove(i);
                    }
                }

                MigrateOldDerivedInterpreterFactoryDatabase(id, baseInterp.Configuration.Version, options.PrefixPath);
                fact = new DerivedInterpreterFactory(
                    baseInterp,
                    new InterpreterFactoryCreationOptions {
                    Id = id,
                    LanguageVersion             = baseInterp.Configuration.Version,
                    Description                 = description,
                    InterpreterPath             = options.InterpreterPath,
                    WindowInterpreterPath       = options.WindowInterpreterPath,
                    LibraryPath                 = options.LibraryPath,
                    PrefixPath                  = options.PrefixPath,
                    PathEnvironmentVariableName = pathVar,
                    Architecture                = baseInterp.Configuration.Architecture,
                    WatchLibraryForNewModules   = true
                }
                    );
            }
            else
            {
                fact = InterpreterFactoryCreator.CreateInterpreterFactory(
                    new InterpreterFactoryCreationOptions {
                    Id = id,
                    LanguageVersion             = options.LanguageVersion,
                    Description                 = options.Description,
                    InterpreterPath             = options.InterpreterPath,
                    WindowInterpreterPath       = options.WindowInterpreterPath,
                    LibraryPath                 = options.LibraryPath,
                    PrefixPath                  = options.PrefixPath,
                    PathEnvironmentVariableName = options.PathEnvironmentVariableName,
                    Architecture                = options.Architecture,
                    WatchLibraryForNewModules   = options.WatchLibraryForNewModules
                }
                    );
            }

            AddInterpreter(fact, true);

            return(id);
        }