Skip to content

Commit 991e829

Browse files
committed
[ty] Add --config-file
217
1 parent 4e68dd9 commit 991e829

File tree

12 files changed

+300
-63
lines changed

12 files changed

+300
-63
lines changed

crates/ruff_benchmark/benches/ty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ fn setup_tomllib_case() -> Case {
7878

7979
let src_root = SystemPath::new("/src");
8080
let mut metadata = ProjectMetadata::discover(src_root, &system).unwrap();
81-
metadata.apply_cli_options(Options {
81+
metadata.apply_options(Options {
8282
environment: Some(EnvironmentOptions {
8383
python_version: Some(RangedValue::cli(PythonVersion::PY312)),
8484
..EnvironmentOptions::default()
@@ -224,7 +224,7 @@ fn setup_micro_case(code: &str) -> Case {
224224

225225
let src_root = SystemPath::new("/src");
226226
let mut metadata = ProjectMetadata::discover(src_root, &system).unwrap();
227-
metadata.apply_cli_options(Options {
227+
metadata.apply_options(Options {
228228
environment: Some(EnvironmentOptions {
229229
python_version: Some(RangedValue::cli(PythonVersion::PY312)),
230230
..EnvironmentOptions::default()

crates/ty/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ ty_server = { workspace = true }
2222

2323
anyhow = { workspace = true }
2424
argfile = { workspace = true }
25-
clap = { workspace = true, features = ["wrap_help", "string"] }
25+
clap = { workspace = true, features = ["wrap_help", "string", "env"] }
2626
clap_complete_command = { workspace = true }
2727
colored = { workspace = true }
2828
countme = { workspace = true, features = ["enable"] }

crates/ty/docs/cli.md

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ty/src/args.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ pub(crate) struct CheckCommand {
107107
#[clap(flatten)]
108108
pub(crate) config: ConfigsArg,
109109

110+
/// The path to a `ty.toml` file to use for configuration.
111+
///
112+
/// While ty configuration can be included in a `pyproject.toml` file, it is not allowed in this context.
113+
#[arg(long, env = "TY_CONFIG_FILE", value_name = "PATH")]
114+
pub(crate) config_file: Option<SystemPathBuf>,
115+
110116
/// The format to use for printing diagnostic messages.
111117
#[arg(long)]
112118
pub(crate) output_format: Option<OutputFormat>,

crates/ty/src/lib.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use ruff_db::diagnostic::{Diagnostic, DisplayDiagnosticConfig, Severity};
2323
use ruff_db::max_parallelism;
2424
use ruff_db::system::{OsSystem, SystemPath, SystemPathBuf};
2525
use salsa::plumbing::ZalsaDatabase;
26-
use ty_project::metadata::options::Options;
26+
use ty_project::metadata::options::ProjectOptionsOverrides;
2727
use ty_project::watch::ProjectWatcher;
2828
use ty_project::{Db, DummyReporter, Reporter, watch};
2929
use ty_project::{ProjectDatabase, ProjectMetadata};
@@ -102,13 +102,21 @@ fn run_check(args: CheckCommand) -> anyhow::Result<ExitStatus> {
102102
.map(|path| SystemPath::absolute(path, &cwd))
103103
.collect();
104104

105-
let system = OsSystem::new(cwd);
105+
let system = OsSystem::new(&cwd);
106106
let watch = args.watch;
107107
let exit_zero = args.exit_zero;
108+
let config_file = args
109+
.config_file
110+
.as_ref()
111+
.map(|path| SystemPath::absolute(path, &cwd));
112+
113+
let mut project_metadata = match &config_file {
114+
Some(config_file) => ProjectMetadata::from_config_file(config_file.clone(), &system)?,
115+
None => ProjectMetadata::discover(&project_path, &system)?,
116+
};
108117

109-
let cli_options = args.into_options();
110-
let mut project_metadata = ProjectMetadata::discover(&project_path, &system)?;
111-
project_metadata.apply_cli_options(cli_options.clone());
118+
let options = args.into_options();
119+
project_metadata.apply_options(options.clone());
112120
project_metadata.apply_configuration_files(&system)?;
113121

114122
let mut db = ProjectDatabase::new(project_metadata, system)?;
@@ -117,7 +125,8 @@ fn run_check(args: CheckCommand) -> anyhow::Result<ExitStatus> {
117125
db.project().set_included_paths(&mut db, check_paths);
118126
}
119127

120-
let (main_loop, main_loop_cancellation_token) = MainLoop::new(cli_options);
128+
let project_options_overrides = ProjectOptionsOverrides::new(config_file, options);
129+
let (main_loop, main_loop_cancellation_token) = MainLoop::new(project_options_overrides);
121130

122131
// Listen to Ctrl+C and abort the watch mode.
123132
let main_loop_cancellation_token = Mutex::new(Some(main_loop_cancellation_token));
@@ -178,19 +187,21 @@ struct MainLoop {
178187
/// The file system watcher, if running in watch mode.
179188
watcher: Option<ProjectWatcher>,
180189

181-
cli_options: Options,
190+
project_options_overrides: ProjectOptionsOverrides,
182191
}
183192

184193
impl MainLoop {
185-
fn new(cli_options: Options) -> (Self, MainLoopCancellationToken) {
194+
fn new(
195+
project_options_overrides: ProjectOptionsOverrides,
196+
) -> (Self, MainLoopCancellationToken) {
186197
let (sender, receiver) = crossbeam_channel::bounded(10);
187198

188199
(
189200
Self {
190201
sender: sender.clone(),
191202
receiver,
192203
watcher: None,
193-
cli_options,
204+
project_options_overrides,
194205
},
195206
MainLoopCancellationToken { sender },
196207
)
@@ -340,7 +351,7 @@ impl MainLoop {
340351
MainLoopMessage::ApplyChanges(changes) => {
341352
revision += 1;
342353
// Automatically cancels any pending queries and waits for them to complete.
343-
db.apply_changes(changes, Some(&self.cli_options));
354+
db.apply_changes(changes, Some(&self.project_options_overrides));
344355
if let Some(watcher) = self.watcher.as_mut() {
345356
watcher.update(db);
346357
}

crates/ty/tests/cli.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,63 @@ fn check_conda_prefix_var_to_resolve_path() -> anyhow::Result<()> {
16291629
----- stderr -----
16301630
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
16311631
");
1632+
1633+
Ok(())
1634+
}
1635+
1636+
#[test]
1637+
fn config_file_override() -> anyhow::Result<()> {
1638+
// Set `error-on-warning` to true in the configuration file
1639+
// Explicitly set `--warn unresolved-reference` to ensure the rule warns instead of errors
1640+
let case = TestCase::with_files(vec![
1641+
("test.py", r"print(x) # [unresolved-reference]"),
1642+
(
1643+
"ty-override.toml",
1644+
r#"
1645+
[terminal]
1646+
error-on-warning = true
1647+
"#,
1648+
),
1649+
])?;
1650+
1651+
// Ensure flag works via CLI arg
1652+
assert_cmd_snapshot!(case.command().arg("--warn").arg("unresolved-reference").arg("--config-file").arg("ty-override.toml"), @r"
1653+
success: false
1654+
exit_code: 1
1655+
----- stdout -----
1656+
warning[unresolved-reference]: Name `x` used when not defined
1657+
--> test.py:1:7
1658+
|
1659+
1 | print(x) # [unresolved-reference]
1660+
| ^
1661+
|
1662+
info: rule `unresolved-reference` was selected on the command line
1663+
1664+
Found 1 diagnostic
1665+
1666+
----- stderr -----
1667+
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
1668+
");
1669+
1670+
// Ensure the flag works via an environment variable
1671+
assert_cmd_snapshot!(case.command().arg("--warn").arg("unresolved-reference").env("TY_CONFIG_FILE", "ty-override.toml"), @r"
1672+
success: false
1673+
exit_code: 1
1674+
----- stdout -----
1675+
warning[unresolved-reference]: Name `x` used when not defined
1676+
--> test.py:1:7
1677+
|
1678+
1 | print(x) # [unresolved-reference]
1679+
| ^
1680+
|
1681+
info: rule `unresolved-reference` was selected on the command line
1682+
1683+
Found 1 diagnostic
1684+
1685+
----- stderr -----
1686+
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
1687+
");
1688+
16321689
Ok(())
16331690
}
16341691

0 commit comments

Comments
 (0)