Allow passing a virtual environment to ruff analyze graph (#17743)

Summary
--

Fixes #16598 by adding the `--python` flag to `ruff analyze graph`,
which adds a `PythonPath` to the `SearchPathSettings` for module
resolution. For the [albatross-virtual-workspace] example from the uv
repo, this updates the output from the initial issue:

```shell
> ruff analyze graph packages/albatross
{
  "packages/albatross/check_installed_albatross.py": [
    "packages/albatross/src/albatross/__init__.py"
  ],
  "packages/albatross/src/albatross/__init__.py": []
}
```

To include both the the workspace `bird_feeder` import _and_ the
third-party `tqdm` import in the output:

```shell
> myruff analyze graph packages/albatross --python .venv
{
  "packages/albatross/check_installed_albatross.py": [
    "packages/albatross/src/albatross/__init__.py"
  ],
  "packages/albatross/src/albatross/__init__.py": [
    ".venv/lib/python3.12/site-packages/tqdm/__init__.py",
    "packages/bird-feeder/src/bird_feeder/__init__.py"
  ]
}
```

Note the hash in the uv link! I was temporarily very confused why my
local tests were showing an `iniconfig` import instead of `tqdm` until I
realized that the example has been updated on the uv main branch, which
I had locally.

Test Plan
--

A new integration test with a stripped down venv based on the
`albatross` example.

[albatross-virtual-workspace]:
aa629c4a54/scripts/workspaces/albatross-virtual-workspace
This commit is contained in:
Brent Westbrook 2025-05-01 11:29:52 -04:00 committed by GitHub
parent 75effb8ed7
commit 163d526407
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 164 additions and 2 deletions

View file

@ -4,7 +4,8 @@ use zip::CompressionMethod;
use red_knot_python_semantic::lint::{LintRegistry, RuleSelection};
use red_knot_python_semantic::{
default_lint_registry, Db, Program, ProgramSettings, PythonPlatform, SearchPathSettings,
default_lint_registry, Db, Program, ProgramSettings, PythonPath, PythonPlatform,
SearchPathSettings,
};
use ruff_db::files::{File, Files};
use ruff_db::system::{OsSystem, System, SystemPathBuf};
@ -32,8 +33,12 @@ impl ModuleDb {
pub fn from_src_roots(
src_roots: Vec<SystemPathBuf>,
python_version: PythonVersion,
venv_path: Option<SystemPathBuf>,
) -> Result<Self> {
let search_paths = SearchPathSettings::new(src_roots);
let mut search_paths = SearchPathSettings::new(src_roots);
if let Some(venv_path) = venv_path {
search_paths.python_path = PythonPath::from_cli_flag(venv_path);
}
let db = Self::default();
Program::from_settings(