Skip to content

Commit b59696e

Browse files
committed
Ignore dunder methods
1 parent 78bdf39 commit b59696e

3 files changed

Lines changed: 72 additions & 1 deletion

File tree

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ Configuration options also exist:
1515
- `unused-arguments-ignore-nested-functions` - don't show warnings for nested
1616
functions. Only show warnings for functions in the top level of a module, or methods
1717
of a class in the top level of a module.
18-
18+
- `unused-arguments-ignore-dunder` - don't show warnings for double-underscore methods.
19+
These methods implement or override native builtin methods which have a specific
20+
signature. Therefore arguments must always be present. This is the case of methods
21+
like `__new__`, `__init__`, `__getitem__`, `__setitem__`, `__reduce_ex__`,
22+
`__enter__`, `__exit__`, etc.
1923

2024
## Changelog
2125

flake8_unused_arguments.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class Plugin:
1919
ignore_variadic_names = False
2020
ignore_lambdas = False
2121
ignore_nested_functions = False
22+
ignore_dunder_methods = False
2223

2324
def __init__(self, tree: ast.Module):
2425
self.tree = tree
@@ -73,13 +74,26 @@ def add_options(cls, option_manager: flake8.options.manager.OptionManager) -> No
7374
),
7475
)
7576

77+
option_manager.add_option(
78+
"--unused-arguments-ignore-dunder",
79+
action="store_true",
80+
parse_from_config=True,
81+
default=cls.ignore_dunder_methods,
82+
dest="unused_arguments_ignore_dunder_methods",
83+
help=(
84+
"If provided, all double-underscore methods are ignored, e.g., __new__, _init__, "
85+
"__enter__, __exit__, __reduce_ex__, etc.",
86+
),
87+
)
88+
7689
@classmethod
7790
def parse_options(cls, options: optparse.Values) -> None:
7891
cls.ignore_abstract = options.unused_arguments_ignore_abstract_functions
7992
cls.ignore_stubs = options.unused_arguments_ignore_stub_functions
8093
cls.ignore_variadic_names = options.unused_arguments_ignore_variadic_names
8194
cls.ignore_lambdas = options.unused_arguments_ignore_lambdas
8295
cls.ignore_nested_functions = options.unused_arguments_ignore_nested_functions
96+
cls.ignore_dunder_methods = options.unused_arguments_ignore_dunder_methods
8397

8498
def run(self) -> Iterable[LintResult]:
8599
finder = FunctionFinder(self.ignore_nested_functions)
@@ -99,6 +113,10 @@ def run(self) -> Iterable[LintResult]:
99113
if self.ignore_lambdas and isinstance(function, ast.Lambda):
100114
continue
101115

116+
# ignore __double_underscore_methods__()
117+
if self.ignore_dunder_methods and is_dunder_method(function):
118+
continue
119+
102120
for i, argument in get_unused_arguments(function):
103121
name = argument.arg
104122
if self.ignore_variadic_names:
@@ -224,6 +242,13 @@ def is_stub_function(function: FunctionTypes) -> bool:
224242
return False
225243

226244

245+
def is_dunder_method(function: FunctionTypes) -> bool:
246+
if isinstance(function, ast.Lambda):
247+
return False
248+
name = function.name
249+
return name and len(name) > 4 and name.startswith("__") and name.endswith("__")
250+
251+
227252
class FunctionFinder(NodeVisitor):
228253
functions: List[FunctionTypes]
229254

test_unused_arguments.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,48 @@ def bar(b):
262262
(5, 13, "U100 Unused argument 'c'", "unused argument"),
263263
],
264264
),
265+
(
266+
"""
267+
class Foo:
268+
def __new__(cls):
269+
return []
270+
def __enter__(self):
271+
return self
272+
def __exit__(self, exc_tp, exc_v, exc_tb):
273+
return False
274+
def __setattr__(self, item, value):
275+
raise ValueError("read-only")
276+
def __reduce_ex__(self, protocol):
277+
return Foo, ()
278+
""",
279+
{"ignore_dunder_methods": False},
280+
[
281+
(3, 16, "U100 Unused argument 'cls'", "unused argument"),
282+
(7, 23, "U100 Unused argument 'exc_tp'", "unused argument"),
283+
(7, 31, "U100 Unused argument 'exc_v'", "unused argument"),
284+
(7, 38, "U100 Unused argument 'exc_tb'", "unused argument"),
285+
(9, 26, "U100 Unused argument 'item'", "unused argument"),
286+
(9, 32, "U100 Unused argument 'value'", "unused argument"),
287+
(11, 28, "U100 Unused argument 'protocol'", "unused argument"),
288+
],
289+
),
290+
(
291+
"""
292+
class Foo:
293+
def __new__(cls):
294+
return []
295+
def __enter__(self):
296+
return self
297+
def __exit__(self, exc_tp, exc_v, exc_tb):
298+
return False
299+
def __setattr__(self, item, value):
300+
raise ValueError("read-only")
301+
def __reduce_ex__(self, protocol):
302+
return Foo, ()
303+
""",
304+
{"ignore_dunder_methods": True},
305+
[],
306+
),
265307
(
266308
"""
267309
def foo(_a):

0 commit comments

Comments
 (0)