Ignore `@override` method when enforcing `bad-dunder-name` rule (#7224)

## Summary

Closes #6958.

If a method has the `override` decorator, there is nothing you can do
about incorrect dunder methods, so they should be ignored.

## Test Plan

Overridden incorrect dunder method was added to the tests to verify ruff
doesn't catch it when evaluating the file. Snapshot changes are all just
line number changes
This commit is contained in:
Brendon Happ 2023-09-12 07:54:40 -04:00 committed by GitHub
parent 08f19226b9
commit b4419c34ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 41 deletions

View File

@ -1,3 +1,6 @@
from typing import override
class Apples:
def _init_(self): # [bad-dunder-name]
pass
@ -21,6 +24,11 @@ class Apples:
# author likely meant to call the invert dunder method
pass
@override
def _ignore__(self): # [bad-dunder-name]
# overridden dunder methods should be ignored
pass
def hello(self):
print("hello")

View File

@ -2,18 +2,12 @@ use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::identifier::Identifier;
use ruff_python_ast::Stmt;
use ruff_python_semantic::analyze::visibility;
use crate::checkers::ast::Checker;
/// ## What it does
/// Checks for any misspelled dunder name method and for any method
/// defined with `_..._` that's not one of the pre-defined methods
///
/// The pre-defined methods encompass all of Python's standard dunder
/// methods.
///
/// Note this includes all methods starting and ending with at least
/// one underscore to detect mistakes.
/// Checks for misspelled and unknown dunder names in method definitions.
///
/// ## Why is this bad?
/// Misspelled dunder name methods may cause your code to not function
@ -24,6 +18,10 @@ use crate::checkers::ast::Checker;
/// that diverges from standard Python dunder methods could potentially
/// confuse someone reading the code.
///
/// This rule will detect all methods starting and ending with at least
/// one underscore (e.g., `_str_`), but ignores known dunder methods (like
/// `__init__`), as well as methods that are marked with `@override`.
///
/// ## Example
/// ```python
/// class Foo:
@ -62,6 +60,9 @@ pub(crate) fn bad_dunder_method_name(checker: &mut Checker, class_body: &[Stmt])
method.name.starts_with('_') && method.name.ends_with('_')
})
{
if visibility::is_override(&method.decorator_list, checker.semantic()) {
continue;
}
checker.diagnostics.push(Diagnostic::new(
BadDunderMethodName {
name: method.name.to_string(),

View File

@ -1,61 +1,61 @@
---
source: crates/ruff/src/rules/pylint/mod.rs
---
bad_dunder_method_name.py:2:9: PLW3201 Bad or misspelled dunder method name `_init_`. (bad-dunder-name)
bad_dunder_method_name.py:5:9: PLW3201 Bad or misspelled dunder method name `_init_`. (bad-dunder-name)
|
1 | class Apples:
2 | def _init_(self): # [bad-dunder-name]
4 | class Apples:
5 | def _init_(self): # [bad-dunder-name]
| ^^^^^^ PLW3201
3 | pass
6 | pass
|
bad_dunder_method_name.py:5:9: PLW3201 Bad or misspelled dunder method name `__hello__`. (bad-dunder-name)
bad_dunder_method_name.py:8:9: PLW3201 Bad or misspelled dunder method name `__hello__`. (bad-dunder-name)
|
3 | pass
4 |
5 | def __hello__(self): # [bad-dunder-name]
6 | pass
7 |
8 | def __hello__(self): # [bad-dunder-name]
| ^^^^^^^^^ PLW3201
6 | print("hello")
9 | print("hello")
|
bad_dunder_method_name.py:8:9: PLW3201 Bad or misspelled dunder method name `__init_`. (bad-dunder-name)
bad_dunder_method_name.py:11:9: PLW3201 Bad or misspelled dunder method name `__init_`. (bad-dunder-name)
|
6 | print("hello")
7 |
8 | def __init_(self): # [bad-dunder-name]
9 | print("hello")
10 |
11 | def __init_(self): # [bad-dunder-name]
| ^^^^^^^ PLW3201
9 | # author likely unintentionally misspelled the correct init dunder.
10 | pass
12 | # author likely unintentionally misspelled the correct init dunder.
13 | pass
|
bad_dunder_method_name.py:12:9: PLW3201 Bad or misspelled dunder method name `_init_`. (bad-dunder-name)
bad_dunder_method_name.py:15:9: PLW3201 Bad or misspelled dunder method name `_init_`. (bad-dunder-name)
|
10 | pass
11 |
12 | def _init_(self): # [bad-dunder-name]
13 | pass
14 |
15 | def _init_(self): # [bad-dunder-name]
| ^^^^^^ PLW3201
13 | # author likely unintentionally misspelled the correct init dunder.
14 | pass
16 | # author likely unintentionally misspelled the correct init dunder.
17 | pass
|
bad_dunder_method_name.py:16:9: PLW3201 Bad or misspelled dunder method name `___neg__`. (bad-dunder-name)
bad_dunder_method_name.py:19:9: PLW3201 Bad or misspelled dunder method name `___neg__`. (bad-dunder-name)
|
14 | pass
15 |
16 | def ___neg__(self): # [bad-dunder-name]
17 | pass
18 |
19 | def ___neg__(self): # [bad-dunder-name]
| ^^^^^^^^ PLW3201
17 | # author likely accidentally added an additional `_`
18 | pass
20 | # author likely accidentally added an additional `_`
21 | pass
|
bad_dunder_method_name.py:20:9: PLW3201 Bad or misspelled dunder method name `__inv__`. (bad-dunder-name)
bad_dunder_method_name.py:23:9: PLW3201 Bad or misspelled dunder method name `__inv__`. (bad-dunder-name)
|
18 | pass
19 |
20 | def __inv__(self): # [bad-dunder-name]
21 | pass
22 |
23 | def __inv__(self): # [bad-dunder-name]
| ^^^^^^^ PLW3201
21 | # author likely meant to call the invert dunder method
22 | pass
24 | # author likely meant to call the invert dunder method
25 | pass
|