[ty] Move venv and conda env discovery to SearchPath::from_settings (#18938)

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
Micha Reiser 2025-06-26 16:39:27 +02:00 committed by GitHub
parent d04e63a6d9
commit 76387295a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 147 additions and 108 deletions

View file

@ -17,6 +17,7 @@ fn command() -> Command {
command.arg("analyze"); command.arg("analyze");
command.arg("graph"); command.arg("graph");
command.arg("--preview"); command.arg("--preview");
command.env_clear();
command command
} }

View file

@ -429,8 +429,7 @@ impl<'a> ProjectBenchmark<'a> {
metadata.apply_options(Options { metadata.apply_options(Options {
environment: Some(EnvironmentOptions { environment: Some(EnvironmentOptions {
python_version: Some(RangedValue::cli(self.project.config.python_version)), python_version: Some(RangedValue::cli(self.project.config.python_version)),
python: (!self.project.config().dependencies.is_empty()) python: Some(RelativePathBuf::cli(SystemPath::new(".venv"))),
.then_some(RelativePathBuf::cli(SystemPath::new(".venv"))),
..EnvironmentOptions::default() ..EnvironmentOptions::default()
}), }),
..Options::default() ..Options::default()

View file

@ -36,8 +36,7 @@ impl<'a> Benchmark<'a> {
metadata.apply_options(Options { metadata.apply_options(Options {
environment: Some(EnvironmentOptions { environment: Some(EnvironmentOptions {
python_version: Some(RangedValue::cli(self.project.config.python_version)), python_version: Some(RangedValue::cli(self.project.config.python_version)),
python: (!self.project.config().dependencies.is_empty()) python: Some(RelativePathBuf::cli(SystemPath::new(".venv"))),
.then_some(RelativePathBuf::cli(SystemPath::new(".venv"))),
..EnvironmentOptions::default() ..EnvironmentOptions::default()
}), }),
..Options::default() ..Options::default()

View file

@ -74,19 +74,17 @@ impl<'a> RealWorldProject<'a> {
}; };
// Install dependencies if specified // Install dependencies if specified
if !checkout.project().dependencies.is_empty() { tracing::debug!(
tracing::debug!( "Installing {} dependencies for project '{}'...",
"Installing {} dependencies for project '{}'...", checkout.project().dependencies.len(),
checkout.project().dependencies.len(), checkout.project().name
checkout.project().name );
); let start_install = std::time::Instant::now();
let start = std::time::Instant::now(); install_dependencies(&checkout)?;
install_dependencies(&checkout)?; tracing::debug!(
tracing::debug!( "Dependency installation completed in {:.2}s",
"Dependency installation completed in {:.2}s", start_install.elapsed().as_secs_f64()
start.elapsed().as_secs_f64() );
);
}
tracing::debug!("Project setup took: {:.2}s", start.elapsed().as_secs_f64()); tracing::debug!("Project setup took: {:.2}s", start.elapsed().as_secs_f64());
@ -281,6 +279,14 @@ fn install_dependencies(checkout: &Checkout) -> Result<()> {
String::from_utf8_lossy(&output.stderr) String::from_utf8_lossy(&output.stderr)
); );
if checkout.project().dependencies.is_empty() {
tracing::debug!(
"No dependencies to install for project '{}'",
checkout.project().name
);
return Ok(());
}
// Install dependencies with date constraint in the isolated environment // Install dependencies with date constraint in the isolated environment
let mut cmd = Command::new("uv"); let mut cmd = Command::new("uv");
cmd.args([ cmd.args([

View file

@ -30,14 +30,14 @@ filetime = { workspace = true }
glob = { workspace = true } glob = { workspace = true }
ignore = { workspace = true, optional = true } ignore = { workspace = true, optional = true }
matchit = { workspace = true } matchit = { workspace = true }
path-slash = { workspace = true }
rustc-hash = { workspace = true }
salsa = { workspace = true } salsa = { workspace = true }
schemars = { workspace = true, optional = true } schemars = { workspace = true, optional = true }
serde = { workspace = true, optional = true } serde = { workspace = true, optional = true }
path-slash = { workspace = true }
thiserror = { workspace = true } thiserror = { workspace = true }
tracing = { workspace = true } tracing = { workspace = true }
tracing-subscriber = { workspace = true, optional = true } tracing-subscriber = { workspace = true, optional = true }
rustc-hash = { workspace = true }
zip = { workspace = true } zip = { workspace = true }
[target.'cfg(target_arch="wasm32")'.dependencies] [target.'cfg(target_arch="wasm32")'.dependencies]

View file

@ -9,7 +9,7 @@ use ruff_db::{Db as SourceDb, Upcast};
use ruff_python_ast::PythonVersion; use ruff_python_ast::PythonVersion;
use ty_python_semantic::lint::{LintRegistry, RuleSelection}; use ty_python_semantic::lint::{LintRegistry, RuleSelection};
use ty_python_semantic::{ use ty_python_semantic::{
Db, Program, ProgramSettings, PythonPath, PythonPlatform, PythonVersionSource, Db, Program, ProgramSettings, PythonEnvironmentPath, PythonPlatform, PythonVersionSource,
PythonVersionWithSource, SearchPathSettings, SysPrefixPathOrigin, default_lint_registry, PythonVersionWithSource, SearchPathSettings, SysPrefixPathOrigin, default_lint_registry,
}; };
@ -36,11 +36,11 @@ impl ModuleDb {
venv_path: Option<SystemPathBuf>, venv_path: Option<SystemPathBuf>,
) -> Result<Self> { ) -> Result<Self> {
let mut search_paths = SearchPathSettings::new(src_roots); let mut search_paths = SearchPathSettings::new(src_roots);
// TODO: Consider setting `PythonPath::Auto` if no venv_path is provided.
if let Some(venv_path) = venv_path { if let Some(venv_path) = venv_path {
search_paths.python_path = search_paths.python_environment =
PythonPath::sys_prefix(venv_path, SysPrefixPathOrigin::PythonCliFlag); PythonEnvironmentPath::explicit(venv_path, SysPrefixPathOrigin::PythonCliFlag);
} }
let db = Self::default(); let db = Self::default();
let search_paths = search_paths let search_paths = search_paths
.to_search_paths(db.system(), db.vendored()) .to_search_paths(db.system(), db.vendored())

View file

@ -708,9 +708,8 @@ impl CliTest {
let mut command = Command::new(get_cargo_bin("ty")); let mut command = Command::new(get_cargo_bin("ty"));
command.current_dir(&self.project_dir).arg("check"); command.current_dir(&self.project_dir).arg("check");
// Unset environment variables that can affect test behavior // Unset all environment variables because they can affect test behavior.
command.env_remove("VIRTUAL_ENV"); command.env_clear();
command.env_remove("CONDA_PREFIX");
command command
} }

View file

@ -3,7 +3,7 @@ use std::{collections::HashMap, hash::BuildHasher};
use ordermap::OrderMap; use ordermap::OrderMap;
use ruff_db::system::SystemPathBuf; use ruff_db::system::SystemPathBuf;
use ruff_python_ast::PythonVersion; use ruff_python_ast::PythonVersion;
use ty_python_semantic::{PythonPath, PythonPlatform}; use ty_python_semantic::{PythonEnvironmentPath, PythonPlatform};
/// Combine two values, preferring the values in `self`. /// Combine two values, preferring the values in `self`.
/// ///
@ -141,7 +141,7 @@ macro_rules! impl_noop_combine {
impl_noop_combine!(SystemPathBuf); impl_noop_combine!(SystemPathBuf);
impl_noop_combine!(PythonPlatform); impl_noop_combine!(PythonPlatform);
impl_noop_combine!(PythonPath); impl_noop_combine!(PythonEnvironmentPath);
impl_noop_combine!(PythonVersion); impl_noop_combine!(PythonVersion);
// std types // std types

View file

@ -2,10 +2,11 @@ use crate::Db;
use crate::combine::Combine; use crate::combine::Combine;
use crate::glob::{ExcludeFilter, IncludeExcludeFilter, IncludeFilter, PortableGlobKind}; use crate::glob::{ExcludeFilter, IncludeExcludeFilter, IncludeFilter, PortableGlobKind};
use crate::metadata::settings::{OverrideSettings, SrcSettings}; use crate::metadata::settings::{OverrideSettings, SrcSettings};
use super::settings::{Override, Settings, TerminalSettings};
use crate::metadata::value::{ use crate::metadata::value::{
RangedValue, RelativeGlobPattern, RelativePathBuf, ValueSource, ValueSourceGuard, RangedValue, RelativeGlobPattern, RelativePathBuf, ValueSource, ValueSourceGuard,
}; };
use ordermap::OrderMap; use ordermap::OrderMap;
use ruff_db::RustDoc; use ruff_db::RustDoc;
use ruff_db::diagnostic::{ use ruff_db::diagnostic::{
@ -28,13 +29,11 @@ use std::sync::Arc;
use thiserror::Error; use thiserror::Error;
use ty_python_semantic::lint::{GetLintError, Level, LintSource, RuleSelection}; use ty_python_semantic::lint::{GetLintError, Level, LintSource, RuleSelection};
use ty_python_semantic::{ use ty_python_semantic::{
ProgramSettings, PythonPath, PythonPlatform, PythonVersionFileSource, PythonVersionSource, ProgramSettings, PythonEnvironmentPath, PythonPlatform, PythonVersionFileSource,
PythonVersionWithSource, SearchPathSettings, SearchPathValidationError, SearchPaths, PythonVersionSource, PythonVersionWithSource, SearchPathSettings, SearchPathValidationError,
SysPrefixPathOrigin, SearchPaths, SysPrefixPathOrigin,
}; };
use super::settings::{Override, Settings, TerminalSettings};
#[derive( #[derive(
Debug, Default, Clone, PartialEq, Eq, Combine, Serialize, Deserialize, OptionsMetadata, Debug, Default, Clone, PartialEq, Eq, Combine, Serialize, Deserialize, OptionsMetadata,
)] )]
@ -231,7 +230,7 @@ impl Options {
.typeshed .typeshed
.as_ref() .as_ref()
.map(|path| path.absolute(project_root, system)), .map(|path| path.absolute(project_root, system)),
python_path: environment python_environment: environment
.python .python
.as_ref() .as_ref()
.map(|python_path| { .map(|python_path| {
@ -242,24 +241,12 @@ impl Options {
python_path.range(), python_path.range(),
), ),
}; };
PythonPath::sys_prefix(python_path.absolute(project_root, system), origin) PythonEnvironmentPath::explicit(
}) python_path.absolute(project_root, system),
.or_else(|| { origin,
system.env_var("VIRTUAL_ENV").ok().map(|virtual_env| {
PythonPath::sys_prefix(virtual_env, SysPrefixPathOrigin::VirtualEnvVar)
})
})
.or_else(|| {
system.env_var("CONDA_PREFIX").ok().map(|path| {
PythonPath::sys_prefix(path, SysPrefixPathOrigin::CondaPrefixVar)
})
})
.unwrap_or_else(|| {
PythonPath::sys_prefix(
project_root.to_path_buf(),
SysPrefixPathOrigin::LocalVenv,
) )
}), })
.unwrap_or_else(|| PythonEnvironmentPath::Discover(project_root.to_path_buf())),
}; };
settings.to_search_paths(system, vendored) settings.to_search_paths(system, vendored)

View file

@ -11,7 +11,7 @@ pub use module_resolver::{
system_module_search_paths, system_module_search_paths,
}; };
pub use program::{ pub use program::{
Program, ProgramSettings, PythonPath, PythonVersionFileSource, PythonVersionSource, Program, ProgramSettings, PythonEnvironmentPath, PythonVersionFileSource, PythonVersionSource,
PythonVersionWithSource, SearchPathSettings, PythonVersionWithSource, SearchPathSettings,
}; };
pub use python_platform::PythonPlatform; pub use python_platform::PythonPlatform;

View file

@ -15,9 +15,12 @@ use ruff_python_ast::PythonVersion;
use crate::db::Db; use crate::db::Db;
use crate::module_name::ModuleName; use crate::module_name::ModuleName;
use crate::module_resolver::typeshed::{TypeshedVersions, vendored_typeshed_versions}; use crate::module_resolver::typeshed::{TypeshedVersions, vendored_typeshed_versions};
use crate::site_packages::{PythonEnvironment, SitePackagesPaths, SysPrefixPathOrigin}; use crate::site_packages::{
PythonEnvironment, SitePackagesDiscoveryError, SitePackagesPaths, SysPrefixPathOrigin,
};
use crate::{ use crate::{
Program, PythonPath, PythonVersionSource, PythonVersionWithSource, SearchPathSettings, Program, PythonEnvironmentPath, PythonVersionSource, PythonVersionWithSource,
SearchPathSettings,
}; };
use super::module::{Module, ModuleKind}; use super::module::{Module, ModuleKind};
@ -188,7 +191,7 @@ impl SearchPaths {
extra_paths, extra_paths,
src_roots, src_roots,
custom_typeshed: typeshed, custom_typeshed: typeshed,
python_path, python_environment: python_path,
} = settings; } = settings;
let mut static_paths = vec![]; let mut static_paths = vec![];
@ -234,37 +237,16 @@ impl SearchPaths {
static_paths.push(stdlib_path); static_paths.push(stdlib_path);
let (site_packages_paths, python_version) = match python_path { let (site_packages_paths, python_version) = match python_path {
PythonPath::IntoSysPrefix(path, origin) => { PythonEnvironmentPath::Discover(project_root) => {
if origin == &SysPrefixPathOrigin::LocalVenv { Self::discover_python_environment(system, project_root)?
tracing::debug!("Discovering virtual environment in `{path}`");
let virtual_env_directory = path.join(".venv");
PythonEnvironment::new(
&virtual_env_directory,
SysPrefixPathOrigin::LocalVenv,
system,
)
.and_then(|venv| venv.into_settings(system))
.inspect_err(|err| {
if system.is_directory(&virtual_env_directory) {
tracing::debug!(
"Ignoring automatically detected virtual environment at `{}`: {}",
&virtual_env_directory,
err
);
}
})
.unwrap_or_else(|_| {
tracing::debug!("No virtual environment found");
(SitePackagesPaths::default(), None)
})
} else {
tracing::debug!("Resolving {origin}: {path}");
PythonEnvironment::new(path, origin.clone(), system)?.into_settings(system)?
}
} }
PythonPath::KnownSitePackages(paths) => ( PythonEnvironmentPath::Explicit(prefix, origin) => {
tracing::debug!("Resolving {origin}: {prefix}");
PythonEnvironment::new(prefix, origin.clone(), system)?.into_settings(system)?
}
PythonEnvironmentPath::Testing(paths) => (
paths paths
.iter() .iter()
.map(|path| canonicalize(path, system)) .map(|path| canonicalize(path, system))
@ -307,6 +289,64 @@ impl SearchPaths {
}) })
} }
fn discover_python_environment(
system: &dyn System,
project_root: &SystemPath,
) -> Result<(SitePackagesPaths, Option<PythonVersionWithSource>), SitePackagesDiscoveryError>
{
fn resolve_environment(
system: &dyn System,
path: &SystemPath,
origin: SysPrefixPathOrigin,
) -> Result<(SitePackagesPaths, Option<PythonVersionWithSource>), SitePackagesDiscoveryError>
{
tracing::debug!("Resolving {origin}: {path}");
PythonEnvironment::new(path, origin, system)?.into_settings(system)
}
if let Ok(virtual_env) = system.env_var("VIRTUAL_ENV") {
return resolve_environment(
system,
SystemPath::new(&virtual_env),
SysPrefixPathOrigin::VirtualEnvVar,
);
}
if let Ok(conda_env) = system.env_var("CONDA_PREFIX") {
return resolve_environment(
system,
SystemPath::new(&conda_env),
SysPrefixPathOrigin::CondaPrefixVar,
);
}
tracing::debug!("Discovering virtual environment in `{project_root}`");
let virtual_env_directory = project_root.join(".venv");
match PythonEnvironment::new(
&virtual_env_directory,
SysPrefixPathOrigin::LocalVenv,
system,
)
.and_then(|venv| venv.into_settings(system))
{
Ok(settings) => return Ok(settings),
Err(err) => {
if system.is_directory(&virtual_env_directory) {
tracing::debug!(
"Ignoring automatically detected virtual environment at `{}`: {}",
&virtual_env_directory,
err
);
}
}
}
tracing::debug!("No virtual environment found");
Ok((SitePackagesPaths::default(), None))
}
pub(crate) fn try_register_static_roots(&self, db: &dyn Db) { pub(crate) fn try_register_static_roots(&self, db: &dyn Db) {
let files = db.files(); let files = db.files();
for path in self.static_paths.iter().chain(self.site_packages.iter()) { for path in self.static_paths.iter().chain(self.site_packages.iter()) {
@ -1494,7 +1534,7 @@ mod tests {
python_platform: PythonPlatform::default(), python_platform: PythonPlatform::default(),
search_paths: SearchPathSettings { search_paths: SearchPathSettings {
custom_typeshed: Some(custom_typeshed), custom_typeshed: Some(custom_typeshed),
python_path: PythonPath::KnownSitePackages(vec![site_packages]), python_environment: PythonEnvironmentPath::Testing(vec![site_packages]),
..SearchPathSettings::new(vec![src.clone()]) ..SearchPathSettings::new(vec![src.clone()])
} }
.to_search_paths(db.system(), db.vendored()) .to_search_paths(db.system(), db.vendored())
@ -2009,7 +2049,7 @@ not_a_directory
python_version: PythonVersionWithSource::default(), python_version: PythonVersionWithSource::default(),
python_platform: PythonPlatform::default(), python_platform: PythonPlatform::default(),
search_paths: SearchPathSettings { search_paths: SearchPathSettings {
python_path: PythonPath::KnownSitePackages(vec![ python_environment: PythonEnvironmentPath::Testing(vec![
venv_site_packages, venv_site_packages,
system_site_packages, system_site_packages,
]), ]),
@ -2126,7 +2166,7 @@ not_a_directory
python_version: PythonVersionWithSource::default(), python_version: PythonVersionWithSource::default(),
python_platform: PythonPlatform::default(), python_platform: PythonPlatform::default(),
search_paths: SearchPathSettings { search_paths: SearchPathSettings {
python_path: PythonPath::KnownSitePackages(vec![site_packages.clone()]), python_environment: PythonEnvironmentPath::Testing(vec![site_packages.clone()]),
..SearchPathSettings::new(vec![project_directory]) ..SearchPathSettings::new(vec![project_directory])
} }
.to_search_paths(db.system(), db.vendored()) .to_search_paths(db.system(), db.vendored())

View file

@ -8,7 +8,8 @@ use ruff_python_ast::PythonVersion;
use crate::db::tests::TestDb; use crate::db::tests::TestDb;
use crate::program::{Program, SearchPathSettings}; use crate::program::{Program, SearchPathSettings};
use crate::{ use crate::{
ProgramSettings, PythonPath, PythonPlatform, PythonVersionSource, PythonVersionWithSource, ProgramSettings, PythonEnvironmentPath, PythonPlatform, PythonVersionSource,
PythonVersionWithSource,
}; };
/// A test case for the module resolver. /// A test case for the module resolver.
@ -245,7 +246,7 @@ impl TestCaseBuilder<MockedTypeshed> {
python_platform, python_platform,
search_paths: SearchPathSettings { search_paths: SearchPathSettings {
custom_typeshed: Some(typeshed.clone()), custom_typeshed: Some(typeshed.clone()),
python_path: PythonPath::KnownSitePackages(vec![site_packages.clone()]), python_environment: PythonEnvironmentPath::Testing(vec![site_packages.clone()]),
..SearchPathSettings::new(vec![src.clone()]) ..SearchPathSettings::new(vec![src.clone()])
} }
.to_search_paths(db.system(), db.vendored()) .to_search_paths(db.system(), db.vendored())
@ -305,7 +306,7 @@ impl TestCaseBuilder<VendoredTypeshed> {
}, },
python_platform, python_platform,
search_paths: SearchPathSettings { search_paths: SearchPathSettings {
python_path: PythonPath::KnownSitePackages(vec![site_packages.clone()]), python_environment: PythonEnvironmentPath::Testing(vec![site_packages.clone()]),
..SearchPathSettings::new(vec![src.clone()]) ..SearchPathSettings::new(vec![src.clone()])
} }
.to_search_paths(db.system(), db.vendored()) .to_search_paths(db.system(), db.vendored())

View file

@ -1,9 +1,8 @@
use std::sync::Arc; use std::sync::Arc;
use crate::Db;
use crate::module_resolver::{SearchPathValidationError, SearchPaths}; use crate::module_resolver::{SearchPathValidationError, SearchPaths};
use crate::python_platform::PythonPlatform; use crate::python_platform::PythonPlatform;
use crate::site_packages::SysPrefixPathOrigin; use crate::{Db, SysPrefixPathOrigin};
use ruff_db::diagnostic::Span; use ruff_db::diagnostic::Span;
use ruff_db::files::system_path_to_file; use ruff_db::files::system_path_to_file;
@ -174,9 +173,9 @@ pub struct SearchPathSettings {
/// bundled as a zip file in the binary /// bundled as a zip file in the binary
pub custom_typeshed: Option<SystemPathBuf>, pub custom_typeshed: Option<SystemPathBuf>,
/// Path to the Python installation from which ty resolves third party dependencies /// Path to the Python environment from which ty resolves third party dependencies
/// and their type information. /// and their type information.
pub python_path: PythonPath, pub python_environment: PythonEnvironmentPath,
} }
impl SearchPathSettings { impl SearchPathSettings {
@ -192,7 +191,7 @@ impl SearchPathSettings {
src_roots: vec![], src_roots: vec![],
extra_paths: vec![], extra_paths: vec![],
custom_typeshed: None, custom_typeshed: None,
python_path: PythonPath::KnownSitePackages(vec![]), python_environment: PythonEnvironmentPath::Testing(vec![]),
} }
} }
@ -206,8 +205,16 @@ impl SearchPathSettings {
} }
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
pub enum PythonPath { pub enum PythonEnvironmentPath {
/// A path that either represents the value of [`sys.prefix`] at runtime in Python /// The path to the Python environment isn't known. Try to discover the Python environment
/// by inspecting environment variables, the project structure, etc. and derive the path from it.
///
/// The path is the project root in which to search for a Python environment.
Discover(SystemPathBuf),
/// Path to a Python environment that is explicitly specified.
///
/// The path that either represents the value of [`sys.prefix`] at runtime in Python
/// for a given Python executable, or which represents a path relative to `sys.prefix` /// for a given Python executable, or which represents a path relative to `sys.prefix`
/// that we will attempt later to resolve into `sys.prefix`. Exactly which this variant /// that we will attempt later to resolve into `sys.prefix`. Exactly which this variant
/// represents depends on the [`SysPrefixPathOrigin`] element in the tuple. /// represents depends on the [`SysPrefixPathOrigin`] element in the tuple.
@ -222,17 +229,17 @@ pub enum PythonPath {
/// `/opt/homebrew/lib/python3.X/site-packages`. /// `/opt/homebrew/lib/python3.X/site-packages`.
/// ///
/// [`sys.prefix`]: https://docs.python.org/3/library/sys.html#sys.prefix /// [`sys.prefix`]: https://docs.python.org/3/library/sys.html#sys.prefix
IntoSysPrefix(SystemPathBuf, SysPrefixPathOrigin), Explicit(SystemPathBuf, SysPrefixPathOrigin),
/// Resolved site packages paths. /// Don't search for a Python environment, instead use the provided site packages paths.
/// ///
/// This variant is mainly intended for testing where we want to skip resolving `site-packages` /// This variant is mainly intended for testing where we want to skip resolving `site-packages`
/// because it would unnecessarily complicate the test setup. /// because it would unnecessarily complicate the test setup.
KnownSitePackages(Vec<SystemPathBuf>), Testing(Vec<SystemPathBuf>),
} }
impl PythonPath { impl PythonEnvironmentPath {
pub fn sys_prefix(path: impl Into<SystemPathBuf>, origin: SysPrefixPathOrigin) -> Self { pub fn explicit(path: impl Into<SystemPathBuf>, origin: SysPrefixPathOrigin) -> Self {
Self::IntoSysPrefix(path.into(), origin) Self::Explicit(path.into(), origin)
} }
} }

View file

@ -21,7 +21,7 @@ use std::fmt::Write;
use ty_python_semantic::pull_types::pull_types; use ty_python_semantic::pull_types::pull_types;
use ty_python_semantic::types::check_types; use ty_python_semantic::types::check_types;
use ty_python_semantic::{ use ty_python_semantic::{
Program, ProgramSettings, PythonPath, PythonPlatform, PythonVersionSource, Program, ProgramSettings, PythonEnvironmentPath, PythonPlatform, PythonVersionSource,
PythonVersionWithSource, SearchPathSettings, SysPrefixPathOrigin, PythonVersionWithSource, SearchPathSettings, SysPrefixPathOrigin,
}; };
@ -271,15 +271,15 @@ fn run_test(
src_roots: vec![src_path], src_roots: vec![src_path],
extra_paths: configuration.extra_paths().unwrap_or_default().to_vec(), extra_paths: configuration.extra_paths().unwrap_or_default().to_vec(),
custom_typeshed: custom_typeshed_path.map(SystemPath::to_path_buf), custom_typeshed: custom_typeshed_path.map(SystemPath::to_path_buf),
python_path: configuration python_environment: configuration
.python() .python()
.map(|sys_prefix| { .map(|sys_prefix| {
PythonPath::IntoSysPrefix( PythonEnvironmentPath::explicit(
sys_prefix.to_path_buf(), sys_prefix.to_path_buf(),
SysPrefixPathOrigin::PythonCliFlag, SysPrefixPathOrigin::PythonCliFlag,
) )
}) })
.unwrap_or(PythonPath::KnownSitePackages(vec![])), .unwrap_or(PythonEnvironmentPath::Testing(vec![])),
} }
.to_search_paths(db.system(), db.vendored()) .to_search_paths(db.system(), db.vendored())
.expect("Failed to resolve search path settings"), .expect("Failed to resolve search path settings"),