protected override void CreateFactory()
 {
     if (_baseConfig != null)
     {
         var baseInterp = _factoryProvider.FindInterpreter(_baseConfig.Id) as PythonInterpreterFactoryWithDatabase;
         if (baseInterp != null)
         {
             _factory = new DerivedInterpreterFactory(
                 baseInterp,
                 Config,
                 new InterpreterFactoryCreationOptions {
                 WatchLibraryForNewModules = true,
             }
                 );
         }
     }
     if (_factory == null)
     {
         _factory = InterpreterFactoryCreator.CreateInterpreterFactory(
             Config,
             new InterpreterFactoryCreationOptions {
             WatchLibraryForNewModules = true
         }
             );
     }
 }
        public InterpreterConfiguration FindBaseInterpreterFromVirtualEnv(
            string prefixPath,
            string libPath
            )
        {
            string basePath = DerivedInterpreterFactory.GetOrigPrefixPath(prefixPath, libPath);

            if (Directory.Exists(basePath))
            {
                foreach (var provider in GetProvidersAndMetadata())
                {
                    foreach (var config in provider.Key.GetInterpreterConfigurations())
                    {
                        if (PathUtils.IsSamePath(config.PrefixPath, basePath))
                        {
                            return(config);
                        }
                    }
                }
            }
            return(null);
        }
        /// <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 = PathUtils.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 (!PathUtils.IsValidPath(dir)) {
                    errors.AppendLine(string.Format("Interpreter has invalid path: {0}", dir ?? "(null)"));
                    anyError = true;
                    continue;
                }
                dir = PathUtils.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 = PathUtils.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 (!PathUtils.IsValidPath(path)) {
                    errors.AppendLine(string.Format("Interpreter {0} has invalid value for '{1}': {2}", dir, InterpreterPathKey, path));
                    hasError = true;
                } else if (!hasError) {
                    path = PathUtils.GetAbsoluteFilePath(dir, path);
                }

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

                var libPath = item.GetMetadataValue(LibraryPathKey);
                if (string.IsNullOrEmpty(libPath)) {
                    libPath = "lib";
                }
                if (!PathUtils.IsValidPath(libPath)) {
                    errors.AppendLine(string.Format("Interpreter {0} has invalid value for '{1}': {2}", dir, LibraryPathKey, libPath));
                    hasError = true;
                } else if (!hasError) {
                    libPath = PathUtils.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());
            }
        }
        /// <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 = PathUtils.GetAbsoluteDirectoryPath(_project.DirectoryPath, _project.GetPropertyValue("ProjectHome"));
            var rootPath = PathUtils.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 = PathUtils.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;
        }
Beispiel #5
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());
            }
        }
Beispiel #6
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);
        }
Beispiel #7
0
 protected override void CreateFactory()
 {
     if (_baseConfig != null) {
         var baseInterp = _factoryProvider.FindInterpreter(_baseConfig.Id) as PythonInterpreterFactoryWithDatabase;
         if (baseInterp != null) {
             _factory = new DerivedInterpreterFactory(
                 baseInterp,
                 Config,
                 new InterpreterFactoryCreationOptions {
                     WatchLibraryForNewModules = true,
                 }
             );
         }
     }
     if (_factory == null) {
         _factory = InterpreterFactoryCreator.CreateInterpreterFactory(
             Config,
             new InterpreterFactoryCreationOptions {
                 WatchLibraryForNewModules = true
             }
         );
     }
 }