diff --git a/crates/red_knot/src/main.rs b/crates/red_knot/src/main.rs index 212c7b177d..e1e647bb9c 100644 --- a/crates/red_knot/src/main.rs +++ b/crates/red_knot/src/main.rs @@ -10,7 +10,6 @@ use red_knot_project::metadata::options::{EnvironmentOptions, Options}; use red_knot_project::watch; use red_knot_project::watch::ProjectWatcher; use red_knot_project::{ProjectDatabase, ProjectMetadata}; -use red_knot_python_semantic::SitePackages; use red_knot_server::run_server; use ruff_db::diagnostic::Diagnostic; use ruff_db::system::{OsSystem, System, SystemPath, SystemPathBuf}; @@ -77,9 +76,7 @@ impl Args { venv_path: self .venv_path .as_ref() - .map(|venv_path| SitePackages::Derived { - venv_path: SystemPath::absolute(venv_path, cli_cwd), - }), + .map(|venv_path| SystemPath::absolute(venv_path, cli_cwd)), typeshed: self .typeshed .as_ref() diff --git a/crates/red_knot/tests/file_watching.rs b/crates/red_knot/tests/file_watching.rs index c9277a4691..49788e9785 100644 --- a/crates/red_knot/tests/file_watching.rs +++ b/crates/red_knot/tests/file_watching.rs @@ -8,9 +8,7 @@ use red_knot_project::metadata::options::{EnvironmentOptions, Options}; use red_knot_project::metadata::pyproject::{PyProject, Tool}; use red_knot_project::watch::{directory_watcher, ChangeEvent, ProjectWatcher}; use red_knot_project::{Db, ProjectDatabase, ProjectMetadata}; -use red_knot_python_semantic::{ - resolve_module, ModuleName, PythonPlatform, PythonVersion, SitePackages, -}; +use red_knot_python_semantic::{resolve_module, ModuleName, PythonPlatform, PythonVersion}; use ruff_db::files::{system_path_to_file, File, FileError}; use ruff_db::source::source_text; use ruff_db::system::{OsSystem, SystemPath, SystemPathBuf}; @@ -324,7 +322,6 @@ where .extra_paths .iter() .chain(program_settings.search_paths.typeshed.as_ref()) - .chain(program_settings.search_paths.site_packages.paths()) { std::fs::create_dir_all(path.as_std_path()) .with_context(|| format!("Failed to create search path `{path}`"))?; @@ -794,7 +791,7 @@ fn search_path() -> anyhow::Result<()> { let mut case = setup_with_options([("bar.py", "import sub.a")], |root_path, _project_path| { Some(Options { environment: Some(EnvironmentOptions { - venv_path: Some(SitePackages::Known(vec![root_path.join("site_packages")])), + extra_paths: Some(vec![root_path.join("site_packages")]), ..EnvironmentOptions::default() }), ..Options::default() @@ -835,7 +832,7 @@ fn add_search_path() -> anyhow::Result<()> { // Register site-packages as a search path. case.update_options(Options { environment: Some(EnvironmentOptions { - venv_path: Some(SitePackages::Known(vec![site_packages.clone()])), + extra_paths: Some(vec![site_packages.clone()]), ..EnvironmentOptions::default() }), ..Options::default() @@ -858,7 +855,7 @@ fn remove_search_path() -> anyhow::Result<()> { let mut case = setup_with_options([("bar.py", "import sub.a")], |root_path, _project_path| { Some(Options { environment: Some(EnvironmentOptions { - venv_path: Some(SitePackages::Known(vec![root_path.join("site_packages")])), + extra_paths: Some(vec![root_path.join("site_packages")]), ..EnvironmentOptions::default() }), ..Options::default() @@ -1381,9 +1378,8 @@ mod unix { |_root, project| { Some(Options { environment: Some(EnvironmentOptions { - venv_path: Some(SitePackages::Known(vec![ - project.join(".venv/lib/python3.12/site-packages") - ])), + extra_paths: Some(vec![project.join(".venv/lib/python3.12/site-packages")]), + python_version: Some(PythonVersion::PY312), ..EnvironmentOptions::default() }), ..Options::default() diff --git a/crates/red_knot_project/src/metadata/options.rs b/crates/red_knot_project/src/metadata/options.rs index 7337540436..df3cf02d9c 100644 --- a/crates/red_knot_project/src/metadata/options.rs +++ b/crates/red_knot_project/src/metadata/options.rs @@ -74,7 +74,9 @@ impl Options { extra_paths: extra_paths.unwrap_or_default(), src_roots, typeshed, - site_packages: python.unwrap_or(SitePackages::Known(vec![])), + site_packages: python + .map(|venv_path| SitePackages::Derived { venv_path }) + .unwrap_or(SitePackages::Known(vec![])), } } } @@ -98,7 +100,7 @@ pub struct EnvironmentOptions { // TODO: Rename to python, see https://github.com/astral-sh/ruff/issues/15530 /// The path to the user's `site-packages` directory, where third-party packages from ``PyPI`` are installed. - pub venv_path: Option, + pub venv_path: Option, } #[derive(Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize)] diff --git a/crates/red_knot_python_semantic/src/module_resolver/resolver.rs b/crates/red_knot_python_semantic/src/module_resolver/resolver.rs index 6cc19c0f24..a058683e4a 100644 --- a/crates/red_knot_python_semantic/src/module_resolver/resolver.rs +++ b/crates/red_knot_python_semantic/src/module_resolver/resolver.rs @@ -222,8 +222,14 @@ impl SearchPaths { static_paths.push(stdlib_path); let site_packages_paths = match site_packages_paths { - SitePackages::Derived { venv_path } => VirtualEnvironment::new(venv_path, system) - .and_then(|venv| venv.site_packages_directories(system))?, + SitePackages::Derived { venv_path } => { + // TODO: We may want to warn here if the venv's python version is older + // than the one resolved in the program settings because it indicates + // that the `target-version` is incorrectly configured or that the + // venv is out of date. + VirtualEnvironment::new(venv_path, system) + .and_then(|venv| venv.site_packages_directories(system))? + } SitePackages::Known(paths) => paths .iter() .map(|path| canonicalize(path, system)) diff --git a/crates/red_knot_python_semantic/src/program.rs b/crates/red_knot_python_semantic/src/program.rs index 7f25b7f8a3..02838a7c58 100644 --- a/crates/red_knot_python_semantic/src/program.rs +++ b/crates/red_knot_python_semantic/src/program.rs @@ -134,12 +134,3 @@ pub enum SitePackages { /// Resolved site packages paths Known(Vec), } - -impl SitePackages { - pub fn paths(&self) -> &[SystemPathBuf] { - match self { - SitePackages::Derived { venv_path } => std::slice::from_ref(venv_path), - SitePackages::Known(paths) => paths, - } - } -}