Skip to content

Commit 4732c58

Browse files
authored
Rename venv-path to python (#16347)
1 parent 45bae29 commit 4732c58

File tree

12 files changed

+83
-59
lines changed

12 files changed

+83
-59
lines changed

crates/red_knot/src/args.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@ pub(crate) struct CheckCommand {
4141
#[arg(long, value_name = "PROJECT")]
4242
pub(crate) project: Option<SystemPathBuf>,
4343

44-
/// Path to the virtual environment the project uses.
44+
/// Path to the Python installation from which Red Knot resolves type information and third-party dependencies.
4545
///
46-
/// If provided, red-knot will use the `site-packages` directory of this virtual environment
47-
/// to resolve type information for the project's third-party dependencies.
46+
/// Red Knot will search in the path's `site-packages` directories for type information and
47+
/// third-party imports.
48+
///
49+
/// This option is commonly used to specify the path to a virtual environment.
4850
#[arg(long, value_name = "PATH")]
49-
pub(crate) venv_path: Option<SystemPathBuf>,
51+
pub(crate) python: Option<SystemPathBuf>,
5052

5153
/// Custom directory to use for stdlib typeshed stubs.
5254
#[arg(long, value_name = "PATH", alias = "custom-typeshed-dir")]
@@ -97,7 +99,7 @@ impl CheckCommand {
9799
python_version: self
98100
.python_version
99101
.map(|version| RangedValue::cli(version.into())),
100-
venv_path: self.venv_path.map(RelativePathBuf::cli),
102+
python: self.python.map(RelativePathBuf::cli),
101103
typeshed: self.typeshed.map(RelativePathBuf::cli),
102104
extra_paths: self.extra_search_path.map(|extra_search_paths| {
103105
extra_search_paths

crates/red_knot/src/main.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use red_knot_project::{watch, Db};
1616
use red_knot_project::{ProjectDatabase, ProjectMetadata};
1717
use red_knot_server::run_server;
1818
use ruff_db::diagnostic::{Diagnostic, DisplayDiagnosticConfig, Severity};
19-
use ruff_db::system::{OsSystem, System, SystemPath, SystemPathBuf};
19+
use ruff_db::system::{OsSystem, SystemPath, SystemPathBuf};
2020
use salsa::plumbing::ZalsaDatabase;
2121

2222
mod args;
@@ -69,7 +69,7 @@ fn run_check(args: CheckCommand) -> anyhow::Result<ExitStatus> {
6969
let _guard = setup_tracing(verbosity)?;
7070

7171
// The base path to which all CLI arguments are relative to.
72-
let cli_base_path = {
72+
let cwd = {
7373
let cwd = std::env::current_dir().context("Failed to get the current working directory")?;
7474
SystemPathBuf::from_path_buf(cwd)
7575
.map_err(|path| {
@@ -80,25 +80,27 @@ fn run_check(args: CheckCommand) -> anyhow::Result<ExitStatus> {
8080
})?
8181
};
8282

83-
let cwd = args
83+
let project_path = args
8484
.project
8585
.as_ref()
86-
.map(|cwd| {
87-
if cwd.as_std_path().is_dir() {
88-
Ok(SystemPath::absolute(cwd, &cli_base_path))
86+
.map(|project| {
87+
if project.as_std_path().is_dir() {
88+
Ok(SystemPath::absolute(project, &cwd))
8989
} else {
90-
Err(anyhow!("Provided project path `{cwd}` is not a directory"))
90+
Err(anyhow!(
91+
"Provided project path `{project}` is not a directory"
92+
))
9193
}
9294
})
9395
.transpose()?
94-
.unwrap_or_else(|| cli_base_path.clone());
96+
.unwrap_or_else(|| cwd.clone());
9597

9698
let system = OsSystem::new(cwd);
9799
let watch = args.watch;
98100
let exit_zero = args.exit_zero;
99101

100102
let cli_options = args.into_options();
101-
let mut project_metadata = ProjectMetadata::discover(system.current_directory(), &system)?;
103+
let mut project_metadata = ProjectMetadata::discover(&project_path, &system)?;
102104
project_metadata.apply_cli_options(cli_options.clone());
103105
project_metadata.apply_configuration_files(&system)?;
104106

crates/red_knot_project/src/combine.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{collections::HashMap, hash::BuildHasher};
22

3-
use red_knot_python_semantic::{PythonPlatform, SitePackages};
3+
use red_knot_python_semantic::{PythonPath, PythonPlatform};
44
use ruff_db::system::SystemPathBuf;
55
use ruff_python_ast::PythonVersion;
66

@@ -128,7 +128,7 @@ macro_rules! impl_noop_combine {
128128

129129
impl_noop_combine!(SystemPathBuf);
130130
impl_noop_combine!(PythonPlatform);
131-
impl_noop_combine!(SitePackages);
131+
impl_noop_combine!(PythonPath);
132132
impl_noop_combine!(PythonVersion);
133133

134134
// std types

crates/red_knot_project/src/metadata/options.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::metadata::value::{RangedValue, RelativePathBuf, ValueSource, ValueSourceGuard};
22
use crate::Db;
33
use red_knot_python_semantic::lint::{GetLintError, Level, LintSource, RuleSelection};
4-
use red_knot_python_semantic::{ProgramSettings, PythonPlatform, SearchPathSettings, SitePackages};
4+
use red_knot_python_semantic::{ProgramSettings, PythonPath, PythonPlatform, SearchPathSettings};
55
use ruff_db::diagnostic::{Diagnostic, DiagnosticId, Severity, Span};
66
use ruff_db::files::system_path_to_file;
77
use ruff_db::system::{System, SystemPath};
@@ -90,7 +90,7 @@ impl Options {
9090
.map(|env| {
9191
(
9292
env.extra_paths.clone(),
93-
env.venv_path.clone(),
93+
env.python.clone(),
9494
env.typeshed.clone(),
9595
)
9696
})
@@ -104,11 +104,11 @@ impl Options {
104104
.collect(),
105105
src_roots,
106106
custom_typeshed: typeshed.map(|path| path.absolute(project_root, system)),
107-
site_packages: python
108-
.map(|venv_path| SitePackages::Derived {
109-
venv_path: venv_path.absolute(project_root, system),
107+
python_path: python
108+
.map(|python_path| {
109+
PythonPath::SysPrefix(python_path.absolute(project_root, system))
110110
})
111-
.unwrap_or(SitePackages::Known(vec![])),
111+
.unwrap_or(PythonPath::KnownSitePackages(vec![])),
112112
}
113113
}
114114

@@ -236,10 +236,14 @@ pub struct EnvironmentOptions {
236236
#[serde(skip_serializing_if = "Option::is_none")]
237237
pub typeshed: Option<RelativePathBuf>,
238238

239-
// TODO: Rename to python, see https://github.com/astral-sh/ruff/issues/15530
240-
/// The path to the user's `site-packages` directory, where third-party packages from ``PyPI`` are installed.
239+
/// Path to the Python installation from which Red Knot resolves type information and third-party dependencies.
240+
///
241+
/// Red Knot will search in the path's `site-packages` directories for type information and
242+
/// third-party imports.
243+
///
244+
/// This option is commonly used to specify the path to a virtual environment.
241245
#[serde(skip_serializing_if = "Option::is_none")]
242-
pub venv_path: Option<RelativePathBuf>,
246+
pub python: Option<RelativePathBuf>,
243247
}
244248

245249
#[derive(Debug, Default, Clone, Eq, PartialEq, Combine, Serialize, Deserialize)]

crates/red_knot_python_semantic/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::suppression::{INVALID_IGNORE_COMMENT, UNKNOWN_RULE, UNUSED_IGNORE_COM
77
pub use db::Db;
88
pub use module_name::ModuleName;
99
pub use module_resolver::{resolve_module, system_module_search_paths, KnownModule, Module};
10-
pub use program::{Program, ProgramSettings, SearchPathSettings, SitePackages};
10+
pub use program::{Program, ProgramSettings, PythonPath, SearchPathSettings};
1111
pub use python_platform::PythonPlatform;
1212
pub use semantic_model::{HasType, SemanticModel};
1313

crates/red_knot_python_semantic/src/module_resolver/resolver.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::db::Db;
1212
use crate::module_name::ModuleName;
1313
use crate::module_resolver::typeshed::{vendored_typeshed_versions, TypeshedVersions};
1414
use crate::site_packages::VirtualEnvironment;
15-
use crate::{Program, SearchPathSettings, SitePackages};
15+
use crate::{Program, PythonPath, SearchPathSettings};
1616

1717
use super::module::{Module, ModuleKind};
1818
use super::path::{ModulePath, SearchPath, SearchPathValidationError};
@@ -171,7 +171,7 @@ impl SearchPaths {
171171
extra_paths,
172172
src_roots,
173173
custom_typeshed: typeshed,
174-
site_packages: site_packages_paths,
174+
python_path,
175175
} = settings;
176176

177177
let system = db.system();
@@ -222,16 +222,16 @@ impl SearchPaths {
222222

223223
static_paths.push(stdlib_path);
224224

225-
let site_packages_paths = match site_packages_paths {
226-
SitePackages::Derived { venv_path } => {
225+
let site_packages_paths = match python_path {
226+
PythonPath::SysPrefix(sys_prefix) => {
227227
// TODO: We may want to warn here if the venv's python version is older
228228
// than the one resolved in the program settings because it indicates
229229
// that the `target-version` is incorrectly configured or that the
230230
// venv is out of date.
231-
VirtualEnvironment::new(venv_path, system)
231+
VirtualEnvironment::new(sys_prefix, system)
232232
.and_then(|venv| venv.site_packages_directories(system))?
233233
}
234-
SitePackages::Known(paths) => paths
234+
PythonPath::KnownSitePackages(paths) => paths
235235
.iter()
236236
.map(|path| canonicalize(path, system))
237237
.collect(),
@@ -1310,7 +1310,7 @@ mod tests {
13101310
extra_paths: vec![],
13111311
src_roots: vec![src.clone()],
13121312
custom_typeshed: Some(custom_typeshed),
1313-
site_packages: SitePackages::Known(vec![site_packages]),
1313+
python_path: PythonPath::KnownSitePackages(vec![site_packages]),
13141314
},
13151315
},
13161316
)
@@ -1816,7 +1816,7 @@ not_a_directory
18161816
extra_paths: vec![],
18171817
src_roots: vec![SystemPathBuf::from("/src")],
18181818
custom_typeshed: None,
1819-
site_packages: SitePackages::Known(vec![
1819+
python_path: PythonPath::KnownSitePackages(vec![
18201820
venv_site_packages,
18211821
system_site_packages,
18221822
]),

crates/red_knot_python_semantic/src/module_resolver/testing.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use ruff_python_ast::PythonVersion;
44

55
use crate::db::tests::TestDb;
66
use crate::program::{Program, SearchPathSettings};
7-
use crate::{ProgramSettings, PythonPlatform, SitePackages};
7+
use crate::{ProgramSettings, PythonPath, PythonPlatform};
88

99
/// A test case for the module resolver.
1010
///
@@ -239,7 +239,7 @@ impl TestCaseBuilder<MockedTypeshed> {
239239
extra_paths: vec![],
240240
src_roots: vec![src.clone()],
241241
custom_typeshed: Some(typeshed.clone()),
242-
site_packages: SitePackages::Known(vec![site_packages.clone()]),
242+
python_path: PythonPath::KnownSitePackages(vec![site_packages.clone()]),
243243
},
244244
},
245245
)
@@ -294,7 +294,7 @@ impl TestCaseBuilder<VendoredTypeshed> {
294294
python_version,
295295
python_platform,
296296
search_paths: SearchPathSettings {
297-
site_packages: SitePackages::Known(vec![site_packages.clone()]),
297+
python_path: PythonPath::KnownSitePackages(vec![site_packages.clone()]),
298298
..SearchPathSettings::new(vec![src.clone()])
299299
},
300300
},

crates/red_knot_python_semantic/src/program.rs

+25-9
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ pub struct SearchPathSettings {
110110
/// bundled as a zip file in the binary
111111
pub custom_typeshed: Option<SystemPathBuf>,
112112

113-
/// The path to the user's `site-packages` directory, where third-party packages from ``PyPI`` are installed.
114-
pub site_packages: SitePackages,
113+
/// Path to the Python installation from which Red Knot resolves third party dependencies
114+
/// and their type information.
115+
pub python_path: PythonPath,
115116
}
116117

117118
impl SearchPathSettings {
@@ -120,17 +121,32 @@ impl SearchPathSettings {
120121
src_roots,
121122
extra_paths: vec![],
122123
custom_typeshed: None,
123-
site_packages: SitePackages::Known(vec![]),
124+
python_path: PythonPath::KnownSitePackages(vec![]),
124125
}
125126
}
126127
}
127128

128129
#[derive(Debug, Clone, Eq, PartialEq)]
129130
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
130-
pub enum SitePackages {
131-
Derived {
132-
venv_path: SystemPathBuf,
133-
},
134-
/// Resolved site packages paths
135-
Known(Vec<SystemPathBuf>),
131+
pub enum PythonPath {
132+
/// A path that represents the value of [`sys.prefix`] at runtime in Python
133+
/// for a given Python executable.
134+
///
135+
/// For the case of a virtual environment, where a
136+
/// Python binary is at `/.venv/bin/python`, `sys.prefix` is the path to
137+
/// the virtual environment the Python binary lies inside, i.e. `/.venv`,
138+
/// and `site-packages` will be at `.venv/lib/python3.X/site-packages`.
139+
/// System Python installations generally work the same way: if a system
140+
/// Python installation lies at `/opt/homebrew/bin/python`, `sys.prefix`
141+
/// will be `/opt/homebrew`, and `site-packages` will be at
142+
/// `/opt/homebrew/lib/python3.X/site-packages`.
143+
///
144+
/// [`sys.prefix`]: https://docs.python.org/3/library/sys.html#sys.prefix
145+
SysPrefix(SystemPathBuf),
146+
147+
/// Resolved site packages paths.
148+
///
149+
/// This variant is mainly intended for testing where we want to skip resolving `site-packages`
150+
/// because it would unnecessarily complicate the test setup.
151+
KnownSitePackages(Vec<SystemPathBuf>),
136152
}

crates/red_knot_python_semantic/src/site_packages.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,11 @@ System site-packages will not be used for module resolution.",
205205

206206
#[derive(Debug, thiserror::Error)]
207207
pub(crate) enum SitePackagesDiscoveryError {
208-
#[error("Invalid --venv-path argument: {0} could not be canonicalized")]
208+
#[error("Invalid --python argument: `{0}` could not be canonicalized")]
209209
VenvDirCanonicalizationError(SystemPathBuf, #[source] io::Error),
210-
#[error("Invalid --venv-path argument: {0} does not point to a directory on disk")]
210+
#[error("Invalid --python argument: `{0}` does not point to a directory on disk")]
211211
VenvDirIsNotADirectory(SystemPathBuf),
212-
#[error("--venv-path points to a broken venv with no pyvenv.cfg file")]
212+
#[error("--python points to a broken venv with no pyvenv.cfg file")]
213213
NoPyvenvCfgFile(#[source] io::Error),
214214
#[error("Failed to parse the pyvenv.cfg file at {0} because {1}")]
215215
PyvenvCfgParseError(SystemPathBuf, PyvenvCfgParseErrorKind),

crates/red_knot_test/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use camino::Utf8Path;
44
use colored::Colorize;
55
use parser as test_parser;
66
use red_knot_python_semantic::types::check_types;
7-
use red_knot_python_semantic::{Program, ProgramSettings, SearchPathSettings, SitePackages};
7+
use red_knot_python_semantic::{Program, ProgramSettings, PythonPath, SearchPathSettings};
88
use ruff_db::diagnostic::{Diagnostic, DisplayDiagnosticConfig, ParseDiagnostic};
99
use ruff_db::files::{system_path_to_file, File, Files};
1010
use ruff_db::panic::catch_unwind;
@@ -180,7 +180,7 @@ fn run_test(
180180
src_roots: vec![src_path],
181181
extra_paths: vec![],
182182
custom_typeshed: custom_typeshed_path,
183-
site_packages: SitePackages::Known(vec![]),
183+
python_path: PythonPath::KnownSitePackages(vec![]),
184184
},
185185
},
186186
)

knot.schema.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@
6262
"type": "string"
6363
}
6464
},
65+
"python": {
66+
"description": "Path to the Python installation from which Red Knot resolves type information and third-party dependencies.\n\nRed Knot will search in the path's `site-packages` directories for type information and third-party imports.\n\nThis option is commonly used to specify the path to a virtual environment.",
67+
"type": [
68+
"string",
69+
"null"
70+
]
71+
},
6572
"python-platform": {
6673
"description": "Specifies the target platform that will be used to execute the source code. If specified, Red Knot will tailor its use of type stub files, which conditionalize type definitions based on the platform.\n\nIf no platform is specified, knot will use `all` or the current platform in the LSP use case.",
6774
"anyOf": [
@@ -90,13 +97,6 @@
9097
"string",
9198
"null"
9299
]
93-
},
94-
"venv-path": {
95-
"description": "The path to the user's `site-packages` directory, where third-party packages from ``PyPI`` are installed.",
96-
"type": [
97-
"string",
98-
"null"
99-
]
100100
}
101101
},
102102
"additionalProperties": false

scripts/knot_benchmark/src/benchmark/cases.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def cold_command(self, project: Project, venv: Venv) -> Command:
7575
if project.include:
7676
command.extend(["--project", project.include[0]])
7777

78-
command.extend(["--venv-path", str(venv.path)])
78+
command.extend(["--python", str(venv.path)])
7979

8080
return Command(
8181
name="knot",

0 commit comments

Comments
 (0)