mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:25:17 +00:00
Add support for configuring knot in pyproject.toml
files (#15493)
## Summary This PR adds support for configuring Red Knot in the `tool.knot` section of the project's `pyproject.toml` section. Options specified on the CLI precede the options in the configuration file. This PR only supports the `environment` and the `src.root` options for now. Other options will be added as separate PRs. There are also a few concerns that I intentionally ignored as part of this PR: * Handling of relative paths: We need to anchor paths relative to the current working directory (CLI), or the project (`pyproject.toml` or `knot.toml`) * Tracking the source of a value. Diagnostics would benefit from knowing from which configuration a value comes so that we can point the user to the right configuration file (or CLI) if the configuration is invalid. * Schema generation and there's a lot more; see https://github.com/astral-sh/ruff/issues/15491 This PR changes the default for first party codes: Our existing default was to only add the project root. Now, Red Knot adds the project root and `src` (if such a directory exists). Theoretically, we'd have to add a file watcher event that changes the first-party search paths if a user later creates a `src` directory. I think this is pretty uncommon, which is why I ignored the complexity for now but I can be persuaded to handle it if it's considered important. Part of https://github.com/astral-sh/ruff/issues/15491 ## Test Plan Existing tests, new file watching test demonstrating that changing the python version and platform is correctly reflected.
This commit is contained in:
parent
9ed67ba33e
commit
eb47a6634d
36 changed files with 820 additions and 413 deletions
|
@ -175,7 +175,7 @@ pub(crate) mod tests {
|
|||
db.write_files(self.files)
|
||||
.context("Failed to write test files")?;
|
||||
|
||||
let mut search_paths = SearchPathSettings::new(src_root);
|
||||
let mut search_paths = SearchPathSettings::new(vec![src_root]);
|
||||
search_paths.typeshed = self.custom_typeshed;
|
||||
|
||||
Program::from_settings(
|
||||
|
|
|
@ -168,7 +168,7 @@ impl SearchPaths {
|
|||
|
||||
let SearchPathSettings {
|
||||
extra_paths,
|
||||
src_root,
|
||||
src_roots,
|
||||
typeshed,
|
||||
site_packages: site_packages_paths,
|
||||
} = settings;
|
||||
|
@ -186,8 +186,10 @@ impl SearchPaths {
|
|||
static_paths.push(SearchPath::extra(system, path)?);
|
||||
}
|
||||
|
||||
tracing::debug!("Adding first-party search path '{src_root}'");
|
||||
static_paths.push(SearchPath::first_party(system, src_root.to_path_buf())?);
|
||||
for src_root in src_roots {
|
||||
tracing::debug!("Adding first-party search path '{src_root}'");
|
||||
static_paths.push(SearchPath::first_party(system, src_root.to_path_buf())?);
|
||||
}
|
||||
|
||||
let (typeshed_versions, stdlib_path) = if let Some(typeshed) = typeshed {
|
||||
let typeshed = canonicalize(typeshed, system);
|
||||
|
@ -1299,7 +1301,7 @@ mod tests {
|
|||
python_platform: PythonPlatform::default(),
|
||||
search_paths: SearchPathSettings {
|
||||
extra_paths: vec![],
|
||||
src_root: src.clone(),
|
||||
src_roots: vec![src.clone()],
|
||||
typeshed: Some(custom_typeshed),
|
||||
site_packages: SitePackages::Known(vec![site_packages]),
|
||||
},
|
||||
|
@ -1805,7 +1807,7 @@ not_a_directory
|
|||
python_platform: PythonPlatform::default(),
|
||||
search_paths: SearchPathSettings {
|
||||
extra_paths: vec![],
|
||||
src_root: SystemPathBuf::from("/src"),
|
||||
src_roots: vec![SystemPathBuf::from("/src")],
|
||||
typeshed: None,
|
||||
site_packages: SitePackages::Known(vec![
|
||||
venv_site_packages,
|
||||
|
|
|
@ -237,7 +237,7 @@ impl TestCaseBuilder<MockedTypeshed> {
|
|||
python_platform,
|
||||
search_paths: SearchPathSettings {
|
||||
extra_paths: vec![],
|
||||
src_root: src.clone(),
|
||||
src_roots: vec![src.clone()],
|
||||
typeshed: Some(typeshed.clone()),
|
||||
site_packages: SitePackages::Known(vec![site_packages.clone()]),
|
||||
},
|
||||
|
@ -295,7 +295,7 @@ impl TestCaseBuilder<VendoredTypeshed> {
|
|||
python_platform,
|
||||
search_paths: SearchPathSettings {
|
||||
site_packages: SitePackages::Known(vec![site_packages.clone()]),
|
||||
..SearchPathSettings::new(src.clone())
|
||||
..SearchPathSettings::new(vec![src.clone()])
|
||||
},
|
||||
},
|
||||
)
|
||||
|
|
|
@ -103,7 +103,7 @@ pub struct SearchPathSettings {
|
|||
pub extra_paths: Vec<SystemPathBuf>,
|
||||
|
||||
/// The root of the project, used for finding first-party modules.
|
||||
pub src_root: SystemPathBuf,
|
||||
pub src_roots: Vec<SystemPathBuf>,
|
||||
|
||||
/// Optional path to a "custom typeshed" directory on disk for us to use for standard-library types.
|
||||
/// If this is not provided, we will fallback to our vendored typeshed stubs for the stdlib,
|
||||
|
@ -115,9 +115,9 @@ pub struct SearchPathSettings {
|
|||
}
|
||||
|
||||
impl SearchPathSettings {
|
||||
pub fn new(src_root: SystemPathBuf) -> Self {
|
||||
pub fn new(src_roots: Vec<SystemPathBuf>) -> Self {
|
||||
Self {
|
||||
src_root,
|
||||
src_roots,
|
||||
extra_paths: vec![],
|
||||
typeshed: None,
|
||||
site_packages: SitePackages::Known(vec![]),
|
||||
|
@ -126,7 +126,7 @@ impl SearchPathSettings {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub enum SitePackages {
|
||||
Derived {
|
||||
venv_path: SystemPathBuf,
|
||||
|
@ -134,3 +134,12 @@ pub enum SitePackages {
|
|||
/// Resolved site packages paths
|
||||
Known(Vec<SystemPathBuf>),
|
||||
}
|
||||
|
||||
impl SitePackages {
|
||||
pub fn paths(&self) -> &[SystemPathBuf] {
|
||||
match self {
|
||||
SitePackages::Derived { venv_path } => std::slice::from_ref(venv_path),
|
||||
SitePackages::Known(paths) => paths,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue