mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 06:41:23 +00:00
[red-knot] Allow module-resolution options to be specified via the CLI (#12246)
This commit is contained in:
parent
f8ff42a13d
commit
000dabcd88
5 changed files with 100 additions and 16 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1864,6 +1864,7 @@ name = "red_knot"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"clap",
|
||||||
"countme",
|
"countme",
|
||||||
"crossbeam",
|
"crossbeam",
|
||||||
"ctrlc",
|
"ctrlc",
|
||||||
|
|
|
@ -19,6 +19,7 @@ ruff_db = { workspace = true }
|
||||||
ruff_python_ast = { workspace = true }
|
ruff_python_ast = { workspace = true }
|
||||||
|
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
|
clap = { workspace = true, features = ["wrap_help"] }
|
||||||
countme = { workspace = true, features = ["enable"] }
|
countme = { workspace = true, features = ["enable"] }
|
||||||
crossbeam = { workspace = true }
|
crossbeam = { workspace = true }
|
||||||
ctrlc = { version = "3.4.4" }
|
ctrlc = { version = "3.4.4" }
|
||||||
|
|
|
@ -8,6 +8,7 @@ use crate::db::Jar;
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod lint;
|
pub mod lint;
|
||||||
pub mod program;
|
pub mod program;
|
||||||
|
pub mod target_version;
|
||||||
pub mod watch;
|
pub mod watch;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
use crossbeam::channel as crossbeam_channel;
|
use crossbeam::channel as crossbeam_channel;
|
||||||
use salsa::ParallelDatabase;
|
use salsa::ParallelDatabase;
|
||||||
use tracing::subscriber::Interest;
|
use tracing::subscriber::Interest;
|
||||||
|
@ -10,13 +11,38 @@ use tracing_subscriber::{Layer, Registry};
|
||||||
use tracing_tree::time::Uptime;
|
use tracing_tree::time::Uptime;
|
||||||
|
|
||||||
use red_knot::program::{FileWatcherChange, Program};
|
use red_knot::program::{FileWatcherChange, Program};
|
||||||
|
use red_knot::target_version::TargetVersion;
|
||||||
use red_knot::watch::FileWatcher;
|
use red_knot::watch::FileWatcher;
|
||||||
use red_knot::Workspace;
|
use red_knot::Workspace;
|
||||||
use red_knot_module_resolver::{
|
use red_knot_module_resolver::{set_module_resolution_settings, RawModuleResolutionSettings};
|
||||||
set_module_resolution_settings, RawModuleResolutionSettings, TargetVersion,
|
|
||||||
};
|
|
||||||
use ruff_db::files::system_path_to_file;
|
use ruff_db::files::system_path_to_file;
|
||||||
use ruff_db::system::{OsSystem, System, SystemPath};
|
use ruff_db::system::{OsSystem, System, SystemPath, SystemPathBuf};
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
#[command(
|
||||||
|
author,
|
||||||
|
name = "red-knot",
|
||||||
|
about = "An experimental multifile analysis backend for Ruff"
|
||||||
|
)]
|
||||||
|
#[command(version)]
|
||||||
|
struct Args {
|
||||||
|
#[clap(help = "File to check", required = true, value_name = "FILE")]
|
||||||
|
entry_point: SystemPathBuf,
|
||||||
|
#[arg(
|
||||||
|
long,
|
||||||
|
value_name = "DIRECTORY",
|
||||||
|
help = "Custom directory to use for stdlib typeshed stubs"
|
||||||
|
)]
|
||||||
|
custom_typeshed_dir: Option<SystemPathBuf>,
|
||||||
|
#[arg(
|
||||||
|
long,
|
||||||
|
value_name = "PATH",
|
||||||
|
help = "Additional path to use as a module-resolution source (can be passed multiple times)"
|
||||||
|
)]
|
||||||
|
extra_search_path: Vec<SystemPathBuf>,
|
||||||
|
#[arg(long, help = "Python version to assume when resolving types", default_value_t = TargetVersion::default(), value_name="VERSION")]
|
||||||
|
target_version: TargetVersion,
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(
|
#[allow(
|
||||||
clippy::print_stdout,
|
clippy::print_stdout,
|
||||||
|
@ -28,30 +54,35 @@ pub fn main() -> anyhow::Result<()> {
|
||||||
countme::enable(true);
|
countme::enable(true);
|
||||||
setup_tracing();
|
setup_tracing();
|
||||||
|
|
||||||
let arguments: Vec<_> = std::env::args().collect();
|
let Args {
|
||||||
|
entry_point,
|
||||||
|
custom_typeshed_dir,
|
||||||
|
extra_search_path: extra_search_paths,
|
||||||
|
target_version,
|
||||||
|
} = Args::parse_from(std::env::args().collect::<Vec<_>>());
|
||||||
|
|
||||||
if arguments.len() < 2 {
|
tracing::trace!("Target version: {target_version}");
|
||||||
eprintln!("Usage: red_knot <path>");
|
if let Some(custom_typeshed) = custom_typeshed_dir.as_ref() {
|
||||||
return Err(anyhow::anyhow!("Invalid arguments"));
|
tracing::trace!("Custom typeshed directory: {custom_typeshed}");
|
||||||
|
}
|
||||||
|
if !extra_search_paths.is_empty() {
|
||||||
|
tracing::trace!("extra search paths: {extra_search_paths:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
let cwd = std::env::current_dir().unwrap();
|
let cwd = std::env::current_dir().unwrap();
|
||||||
let cwd = SystemPath::from_std_path(&cwd).unwrap();
|
let cwd = SystemPath::from_std_path(&cwd).unwrap();
|
||||||
let system = OsSystem::new(cwd);
|
let system = OsSystem::new(cwd);
|
||||||
let entry_point = SystemPath::new(&arguments[1]);
|
|
||||||
|
|
||||||
if !system.path_exists(entry_point) {
|
if !system.path_exists(&entry_point) {
|
||||||
eprintln!("The entry point does not exist.");
|
eprintln!("The entry point does not exist.");
|
||||||
return Err(anyhow::anyhow!("Invalid arguments"));
|
return Err(anyhow::anyhow!("Invalid arguments"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !system.is_file(entry_point) {
|
if !system.is_file(&entry_point) {
|
||||||
eprintln!("The entry point is not a file.");
|
eprintln!("The entry point is not a file.");
|
||||||
return Err(anyhow::anyhow!("Invalid arguments"));
|
return Err(anyhow::anyhow!("Invalid arguments"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let entry_point = entry_point.to_path_buf();
|
|
||||||
|
|
||||||
let workspace_folder = entry_point.parent().unwrap();
|
let workspace_folder = entry_point.parent().unwrap();
|
||||||
let workspace = Workspace::new(workspace_folder.to_path_buf());
|
let workspace = Workspace::new(workspace_folder.to_path_buf());
|
||||||
|
|
||||||
|
@ -62,11 +93,11 @@ pub fn main() -> anyhow::Result<()> {
|
||||||
set_module_resolution_settings(
|
set_module_resolution_settings(
|
||||||
&mut program,
|
&mut program,
|
||||||
RawModuleResolutionSettings {
|
RawModuleResolutionSettings {
|
||||||
extra_paths: vec![],
|
extra_paths: extra_search_paths,
|
||||||
workspace_root: workspace_search_path,
|
workspace_root: workspace_search_path,
|
||||||
site_packages: None,
|
site_packages: None,
|
||||||
custom_typeshed: None,
|
custom_typeshed: custom_typeshed_dir,
|
||||||
target_version: TargetVersion::Py38,
|
target_version: red_knot_module_resolver::TargetVersion::from(target_version),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
50
crates/red_knot/src/target_version.rs
Normal file
50
crates/red_knot/src/target_version.rs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// Enumeration of all supported Python versions
|
||||||
|
///
|
||||||
|
/// TODO: unify with the `PythonVersion` enum in the linter/formatter crates?
|
||||||
|
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Default, clap::ValueEnum)]
|
||||||
|
pub enum TargetVersion {
|
||||||
|
Py37,
|
||||||
|
#[default]
|
||||||
|
Py38,
|
||||||
|
Py39,
|
||||||
|
Py310,
|
||||||
|
Py311,
|
||||||
|
Py312,
|
||||||
|
Py313,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TargetVersion {
|
||||||
|
const fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Py37 => "py37",
|
||||||
|
Self::Py38 => "py38",
|
||||||
|
Self::Py39 => "py39",
|
||||||
|
Self::Py310 => "py310",
|
||||||
|
Self::Py311 => "py311",
|
||||||
|
Self::Py312 => "py312",
|
||||||
|
Self::Py313 => "py313",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for TargetVersion {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(self.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TargetVersion> for red_knot_module_resolver::TargetVersion {
|
||||||
|
fn from(value: TargetVersion) -> Self {
|
||||||
|
match value {
|
||||||
|
TargetVersion::Py37 => red_knot_module_resolver::TargetVersion::Py37,
|
||||||
|
TargetVersion::Py38 => red_knot_module_resolver::TargetVersion::Py38,
|
||||||
|
TargetVersion::Py39 => red_knot_module_resolver::TargetVersion::Py39,
|
||||||
|
TargetVersion::Py310 => red_knot_module_resolver::TargetVersion::Py310,
|
||||||
|
TargetVersion::Py311 => red_knot_module_resolver::TargetVersion::Py311,
|
||||||
|
TargetVersion::Py312 => red_knot_module_resolver::TargetVersion::Py312,
|
||||||
|
TargetVersion::Py313 => red_knot_module_resolver::TargetVersion::Py313,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue