RUF064: offer a safe fix for multi-digit zeros (#19847)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions

Fixes #19010

## Summary

See #19010. `0` was not considered a violation, but `000` was. The
latter will now be fixed to `0o000`.
This commit is contained in:
Frazer McLean 2025-08-10 22:35:27 +02:00 committed by GitHub
parent 8230b79829
commit 4d8ccb6125
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 98 additions and 1 deletions

View file

@ -51,3 +51,11 @@ dbm.ndbm.open("db", "r", 0o600) # OK
os.fchmod(0, 256) # 0o400
os.fchmod(0, 493) # 0o755
# https://github.com/astral-sh/ruff/issues/19010
os.chmod("foo", 000) # Error
os.chmod("foo", 0000) # Error
os.chmod("foo", 0b0) # Error
os.chmod("foo", 0x0) # Error
os.chmod("foo", 0) # Ok

View file

@ -57,6 +57,17 @@ use crate::{FixAvailability, Violation};
/// original code really intended to use `0o256` (`u=w,g=rx,o=rw`) instead of
/// `256`, this fix should not be accepted.
///
/// As a special case, zero is allowed to omit the `0o` prefix unless it has
/// multiple digits:
///
/// ```python
/// os.chmod("foo", 0) # Ok
/// os.chmod("foo", 0o000) # Ok
/// os.chmod("foo", 000) # Lint emitted and fix suggested
/// ```
///
/// Ruff will suggest a safe fix for multi-digit zeros to add the `0o` prefix.
///
/// ## Fix availability
///
/// A fix is only available if the integer literal matches a set of common modes.
@ -102,7 +113,14 @@ pub(crate) fn non_octal_permissions(checker: &Checker, call: &ExprCall) {
let mut diagnostic = checker.report_diagnostic(NonOctalPermissions, mode_arg.range());
// Don't suggest a fix for 0x or 0b literals.
if mode_literal.starts_with('0') {
if mode_literal.starts_with("0x") || mode_literal.starts_with("0b") {
return;
}
if mode_literal.chars().all(|c| c == '0') {
// Fix e.g. 000 as 0o000
let edit = Edit::range_replacement(format!("0o{mode_literal}"), mode_arg.range());
diagnostic.set_fix(Fix::safe_edit(edit));
return;
}

View file

@ -348,6 +348,8 @@ help: Replace with octal literal
52 |-os.fchmod(0, 256) # 0o400
52 |+os.fchmod(0, 0o400) # 0o400
53 53 | os.fchmod(0, 493) # 0o755
54 54 |
55 55 | # https://github.com/astral-sh/ruff/issues/19010
RUF064 [*] Non-octal mode
--> RUF064.py:53:14
@ -355,6 +357,8 @@ RUF064 [*] Non-octal mode
52 | os.fchmod(0, 256) # 0o400
53 | os.fchmod(0, 493) # 0o755
| ^^^
54 |
55 | # https://github.com/astral-sh/ruff/issues/19010
|
help: Replace with octal literal
@ -364,3 +368,70 @@ help: Replace with octal literal
52 52 | os.fchmod(0, 256) # 0o400
53 |-os.fchmod(0, 493) # 0o755
53 |+os.fchmod(0, 0o755) # 0o755
54 54 |
55 55 | # https://github.com/astral-sh/ruff/issues/19010
56 56 | os.chmod("foo", 000) # Error
RUF064 [*] Non-octal mode
--> RUF064.py:56:17
|
55 | # https://github.com/astral-sh/ruff/issues/19010
56 | os.chmod("foo", 000) # Error
| ^^^
57 | os.chmod("foo", 0000) # Error
|
help: Replace with octal literal
Safe fix
53 53 | os.fchmod(0, 493) # 0o755
54 54 |
55 55 | # https://github.com/astral-sh/ruff/issues/19010
56 |-os.chmod("foo", 000) # Error
56 |+os.chmod("foo", 0o000) # Error
57 57 | os.chmod("foo", 0000) # Error
58 58 |
59 59 | os.chmod("foo", 0b0) # Error
RUF064 [*] Non-octal mode
--> RUF064.py:57:17
|
55 | # https://github.com/astral-sh/ruff/issues/19010
56 | os.chmod("foo", 000) # Error
57 | os.chmod("foo", 0000) # Error
| ^^^^
58 |
59 | os.chmod("foo", 0b0) # Error
|
help: Replace with octal literal
Safe fix
54 54 |
55 55 | # https://github.com/astral-sh/ruff/issues/19010
56 56 | os.chmod("foo", 000) # Error
57 |-os.chmod("foo", 0000) # Error
57 |+os.chmod("foo", 0o0000) # Error
58 58 |
59 59 | os.chmod("foo", 0b0) # Error
60 60 | os.chmod("foo", 0x0) # Error
RUF064 Non-octal mode
--> RUF064.py:59:17
|
57 | os.chmod("foo", 0000) # Error
58 |
59 | os.chmod("foo", 0b0) # Error
| ^^^
60 | os.chmod("foo", 0x0) # Error
61 | os.chmod("foo", 0) # Ok
|
help: Replace with octal literal
RUF064 Non-octal mode
--> RUF064.py:60:17
|
59 | os.chmod("foo", 0b0) # Error
60 | os.chmod("foo", 0x0) # Error
| ^^^
61 | os.chmod("foo", 0) # Ok
|
help: Replace with octal literal