Add a subcommand to generate dependency graphs (#13402)

## Summary

This PR adds an experimental Ruff subcommand to generate dependency
graphs based on module resolution.

A few highlights:

- You can generate either dependency or dependent graphs via the
`--direction` command-line argument.
- Like Pants, we also provide an option to identify imports from string
literals (`--detect-string-imports`).
- Users can also provide additional dependency data via the
`include-dependencies` key under `[tool.ruff.import-map]`. This map uses
file paths as keys, and lists of strings as values. Those strings can be
file paths or globs.

The dependency resolution uses the red-knot module resolver which is
intended to be fully spec compliant, so it's also a chance to expose the
module resolver in a real-world setting.

The CLI is, e.g., `ruff graph build ../autobot`, which will output a
JSON map from file to files it depends on for the `autobot` project.
This commit is contained in:
Charlie Marsh 2024-09-19 21:06:32 -04:00 committed by GitHub
parent 260c2ecd15
commit 4e935f7d7d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 1339 additions and 45 deletions

View file

@ -1,6 +1,7 @@
use path_absolutize::path_dedot;
use ruff_cache::cache_dir;
use ruff_formatter::{FormatOptions, IndentStyle, IndentWidth, LineWidth};
use ruff_graph::AnalyzeSettings;
use ruff_linter::display_settings;
use ruff_linter::settings::types::{
ExtensionMapping, FilePattern, FilePatternSet, OutputFormat, UnsafeFixes,
@ -35,6 +36,7 @@ pub struct Settings {
pub file_resolver: FileResolverSettings,
pub linter: LinterSettings,
pub formatter: FormatterSettings,
pub analyze: AnalyzeSettings,
}
impl Default for Settings {
@ -50,6 +52,7 @@ impl Default for Settings {
linter: LinterSettings::new(project_root),
file_resolver: FileResolverSettings::new(project_root),
formatter: FormatterSettings::default(),
analyze: AnalyzeSettings::default(),
}
}
}
@ -68,7 +71,8 @@ impl fmt::Display for Settings {
self.unsafe_fixes,
self.file_resolver | nested,
self.linter | nested,
self.formatter | nested
self.formatter | nested,
self.analyze | nested,
]
}
Ok(())