Skip to content

Commit 71c144b

Browse files
committed
fix(executable): stricter regex for uv/uvx/uv tool run
1 parent d9f9a4f commit 71c144b

4 files changed

Lines changed: 76 additions & 16 deletions

File tree

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
#!/usr/bin/env -S uv run
22
print("hello world")
33

4-
#!/usr/bin/env uv --quiet run
54
#!/usr/bin/env uv --offline run
5+
print("offline")
6+
7+
#!/usr/bin/env uvx run
8+
print("uvx")
9+
10+
#!/usr/bin/env uv tool run
11+
print("uv tool")
12+
13+
#!/usr/bin/env uvx --quiet run
14+
print("uvx quiet")
15+
16+
#!/usr/bin/env uv_not_really_run
17+
print("this should fail")

crates/ruff_linter/src/rules/flake8_executable/rules/shebang_missing_python.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
use ruff_text_size::TextRange;
1+
use std::sync::LazyLock;
22

3+
use regex::Regex;
34
use ruff_macros::{ViolationMetadata, derive_message_formats};
5+
use ruff_text_size::TextRange;
46

57
use crate::Violation;
68
use crate::checkers::ast::LintContext;
79
use crate::comments::shebang::ShebangDirective;
810

11+
static UV_RUN_REGEX: LazyLock<Regex> =
12+
LazyLock::new(|| Regex::new(r"(?x) \b(?:uv|uvx|uv\s+tool)\b .* \s run \b").unwrap());
13+
914
/// ## What it does
1015
/// Checks for a shebang directive in `.py` files that does not contain `python`,
1116
/// `pytest`, or `uv run`.
@@ -48,12 +53,7 @@ pub(crate) fn shebang_missing_python(
4853
shebang: &ShebangDirective,
4954
context: &LintContext,
5055
) {
51-
if shebang.contains("python")
52-
|| shebang.contains("pytest")
53-
|| (shebang.contains("uv") && shebang.contains("run"))
54-
|| shebang.contains("uvx")
55-
|| shebang.contains("uv tool run")
56-
{
56+
if shebang.contains("python") || shebang.contains("pytest") || UV_RUN_REGEX.is_match(shebang) {
5757
return;
5858
}
5959

crates/ruff_linter/src/rules/flake8_executable/snapshots/ruff_linter__rules__flake8_executable__tests__EXE003_uv.py.snap

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,57 @@ EXE005 Shebang should be at the beginning of the file
66
|
77
2 | print("hello world")
88
3 |
9-
4 | #!/usr/bin/env uv --quiet run
10-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11-
5 | #!/usr/bin/env uv --offline run
9+
4 | #!/usr/bin/env uv --offline run
10+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11+
5 | print("offline")
1212
|
1313

1414
EXE005 Shebang should be at the beginning of the file
15-
--> EXE003_uv.py:5:1
15+
--> EXE003_uv.py:7:1
1616
|
17-
4 | #!/usr/bin/env uv --quiet run
18-
5 | #!/usr/bin/env uv --offline run
19-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
17+
5 | print("offline")
18+
6 |
19+
7 | #!/usr/bin/env uvx run
20+
| ^^^^^^^^^^^^^^^^^^^^^^
21+
8 | print("uvx")
2022
|
23+
24+
EXE005 Shebang should be at the beginning of the file
25+
--> EXE003_uv.py:10:1
26+
|
27+
8 | print("uvx")
28+
9 |
29+
10 | #!/usr/bin/env uv tool run
30+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
31+
11 | print("uv tool")
32+
|
33+
34+
EXE005 Shebang should be at the beginning of the file
35+
--> EXE003_uv.py:13:1
36+
|
37+
11 | print("uv tool")
38+
12 |
39+
13 | #!/usr/bin/env uvx --quiet run
40+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
41+
14 | print("uvx quiet")
42+
|
43+
44+
EXE003 Shebang should contain `python`, `pytest`, or `uv run`
45+
--> EXE003_uv.py:16:1
46+
|
47+
14 | print("uvx quiet")
48+
15 |
49+
16 | #!/usr/bin/env uv_not_really_run
50+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
51+
17 | print("this should fail")
52+
|
53+
54+
EXE005 Shebang should be at the beginning of the file
55+
--> EXE003_uv.py:16:1
56+
|
57+
14 | print("uvx quiet")
58+
15 |
59+
16 | #!/usr/bin/env uv_not_really_run
60+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
61+
17 | print("this should fail")
62+
|
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
---
22
source: crates/ruff_linter/src/rules/flake8_executable/mod.rs
33
---
4-
4+
EXE003 Shebang should contain `python`, `pytest`, or `uv run`
5+
--> EXE003_uvx.py:1:1
6+
|
7+
1 | #!/usr/bin/env -S uvx ruff check --isolated --select EXE003
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9+
2 | print("hello world")
10+
|

0 commit comments

Comments
 (0)