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; }
/// <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()); } }
/// <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); }