Пример #1
0
 private InterpreterConfiguration(Dictionary <string, object> properties)
 {
     Id                      = Read(properties, nameof(Id));
     _description            = Read(properties, nameof(Description)) ?? "";
     PrefixPath              = Read(properties, nameof(PrefixPath));
     InterpreterPath         = Read(properties, nameof(InterpreterPath));
     WindowsInterpreterPath  = Read(properties, nameof(WindowsInterpreterPath));
     PathEnvironmentVariable = Read(properties, nameof(PathEnvironmentVariable));
     Architecture            = InterpreterArchitecture.TryParse(Read(properties, nameof(Architecture)));
     try {
         Version = Version.Parse(Read(properties, nameof(Version)));
     } catch (ArgumentException) {
         Version = new Version();
     } catch (FormatException) {
         Version = new Version();
     }
     UIMode = 0;
     foreach (var bit in (Read(properties, nameof(UIMode)) ?? "").Split('|'))
     {
         InterpreterUIMode m;
         if (Enum.TryParse(bit, out m))
         {
             UIMode |= m;
         }
     }
 }
 private InterpreterConfiguration(Dictionary <string, object> properties)
 {
     Id                      = Read(properties, nameof(Id));
     _description            = Read(properties, nameof(Description)) ?? "";
     InterpreterPath         = Read(properties, nameof(InterpreterPath));
     PathEnvironmentVariable = Read(properties, nameof(PathEnvironmentVariable));
     LibraryPath             = Read(properties, nameof(LibraryPath));
     Architecture            = InterpreterArchitecture.TryParse(Read(properties, nameof(Architecture)));
     try {
         Version = Version.Parse(Read(properties, nameof(Version)));
     } catch (Exception ex) when(ex is ArgumentException || ex is FormatException)
     {
         Version = new Version();
     }
     if (properties.TryGetValue(nameof(SearchPaths), out object o))
     {
         SearchPaths.Clear();
         if (o is string s)
         {
             SearchPaths.AddRange(s.Split(';'));
         }
         else if (o is IEnumerable <string> ss)
         {
             SearchPaths.AddRange(ss);
         }
     }
 }
        /// <summary>
        /// Reconstructs an interpreter configuration from a dictionary.
        /// </summary>
        public static VisualStudioInterpreterConfiguration CreateFromDictionary(Dictionary <string, object> properties)
        {
            var id                      = Read(properties, nameof(InterpreterConfiguration.Id));
            var description             = Read(properties, nameof(InterpreterConfiguration.Description)) ?? "";
            var prefixPath              = Read(properties, nameof(PrefixPath));
            var interpreterPath         = Read(properties, nameof(InterpreterConfiguration.InterpreterPath));
            var windowsInterpreterPath  = Read(properties, nameof(WindowsInterpreterPath));
            var pathEnvironmentVariable = Read(properties, nameof(InterpreterConfiguration.PathEnvironmentVariable));
            var architecture            = InterpreterArchitecture.TryParse(Read(properties, nameof(InterpreterConfiguration.Architecture)));

            var version = default(Version);

            try {
                version = Version.Parse(Read(properties, nameof(Version)));
            } catch (Exception ex) when(ex is ArgumentException || ex is FormatException)
            {
                version = new Version();
            }

            InterpreterUIMode uiMode = 0;

            foreach (var bit in (Read(properties, nameof(UIMode)) ?? "").Split('|'))
            {
                if (Enum.TryParse(bit, out InterpreterUIMode m))
                {
                    uiMode |= m;
                }
            }

            var configuration = new VisualStudioInterpreterConfiguration(id, description, prefixPath, interpreterPath, windowsInterpreterPath, pathEnvironmentVariable, architecture, version, uiMode);

            if (properties.TryGetValue(nameof(InterpreterConfiguration.SearchPaths), out object o))
            {
                configuration.SearchPaths.Clear();
                switch (o)
                {
                case string s:
                    configuration.SearchPaths.AddRange(s.Split(';'));
                    break;

                case IEnumerable <string> ss:
                    configuration.SearchPaths.AddRange(ss);
                    break;
                }
            }

            return(configuration);
        }
Пример #4
0
 private InterpreterConfiguration(Dictionary <string, object> properties)
 {
     Id                      = Read(properties, nameof(Id));
     _description            = Read(properties, nameof(Description)) ?? "";
     PrefixPath              = Read(properties, nameof(PrefixPath));
     InterpreterPath         = Read(properties, nameof(InterpreterPath));
     WindowsInterpreterPath  = Read(properties, nameof(WindowsInterpreterPath));
     PathEnvironmentVariable = Read(properties, nameof(PathEnvironmentVariable));
     Architecture            = InterpreterArchitecture.TryParse(Read(properties, nameof(Architecture)));
     try {
         Version = Version.Parse(Read(properties, nameof(Version)));
     } catch (ArgumentException) {
         Version = new Version();
     } catch (FormatException) {
         Version = new Version();
     }
     UIMode = 0;
     foreach (var bit in (Read(properties, nameof(UIMode)) ?? "").Split('|'))
     {
         InterpreterUIMode m;
         if (Enum.TryParse(bit, out m))
         {
             UIMode |= m;
         }
     }
     if (properties.TryGetValue(nameof(SearchPaths), out object o))
     {
         SearchPaths.Clear();
         if (o is string s)
         {
             SearchPaths.AddRange(s.Split(';'));
         }
         else if (o is IEnumerable <string> ss)
         {
             SearchPaths.AddRange(ss);
         }
     }
 }
        /// <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>
        private bool DiscoverInterpreters(ProjectInfo projectInfo)
        {
            // <Interpreter Include="InterpreterDirectory">
            //   <Id>factoryProviderId;interpreterFactoryId</Id>
            //   <Version>...</Version>
            //   <InterpreterPath>...</InterpreterPath>
            //   <WindowsInterpreterPath>...</WindowsInterpreterPath>
            //   <PathEnvironmentVariable>...</PathEnvironmentVariable>
            //   <Description>...</Description>
            // </Interpreter>
            var projectHome = PathUtils.GetAbsoluteDirectoryPath(
                Path.GetDirectoryName(projectInfo.FullPath),
                projectInfo.GetPropertyValue("ProjectHome")
                );
            var factories = new Dictionary <string, FactoryInfo>();

            foreach (var item in projectInfo.GetInterpreters())
            {
                // Errors in these options are fatal, so we set anyError and
                // continue with the next entry.
                var dir = GetValue(item, "EvaluatedInclude");
                if (!PathUtils.IsValidPath(dir))
                {
                    Log("Interpreter has invalid path: {0}", dir ?? "(null)");
                    continue;
                }
                dir = PathUtils.GetAbsoluteDirectoryPath(projectHome, dir);

                var id = GetValue(item, MSBuildConstants.IdKey);
                if (string.IsNullOrEmpty(id))
                {
                    Log("Interpreter {0} has invalid value for '{1}': {2}", dir, MSBuildConstants.IdKey, id);
                    continue;
                }
                if (factories.ContainsKey(id))
                {
                    Log("Interpreter {0} has a non-unique id: {1}", dir, id);
                    continue;
                }

                var     verStr = GetValue(item, MSBuildConstants.VersionKey);
                Version ver;
                if (string.IsNullOrEmpty(verStr) || !Version.TryParse(verStr, out ver))
                {
                    Log("Interpreter {0} has invalid value for '{1}': {2}", dir, MSBuildConstants.VersionKey, verStr);
                    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 = GetValue(item, MSBuildConstants.DescriptionKey);
                if (string.IsNullOrEmpty(description))
                {
                    description = PathUtils.CreateFriendlyDirectoryPath(projectHome, dir);
                }

                var path = GetValue(item, MSBuildConstants.InterpreterPathKey);
                if (!PathUtils.IsValidPath(path))
                {
                    Log("Interpreter {0} has invalid value for '{1}': {2}", dir, MSBuildConstants.InterpreterPathKey, path);
                    hasError = true;
                }
                else if (!hasError)
                {
                    path = PathUtils.GetAbsoluteFilePath(dir, path);
                }

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

                var pathVar = GetValue(item, MSBuildConstants.PathEnvVarKey);
                if (string.IsNullOrEmpty(pathVar))
                {
                    pathVar = "PYTHONPATH";
                }

                var arch = InterpreterArchitecture.TryParse(GetValue(item, MSBuildConstants.ArchitectureKey));

                string fullId = GetInterpreterId(projectInfo.FullPath, id);

                FactoryInfo info;
                if (hasError)
                {
                    info = new ErrorFactoryInfo(fullId, ver, description, dir);
                }
                else
                {
                    info = new ConfiguredFactoryInfo(this, new InterpreterConfiguration(
                                                         fullId,
                                                         description,
                                                         dir,
                                                         path,
                                                         winPath,
                                                         pathVar,
                                                         arch,
                                                         ver,
                                                         InterpreterUIMode.CannotBeDefault | InterpreterUIMode.CannotBeConfigured | InterpreterUIMode.SupportsDatabase
                                                         ));
                }

                MergeFactory(projectInfo, factories, info);
            }

            HashSet <FactoryInfo> previousFactories = new HashSet <FactoryInfo>();

            if (projectInfo.Factories != null)
            {
                previousFactories.UnionWith(projectInfo.Factories.Values);
            }
            HashSet <FactoryInfo> newFactories = new HashSet <FactoryInfo>(factories.Values);

            bool anyChange = !newFactories.SetEquals(previousFactories);

            if (anyChange || projectInfo.Factories == null)
            {
                // Lock here mainly to ensure that any searches complete before
                // we trigger the changed event.
                lock (projectInfo) {
                    projectInfo.Factories = factories;
                }

                foreach (var removed in previousFactories.Except(newFactories))
                {
                    projectInfo.ContextProvider.InterpreterUnloaded(
                        projectInfo.Context,
                        removed.Config
                        );

                    IDisposable disp = removed as IDisposable;
                    if (disp != null)
                    {
                        disp.Dispose();
                    }
                }

                foreach (var added in newFactories.Except(previousFactories))
                {
                    foreach (var factory in factories)
                    {
                        projectInfo.ContextProvider.InterpreterLoaded(
                            projectInfo.Context,
                            factory.Value.Config
                            );
                    }
                }
            }

            return(anyChange);
        }
Пример #6
0
        private InterpreterConfiguration TryReadConfiguration(
            string company,
            string tag,
            RegistryKey tagKey,
            RegistryKey installKey,
            bool pythonCoreCompatibility,
            InterpreterArchitecture assumedArch
            )
        {
            if (tagKey == null || installKey == null)
            {
                return(null);
            }

            var prefixPath = installKey.GetValue(null) as string;
            var exePath    = installKey.GetValue("ExecutablePath") as string;
            var exewPath   = installKey.GetValue("WindowedExecutablePath") as string;

            if (pythonCoreCompatibility && !string.IsNullOrEmpty(prefixPath))
            {
                if (string.IsNullOrEmpty(exePath))
                {
                    exePath = PathUtils.GetAbsoluteFilePath(prefixPath, CPythonInterpreterFactoryConstants.ConsoleExecutable);
                }
                if (string.IsNullOrEmpty(exewPath))
                {
                    exewPath = PathUtils.GetAbsoluteFilePath(prefixPath, CPythonInterpreterFactoryConstants.WindowsExecutable);
                }
            }

            var version = tagKey.GetValue("Version") as string;

            if (pythonCoreCompatibility && string.IsNullOrEmpty(version) && tag.Length >= 3)
            {
                version = tag.Substring(0, 3);
            }

            Version sysVersion;
            var     sysVersionString = tagKey.GetValue("SysVersion") as string;

            if (pythonCoreCompatibility && string.IsNullOrEmpty(sysVersionString) && tag.Length >= 3)
            {
                sysVersionString = tag.Substring(0, 3);
            }
            if (string.IsNullOrEmpty(sysVersionString) || !Version.TryParse(sysVersionString, out sysVersion))
            {
                sysVersion = new Version(0, 0);
            }

            PythonLanguageVersion langVersion;

            try {
                langVersion = sysVersion.ToLanguageVersion();
            } catch (InvalidOperationException) {
                langVersion = PythonLanguageVersion.None;
                sysVersion  = new Version(0, 0);
            }

            InterpreterArchitecture arch;

            if (!InterpreterArchitecture.TryParse(tagKey.GetValue("SysArchitecture", null) as string, out arch))
            {
                arch = assumedArch;
            }

            if (arch == InterpreterArchitecture.Unknown && File.Exists(exePath))
            {
                switch (NativeMethods.GetBinaryType(exePath))
                {
                case System.Reflection.ProcessorArchitecture.X86:
                    arch = InterpreterArchitecture.x86;
                    break;

                case System.Reflection.ProcessorArchitecture.Amd64:
                    arch = InterpreterArchitecture.x64;
                    break;
                }
            }

            if (pythonCoreCompatibility && sysVersion != null && sysVersion < new Version(3, 5) && arch == InterpreterArchitecture.x86)
            {
                // Older versions of CPython did not include
                // "-32" in their Tag, so we will add it here
                // for uniqueness.
                tag += "-32";
            }

            var id = CPythonInterpreterFactoryConstants.GetInterpreterId(company, tag);

            var description = tagKey.GetValue("DisplayName") as string;

            if (string.IsNullOrEmpty(description))
            {
                if (pythonCoreCompatibility)
                {
                    description = "Python {0}{1: ()}".FormatUI(version, arch);
                }
                else
                {
                    description = "{0} {1}".FormatUI(company, tag);
                }
            }

            return(new InterpreterConfiguration(
                       id,
                       description,
                       prefixPath,
                       exePath,
                       exewPath,
                       CPythonInterpreterFactoryConstants.PathEnvironmentVariableName,
                       arch,
                       sysVersion
                       ));
        }
Пример #7
0
        private VisualStudioInterpreterConfiguration TryReadConfiguration(
            string company,
            string tag,
            RegistryKey tagKey,
            RegistryKey installKey,
            bool pythonCoreCompatibility,
            InterpreterArchitecture assumedArch
            )
        {
            if (tagKey == null || installKey == null)
            {
                return(null);
            }

            string prefixPath, exePath, exewPath;

            try {
                prefixPath = PathUtils.NormalizePath(installKey.GetValue(null) as string);
                exePath    = PathUtils.NormalizePath(installKey.GetValue("ExecutablePath") as string);
                exewPath   = PathUtils.NormalizePath(installKey.GetValue("WindowedExecutablePath") as string);
            } catch (ArgumentException ex) {
                Debug.Fail(ex.ToUnhandledExceptionMessage(GetType()));
                return(null);
            }
            if (pythonCoreCompatibility && !string.IsNullOrEmpty(prefixPath))
            {
                if (string.IsNullOrEmpty(exePath))
                {
                    try {
                        exePath = PathUtils.GetAbsoluteFilePath(prefixPath, CPythonInterpreterFactoryConstants.ConsoleExecutable);
                    } catch (ArgumentException) {
                    }
                }
                if (string.IsNullOrEmpty(exewPath))
                {
                    try {
                        exewPath = PathUtils.GetAbsoluteFilePath(prefixPath, CPythonInterpreterFactoryConstants.WindowsExecutable);
                    } catch (ArgumentException) {
                    }
                }
            }

            var version = tagKey.GetValue("Version") as string;

            if (pythonCoreCompatibility && string.IsNullOrEmpty(version) && tag.Length >= 3)
            {
                version = tag.Substring(0, 3);
            }

            var sysVersionString = tagKey.GetValue("SysVersion") as string;

            if (pythonCoreCompatibility && string.IsNullOrEmpty(sysVersionString) && tag.Length >= 3)
            {
                sysVersionString = tag.Substring(0, 3);
            }
            if (string.IsNullOrEmpty(sysVersionString) || !Version.TryParse(sysVersionString, out var sysVersion))
            {
                sysVersion = new Version(0, 0);
            }

            if (sysVersion < new Version(3, 0))
            {
                return(null); // Python 2.x is no longer supported.
            }

            try {
                sysVersion.ToLanguageVersion();
            } catch (InvalidOperationException) {
                sysVersion = new Version(0, 0);
            }

            if (!InterpreterArchitecture.TryParse(tagKey.GetValue("SysArchitecture", null) as string, out var arch))
            {
                arch = assumedArch;
            }

            if (arch == InterpreterArchitecture.Unknown && File.Exists(exePath))
            {
                switch (NativeMethods.GetBinaryType(exePath))
                {
                case System.Reflection.ProcessorArchitecture.X86:
                    arch = InterpreterArchitecture.x86;
                    break;

                case System.Reflection.ProcessorArchitecture.Amd64:
                    arch = InterpreterArchitecture.x64;
                    break;
                }
            }

            if (pythonCoreCompatibility && sysVersion != null && sysVersion < new Version(3, 5) && arch == InterpreterArchitecture.x86)
            {
                // Older versions of CPython did not include
                // "-32" in their Tag, so we will add it here
                // for uniqueness.
                tag += "-32";
            }

            var pathVar = tagKey.GetValue("PathEnvironmentVariable") as string ??
                          CPythonInterpreterFactoryConstants.PathEnvironmentVariableName;

            var id = CPythonInterpreterFactoryConstants.GetInterpreterId(company, tag);

            var description = tagKey.GetValue("DisplayName") as string;

            if (string.IsNullOrEmpty(description))
            {
                description = pythonCoreCompatibility
                    ? "Python {0}{1: ()}".FormatUI(version, arch)
                    : "{0} {1}".FormatUI(company, tag);
            }

            return(new VisualStudioInterpreterConfiguration(
                       id,
                       description,
                       prefixPath,
                       exePath,
                       exewPath,
                       pathVar,
                       arch,
                       sysVersion
                       ));
        }