/// <summary> /// Gets the set of search paths by running the interpreter. /// </summary> /// <param name="interpreter">Path to the interpreter.</param> /// <param name="fs">File system services.</param> /// <param name="ps">Process services.</param> /// <param name="cancellationToken">Cancellation token.</param> /// <returns>A list of search paths for the interpreter.</returns> public static async Task <List <PythonLibraryPath> > GetSearchPathsFromInterpreterAsync(string interpreter, IFileSystem fs, IProcessServices ps, CancellationToken cancellationToken = default) { // sys.path will include the working directory, so we make an empty // path that we can filter out later var tempWorkingDir = IOPath.Combine(IOPath.GetTempPath(), IOPath.GetRandomFileName()); fs.CreateDirectory(tempWorkingDir); if (!InstallPath.TryGetFile("get_search_paths.py", out var srcGetSearchPaths)) { return(new List <PythonLibraryPath>()); } var getSearchPaths = IOPath.Combine(tempWorkingDir, PathUtils.GetFileName(srcGetSearchPaths)); File.Copy(srcGetSearchPaths, getSearchPaths); var startInfo = new ProcessStartInfo( interpreter, new[] { "-S", "-E", getSearchPaths }.AsQuotedArguments() ) { WorkingDirectory = tempWorkingDir, UseShellExecute = false, ErrorDialog = false, CreateNoWindow = true, RedirectStandardInput = true, RedirectStandardOutput = true }; try { var output = await ps.ExecuteAndCaptureOutputAsync(startInfo, cancellationToken); return(output.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Select(s => { try { var p = Parse(s); if (PathUtils.PathStartsWith(p.Path, tempWorkingDir)) { return null; } return p; } catch (ArgumentException) { Debug.Fail("Invalid search path: " + (s ?? "<null>")); return null; } catch (FormatException) { Debug.Fail("Invalid format for search path: " + s); return null; } }).Where(p => p != null).ToList()); } finally { fs.DeleteDirectory(tempWorkingDir, true); } }
/// <summary> /// Gets the set of search paths by running the interpreter. /// </summary> /// <param name="interpreter">Path to the interpreter.</param> /// <param name="fs">File system services.</param> /// <param name="ps">Process services.</param> /// <param name="cancellationToken">Cancellation token.</param> /// <returns>A list of search paths for the interpreter.</returns> public static async Task <ImmutableArray <PythonLibraryPath> > GetSearchPathsFromInterpreterAsync(string interpreter, IFileSystem fs, IProcessServices ps, CancellationToken cancellationToken = default) { // sys.path will include the working directory, so we make an empty // path that we can filter out later var getSearchPathScript = Infrastructure.PythonToolsInstallPath.TryGetFile("get_search_paths.py"); if (getSearchPathScript == null) { return(new ImmutableArray <PythonLibraryPath>()); } var startInfo = new ProcessStartInfo( interpreter, new[] { "-S", "-E", getSearchPathScript }.AsQuotedArguments() ) { WorkingDirectory = IOPath.GetDirectoryName(getSearchPathScript), UseShellExecute = false, ErrorDialog = false, CreateNoWindow = true, RedirectStandardInput = true, RedirectStandardOutput = true }; var output = await ps.ExecuteAndCaptureOutputAsync(startInfo, cancellationToken); return(output.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries) .Select(s => { try { return Parse(s); } catch (ArgumentException) { Debug.Fail("Invalid search path: " + (s ?? "<null>")); return null; } catch (FormatException) { Debug.Fail("Invalid format for search path: " + s); return null; } }).Where(p => p != null).ToImmutableArray()); }