public DerivedInterpreterFactory( PythonInterpreterFactoryWithDatabase baseFactory, InterpreterFactoryCreationOptions options ) : base( options.Id, options.Description, new InterpreterConfiguration( options.PrefixPath, options.InterpreterPath, options.WindowInterpreterPath, options.LibraryPath, options.PathEnvironmentVariableName, options.Architecture, options.LanguageVersion, InterpreterUIMode.CannotBeDefault | InterpreterUIMode.CannotBeConfigured ), options.WatchLibraryForNewModules ) { if (baseFactory.Configuration.Version != options.LanguageVersion) { throw new ArgumentException("Language versions do not match", "options"); } _base = baseFactory; _base.IsCurrentChanged += Base_IsCurrentChanged; _base.NewDatabaseAvailable += Base_NewDatabaseAvailable; _description = options.Description; if (Volatile.Read(ref _deferRefreshIsCurrent)) { // This rare race condition is due to a design flaw that is in // shipped public API and cannot be fixed without breaking // compatibility with 3rd parties. RefreshIsCurrent(); } }
/// <summary> /// Creates a new interpreter factory with the specified options. This /// interpreter always includes a cached completion database. /// </summary> public static PythonInterpreterFactoryWithDatabase CreateInterpreterFactory(InterpreterConfiguration configuration, InterpreterFactoryCreationOptions options = null) { options = options?.Clone() ?? new InterpreterFactoryCreationOptions(); if (string.IsNullOrEmpty(options.DatabasePath)) { options.DatabasePath = Path.Combine( PythonTypeDatabase.CompletionDatabasePath, GetRelativePathForConfigurationId(configuration.Id) ); } var fact = new CPythonInterpreterFactory(configuration, options); if (options.WatchFileSystem) { fact.BeginRefreshIsCurrent(); } return fact; }
public DerivedInterpreterFactory( PythonInterpreterFactoryWithDatabase baseFactory, InterpreterConfiguration config, InterpreterFactoryCreationOptions options ) : base(config, options.WatchLibraryForNewModules) { _base = baseFactory; _base.IsCurrentChanged += Base_IsCurrentChanged; _base.NewDatabaseAvailable += Base_NewDatabaseAvailable; if (Volatile.Read(ref _deferRefreshIsCurrent)) { // This rare race condition is due to a design flaw that is in // shipped public API and cannot be fixed without breaking // compatibility with 3rd parties. RefreshIsCurrent(); } }
/// <summary> /// Creates a new interpreter factory with the specified options. This /// interpreter always includes a cached completion database. /// </summary> public static PythonInterpreterFactoryWithDatabase CreateInterpreterFactory(InterpreterFactoryCreationOptions options) { var ver = options.LanguageVersion ?? new Version(2, 7); var description = options.Description ?? string.Format("Unknown Python {0}", ver); var prefixPath = options.PrefixPath; if (string.IsNullOrEmpty(prefixPath) && !string.IsNullOrEmpty(options.InterpreterPath)) { prefixPath = Path.GetDirectoryName(options.InterpreterPath); } return new CPythonInterpreterFactory( ver, (options.Id == default(Guid)) ? Guid.NewGuid() : options.Id, description, prefixPath ?? string.Empty, options.InterpreterPath ?? string.Empty, options.WindowInterpreterPath ?? string.Empty, options.LibraryPath ?? string.Empty, options.PathEnvironmentVariableName ?? "PYTHONPATH", options.Architecture, options.WatchLibraryForNewModules ); }
public static InterpreterFactoryCreationOptions FindInterpreterOptions( string prefixPath, IInterpreterOptionsService service, IPythonInterpreterFactory baseInterpreter = null ) { var result = new InterpreterFactoryCreationOptions(); var libPath = DerivedInterpreterFactory.FindLibPath(prefixPath); result.PrefixPath = prefixPath; result.LibraryPath = libPath; if (baseInterpreter == null) { baseInterpreter = DerivedInterpreterFactory.FindBaseInterpreterFromVirtualEnv( prefixPath, libPath, service ); } string interpExe, winterpExe; if (baseInterpreter != null) { // The interpreter name should be the same as the base interpreter. interpExe = Path.GetFileName(baseInterpreter.Configuration.InterpreterPath); winterpExe = Path.GetFileName(baseInterpreter.Configuration.WindowsInterpreterPath); var scripts = new[] { "Scripts", "bin" }; result.InterpreterPath = CommonUtils.FindFile(prefixPath, interpExe, firstCheck: scripts); result.WindowInterpreterPath = CommonUtils.FindFile(prefixPath, winterpExe, firstCheck: scripts); result.PathEnvironmentVariableName = baseInterpreter.Configuration.PathEnvironmentVariable; } else { result.InterpreterPath = string.Empty; result.WindowInterpreterPath = string.Empty; result.PathEnvironmentVariableName = string.Empty; } if (baseInterpreter != null) { result.Description = string.Format( "{0} ({1})", CommonUtils.GetFileOrDirectoryName(prefixPath), baseInterpreter.Description ); result.Id = baseInterpreter.Id; result.LanguageVersion = baseInterpreter.Configuration.Version; result.Architecture = baseInterpreter.Configuration.Architecture; result.WatchLibraryForNewModules = true; } else { result.Description = CommonUtils.GetFileOrDirectoryName(prefixPath); result.Id = Guid.Empty; result.LanguageVersion = new Version(0, 0); result.Architecture = ProcessorArchitecture.None; result.WatchLibraryForNewModules = false; } return result; }
/// <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; }
private static ProjectItemElement AddVirtualEnvironment( ProjectRootElement project, string sourcePath, InterpreterFactoryCreationOptions options ) { var prefixPath = options.PrefixPath ?? string.Empty; var interpreterPath = string.IsNullOrEmpty(options.InterpreterPath) ? string.Empty : CommonUtils.GetRelativeFilePath(prefixPath, options.InterpreterPath); var windowInterpreterPath = string.IsNullOrEmpty(options.WindowInterpreterPath) ? string.Empty : CommonUtils.GetRelativeFilePath(prefixPath, options.WindowInterpreterPath); var libraryPath = string.IsNullOrEmpty(options.LibraryPath) ? string.Empty : CommonUtils.GetRelativeDirectoryPath(prefixPath, options.LibraryPath); prefixPath = CommonUtils.GetRelativeDirectoryPath(sourcePath, prefixPath); return project.AddItem( MSBuildProjectInterpreterFactoryProvider.InterpreterItem, prefixPath, new Dictionary<string, string> { { MSBuildProjectInterpreterFactoryProvider.IdKey, Guid.NewGuid().ToString("B") }, { MSBuildProjectInterpreterFactoryProvider.DescriptionKey, options.Description }, { MSBuildProjectInterpreterFactoryProvider.BaseInterpreterKey, options.IdString }, { MSBuildProjectInterpreterFactoryProvider.InterpreterPathKey, interpreterPath }, { MSBuildProjectInterpreterFactoryProvider.WindowsPathKey, windowInterpreterPath }, { MSBuildProjectInterpreterFactoryProvider.LibraryPathKey, libraryPath }, { MSBuildProjectInterpreterFactoryProvider.VersionKey, options.LanguageVersionString }, { MSBuildProjectInterpreterFactoryProvider.ArchitectureKey, options.ArchitectureString }, { MSBuildProjectInterpreterFactoryProvider.PathEnvVarKey, options.PathEnvironmentVariableName } } ); }
public IPythonInterpreterFactory SetOptions(InterpreterFactoryCreationOptions options) { var collection = PythonInterpreterKey + "\\" + options.IdString; var store = _settings.GetWritableSettingsStore(SettingsScope.UserSettings); store.CreateCollection(collection); store.SetString(collection, PathKey, options.InterpreterPath ?? string.Empty); store.SetString(collection, WindowsPathKey, options.WindowInterpreterPath ?? string.Empty); store.SetString(collection, LibraryPathKey, options.LibraryPath ?? string.Empty); store.SetString(collection, ArchitectureKey, options.ArchitectureString); store.SetString(collection, VersionKey, options.LanguageVersionString); store.SetString(collection, PathEnvVarKey, options.PathEnvironmentVariableName ?? string.Empty); store.SetString(collection, DescriptionKey, options.Description ?? string.Empty); var newInterp = LoadUserDefinedInterpreter(store, options.IdString); if (newInterp == null) { throw new InvalidOperationException("Unable to load user defined interpreter"); } PythonInterpreterFactoryWithDatabase existing; if (_interpreters.TryGetValue(newInterp.Id, out existing)) { existing.Dispose(); } _interpreters[newInterp.Id] = newInterp; OnInterpreterFactoriesChanged(); return newInterp; }
/// <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); }
/// <summary> /// Creates a new interpreter factory backed by a type database. /// </summary> /// <remarks> /// <see cref="RefreshIsCurrent"/> must be called after creation to /// ensure the database state is correctly reflected. /// </remarks> public PythonInterpreterFactoryWithDatabase( InterpreterConfiguration config, InterpreterFactoryCreationOptions options ) { if (config == null) { throw new ArgumentNullException(nameof(config)); } if (options == null) { options = new InterpreterFactoryCreationOptions(); } Configuration = config; DatabasePath = options.DatabasePath; // Avoid creating a interpreter with an unsupported version. // https://github.com/Microsoft/PTVS/issues/706 try { var langVer = config.Version.ToLanguageVersion(); } catch (InvalidOperationException ex) { throw new ArgumentException(ex.Message, ex); } if (options.WatchFileSystem && !string.IsNullOrEmpty(DatabasePath)) { // Assume the database is valid if the version is up to date, then // switch to invalid after we've checked. _isValid = PythonTypeDatabase.IsDatabaseVersionCurrent(DatabasePath); _isCheckingDatabase = true; _verWatcher = CreateDatabaseVerWatcher(); _verDirWatcher = CreateDatabaseDirectoryWatcher(); #if DEBUG var creationStack = new StackTrace(true).ToString(); Task.Delay(1000).ContinueWith(t => { Debug.Assert( _hasEverCheckedDatabase, "Database check was not triggered for {0}".FormatUI(Configuration.Id), creationStack ); }); #endif } else { // Assume the database is valid _isValid = true; } try { var pm = options.PackageManager; if (pm != null) { pm.SetInterpreterFactory(this); pm.InstalledFilesChanged += PackageManager_InstalledFilesChanged; PackageManager = pm; } } catch (NotSupportedException) { } }
/// <summary> /// Creates a new interpreter factory with the specified options. This /// interpreter always includes a cached completion database. /// </summary> public static PythonInterpreterFactoryWithDatabase CreateInterpreterFactory(InterpreterConfiguration configuration, InterpreterFactoryCreationOptions options = null) { options = options?.Clone() ?? new InterpreterFactoryCreationOptions(); if (string.IsNullOrEmpty(options.DatabasePath)) { options.DatabasePath = Path.Combine( PythonTypeDatabase.CompletionDatabasePath, GetRelativePathForConfigurationId(configuration.Id) ); } var fact = new CPythonInterpreterFactory(configuration, options); if (options.WatchFileSystem) { fact.BeginRefreshIsCurrent(); } return(fact); }
/// <summary> /// Creates a new interpreter factory with the specified options. This /// interpreter always includes a cached completion database. /// </summary> public static IPythonInterpreterFactory CreateInterpreterFactory(InterpreterConfiguration configuration, InterpreterFactoryCreationOptions options = null) { options = options?.Clone() ?? new InterpreterFactoryCreationOptions(); if (string.IsNullOrEmpty(options.DatabasePath)) { options.DatabasePath = Path.Combine( PythonTypeDatabase.CompletionDatabasePath, GetRelativePathForConfigurationId(configuration.Id) ); } if (options.NoDatabase) { // Use the (currenty experimental) non-database backed factory var fact = new Ast.AstPythonInterpreterFactory(configuration, options); return(fact); } else { // Use the database-backed factory var fact = new CPythonInterpreterFactory(configuration, options); if (options.WatchFileSystem) { fact.BeginRefreshIsCurrent(); } return(fact); } }
public static PythonInterpreterFactoryWithDatabase CreateInterpreterFactory(InterpreterConfiguration configuration, InterpreterFactoryCreationOptions options) { return(new CPythonInterpreterFactory(configuration, options)); }
public AstPythonInterpreterFactory(InterpreterConfiguration config, InterpreterFactoryCreationOptions options) : this(config, options, string.IsNullOrEmpty(options?.DatabasePath)) { }
/// <summary> /// Creates a new interpreter factory with the specified options. This /// interpreter always includes a cached completion database. /// </summary> public static PythonInterpreterFactoryWithDatabase CreateInterpreterFactory(InterpreterConfiguration configuration, InterpreterFactoryCreationOptions options = null) { options = options?.Clone() ?? new InterpreterFactoryCreationOptions(); if (string.IsNullOrEmpty(options.DatabasePath)) { var subpath = configuration.Id.Replace('|', '\\'); if (!PathUtils.IsValidPath(subpath)) { subpath = Convert.ToBase64String(new UTF8Encoding(false).GetBytes(configuration.Id)); } options.DatabasePath = Path.Combine(PythonTypeDatabase.CompletionDatabasePath, subpath); } var fact = new CPythonInterpreterFactory(configuration, options); if (options.WatchFileSystem) { fact.BeginRefreshIsCurrent(); } return(fact); }