mirror of https://github.com/astral-sh/ruff
Avoid attempting infinite open fix with re-bound builtin (#3650)
This commit is contained in:
parent
33394e4a69
commit
3b1709ba1e
|
|
@ -1,9 +1,9 @@
|
|||
from io import open
|
||||
|
||||
with open("f.txt") as f:
|
||||
print(f.read())
|
||||
|
||||
import io
|
||||
|
||||
with io.open("f.txt", mode="r", buffering=-1, **kwargs) as f:
|
||||
print(f.read())
|
||||
|
||||
from io import open
|
||||
|
||||
with open("f.txt") as f:
|
||||
print(f.read())
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ mod tests {
|
|||
#[test_case(Rule::RedundantOpenModes, Path::new("UP015.py"); "UP015")]
|
||||
#[test_case(Rule::NativeLiterals, Path::new("UP018.py"); "UP018")]
|
||||
#[test_case(Rule::TypingTextStrAlias, Path::new("UP019.py"); "UP019")]
|
||||
#[test_case(Rule::OpenAlias, Path::new("UP020.py"); "UP020")]
|
||||
#[test_case(Rule::ReplaceUniversalNewlines, Path::new("UP021.py"); "UP021")]
|
||||
#[test_case(Rule::ReplaceStdoutStderr, Path::new("UP022.py"); "UP022")]
|
||||
#[test_case(Rule::DeprecatedCElementTree, Path::new("UP023.py"); "UP023")]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use rustpython_parser::ast::Expr;
|
||||
|
||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Fix};
|
||||
use ruff_diagnostics::{AutofixKind, Diagnostic, Fix, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::types::Range;
|
||||
|
||||
|
|
@ -8,16 +8,21 @@ use crate::checkers::ast::Checker;
|
|||
use crate::registry::AsRule;
|
||||
|
||||
#[violation]
|
||||
pub struct OpenAlias;
|
||||
pub struct OpenAlias {
|
||||
pub fixable: bool,
|
||||
}
|
||||
|
||||
impl Violation for OpenAlias {
|
||||
const AUTOFIX: AutofixKind = AutofixKind::Sometimes;
|
||||
|
||||
impl AlwaysAutofixableViolation for OpenAlias {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Use builtin `open`")
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
"Replace with builtin `open`".to_string()
|
||||
fn autofix_title_formatter(&self) -> Option<fn(&Self) -> String> {
|
||||
self.fixable
|
||||
.then_some(|_| format!("Replace with builtin `open`"))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -28,8 +33,12 @@ pub fn open_alias(checker: &mut Checker, expr: &Expr, func: &Expr) {
|
|||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| call_path.as_slice() == ["io", "open"])
|
||||
{
|
||||
let mut diagnostic = Diagnostic::new(OpenAlias, Range::from(expr));
|
||||
if checker.patch(diagnostic.kind.rule()) {
|
||||
let fixable = checker
|
||||
.ctx
|
||||
.find_binding("open")
|
||||
.map_or(true, |binding| binding.kind.is_builtin());
|
||||
let mut diagnostic = Diagnostic::new(OpenAlias { fixable }, Range::from(expr));
|
||||
if fixable && checker.patch(diagnostic.kind.rule()) {
|
||||
diagnostic.amend(Fix::replacement(
|
||||
"open".to_string(),
|
||||
func.location,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
source: crates/ruff/src/rules/pyupgrade/mod.rs
|
||||
expression: diagnostics
|
||||
---
|
||||
- kind:
|
||||
name: OpenAlias
|
||||
body: "Use builtin `open`"
|
||||
suggestion: "Replace with builtin `open`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 3
|
||||
column: 5
|
||||
end_location:
|
||||
row: 3
|
||||
column: 55
|
||||
fix:
|
||||
content: open
|
||||
location:
|
||||
row: 3
|
||||
column: 5
|
||||
end_location:
|
||||
row: 3
|
||||
column: 12
|
||||
parent: ~
|
||||
- kind:
|
||||
name: OpenAlias
|
||||
body: "Use builtin `open`"
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 8
|
||||
column: 5
|
||||
end_location:
|
||||
row: 8
|
||||
column: 18
|
||||
fix: ~
|
||||
parent: ~
|
||||
|
||||
Loading…
Reference in New Issue