From 291ee9b5b3230f1a7e1c0e24e094e63b569a7043 Mon Sep 17 00:00:00 2001
From: feiyang
Date: Sat, 24 Jan 2026 10:18:54 +0000
Subject: [PATCH 1/5] feature ignore/warn/select all rules
---
crates/ty/src/args.rs | 6 +++---
crates/ty_project/src/metadata/options.rs | 23 ++++++++++++++++++-----
2 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/crates/ty/src/args.rs b/crates/ty/src/args.rs
index 1e556461a2609c..3686004af17e86 100644
--- a/crates/ty/src/args.rs
+++ b/crates/ty/src/args.rs
@@ -315,7 +315,7 @@ impl clap::Args for RulesArg {
clap::Arg::new("error")
.long("error")
.action(ArgAction::Append)
- .help("Treat the given rule as having severity 'error'. Can be specified multiple times.")
+ .help("Treat the given rule as having severity 'error'. Can be specified multiple times. Use 'all' to apply to all rules.")
.value_name("RULE")
.help_heading(HELP_HEADING),
)
@@ -323,7 +323,7 @@ impl clap::Args for RulesArg {
clap::Arg::new("warn")
.long("warn")
.action(ArgAction::Append)
- .help("Treat the given rule as having severity 'warn'. Can be specified multiple times.")
+ .help("Treat the given rule as having severity 'warn'. Can be specified multiple times. Use 'all' to apply to all rules.")
.value_name("RULE")
.help_heading(HELP_HEADING),
)
@@ -331,7 +331,7 @@ impl clap::Args for RulesArg {
clap::Arg::new("ignore")
.long("ignore")
.action(ArgAction::Append)
- .help("Disables the rule. Can be specified multiple times.")
+ .help("Disables the rule. Can be specified multiple times. Use 'all' to apply to all rules.")
.value_name("RULE")
.help_heading(HELP_HEADING),
)
diff --git a/crates/ty_project/src/metadata/options.rs b/crates/ty_project/src/metadata/options.rs
index 1eea1239acc2c5..6f1a510a27123a 100644
--- a/crates/ty_project/src/metadata/options.rs
+++ b/crates/ty_project/src/metadata/options.rs
@@ -882,13 +882,26 @@ impl Rules {
for (rule_name, level) in &self.inner {
let source = rule_name.source();
+ let lint_source = match source {
+ ValueSource::File(_) => LintSource::File,
+ ValueSource::Cli => LintSource::Cli,
+ ValueSource::Editor => LintSource::Editor,
+ };
+
+ // Handle "all" as a special case - apply the level to all rules
+ if rule_name.eq_ignore_ascii_case("all") {
+ for lint in registry.lints() {
+ if let Ok(severity) = Severity::try_from(**level) {
+ selection.enable(*lint, severity, lint_source);
+ } else {
+ selection.disable(*lint);
+ }
+ }
+ continue;
+ }
+
match registry.get(rule_name) {
Ok(lint) => {
- let lint_source = match source {
- ValueSource::File(_) => LintSource::File,
- ValueSource::Cli => LintSource::Cli,
- ValueSource::Editor => LintSource::Editor,
- };
if let Ok(severity) = Severity::try_from(**level) {
selection.enable(lint, severity, lint_source);
} else {
From cf0cde897b809ec93d0e500acd7e3508835b2682 Mon Sep 17 00:00:00 2001
From: feiyang
Date: Sat, 24 Jan 2026 10:32:10 +0000
Subject: [PATCH 2/5] add tests
---
crates/ty/tests/cli/rule_selection.rs | 233 ++++++++++++++++++++++++++
1 file changed, 233 insertions(+)
diff --git a/crates/ty/tests/cli/rule_selection.rs b/crates/ty/tests/cli/rule_selection.rs
index 56b944e05b3f16..65bcd1cc3d9a00 100644
--- a/crates/ty/tests/cli/rule_selection.rs
+++ b/crates/ty/tests/cli/rule_selection.rs
@@ -888,3 +888,236 @@ fn overrides_unknown_rules() -> anyhow::Result<()> {
Ok(())
}
+
+/// The "all" keyword can be used to set all rules to a specific severity
+#[test]
+fn cli_all_rules_ignore() -> anyhow::Result<()> {
+ let case = CliTest::with_file(
+ "test.py",
+ r#"
+ import does_not_exit
+
+ y = 4 / 0
+
+ prin(y) # unresolved-reference
+ "#,
+ )?;
+
+ // Using --ignore all should disable all rules
+ assert_cmd_snapshot!(
+ case
+ .command()
+ .arg("--ignore")
+ .arg("all"),
+ @"
+ success: true
+ exit_code: 0
+ ----- stdout -----
+ All checks passed!
+
+ ----- stderr -----
+ "
+ );
+
+ Ok(())
+}
+
+/// The "all" keyword works with --warn to set all rules to warn severity
+#[test]
+fn cli_all_rules_warn() -> anyhow::Result<()> {
+ let case = CliTest::with_file(
+ "test.py",
+ r#"
+ prin(x) # unresolved-reference
+ "#,
+ )?;
+
+ // Using --warn all should make all rules warnings (not errors)
+ assert_cmd_snapshot!(
+ case
+ .command()
+ .arg("--warn")
+ .arg("all"),
+ @"
+ success: true
+ exit_code: 0
+ ----- stdout -----
+ warning[unresolved-reference]: Name `prin` used when not defined
+ --> test.py:2:1
+ |
+ 2 | prin(x) # unresolved-reference
+ | ^^^^
+ |
+ info: rule `unresolved-reference` was selected on the command line
+
+ warning[unresolved-reference]: Name `x` used when not defined
+ --> test.py:2:6
+ |
+ 2 | prin(x) # unresolved-reference
+ | ^
+ |
+ info: rule `unresolved-reference` was selected on the command line
+
+ Found 2 diagnostics
+
+ ----- stderr -----
+ "
+ );
+
+ Ok(())
+}
+
+/// The "all" keyword can be overridden by subsequent specific rule settings
+#[test]
+fn cli_all_rules_with_override() -> anyhow::Result<()> {
+ let case = CliTest::with_file(
+ "test.py",
+ r#"
+ import does_not_exit
+
+ y = 4 / 0
+
+ prin(y) # unresolved-reference
+ "#,
+ )?;
+
+ // Using --ignore all followed by --error for a specific rule should
+ // disable all rules except the one specified
+ assert_cmd_snapshot!(
+ case
+ .command()
+ .arg("--ignore")
+ .arg("all")
+ .arg("--error")
+ .arg("unresolved-reference"),
+ @"
+ success: false
+ exit_code: 1
+ ----- stdout -----
+ error[unresolved-reference]: Name `prin` used when not defined
+ --> test.py:6:1
+ |
+ 4 | y = 4 / 0
+ 5 |
+ 6 | prin(y) # unresolved-reference
+ | ^^^^
+ |
+ info: rule `unresolved-reference` was selected on the command line
+
+ Found 1 diagnostic
+
+ ----- stderr -----
+ "
+ );
+
+ Ok(())
+}
+
+/// The "all" keyword is case-insensitive
+#[test]
+fn cli_all_rules_case_insensitive() -> anyhow::Result<()> {
+ let case = CliTest::with_file(
+ "test.py",
+ r#"
+ prin(x) # unresolved-reference
+ "#,
+ )?;
+
+ // Using --ignore ALL (uppercase) should work the same as --ignore all
+ assert_cmd_snapshot!(
+ case
+ .command()
+ .arg("--ignore")
+ .arg("ALL"),
+ @"
+ success: true
+ exit_code: 0
+ ----- stdout -----
+ All checks passed!
+
+ ----- stderr -----
+ "
+ );
+
+ Ok(())
+}
+
+/// A specific rule can be set first and then overridden by "all"
+#[test]
+fn cli_specific_then_all() -> anyhow::Result<()> {
+ let case = CliTest::with_file(
+ "test.py",
+ r#"
+ prin(x) # unresolved-reference
+ "#,
+ )?;
+
+ // Using --error for a specific rule followed by --ignore all should
+ // ignore all rules (including the previously set one)
+ assert_cmd_snapshot!(
+ case
+ .command()
+ .arg("--error")
+ .arg("unresolved-reference")
+ .arg("--ignore")
+ .arg("all"),
+ @"
+ success: true
+ exit_code: 0
+ ----- stdout -----
+ All checks passed!
+
+ ----- stderr -----
+ "
+ );
+
+ Ok(())
+}
+
+/// The "all" keyword works in configuration files
+#[test]
+fn configuration_all_rules() -> anyhow::Result<()> {
+ let case = CliTest::with_files([
+ (
+ "pyproject.toml",
+ r#"
+ [tool.ty.rules]
+ all = "ignore"
+ unresolved-reference = "error"
+ "#,
+ ),
+ (
+ "test.py",
+ r#"
+ import does_not_exit
+
+ y = 4 / 0
+
+ prin(y) # unresolved-reference
+ "#,
+ ),
+ ])?;
+
+ // The "all" rule should be processed first, ignoring all rules,
+ // then unresolved-reference should be enabled as error
+ assert_cmd_snapshot!(case.command(), @"
+ success: false
+ exit_code: 1
+ ----- stdout -----
+ error[unresolved-reference]: Name `prin` used when not defined
+ --> test.py:6:1
+ |
+ 4 | y = 4 / 0
+ 5 |
+ 6 | prin(y) # unresolved-reference
+ | ^^^^
+ |
+ info: rule `unresolved-reference` was selected in the configuration file
+
+ Found 1 diagnostic
+
+ ----- stderr -----
+ ");
+
+ Ok(())
+}
From 46420b690fe1b005d5fabb2f1262bbac4e5096d7 Mon Sep 17 00:00:00 2001
From: feiyang
Date: Sat, 24 Jan 2026 10:37:17 +0000
Subject: [PATCH 3/5] add comment
---
crates/ty_project/src/metadata/options.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/crates/ty_project/src/metadata/options.rs b/crates/ty_project/src/metadata/options.rs
index 6f1a510a27123a..d44364105d731f 100644
--- a/crates/ty_project/src/metadata/options.rs
+++ b/crates/ty_project/src/metadata/options.rs
@@ -894,6 +894,7 @@ impl Rules {
if let Ok(severity) = Severity::try_from(**level) {
selection.enable(*lint, severity, lint_source);
} else {
+ // ignore
selection.disable(*lint);
}
}
From b9387c3b5d9a35bf6cc41c92038d20d5cfe4f62a Mon Sep 17 00:00:00 2001
From: feiyang
Date: Tue, 27 Jan 2026 08:30:20 +0000
Subject: [PATCH 4/5] auto update docs
---
crates/ty/docs/cli.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/crates/ty/docs/cli.md b/crates/ty/docs/cli.md
index 5eedd09624c2d6..755af1b667c3fb 100644
--- a/crates/ty/docs/cli.md
+++ b/crates/ty/docs/cli.md
@@ -50,7 +50,7 @@ overriding a specific configuration option.
over all configuration files.
--config-file pathThe path to a ty.toml file to use for configuration.
While ty configuration can be included in a pyproject.toml file, it is not allowed in this context.
-May also be set with the TY_CONFIG_FILE environment variable.
--error ruleTreat the given rule as having severity 'error'. Can be specified multiple times.
+May also be set with the TY_CONFIG_FILE environment variable.
--error ruleTreat the given rule as having severity 'error'. Can be specified multiple times. Use 'all' to apply to all rules.
--error-on-warningUse exit code 1 if there are any warning-level diagnostics
--exclude excludeGlob patterns for files to exclude from type checking.
Uses gitignore-style syntax to exclude files and directories from type checking. Supports patterns like tests/, *.tmp, **/__pycache__/**.
@@ -59,7 +59,7 @@ over all configuration files.
This is an advanced option that should usually only be used for first-party or third-party modules that are not installed into your Python environment in a conventional way. Use --python to point ty to your Python environment if it is in an unusual location.
--force-excludeEnforce exclusions, even for paths passed to ty directly on the command-line. Use --no-force-exclude to disable
--help, -hPrint help (see a summary with '-h')
---ignore ruleDisables the rule. Can be specified multiple times.
+--ignore ruleDisables the rule. Can be specified multiple times. Use 'all' to apply to all rules.
--no-progressHide all progress outputs.
For example, spinners or progress bars.
--output-format output-formatThe format to use for printing diagnostic messages
@@ -95,7 +95,7 @@ over all configuration files.
--respect-ignore-filesRespect file exclusions via .gitignore and other standard ignore files. Use --no-respect-ignore-files to disable
--typeshed, --custom-typeshed-dir pathCustom directory to use for stdlib typeshed stubs
--verbose, -vUse verbose output (or -vv and -vvv for more verbose output)
---warn ruleTreat the given rule as having severity 'warn'. Can be specified multiple times.
+--warn ruleTreat the given rule as having severity 'warn'. Can be specified multiple times. Use 'all' to apply to all rules.
--watch, -WWatch files for changes and recheck files related to the changed files
From e9218d1e327d937c20d7c81ff64bf380193220dc Mon Sep 17 00:00:00 2001
From: feiyang
Date: Wed, 28 Jan 2026 08:12:18 +0000
Subject: [PATCH 5/5] share set lint level closure
---
crates/ty_project/src/metadata/options.rs | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/crates/ty_project/src/metadata/options.rs b/crates/ty_project/src/metadata/options.rs
index d44364105d731f..5428014b1a2b87 100644
--- a/crates/ty_project/src/metadata/options.rs
+++ b/crates/ty_project/src/metadata/options.rs
@@ -888,26 +888,25 @@ impl Rules {
ValueSource::Editor => LintSource::Editor,
};
+ let mut set_lint_level = |lint| {
+ if let Ok(severity) = Severity::try_from(**level) {
+ selection.enable(lint, severity, lint_source);
+ } else {
+ selection.disable(lint);
+ }
+ };
+
// Handle "all" as a special case - apply the level to all rules
if rule_name.eq_ignore_ascii_case("all") {
for lint in registry.lints() {
- if let Ok(severity) = Severity::try_from(**level) {
- selection.enable(*lint, severity, lint_source);
- } else {
- // ignore
- selection.disable(*lint);
- }
+ set_lint_level(*lint);
}
continue;
}
match registry.get(rule_name) {
Ok(lint) => {
- if let Ok(severity) = Severity::try_from(**level) {
- selection.enable(lint, severity, lint_source);
- } else {
- selection.disable(lint);
- }
+ set_lint_level(lint);
}
Err(error) => {
// `system_path_to_file` can return `Err` if the file was deleted since the configuration