mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-03 05:13:00 +00:00
[ty] File inclusion and exclusion (#18498)
This commit is contained in:
parent
3c6c017950
commit
1f27d53fd5
23 changed files with 2728 additions and 159 deletions
2
crates/ty/docs/cli.md
generated
2
crates/ty/docs/cli.md
generated
|
|
@ -51,6 +51,8 @@ over all configuration files.</p>
|
|||
<p>While ty configuration can be included in a <code>pyproject.toml</code> file, it is not allowed in this context.</p>
|
||||
<p>May also be set with the <code>TY_CONFIG_FILE</code> environment variable.</p></dd><dt id="ty-check--error"><a href="#ty-check--error"><code>--error</code></a> <i>rule</i></dt><dd><p>Treat the given rule as having severity 'error'. Can be specified multiple times.</p>
|
||||
</dd><dt id="ty-check--error-on-warning"><a href="#ty-check--error-on-warning"><code>--error-on-warning</code></a></dt><dd><p>Use exit code 1 if there are any warning-level diagnostics</p>
|
||||
</dd><dt id="ty-check--exclude"><a href="#ty-check--exclude"><code>--exclude</code></a> <i>exclude</i></dt><dd><p>Glob patterns for files to exclude from type checking.</p>
|
||||
<p>Uses gitignore-style syntax to exclude files and directories from type checking. Supports patterns like <code>tests/</code>, <code>*.tmp</code>, <code>**/__pycache__/**</code>.</p>
|
||||
</dd><dt id="ty-check--exit-zero"><a href="#ty-check--exit-zero"><code>--exit-zero</code></a></dt><dd><p>Always use exit code 0, even when there are error-level diagnostics</p>
|
||||
</dd><dt id="ty-check--extra-search-path"><a href="#ty-check--extra-search-path"><code>--extra-search-path</code></a> <i>path</i></dt><dd><p>Additional path to use as a module-resolution source (can be passed multiple times)</p>
|
||||
</dd><dt id="ty-check--help"><a href="#ty-check--help"><code>--help</code></a>, <code>-h</code></dt><dd><p>Print help (see a summary with '-h')</p>
|
||||
|
|
|
|||
61
crates/ty/docs/configuration.md
generated
61
crates/ty/docs/configuration.md
generated
|
|
@ -153,6 +153,67 @@ typeshed = "/path/to/custom/typeshed"
|
|||
|
||||
## `src`
|
||||
|
||||
#### `exclude`
|
||||
|
||||
A list of file and directory patterns to exclude from type checking.
|
||||
|
||||
Patterns follow a syntax similar to `.gitignore`:
|
||||
- `./src/` matches only a directory
|
||||
- `./src` matches both files and directories
|
||||
- `src` matches files or directories named `src` anywhere in the tree (e.g. `./src` or `./tests/src`)
|
||||
- `*` matches any (possibly empty) sequence of characters (except `/`).
|
||||
- `**` matches zero or more path components.
|
||||
This sequence **must** form a single path component, so both `**a` and `b**` are invalid and will result in an error.
|
||||
A sequence of more than two consecutive `*` characters is also invalid.
|
||||
- `?` matches any single character except `/`
|
||||
- `[abc]` matches any character inside the brackets. Character sequences can also specify ranges of characters, as ordered by Unicode,
|
||||
so e.g. `[0-9]` specifies any character between `0` and `9` inclusive. An unclosed bracket is invalid.
|
||||
- `!pattern` negates a pattern (undoes the exclusion of files that would otherwise be excluded)
|
||||
|
||||
By default, the following directories are excluded:
|
||||
|
||||
- `.bzr`
|
||||
- `.direnv`
|
||||
- `.eggs`
|
||||
- `.git`
|
||||
- `.git-rewrite`
|
||||
- `.hg`
|
||||
- `.mypy_cache`
|
||||
- `.nox`
|
||||
- `.pants.d`
|
||||
- `.pytype`
|
||||
- `.ruff_cache`
|
||||
- `.svn`
|
||||
- `.tox`
|
||||
- `.venv`
|
||||
- `__pypackages__`
|
||||
- `_build`
|
||||
- `buck-out`
|
||||
- `dist`
|
||||
- `node_modules`
|
||||
- `venv`
|
||||
|
||||
You can override any default exclude by using a negated pattern. For example,
|
||||
to re-include `dist` use `exclude = ["!dist"]`
|
||||
|
||||
**Default value**: `null`
|
||||
|
||||
**Type**: `list[str]`
|
||||
|
||||
**Example usage** (`pyproject.toml`):
|
||||
|
||||
```toml
|
||||
[tool.ty.src]
|
||||
exclude = [
|
||||
"generated",
|
||||
"*.proto",
|
||||
"tests/fixtures/**",
|
||||
"!tests/fixtures/important.py" # Include this one file
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `respect-ignore-files`
|
||||
|
||||
Whether to automatically exclude files that are ignored by `.ignore`,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ use clap::{ArgAction, ArgMatches, Error, Parser};
|
|||
use ruff_db::system::SystemPathBuf;
|
||||
use ty_project::combine::Combine;
|
||||
use ty_project::metadata::options::{EnvironmentOptions, Options, SrcOptions, TerminalOptions};
|
||||
use ty_project::metadata::value::{RangedValue, RelativePathBuf, ValueSource};
|
||||
use ty_project::metadata::value::{
|
||||
RangedValue, RelativeExcludePattern, RelativePathBuf, ValueSource,
|
||||
};
|
||||
use ty_python_semantic::lint;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
|
|
@ -148,6 +150,13 @@ pub(crate) struct CheckCommand {
|
|||
respect_ignore_files: Option<bool>,
|
||||
#[clap(long, overrides_with("respect_ignore_files"), hide = true)]
|
||||
no_respect_ignore_files: bool,
|
||||
|
||||
/// Glob 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__/**`.
|
||||
#[arg(long, help_heading = "File selection")]
|
||||
exclude: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
impl CheckCommand {
|
||||
|
|
@ -195,6 +204,12 @@ impl CheckCommand {
|
|||
}),
|
||||
src: Some(SrcOptions {
|
||||
respect_ignore_files,
|
||||
exclude: self.exclude.map(|excludes| {
|
||||
excludes
|
||||
.iter()
|
||||
.map(|exclude| RelativeExcludePattern::cli(exclude))
|
||||
.collect()
|
||||
}),
|
||||
..SrcOptions::default()
|
||||
}),
|
||||
rules,
|
||||
|
|
|
|||
726
crates/ty/tests/cli/file_selection.rs
Normal file
726
crates/ty/tests/cli/file_selection.rs
Normal file
|
|
@ -0,0 +1,726 @@
|
|||
use insta_cmd::assert_cmd_snapshot;
|
||||
|
||||
use crate::CliTest;
|
||||
|
||||
/// Test exclude CLI argument functionality
|
||||
#[test]
|
||||
fn exclude_argument() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_files([
|
||||
(
|
||||
"src/main.py",
|
||||
r#"
|
||||
print(undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"tests/test_main.py",
|
||||
r#"
|
||||
print(another_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"temp_file.py",
|
||||
r#"
|
||||
print(temp_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
])?;
|
||||
|
||||
// Test that exclude argument is recognized and works
|
||||
assert_cmd_snapshot!(case.command().arg("--exclude").arg("tests/"), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `undefined_var` used when not defined
|
||||
--> src/main.py:2:7
|
||||
|
|
||||
2 | print(undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
error[unresolved-reference]: Name `temp_undefined_var` used when not defined
|
||||
--> temp_file.py:2:7
|
||||
|
|
||||
2 | print(temp_undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 2 diagnostics
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
// Test multiple exclude patterns
|
||||
assert_cmd_snapshot!(case.command().arg("--exclude").arg("tests/").arg("--exclude").arg("temp_*.py"), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `undefined_var` used when not defined
|
||||
--> src/main.py:2:7
|
||||
|
|
||||
2 | print(undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 1 diagnostic
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Test configuration file include functionality
|
||||
#[test]
|
||||
fn configuration_include() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_files([
|
||||
(
|
||||
"src/main.py",
|
||||
r#"
|
||||
print(undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"tests/test_main.py",
|
||||
r#"
|
||||
print(another_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"other.py",
|
||||
r#"
|
||||
print(other_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
])?;
|
||||
|
||||
// Test include via configuration - should only check included files
|
||||
case.write_file(
|
||||
"ty.toml",
|
||||
r#"
|
||||
[src]
|
||||
include = ["src"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
assert_cmd_snapshot!(case.command(), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `undefined_var` used when not defined
|
||||
--> src/main.py:2:7
|
||||
|
|
||||
2 | print(undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 1 diagnostic
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
// Test multiple include patterns via configuration
|
||||
case.write_file(
|
||||
"ty.toml",
|
||||
r#"
|
||||
[src]
|
||||
include = ["src", "other.py"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
assert_cmd_snapshot!(case.command(), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `other_undefined_var` used when not defined
|
||||
--> other.py:2:7
|
||||
|
|
||||
2 | print(other_undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
error[unresolved-reference]: Name `undefined_var` used when not defined
|
||||
--> src/main.py:2:7
|
||||
|
|
||||
2 | print(undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 2 diagnostics
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Test configuration file exclude functionality
|
||||
#[test]
|
||||
fn configuration_exclude() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_files([
|
||||
(
|
||||
"src/main.py",
|
||||
r#"
|
||||
print(undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"tests/test_main.py",
|
||||
r#"
|
||||
print(another_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"temp_file.py",
|
||||
r#"
|
||||
print(temp_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
])?;
|
||||
|
||||
// Test exclude via configuration
|
||||
case.write_file(
|
||||
"ty.toml",
|
||||
r#"
|
||||
[src]
|
||||
exclude = ["tests/"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
assert_cmd_snapshot!(case.command(), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `undefined_var` used when not defined
|
||||
--> src/main.py:2:7
|
||||
|
|
||||
2 | print(undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
error[unresolved-reference]: Name `temp_undefined_var` used when not defined
|
||||
--> temp_file.py:2:7
|
||||
|
|
||||
2 | print(temp_undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 2 diagnostics
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
// Test multiple exclude patterns via configuration
|
||||
case.write_file(
|
||||
"ty.toml",
|
||||
r#"
|
||||
[src]
|
||||
exclude = ["tests/", "temp_*.py"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
assert_cmd_snapshot!(case.command(), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `undefined_var` used when not defined
|
||||
--> src/main.py:2:7
|
||||
|
|
||||
2 | print(undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 1 diagnostic
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Test that exclude takes precedence over include in configuration
|
||||
#[test]
|
||||
fn exclude_precedence_over_include() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_files([
|
||||
(
|
||||
"src/main.py",
|
||||
r#"
|
||||
print(undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"src/test_helper.py",
|
||||
r#"
|
||||
print(helper_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"other.py",
|
||||
r#"
|
||||
print(other_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
])?;
|
||||
|
||||
// Include all src files but exclude test files - exclude should win
|
||||
case.write_file(
|
||||
"ty.toml",
|
||||
r#"
|
||||
[src]
|
||||
include = ["src"]
|
||||
exclude = ["test_*.py"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
assert_cmd_snapshot!(case.command(), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `undefined_var` used when not defined
|
||||
--> src/main.py:2:7
|
||||
|
|
||||
2 | print(undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 1 diagnostic
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Test that CLI exclude overrides configuration include
|
||||
#[test]
|
||||
fn exclude_argument_precedence_include_argument() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_files([
|
||||
(
|
||||
"src/main.py",
|
||||
r#"
|
||||
print(undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"tests/test_main.py",
|
||||
r#"
|
||||
print(another_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"other.py",
|
||||
r#"
|
||||
print(other_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
])?;
|
||||
|
||||
// Configuration includes all files, but CLI excludes tests
|
||||
case.write_file(
|
||||
"ty.toml",
|
||||
r#"
|
||||
[src]
|
||||
include = ["src/", "tests/"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
assert_cmd_snapshot!(case.command().arg("--exclude").arg("tests/"), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `undefined_var` used when not defined
|
||||
--> src/main.py:2:7
|
||||
|
|
||||
2 | print(undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 1 diagnostic
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Test that default excludes can be removed using negated patterns
|
||||
#[test]
|
||||
fn remove_default_exclude() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_files([
|
||||
(
|
||||
"src/main.py",
|
||||
r#"
|
||||
print(undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"dist/generated.py",
|
||||
r#"
|
||||
print(another_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
])?;
|
||||
|
||||
// By default, 'dist' directory should be excluded (see default excludes)
|
||||
assert_cmd_snapshot!(case.command(), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `undefined_var` used when not defined
|
||||
--> src/main.py:2:7
|
||||
|
|
||||
2 | print(undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 1 diagnostic
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
// Now override the default exclude by using a negated pattern to re-include 'dist'
|
||||
case.write_file(
|
||||
"ty.toml",
|
||||
r#"
|
||||
[src]
|
||||
exclude = ["!dist"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
assert_cmd_snapshot!(case.command(), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `another_undefined_var` used when not defined
|
||||
--> dist/generated.py:2:7
|
||||
|
|
||||
2 | print(another_undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
error[unresolved-reference]: Name `undefined_var` used when not defined
|
||||
--> src/main.py:2:7
|
||||
|
|
||||
2 | print(undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 2 diagnostics
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Test that configuration excludes can be removed via CLI negation
|
||||
#[test]
|
||||
fn cli_removes_config_exclude() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_files([
|
||||
(
|
||||
"src/main.py",
|
||||
r#"
|
||||
print(undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"build/output.py",
|
||||
r#"
|
||||
print(build_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
])?;
|
||||
|
||||
// Configuration excludes the build directory
|
||||
case.write_file(
|
||||
"ty.toml",
|
||||
r#"
|
||||
[src]
|
||||
exclude = ["build/"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
// Verify that build/ is excluded by configuration
|
||||
assert_cmd_snapshot!(case.command(), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `undefined_var` used when not defined
|
||||
--> src/main.py:2:7
|
||||
|
|
||||
2 | print(undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 1 diagnostic
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
// Now remove the configuration exclude via CLI negation
|
||||
assert_cmd_snapshot!(case.command().arg("--exclude").arg("!build/"), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `build_undefined_var` used when not defined
|
||||
--> build/output.py:2:7
|
||||
|
|
||||
2 | print(build_undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
error[unresolved-reference]: Name `undefined_var` used when not defined
|
||||
--> src/main.py:2:7
|
||||
|
|
||||
2 | print(undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 2 diagnostics
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Test behavior when explicitly checking a path that matches an exclude pattern
|
||||
#[test]
|
||||
fn explicit_path_overrides_exclude() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_files([
|
||||
(
|
||||
"src/main.py",
|
||||
r#"
|
||||
print(undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"tests/generated.py",
|
||||
r#"
|
||||
print(dist_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"dist/other.py",
|
||||
r#"
|
||||
print(other_undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"ty.toml",
|
||||
r#"
|
||||
[src]
|
||||
exclude = ["tests/generated.py"]
|
||||
"#,
|
||||
),
|
||||
])?;
|
||||
|
||||
// dist is excluded by default and `tests/generated` is excluded in the project, so only src/main.py should be checked
|
||||
assert_cmd_snapshot!(case.command(), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `undefined_var` used when not defined
|
||||
--> src/main.py:2:7
|
||||
|
|
||||
2 | print(undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 1 diagnostic
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
// Explicitly checking a file in an excluded directory should still check that file
|
||||
assert_cmd_snapshot!(case.command().arg("tests/generated.py"), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `dist_undefined_var` used when not defined
|
||||
--> tests/generated.py:2:7
|
||||
|
|
||||
2 | print(dist_undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 1 diagnostic
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
// Explicitly checking the entire excluded directory should check all files in it
|
||||
assert_cmd_snapshot!(case.command().arg("dist/"), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `other_undefined_var` used when not defined
|
||||
--> dist/other.py:2:7
|
||||
|
|
||||
2 | print(other_undefined_var) # error: unresolved-reference
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 1 diagnostic
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_include_pattern() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_files([
|
||||
(
|
||||
"src/main.py",
|
||||
r#"
|
||||
print(undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"ty.toml",
|
||||
r#"
|
||||
[src]
|
||||
include = [
|
||||
"src/**test/"
|
||||
]
|
||||
"#,
|
||||
),
|
||||
])?;
|
||||
|
||||
// By default, dist/ is excluded, so only src/main.py should be checked
|
||||
assert_cmd_snapshot!(case.command(), @r#"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
ty failed
|
||||
Cause: error[invalid-glob]: Invalid include pattern
|
||||
--> ty.toml:4:5
|
||||
|
|
||||
2 | [src]
|
||||
3 | include = [
|
||||
4 | "src/**test/"
|
||||
| ^^^^^^^^^^^^^ Too many stars at position 5 in glob: `src/**test/`
|
||||
5 | ]
|
||||
|
|
||||
"#);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_include_pattern_concise_output() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_files([
|
||||
(
|
||||
"src/main.py",
|
||||
r#"
|
||||
print(undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"ty.toml",
|
||||
r#"
|
||||
[src]
|
||||
include = [
|
||||
"src/**test/"
|
||||
]
|
||||
"#,
|
||||
),
|
||||
])?;
|
||||
|
||||
// By default, dist/ is excluded, so only src/main.py should be checked
|
||||
assert_cmd_snapshot!(case.command().arg("--output-format").arg("concise"), @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
ty failed
|
||||
Cause: error[invalid-glob] ty.toml:4:5: Invalid include pattern: Too many stars at position 5 in glob: `src/**test/`
|
||||
");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_exclude_pattern() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_files([
|
||||
(
|
||||
"src/main.py",
|
||||
r#"
|
||||
print(undefined_var) # error: unresolved-reference
|
||||
"#,
|
||||
),
|
||||
(
|
||||
"ty.toml",
|
||||
r#"
|
||||
[src]
|
||||
exclude = [
|
||||
"../src"
|
||||
]
|
||||
"#,
|
||||
),
|
||||
])?;
|
||||
|
||||
// By default, dist/ is excluded, so only src/main.py should be checked
|
||||
assert_cmd_snapshot!(case.command(), @r#"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
WARN ty is pre-release software and not ready for production use. Expect to encounter bugs, missing features, and fatal errors.
|
||||
ty failed
|
||||
Cause: error[invalid-glob]: Invalid exclude pattern
|
||||
--> ty.toml:4:5
|
||||
|
|
||||
2 | [src]
|
||||
3 | exclude = [
|
||||
4 | "../src"
|
||||
| ^^^^^^^^ The parent directory operator (`..`) at position 1 is not allowed in glob: `../src`
|
||||
5 | ]
|
||||
|
|
||||
"#);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
mod config_option;
|
||||
mod exit_code;
|
||||
mod file_selection;
|
||||
mod python_environment;
|
||||
mod rule_selection;
|
||||
|
||||
|
|
|
|||
|
|
@ -254,12 +254,12 @@ fn configuration_unknown_rules() -> anyhow::Result<()> {
|
|||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
warning[unknown-rule]
|
||||
warning[unknown-rule]: Unknown lint rule `division-by-zer`
|
||||
--> pyproject.toml:3:1
|
||||
|
|
||||
2 | [tool.ty.rules]
|
||||
3 | division-by-zer = "warn" # incorrect rule name
|
||||
| ^^^^^^^^^^^^^^^ Unknown lint rule `division-by-zer`
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
|
||||
Found 1 diagnostic
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue