mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-02 12:58:27 +00:00
[pyupgrade] Apply UP008 only when the __class__ cell exists (#19424)
## Summary Resolves #19357 Skip UP008 diagnostic for `builtins.super(P, self)` calls when `__class__` is not referenced locally, preventing incorrect fixes. **Note:** I haven't found concrete information about which cases `__class__` will be loaded into the scope. Let me know if anyone has references, it would be useful to enhance the implementation. I did a lot of tests to determine when `__class__` is loaded. Considered sources: 1. [Python doc super](https://docs.python.org/3/library/functions.html#super) 2. [Python doc classes](https://docs.python.org/3/tutorial/classes.html) 3. [pep-3135](https://peps.python.org/pep-3135/#specification) As I understand it, Python will inject at runtime into local scope a `__class__` variable if it detects references to `super` or `__class__`. This allows calling `super()` and passing appropriate parameters. However, the compiler doesn't do the same for `builtins.super`, so we need to somehow introduce `__class__` into the local scope. I figured out `__class__` will be in scope with valid value when two conditions are met: 1. `super` or `__class__` names have been loaded within function scope 4. `__class__` is not overridden. I think my solution isn't elegant, so I would be appreciate a detailed review. ## Test Plan Added 19 test cases, updated snapshots. --------- Co-authored-by: Igor Drokin <drokinii1017@gmail.com>
This commit is contained in:
parent
d7524ea6d4
commit
54df73c9f7
4 changed files with 620 additions and 41 deletions
|
|
@ -141,3 +141,133 @@ class ExampleWithKeywords:
|
||||||
|
|
||||||
def method3(self):
|
def method3(self):
|
||||||
super(ExampleWithKeywords, self).some_method() # Should be fixed - no keywords
|
super(ExampleWithKeywords, self).some_method() # Should be fixed - no keywords
|
||||||
|
|
||||||
|
# See: https://github.com/astral-sh/ruff/issues/19357
|
||||||
|
# Must be detected
|
||||||
|
class ParentD:
|
||||||
|
def f(self):
|
||||||
|
print("D")
|
||||||
|
|
||||||
|
class ChildD1(ParentD):
|
||||||
|
def f(self):
|
||||||
|
if False: __class__ # Python injects __class__ into scope
|
||||||
|
builtins.super(ChildD1, self).f()
|
||||||
|
|
||||||
|
class ChildD2(ParentD):
|
||||||
|
def f(self):
|
||||||
|
if False: super # Python injects __class__ into scope
|
||||||
|
builtins.super(ChildD2, self).f()
|
||||||
|
|
||||||
|
class ChildD3(ParentD):
|
||||||
|
def f(self):
|
||||||
|
builtins.super(ChildD3, self).f()
|
||||||
|
super # Python injects __class__ into scope
|
||||||
|
|
||||||
|
import builtins as builtins_alias
|
||||||
|
class ChildD4(ParentD):
|
||||||
|
def f(self):
|
||||||
|
builtins_alias.super(ChildD4, self).f()
|
||||||
|
super # Python injects __class__ into scope
|
||||||
|
|
||||||
|
class ChildD5(ParentD):
|
||||||
|
def f(self):
|
||||||
|
super = 1
|
||||||
|
super # Python injects __class__ into scope
|
||||||
|
builtins.super(ChildD5, self).f()
|
||||||
|
|
||||||
|
class ChildD6(ParentD):
|
||||||
|
def f(self):
|
||||||
|
super: "Any"
|
||||||
|
__class__ # Python injects __class__ into scope
|
||||||
|
builtins.super(ChildD6, self).f()
|
||||||
|
|
||||||
|
class ChildD7(ParentD):
|
||||||
|
def f(self):
|
||||||
|
def x():
|
||||||
|
__class__ # Python injects __class__ into scope
|
||||||
|
builtins.super(ChildD7, self).f()
|
||||||
|
|
||||||
|
class ChildD8(ParentD):
|
||||||
|
def f(self):
|
||||||
|
def x():
|
||||||
|
super = 1
|
||||||
|
super # Python injects __class__ into scope
|
||||||
|
builtins.super(ChildD8, self).f()
|
||||||
|
|
||||||
|
class ChildD9(ParentD):
|
||||||
|
def f(self):
|
||||||
|
def x():
|
||||||
|
__class__ = 1
|
||||||
|
__class__ # Python injects __class__ into scope
|
||||||
|
builtins.super(ChildD9, self).f()
|
||||||
|
|
||||||
|
class ChildD10(ParentD):
|
||||||
|
def f(self):
|
||||||
|
def x():
|
||||||
|
__class__ = 1
|
||||||
|
super # Python injects __class__ into scope
|
||||||
|
builtins.super(ChildD10, self).f()
|
||||||
|
|
||||||
|
|
||||||
|
# Must be ignored
|
||||||
|
class ParentI:
|
||||||
|
def f(self):
|
||||||
|
print("I")
|
||||||
|
|
||||||
|
class ChildI1(ParentI):
|
||||||
|
def f(self):
|
||||||
|
builtins.super(ChildI1, self).f() # no __class__ in the local scope
|
||||||
|
|
||||||
|
|
||||||
|
class ChildI2(ParentI):
|
||||||
|
def b(self):
|
||||||
|
x = __class__
|
||||||
|
if False: super
|
||||||
|
|
||||||
|
def f(self):
|
||||||
|
self.b()
|
||||||
|
builtins.super(ChildI2, self).f() # no __class__ in the local scope
|
||||||
|
|
||||||
|
class ChildI3(ParentI):
|
||||||
|
def f(self):
|
||||||
|
if False: super
|
||||||
|
def x(_):
|
||||||
|
builtins.super(ChildI3, self).f() # no __class__ in the local scope
|
||||||
|
x(None)
|
||||||
|
|
||||||
|
class ChildI4(ParentI):
|
||||||
|
def f(self):
|
||||||
|
super: "str"
|
||||||
|
builtins.super(ChildI4, self).f() # no __class__ in the local scope
|
||||||
|
|
||||||
|
class ChildI5(ParentI):
|
||||||
|
def f(self):
|
||||||
|
super = 1
|
||||||
|
__class__ = 3
|
||||||
|
builtins.super(ChildI5, self).f() # no __class__ in the local scope
|
||||||
|
|
||||||
|
class ChildI6(ParentI):
|
||||||
|
def f(self):
|
||||||
|
__class__ = None
|
||||||
|
__class__
|
||||||
|
builtins.super(ChildI6, self).f() # no __class__ in the local scope
|
||||||
|
|
||||||
|
class ChildI7(ParentI):
|
||||||
|
def f(self):
|
||||||
|
__class__ = None
|
||||||
|
super
|
||||||
|
builtins.super(ChildI7, self).f()
|
||||||
|
|
||||||
|
class ChildI8(ParentI):
|
||||||
|
def f(self):
|
||||||
|
__class__: "Any"
|
||||||
|
super
|
||||||
|
builtins.super(ChildI8, self).f()
|
||||||
|
|
||||||
|
class ChildI9(ParentI):
|
||||||
|
def f(self):
|
||||||
|
class A:
|
||||||
|
def foo(self):
|
||||||
|
if False: super
|
||||||
|
if False: __class__
|
||||||
|
builtins.super(ChildI9, self).f()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
use ruff_diagnostics::Applicability;
|
use ruff_diagnostics::Applicability;
|
||||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||||
|
use ruff_python_ast::visitor::{Visitor, walk_expr, walk_stmt};
|
||||||
use ruff_python_ast::{self as ast, Expr, Stmt};
|
use ruff_python_ast::{self as ast, Expr, Stmt};
|
||||||
|
use ruff_python_semantic::SemanticModel;
|
||||||
use ruff_text_size::{Ranged, TextSize};
|
use ruff_text_size::{Ranged, TextSize};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
@ -94,14 +96,22 @@ pub(crate) fn super_call_with_parameters(checker: &Checker, call: &ast::ExprCall
|
||||||
};
|
};
|
||||||
|
|
||||||
// Find the enclosing function definition (if any).
|
// Find the enclosing function definition (if any).
|
||||||
let Some(Stmt::FunctionDef(ast::StmtFunctionDef {
|
let Some(
|
||||||
parameters: parent_parameters,
|
func_stmt @ Stmt::FunctionDef(ast::StmtFunctionDef {
|
||||||
..
|
parameters: parent_parameters,
|
||||||
})) = parents.find(|stmt| stmt.is_function_def_stmt())
|
..
|
||||||
|
}),
|
||||||
|
) = parents.find(|stmt| stmt.is_function_def_stmt())
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if is_builtins_super(checker.semantic(), call)
|
||||||
|
&& !has_local_dunder_class_var_ref(checker.semantic(), func_stmt)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Extract the name of the first argument to the enclosing function.
|
// Extract the name of the first argument to the enclosing function.
|
||||||
let Some(parent_arg) = parent_parameters.args.first() else {
|
let Some(parent_arg) = parent_parameters.args.first() else {
|
||||||
return;
|
return;
|
||||||
|
|
@ -193,3 +203,67 @@ pub(crate) fn super_call_with_parameters(checker: &Checker, call: &ast::ExprCall
|
||||||
fn is_super_call_with_arguments(call: &ast::ExprCall, checker: &Checker) -> bool {
|
fn is_super_call_with_arguments(call: &ast::ExprCall, checker: &Checker) -> bool {
|
||||||
checker.semantic().match_builtin_expr(&call.func, "super") && !call.arguments.is_empty()
|
checker.semantic().match_builtin_expr(&call.func, "super") && !call.arguments.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the function contains load references to `__class__` or `super` without
|
||||||
|
/// local binding.
|
||||||
|
///
|
||||||
|
/// This indicates that the function relies on the implicit `__class__` cell variable created by
|
||||||
|
/// Python when `super()` is called without arguments, making it unsafe to remove `super()` parameters.
|
||||||
|
fn has_local_dunder_class_var_ref(semantic: &SemanticModel, func_stmt: &Stmt) -> bool {
|
||||||
|
if semantic.current_scope().has("__class__") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut finder = ClassCellReferenceFinder::new();
|
||||||
|
finder.visit_stmt(func_stmt);
|
||||||
|
|
||||||
|
finder.found()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the call is to the built-in `builtins.super` function.
|
||||||
|
fn is_builtins_super(semantic: &SemanticModel, call: &ast::ExprCall) -> bool {
|
||||||
|
semantic
|
||||||
|
.resolve_qualified_name(&call.func)
|
||||||
|
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["builtins", "super"]))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A [`Visitor`] that searches for implicit reference to `__class__` cell,
|
||||||
|
/// excluding nested class definitions.
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct ClassCellReferenceFinder {
|
||||||
|
has_class_cell: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClassCellReferenceFinder {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
ClassCellReferenceFinder {
|
||||||
|
has_class_cell: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) fn found(&self) -> bool {
|
||||||
|
self.has_class_cell
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Visitor<'a> for ClassCellReferenceFinder {
|
||||||
|
fn visit_stmt(&mut self, stmt: &'a Stmt) {
|
||||||
|
match stmt {
|
||||||
|
Stmt::ClassDef(_) => {}
|
||||||
|
_ => {
|
||||||
|
if !self.has_class_cell {
|
||||||
|
walk_stmt(self, stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||||
|
if expr.as_name_expr().is_some_and(|name| {
|
||||||
|
matches!(name.id.as_str(), "super" | "__class__") && name.ctx.is_load()
|
||||||
|
}) {
|
||||||
|
self.has_class_cell = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
walk_expr(self, expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -146,25 +146,6 @@ help: Remove `super()` parameters
|
||||||
95 | # see: https://github.com/astral-sh/ruff/issues/18684
|
95 | # see: https://github.com/astral-sh/ruff/issues/18684
|
||||||
note: This is an unsafe fix and may change runtime behavior
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
|
||||||
--> UP008.py:107:23
|
|
||||||
|
|
|
||||||
105 | class C:
|
|
||||||
106 | def f(self):
|
|
||||||
107 | builtins.super(C, self)
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
help: Remove `super()` parameters
|
|
||||||
104 |
|
|
||||||
105 | class C:
|
|
||||||
106 | def f(self):
|
|
||||||
- builtins.super(C, self)
|
|
||||||
107 + builtins.super()
|
|
||||||
108 |
|
|
||||||
109 |
|
|
||||||
110 | # see: https://github.com/astral-sh/ruff/issues/18533
|
|
||||||
note: This is an unsafe fix and may change runtime behavior
|
|
||||||
|
|
||||||
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
--> UP008.py:113:14
|
--> UP008.py:113:14
|
||||||
|
|
|
|
||||||
|
|
@ -294,6 +275,8 @@ UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
142 | def method3(self):
|
142 | def method3(self):
|
||||||
143 | super(ExampleWithKeywords, self).some_method() # Should be fixed - no keywords
|
143 | super(ExampleWithKeywords, self).some_method() # Should be fixed - no keywords
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
144 |
|
||||||
|
145 | # See: https://github.com/astral-sh/ruff/issues/19357
|
||||||
|
|
|
|
||||||
help: Remove `super()` parameters
|
help: Remove `super()` parameters
|
||||||
140 | super(ExampleWithKeywords, self, **{"kwarg": "value"}).some_method() # Should emit diagnostic but NOT be fixed
|
140 | super(ExampleWithKeywords, self, **{"kwarg": "value"}).some_method() # Should emit diagnostic but NOT be fixed
|
||||||
|
|
@ -301,4 +284,213 @@ help: Remove `super()` parameters
|
||||||
142 | def method3(self):
|
142 | def method3(self):
|
||||||
- super(ExampleWithKeywords, self).some_method() # Should be fixed - no keywords
|
- super(ExampleWithKeywords, self).some_method() # Should be fixed - no keywords
|
||||||
143 + super().some_method() # Should be fixed - no keywords
|
143 + super().some_method() # Should be fixed - no keywords
|
||||||
|
144 |
|
||||||
|
145 | # See: https://github.com/astral-sh/ruff/issues/19357
|
||||||
|
146 | # Must be detected
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:154:23
|
||||||
|
|
|
||||||
|
152 | def f(self):
|
||||||
|
153 | if False: __class__ # Python injects __class__ into scope
|
||||||
|
154 | builtins.super(ChildD1, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
155 |
|
||||||
|
156 | class ChildD2(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
151 | class ChildD1(ParentD):
|
||||||
|
152 | def f(self):
|
||||||
|
153 | if False: __class__ # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD1, self).f()
|
||||||
|
154 + builtins.super().f()
|
||||||
|
155 |
|
||||||
|
156 | class ChildD2(ParentD):
|
||||||
|
157 | def f(self):
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:159:23
|
||||||
|
|
|
||||||
|
157 | def f(self):
|
||||||
|
158 | if False: super # Python injects __class__ into scope
|
||||||
|
159 | builtins.super(ChildD2, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
160 |
|
||||||
|
161 | class ChildD3(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
156 | class ChildD2(ParentD):
|
||||||
|
157 | def f(self):
|
||||||
|
158 | if False: super # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD2, self).f()
|
||||||
|
159 + builtins.super().f()
|
||||||
|
160 |
|
||||||
|
161 | class ChildD3(ParentD):
|
||||||
|
162 | def f(self):
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:163:23
|
||||||
|
|
|
||||||
|
161 | class ChildD3(ParentD):
|
||||||
|
162 | def f(self):
|
||||||
|
163 | builtins.super(ChildD3, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
164 | super # Python injects __class__ into scope
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
160 |
|
||||||
|
161 | class ChildD3(ParentD):
|
||||||
|
162 | def f(self):
|
||||||
|
- builtins.super(ChildD3, self).f()
|
||||||
|
163 + builtins.super().f()
|
||||||
|
164 | super # Python injects __class__ into scope
|
||||||
|
165 |
|
||||||
|
166 | import builtins as builtins_alias
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:169:29
|
||||||
|
|
|
||||||
|
167 | class ChildD4(ParentD):
|
||||||
|
168 | def f(self):
|
||||||
|
169 | builtins_alias.super(ChildD4, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
170 | super # Python injects __class__ into scope
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
166 | import builtins as builtins_alias
|
||||||
|
167 | class ChildD4(ParentD):
|
||||||
|
168 | def f(self):
|
||||||
|
- builtins_alias.super(ChildD4, self).f()
|
||||||
|
169 + builtins_alias.super().f()
|
||||||
|
170 | super # Python injects __class__ into scope
|
||||||
|
171 |
|
||||||
|
172 | class ChildD5(ParentD):
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:176:23
|
||||||
|
|
|
||||||
|
174 | super = 1
|
||||||
|
175 | super # Python injects __class__ into scope
|
||||||
|
176 | builtins.super(ChildD5, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
177 |
|
||||||
|
178 | class ChildD6(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
173 | def f(self):
|
||||||
|
174 | super = 1
|
||||||
|
175 | super # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD5, self).f()
|
||||||
|
176 + builtins.super().f()
|
||||||
|
177 |
|
||||||
|
178 | class ChildD6(ParentD):
|
||||||
|
179 | def f(self):
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:182:23
|
||||||
|
|
|
||||||
|
180 | super: "Any"
|
||||||
|
181 | __class__ # Python injects __class__ into scope
|
||||||
|
182 | builtins.super(ChildD6, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
183 |
|
||||||
|
184 | class ChildD7(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
179 | def f(self):
|
||||||
|
180 | super: "Any"
|
||||||
|
181 | __class__ # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD6, self).f()
|
||||||
|
182 + builtins.super().f()
|
||||||
|
183 |
|
||||||
|
184 | class ChildD7(ParentD):
|
||||||
|
185 | def f(self):
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:188:23
|
||||||
|
|
|
||||||
|
186 | def x():
|
||||||
|
187 | __class__ # Python injects __class__ into scope
|
||||||
|
188 | builtins.super(ChildD7, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
189 |
|
||||||
|
190 | class ChildD8(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
185 | def f(self):
|
||||||
|
186 | def x():
|
||||||
|
187 | __class__ # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD7, self).f()
|
||||||
|
188 + builtins.super().f()
|
||||||
|
189 |
|
||||||
|
190 | class ChildD8(ParentD):
|
||||||
|
191 | def f(self):
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:195:23
|
||||||
|
|
|
||||||
|
193 | super = 1
|
||||||
|
194 | super # Python injects __class__ into scope
|
||||||
|
195 | builtins.super(ChildD8, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
196 |
|
||||||
|
197 | class ChildD9(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
192 | def x():
|
||||||
|
193 | super = 1
|
||||||
|
194 | super # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD8, self).f()
|
||||||
|
195 + builtins.super().f()
|
||||||
|
196 |
|
||||||
|
197 | class ChildD9(ParentD):
|
||||||
|
198 | def f(self):
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:202:23
|
||||||
|
|
|
||||||
|
200 | __class__ = 1
|
||||||
|
201 | __class__ # Python injects __class__ into scope
|
||||||
|
202 | builtins.super(ChildD9, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
203 |
|
||||||
|
204 | class ChildD10(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
199 | def x():
|
||||||
|
200 | __class__ = 1
|
||||||
|
201 | __class__ # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD9, self).f()
|
||||||
|
202 + builtins.super().f()
|
||||||
|
203 |
|
||||||
|
204 | class ChildD10(ParentD):
|
||||||
|
205 | def f(self):
|
||||||
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:209:23
|
||||||
|
|
|
||||||
|
207 | __class__ = 1
|
||||||
|
208 | super # Python injects __class__ into scope
|
||||||
|
209 | builtins.super(ChildD10, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
206 | def x():
|
||||||
|
207 | __class__ = 1
|
||||||
|
208 | super # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD10, self).f()
|
||||||
|
209 + builtins.super().f()
|
||||||
|
210 |
|
||||||
|
211 |
|
||||||
|
212 | # Must be ignored
|
||||||
note: This is an unsafe fix and may change runtime behavior
|
note: This is an unsafe fix and may change runtime behavior
|
||||||
|
|
|
||||||
|
|
@ -139,24 +139,6 @@ help: Remove `super()` parameters
|
||||||
94 |
|
94 |
|
||||||
95 | # see: https://github.com/astral-sh/ruff/issues/18684
|
95 | # see: https://github.com/astral-sh/ruff/issues/18684
|
||||||
|
|
||||||
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
|
||||||
--> UP008.py:107:23
|
|
||||||
|
|
|
||||||
105 | class C:
|
|
||||||
106 | def f(self):
|
|
||||||
107 | builtins.super(C, self)
|
|
||||||
| ^^^^^^^^^
|
|
||||||
|
|
|
||||||
help: Remove `super()` parameters
|
|
||||||
104 |
|
|
||||||
105 | class C:
|
|
||||||
106 | def f(self):
|
|
||||||
- builtins.super(C, self)
|
|
||||||
107 + builtins.super()
|
|
||||||
108 |
|
|
||||||
109 |
|
|
||||||
110 | # see: https://github.com/astral-sh/ruff/issues/18533
|
|
||||||
|
|
||||||
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
--> UP008.py:113:14
|
--> UP008.py:113:14
|
||||||
|
|
|
|
||||||
|
|
@ -286,6 +268,8 @@ UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
142 | def method3(self):
|
142 | def method3(self):
|
||||||
143 | super(ExampleWithKeywords, self).some_method() # Should be fixed - no keywords
|
143 | super(ExampleWithKeywords, self).some_method() # Should be fixed - no keywords
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
144 |
|
||||||
|
145 | # See: https://github.com/astral-sh/ruff/issues/19357
|
||||||
|
|
|
|
||||||
help: Remove `super()` parameters
|
help: Remove `super()` parameters
|
||||||
140 | super(ExampleWithKeywords, self, **{"kwarg": "value"}).some_method() # Should emit diagnostic but NOT be fixed
|
140 | super(ExampleWithKeywords, self, **{"kwarg": "value"}).some_method() # Should emit diagnostic but NOT be fixed
|
||||||
|
|
@ -293,3 +277,202 @@ help: Remove `super()` parameters
|
||||||
142 | def method3(self):
|
142 | def method3(self):
|
||||||
- super(ExampleWithKeywords, self).some_method() # Should be fixed - no keywords
|
- super(ExampleWithKeywords, self).some_method() # Should be fixed - no keywords
|
||||||
143 + super().some_method() # Should be fixed - no keywords
|
143 + super().some_method() # Should be fixed - no keywords
|
||||||
|
144 |
|
||||||
|
145 | # See: https://github.com/astral-sh/ruff/issues/19357
|
||||||
|
146 | # Must be detected
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:154:23
|
||||||
|
|
|
||||||
|
152 | def f(self):
|
||||||
|
153 | if False: __class__ # Python injects __class__ into scope
|
||||||
|
154 | builtins.super(ChildD1, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
155 |
|
||||||
|
156 | class ChildD2(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
151 | class ChildD1(ParentD):
|
||||||
|
152 | def f(self):
|
||||||
|
153 | if False: __class__ # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD1, self).f()
|
||||||
|
154 + builtins.super().f()
|
||||||
|
155 |
|
||||||
|
156 | class ChildD2(ParentD):
|
||||||
|
157 | def f(self):
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:159:23
|
||||||
|
|
|
||||||
|
157 | def f(self):
|
||||||
|
158 | if False: super # Python injects __class__ into scope
|
||||||
|
159 | builtins.super(ChildD2, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
160 |
|
||||||
|
161 | class ChildD3(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
156 | class ChildD2(ParentD):
|
||||||
|
157 | def f(self):
|
||||||
|
158 | if False: super # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD2, self).f()
|
||||||
|
159 + builtins.super().f()
|
||||||
|
160 |
|
||||||
|
161 | class ChildD3(ParentD):
|
||||||
|
162 | def f(self):
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:163:23
|
||||||
|
|
|
||||||
|
161 | class ChildD3(ParentD):
|
||||||
|
162 | def f(self):
|
||||||
|
163 | builtins.super(ChildD3, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
164 | super # Python injects __class__ into scope
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
160 |
|
||||||
|
161 | class ChildD3(ParentD):
|
||||||
|
162 | def f(self):
|
||||||
|
- builtins.super(ChildD3, self).f()
|
||||||
|
163 + builtins.super().f()
|
||||||
|
164 | super # Python injects __class__ into scope
|
||||||
|
165 |
|
||||||
|
166 | import builtins as builtins_alias
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:169:29
|
||||||
|
|
|
||||||
|
167 | class ChildD4(ParentD):
|
||||||
|
168 | def f(self):
|
||||||
|
169 | builtins_alias.super(ChildD4, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
170 | super # Python injects __class__ into scope
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
166 | import builtins as builtins_alias
|
||||||
|
167 | class ChildD4(ParentD):
|
||||||
|
168 | def f(self):
|
||||||
|
- builtins_alias.super(ChildD4, self).f()
|
||||||
|
169 + builtins_alias.super().f()
|
||||||
|
170 | super # Python injects __class__ into scope
|
||||||
|
171 |
|
||||||
|
172 | class ChildD5(ParentD):
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:176:23
|
||||||
|
|
|
||||||
|
174 | super = 1
|
||||||
|
175 | super # Python injects __class__ into scope
|
||||||
|
176 | builtins.super(ChildD5, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
177 |
|
||||||
|
178 | class ChildD6(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
173 | def f(self):
|
||||||
|
174 | super = 1
|
||||||
|
175 | super # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD5, self).f()
|
||||||
|
176 + builtins.super().f()
|
||||||
|
177 |
|
||||||
|
178 | class ChildD6(ParentD):
|
||||||
|
179 | def f(self):
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:182:23
|
||||||
|
|
|
||||||
|
180 | super: "Any"
|
||||||
|
181 | __class__ # Python injects __class__ into scope
|
||||||
|
182 | builtins.super(ChildD6, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
183 |
|
||||||
|
184 | class ChildD7(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
179 | def f(self):
|
||||||
|
180 | super: "Any"
|
||||||
|
181 | __class__ # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD6, self).f()
|
||||||
|
182 + builtins.super().f()
|
||||||
|
183 |
|
||||||
|
184 | class ChildD7(ParentD):
|
||||||
|
185 | def f(self):
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:188:23
|
||||||
|
|
|
||||||
|
186 | def x():
|
||||||
|
187 | __class__ # Python injects __class__ into scope
|
||||||
|
188 | builtins.super(ChildD7, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
189 |
|
||||||
|
190 | class ChildD8(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
185 | def f(self):
|
||||||
|
186 | def x():
|
||||||
|
187 | __class__ # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD7, self).f()
|
||||||
|
188 + builtins.super().f()
|
||||||
|
189 |
|
||||||
|
190 | class ChildD8(ParentD):
|
||||||
|
191 | def f(self):
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:195:23
|
||||||
|
|
|
||||||
|
193 | super = 1
|
||||||
|
194 | super # Python injects __class__ into scope
|
||||||
|
195 | builtins.super(ChildD8, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
196 |
|
||||||
|
197 | class ChildD9(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
192 | def x():
|
||||||
|
193 | super = 1
|
||||||
|
194 | super # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD8, self).f()
|
||||||
|
195 + builtins.super().f()
|
||||||
|
196 |
|
||||||
|
197 | class ChildD9(ParentD):
|
||||||
|
198 | def f(self):
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:202:23
|
||||||
|
|
|
||||||
|
200 | __class__ = 1
|
||||||
|
201 | __class__ # Python injects __class__ into scope
|
||||||
|
202 | builtins.super(ChildD9, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
203 |
|
||||||
|
204 | class ChildD10(ParentD):
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
199 | def x():
|
||||||
|
200 | __class__ = 1
|
||||||
|
201 | __class__ # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD9, self).f()
|
||||||
|
202 + builtins.super().f()
|
||||||
|
203 |
|
||||||
|
204 | class ChildD10(ParentD):
|
||||||
|
205 | def f(self):
|
||||||
|
|
||||||
|
UP008 [*] Use `super()` instead of `super(__class__, self)`
|
||||||
|
--> UP008.py:209:23
|
||||||
|
|
|
||||||
|
207 | __class__ = 1
|
||||||
|
208 | super # Python injects __class__ into scope
|
||||||
|
209 | builtins.super(ChildD10, self).f()
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
help: Remove `super()` parameters
|
||||||
|
206 | def x():
|
||||||
|
207 | __class__ = 1
|
||||||
|
208 | super # Python injects __class__ into scope
|
||||||
|
- builtins.super(ChildD10, self).f()
|
||||||
|
209 + builtins.super().f()
|
||||||
|
210 |
|
||||||
|
211 |
|
||||||
|
212 | # Must be ignored
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue