private void OnChanged(object sender, FileSystemEventArgs e) { if ((Directory.Exists(e.FullPath) && !PathUtils.GetFileOrDirectoryName(e.FullPath).Equals("__pycache__", StringComparison.OrdinalIgnoreCase)) || ModulePath.IsPythonFile(e.FullPath, false, true, false) ) { try { _refreshIsCurrentTrigger.Change(1000, Timeout.Infinite); } catch (ObjectDisposedException) { } } }
private async Task CreateLibraryWatchers() { Debug.Assert(_libWatchers != null, "Should not create watchers when suppressed"); IReadOnlyList <string> paths = null; if (_factory.Configuration.SearchPaths.Any()) { paths = _factory.Configuration.SearchPaths; } if (paths == null) { try { paths = (await PythonLibraryPath.GetSearchPathsAsync(_factory.Configuration, new FileSystem(new OSPlatform()), new ProcessServices())) .Select(p => p.Path) .ToArray(); } catch (InvalidOperationException) { return; } } paths = paths .Where(Directory.Exists) .OrderBy(p => p.Length) .ToList(); var watching = new List <string>(); var watchers = new List <FileSystemWatcher>(); foreach (var path in paths) { if (watching.Any(p => PathUtils.IsSubpathOf(p, path))) { continue; } FileSystemWatcher watcher = null; try { watcher = new FileSystemWatcher { IncludeSubdirectories = true, Path = path, NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.LastWrite }; watcher.Created += OnChanged; watcher.Deleted += OnChanged; watcher.Changed += OnChanged; watcher.Renamed += OnRenamed; watcher.EnableRaisingEvents = true; watching.Add(path); watchers.Add(watcher); } catch (IOException) { // Raced with directory deletion. We normally handle the // library being deleted by disposing the watcher, but this // occurs in response to an event from the watcher. Because // we never got to start watching, we will just dispose // immediately. watcher?.Dispose(); } catch (ArgumentException ex) { watcher?.Dispose(); Debug.WriteLine("Error starting FileSystemWatcher:\r\n{0}", ex); } } List <FileSystemWatcher> oldWatchers; lock (_libWatchers) { oldWatchers = _libWatchers.ToList(); _libWatchers.Clear(); _libWatchers.AddRange(watchers); } foreach (var oldWatcher in oldWatchers) { oldWatcher.EnableRaisingEvents = false; oldWatcher.Dispose(); } }
private async Task CacheInstalledPackagesAsync( bool alreadyHasLock, bool alreadyHasConcurrencyLock, CancellationToken cancellationToken ) { if (!IsReady) { await UpdateIsReadyAsync(alreadyHasLock, cancellationToken); if (!IsReady) { return; } } List <PackageSpec> packages = null; var workingLock = alreadyHasLock ? null : await _working.LockAsync(cancellationToken); try { var args = _pipListHasFormatOption ? _commands.ListJson() : _commands.List(); var concurrencyLock = alreadyHasConcurrencyLock ? null : await _concurrencyLock.LockAsync(cancellationToken); try { var envVars = await GetEnvironmentVariables(); using (var proc = ProcessOutput.Run( _factory.Configuration.InterpreterPath, args, _factory.Configuration.GetPrefixPath(), envVars, false, null )) { try { if ((await proc) == 0) { if (_pipListHasFormatOption) { try { var data = JToken.ReadFrom(new JsonTextReader(new StringListReader(proc.StandardOutputLines))); packages = data .Select(j => new PackageSpec(j.Value <string>("name"), j.Value <string>("version"))) .Where(p => p.IsValid) .OrderBy(p => p.Name) .ToList(); } catch (JsonException ex) { Debug.WriteLine("Failed to parse: {0}".FormatInvariant(ex.Message)); foreach (var l in proc.StandardOutputLines) { Debug.WriteLine(l); } } } else { packages = proc.StandardOutputLines .Select(i => PackageSpec.FromPipList(i)) .Where(p => p.IsValid) .OrderBy(p => p.Name) .ToList(); } } else if (_pipListHasFormatOption) { // Actually, pip probably doesn't have the --format option Debug.WriteLine("{0} does not support --format".FormatInvariant(_factory.Configuration.InterpreterPath)); _pipListHasFormatOption = false; await CacheInstalledPackagesAsync(true, true, cancellationToken); return; } else { } } catch (OperationCanceledException) { // Process failed to run Debug.WriteLine("Failed to run pip to collect packages"); foreach (var line in proc.StandardOutputLines) { Debug.WriteLine(line); } } } if (packages == null) { // Pip failed, so return a directory listing var paths = await PythonLibraryPath.GetSearchPathsAsync( _factory.Configuration, new FileSystem(new OSPlatform()), new ProcessServices() ); packages = await Task.Run(() => paths.Where(p => p.Type != PythonLibraryPathType.StdLib && Directory.Exists(p.Path)) .SelectMany(p => PathUtils.EnumerateDirectories(p.Path, recurse: false)) .Select(path => Path.GetFileName(path)) .Select(name => PackageNameRegex.Match(name)) .Where(match => match.Success) .Select(match => new PackageSpec(match.Groups["name"].Value)) .Where(p => p.IsValid) .OrderBy(p => p.Name) .ToList()); } } finally { concurrencyLock?.Dispose(); } // Outside of concurrency lock, still in working lock _packages.Clear(); _packages.AddRange(packages); _everCached = true; } finally { workingLock?.Dispose(); } InstalledPackagesChanged?.Invoke(this, EventArgs.Empty); _factory.NotifyImportNamesChanged(); }