mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 12:55:05 +00:00
[ty] Do not allow invalid virtual environments from discovered .venv
or VIRTUAL_ENV
(#18003)
Follow-up to https://github.com/astral-sh/ruff/pull/17991 ensuring we do not allow detection of system environments when the origin is `VIRTUAL_ENV` or a discovered `.venv` directory — i.e., those always require a `pyvenv.cfg` file.
This commit is contained in:
parent
2923c55698
commit
0bb8cbdf07
1 changed files with 67 additions and 9 deletions
|
@ -39,7 +39,9 @@ impl PythonEnvironment {
|
||||||
Ok(venv) => Ok(Self::Virtual(venv)),
|
Ok(venv) => Ok(Self::Virtual(venv)),
|
||||||
// If there's not a `pyvenv.cfg` marker, attempt to inspect as a system environment
|
// If there's not a `pyvenv.cfg` marker, attempt to inspect as a system environment
|
||||||
//
|
//
|
||||||
Err(SitePackagesDiscoveryError::NoPyvenvCfgFile(_, _)) => {
|
Err(SitePackagesDiscoveryError::NoPyvenvCfgFile(_, _))
|
||||||
|
if !origin.must_be_virtual_env() =>
|
||||||
|
{
|
||||||
Ok(Self::System(SystemEnvironment::new(path)))
|
Ok(Self::System(SystemEnvironment::new(path)))
|
||||||
}
|
}
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
|
@ -531,6 +533,17 @@ pub enum SysPrefixPathOrigin {
|
||||||
LocalVenv,
|
LocalVenv,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SysPrefixPathOrigin {
|
||||||
|
/// Whether the given `sys.prefix` path must be a virtual environment (rather than a system
|
||||||
|
/// Python environment).
|
||||||
|
pub(crate) fn must_be_virtual_env(self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::LocalVenv | Self::VirtualEnvVar => true,
|
||||||
|
Self::PythonCliFlag | Self::Derived => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for SysPrefixPathOrigin {
|
impl Display for SysPrefixPathOrigin {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
@ -626,6 +639,7 @@ mod tests {
|
||||||
system: TestSystem,
|
system: TestSystem,
|
||||||
minor_version: u8,
|
minor_version: u8,
|
||||||
free_threaded: bool,
|
free_threaded: bool,
|
||||||
|
origin: SysPrefixPathOrigin,
|
||||||
virtual_env: Option<VirtualEnvironmentTestCase>,
|
virtual_env: Option<VirtualEnvironmentTestCase>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,6 +650,7 @@ mod tests {
|
||||||
system,
|
system,
|
||||||
minor_version,
|
minor_version,
|
||||||
free_threaded,
|
free_threaded,
|
||||||
|
origin: _,
|
||||||
virtual_env,
|
virtual_env,
|
||||||
} = self;
|
} = self;
|
||||||
let memory_fs = system.memory_file_system();
|
let memory_fs = system.memory_file_system();
|
||||||
|
@ -706,14 +721,17 @@ mod tests {
|
||||||
venv_sys_prefix
|
venv_sys_prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn err(self) -> SitePackagesDiscoveryError {
|
||||||
|
PythonEnvironment::new(self.build(), self.origin, &self.system)
|
||||||
|
.expect_err("Expected environment construction to fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
fn run(self) {
|
fn run(self) {
|
||||||
let env_path = self.build();
|
let env_path = self.build();
|
||||||
let env = PythonEnvironment::new(
|
let env = PythonEnvironment::new(env_path.clone(), self.origin, &self.system)
|
||||||
env_path.clone(),
|
.expect("Expected environment construction to succeed");
|
||||||
SysPrefixPathOrigin::VirtualEnvVar,
|
|
||||||
&self.system,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let expect_virtual_env = self.virtual_env.is_some();
|
let expect_virtual_env = self.virtual_env.is_some();
|
||||||
match env {
|
match env {
|
||||||
|
@ -747,7 +765,7 @@ mod tests {
|
||||||
venv.root_path,
|
venv.root_path,
|
||||||
SysPrefixPath {
|
SysPrefixPath {
|
||||||
inner: self.system.canonicalize_path(expected_env_path).unwrap(),
|
inner: self.system.canonicalize_path(expected_env_path).unwrap(),
|
||||||
origin: SysPrefixPathOrigin::VirtualEnvVar,
|
origin: self.origin,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -830,7 +848,7 @@ mod tests {
|
||||||
env.root_path,
|
env.root_path,
|
||||||
SysPrefixPath {
|
SysPrefixPath {
|
||||||
inner: self.system.canonicalize_path(expected_env_path).unwrap(),
|
inner: self.system.canonicalize_path(expected_env_path).unwrap(),
|
||||||
origin: SysPrefixPathOrigin::VirtualEnvVar,
|
origin: self.origin,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -863,6 +881,7 @@ mod tests {
|
||||||
system: TestSystem::default(),
|
system: TestSystem::default(),
|
||||||
minor_version: 12,
|
minor_version: 12,
|
||||||
free_threaded: false,
|
free_threaded: false,
|
||||||
|
origin: SysPrefixPathOrigin::PythonCliFlag,
|
||||||
virtual_env: None,
|
virtual_env: None,
|
||||||
};
|
};
|
||||||
test.run();
|
test.run();
|
||||||
|
@ -874,17 +893,51 @@ mod tests {
|
||||||
system: TestSystem::default(),
|
system: TestSystem::default(),
|
||||||
minor_version: 13,
|
minor_version: 13,
|
||||||
free_threaded: true,
|
free_threaded: true,
|
||||||
|
origin: SysPrefixPathOrigin::PythonCliFlag,
|
||||||
virtual_env: None,
|
virtual_env: None,
|
||||||
};
|
};
|
||||||
test.run();
|
test.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cannot_find_site_packages_directory_no_virtual_env_at_origin_virtual_env_var() {
|
||||||
|
let test = PythonEnvironmentTestCase {
|
||||||
|
system: TestSystem::default(),
|
||||||
|
minor_version: 13,
|
||||||
|
free_threaded: false,
|
||||||
|
origin: SysPrefixPathOrigin::VirtualEnvVar,
|
||||||
|
virtual_env: None,
|
||||||
|
};
|
||||||
|
let err = test.err();
|
||||||
|
assert!(
|
||||||
|
matches!(err, SitePackagesDiscoveryError::NoPyvenvCfgFile(..)),
|
||||||
|
"Got {err:?}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cannot_find_site_packages_directory_no_virtual_env_at_origin_local_venv() {
|
||||||
|
let test = PythonEnvironmentTestCase {
|
||||||
|
system: TestSystem::default(),
|
||||||
|
minor_version: 13,
|
||||||
|
free_threaded: false,
|
||||||
|
origin: SysPrefixPathOrigin::LocalVenv,
|
||||||
|
virtual_env: None,
|
||||||
|
};
|
||||||
|
let err = test.err();
|
||||||
|
assert!(
|
||||||
|
matches!(err, SitePackagesDiscoveryError::NoPyvenvCfgFile(..)),
|
||||||
|
"Got {err:?}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_find_site_packages_directory_no_version_field_in_pyvenv_cfg() {
|
fn can_find_site_packages_directory_no_version_field_in_pyvenv_cfg() {
|
||||||
let test = PythonEnvironmentTestCase {
|
let test = PythonEnvironmentTestCase {
|
||||||
system: TestSystem::default(),
|
system: TestSystem::default(),
|
||||||
minor_version: 12,
|
minor_version: 12,
|
||||||
free_threaded: false,
|
free_threaded: false,
|
||||||
|
origin: SysPrefixPathOrigin::VirtualEnvVar,
|
||||||
virtual_env: Some(VirtualEnvironmentTestCase {
|
virtual_env: Some(VirtualEnvironmentTestCase {
|
||||||
system_site_packages: false,
|
system_site_packages: false,
|
||||||
pyvenv_cfg_version_field: None,
|
pyvenv_cfg_version_field: None,
|
||||||
|
@ -899,6 +952,7 @@ mod tests {
|
||||||
system: TestSystem::default(),
|
system: TestSystem::default(),
|
||||||
minor_version: 12,
|
minor_version: 12,
|
||||||
free_threaded: false,
|
free_threaded: false,
|
||||||
|
origin: SysPrefixPathOrigin::VirtualEnvVar,
|
||||||
virtual_env: Some(VirtualEnvironmentTestCase {
|
virtual_env: Some(VirtualEnvironmentTestCase {
|
||||||
system_site_packages: false,
|
system_site_packages: false,
|
||||||
pyvenv_cfg_version_field: Some("version = 3.12"),
|
pyvenv_cfg_version_field: Some("version = 3.12"),
|
||||||
|
@ -913,6 +967,7 @@ mod tests {
|
||||||
system: TestSystem::default(),
|
system: TestSystem::default(),
|
||||||
minor_version: 12,
|
minor_version: 12,
|
||||||
free_threaded: false,
|
free_threaded: false,
|
||||||
|
origin: SysPrefixPathOrigin::VirtualEnvVar,
|
||||||
virtual_env: Some(VirtualEnvironmentTestCase {
|
virtual_env: Some(VirtualEnvironmentTestCase {
|
||||||
system_site_packages: false,
|
system_site_packages: false,
|
||||||
pyvenv_cfg_version_field: Some("version_info = 3.12"),
|
pyvenv_cfg_version_field: Some("version_info = 3.12"),
|
||||||
|
@ -927,6 +982,7 @@ mod tests {
|
||||||
system: TestSystem::default(),
|
system: TestSystem::default(),
|
||||||
minor_version: 12,
|
minor_version: 12,
|
||||||
free_threaded: false,
|
free_threaded: false,
|
||||||
|
origin: SysPrefixPathOrigin::VirtualEnvVar,
|
||||||
virtual_env: Some(VirtualEnvironmentTestCase {
|
virtual_env: Some(VirtualEnvironmentTestCase {
|
||||||
system_site_packages: false,
|
system_site_packages: false,
|
||||||
pyvenv_cfg_version_field: Some("version_info = 3.12.0rc2"),
|
pyvenv_cfg_version_field: Some("version_info = 3.12.0rc2"),
|
||||||
|
@ -941,6 +997,7 @@ mod tests {
|
||||||
system: TestSystem::default(),
|
system: TestSystem::default(),
|
||||||
minor_version: 13,
|
minor_version: 13,
|
||||||
free_threaded: true,
|
free_threaded: true,
|
||||||
|
origin: SysPrefixPathOrigin::VirtualEnvVar,
|
||||||
virtual_env: Some(VirtualEnvironmentTestCase {
|
virtual_env: Some(VirtualEnvironmentTestCase {
|
||||||
system_site_packages: false,
|
system_site_packages: false,
|
||||||
pyvenv_cfg_version_field: Some("version_info = 3.13"),
|
pyvenv_cfg_version_field: Some("version_info = 3.13"),
|
||||||
|
@ -955,6 +1012,7 @@ mod tests {
|
||||||
system: TestSystem::default(),
|
system: TestSystem::default(),
|
||||||
minor_version: 13,
|
minor_version: 13,
|
||||||
free_threaded: true,
|
free_threaded: true,
|
||||||
|
origin: SysPrefixPathOrigin::VirtualEnvVar,
|
||||||
virtual_env: Some(VirtualEnvironmentTestCase {
|
virtual_env: Some(VirtualEnvironmentTestCase {
|
||||||
system_site_packages: true,
|
system_site_packages: true,
|
||||||
pyvenv_cfg_version_field: Some("version_info = 3.13"),
|
pyvenv_cfg_version_field: Some("version_info = 3.13"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue