private static void AddConfiguredConstructionInfos( ICollection <IConstructionInfo> constructionInfos, ConstructionKey key, out bool otherConstructionRequired) { var mapperData = key.MappingData.MapperData; var configuredFactories = mapperData .MapperContext .UserConfigurations .QueryObjectFactories(mapperData); foreach (var configuredFactory in configuredFactories) { var configuredConstructionInfo = new ConfiguredFactoryInfo(configuredFactory, mapperData); constructionInfos.Add(configuredConstructionInfo); if (configuredConstructionInfo.IsUnconditional) { otherConstructionRequired = false; return; } } otherConstructionRequired = true; }
public override bool Equals(object obj) { ConfiguredFactoryInfo other = obj as ConfiguredFactoryInfo; if (other != null) { return(other.Config == Config); } return(false); }
/// <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); }
/// <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> // <BaseInterpreter>factoryProviderId;interpreterFactoryId</BaseInterpreter> // <Version>...</Version> // <InterpreterPath>...</InterpreterPath> // <WindowsInterpreterPath>...</WindowsInterpreterPath> // <LibraryPath>...</LibraryPath> // <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; bool hasDescription = true; var description = GetValue(item, MSBuildConstants.DescriptionKey); if (string.IsNullOrEmpty(description)) { hasDescription = false; description = PathUtils.CreateFriendlyDirectoryPath(projectHome, dir); } var baseInterpId = GetValue(item, MSBuildConstants.BaseInterpreterKey); 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 libPath = GetValue(item, MSBuildConstants.LibraryPathKey); if (string.IsNullOrEmpty(libPath)) { libPath = "lib"; } if (!PathUtils.IsValidPath(libPath)) { Log("Interpreter {0} has invalid value for '{1}': {2}", dir, MSBuildConstants.LibraryPathKey, libPath); hasError = true; } else if (!hasError) { libPath = PathUtils.GetAbsoluteDirectoryPath(dir, libPath); } InterpreterConfiguration baseInterp = null; if (!string.IsNullOrEmpty(baseInterpId)) { // 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. baseInterp = FindConfiguration(baseInterpId); } var pathVar = GetValue(item, MSBuildConstants.PathEnvVarKey); if (string.IsNullOrEmpty(pathVar)) { if (baseInterp != null) { pathVar = baseInterp.PathEnvironmentVariable; } else { pathVar = "PYTHONPATH"; } } string arch = null; if (baseInterp == null) { arch = GetValue(item, MSBuildConstants.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 = FindBaseInterpreterFromVirtualEnv(dir, libPath); if (baseInterp == null) { Log("Interpreter {0} has invalid value for '{1}': {2}", dir, MSBuildConstants.BaseInterpreterKey, baseInterpId ?? "(null)"); hasError = true; } } string fullId = GetInterpreterId(projectInfo.FullPath, id); FactoryInfo info; if (hasError) { info = new ErrorFactoryInfo(fullId, ver, description, dir); } else { Debug.Assert(baseInterp != null, "we reported an error if we didn't have a base interpreter"); if (!hasDescription) { description = string.Format("{0} ({1})", description, baseInterp.Description); } info = new ConfiguredFactoryInfo( this, baseInterp, new InterpreterConfiguration( fullId, description, dir, path, winPath, libPath, pathVar, baseInterp.Architecture, baseInterp.Version, 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); }
/// <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> // <BaseInterpreter>factoryProviderId;interpreterFactoryId</BaseInterpreter> // <Version>...</Version> // <InterpreterPath>...</InterpreterPath> // <WindowsInterpreterPath>...</WindowsInterpreterPath> // <LibraryPath>...</LibraryPath> // <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 baseInterpId = GetValue(item, MSBuildConstants.BaseInterpreterKey); 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 libPath = GetValue(item, MSBuildConstants.LibraryPathKey); if (string.IsNullOrEmpty(libPath)) { libPath = "lib"; } if (!PathUtils.IsValidPath(libPath)) { Log("Interpreter {0} has invalid value for '{1}': {2}", dir, MSBuildConstants.LibraryPathKey, libPath); hasError = true; } else if (!hasError) { libPath = PathUtils.GetAbsoluteDirectoryPath(dir, libPath); } InterpreterConfiguration baseInterp = null; if (!string.IsNullOrEmpty(baseInterpId)) { // 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. baseInterp = FindConfiguration(baseInterpId); } var pathVar = GetValue(item, MSBuildConstants.PathEnvVarKey); if (string.IsNullOrEmpty(pathVar)) { if (baseInterp != null) { pathVar = baseInterp.PathEnvironmentVariable; } else { pathVar = "PYTHONPATH"; } } string arch = null; if (baseInterp == null) { arch = GetValue(item, MSBuildConstants.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 = FindBaseInterpreterFromVirtualEnv(dir, libPath); if (baseInterp == null) { Log("Interpreter {0} has invalid value for '{1}': {2}", dir, MSBuildConstants.BaseInterpreterKey, baseInterpId ?? "(null)"); hasError = true; } } string fullId = GetInterpreterId(projectInfo.FullPath, id); FactoryInfo info; if (hasError) { info = new ErrorFactoryInfo(fullId, ver, description, dir); } else { Debug.Assert(baseInterp != null, "we reported an error if we didn't have a base interpreter"); info = new ConfiguredFactoryInfo( this, baseInterp, new InterpreterConfiguration( fullId, description, dir, path, winPath, libPath, pathVar, baseInterp.Architecture, baseInterp.Version, InterpreterUIMode.CannotBeDefault | InterpreterUIMode.CannotBeConfigured | InterpreterUIMode.SupportsDatabase, baseInterp != null ? string.Format("({0})", baseInterp.FullDescription) : null ) ); } 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; }
/// <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; }