16
16
from pylint .lint import PyLinter
17
17
18
18
19
- DUNDER_METHODS : dict [str , str ] = {
20
- "__init__" : "Instantiate class directly" ,
21
- "__del__" : "Use del keyword" ,
22
- "__repr__" : "Use repr built-in function" ,
23
- "__str__" : "Use str built-in function" ,
24
- "__bytes__" : "Use bytes built-in function" ,
25
- "__format__" : "Use format built-in function, format string method, or f-string" ,
26
- "__lt__" : "Use < operator" ,
27
- "__le__" : "Use <= operator" ,
28
- "__eq__" : "Use == operator" ,
29
- "__ne__" : "Use != operator" ,
30
- "__gt__" : "Use > operator" ,
31
- "__ge__" : "Use >= operator" ,
32
- "__hash__" : "Use hash built-in function" ,
33
- "__bool__" : "Use bool built-in function" ,
34
- "__getattr__" : "Access attribute directly or use getattr built-in function" ,
35
- "__getattribute__" : "Access attribute directly or use getattr built-in function" ,
36
- "__setattr__" : "Set attribute directly or use setattr built-in function" ,
37
- "__delattr__" : "Use del keyword" ,
38
- "__dir__" : "Use dir built-in function" ,
39
- "__get__" : "Use get method" ,
40
- "__set__" : "Use set method" ,
41
- "__delete__" : "Use del keyword" ,
42
- "__instancecheck__" : "Use isinstance built-in function" ,
43
- "__subclasscheck__" : "Use issubclass built-in function" ,
44
- "__call__" : "Invoke instance directly" ,
45
- "__len__" : "Use len built-in function" ,
46
- "__length_hint__" : "Use length_hint method" ,
47
- "__getitem__" : "Access item via subscript" ,
48
- "__setitem__" : "Set item via subscript" ,
49
- "__delitem__" : "Use del keyword" ,
50
- "__iter__" : "Use iter built-in function" ,
51
- "__next__" : "Use next built-in function" ,
52
- "__reversed__" : "Use reversed built-in function" ,
53
- "__contains__" : "Use in keyword" ,
54
- "__add__" : "Use + operator" ,
55
- "__sub__" : "Use - operator" ,
56
- "__mul__" : "Use * operator" ,
57
- "__matmul__" : "Use @ operator" ,
58
- "__truediv__" : "Use / operator" ,
59
- "__floordiv__" : "Use // operator" ,
60
- "__mod__" : "Use % operator" ,
61
- "__divmod__" : "Use divmod built-in function" ,
62
- "__pow__" : "Use ** operator or pow built-in function" ,
63
- "__lshift__" : "Use << operator" ,
64
- "__rshift__" : "Use >> operator" ,
65
- "__and__" : "Use & operator" ,
66
- "__xor__" : "Use ^ operator" ,
67
- "__or__" : "Use | operator" ,
68
- "__radd__" : "Use + operator" ,
69
- "__rsub__" : "Use - operator" ,
70
- "__rmul__" : "Use * operator" ,
71
- "__rmatmul__" : "Use @ operator" ,
72
- "__rtruediv__" : "Use / operator" ,
73
- "__rfloordiv__" : "Use // operator" ,
74
- "__rmod__" : "Use % operator" ,
75
- "__rdivmod__" : "Use divmod built-in function" ,
76
- "__rpow__" : "Use ** operator or pow built-in function" ,
77
- "__rlshift__" : "Use << operator" ,
78
- "__rrshift__" : "Use >> operator" ,
79
- "__rand__" : "Use & operator" ,
80
- "__rxor__" : "Use ^ operator" ,
81
- "__ror__" : "Use | operator" ,
82
- "__iadd__" : "Use += operator" ,
83
- "__isub__" : "Use -= operator" ,
84
- "__imul__" : "Use *= operator" ,
85
- "__imatmul__" : "Use @= operator" ,
86
- "__itruediv__" : "Use /= operator" ,
87
- "__ifloordiv__" : "Use //= operator" ,
88
- "__imod__" : "Use %= operator" ,
89
- "__ipow__" : "Use **= operator" ,
90
- "__ilshift__" : "Use <<= operator" ,
91
- "__irshift__" : "Use >>= operator" ,
92
- "__iand__" : "Use &= operator" ,
93
- "__ixor__" : "Use ^= operator" ,
94
- "__ior__" : "Use |= operator" ,
95
- "__neg__" : "Multiply by -1 instead" ,
96
- "__pos__" : "Multiply by +1 instead" ,
97
- "__abs__" : "Use abs built-in function" ,
98
- "__invert__" : "Use ~ operator" ,
99
- "__complex__" : "Use complex built-in function" ,
100
- "__int__" : "Use int built-in function" ,
101
- "__float__" : "Use float built-in function" ,
102
- "__index__" : "Use index method" ,
103
- "__round__" : "Use round built-in function" ,
104
- "__trunc__" : "Use math.trunc function" ,
105
- "__floor__" : "Use math.floor function" ,
106
- "__ceil__" : "Use math.ceil function" ,
107
- "__enter__" : "Invoke context manager directly" ,
108
- "__aiter__" : "Use iter built-in function" ,
109
- "__anext__" : "Use next built-in function" ,
110
- "__aenter__" : "Invoke context manager directly" ,
111
- "__copy__" : "Use copy.copy function" ,
112
- "__deepcopy__" : "Use copy.deepcopy function" ,
113
- "__fspath__" : "Use os.fspath function instead" ,
19
+ DUNDER_METHODS : dict [tuple [int , int ], dict [str , str ]] = {
20
+ (0 , 0 ): {
21
+ "__init__" : "Instantiate class directly" ,
22
+ "__del__" : "Use del keyword" ,
23
+ "__repr__" : "Use repr built-in function" ,
24
+ "__str__" : "Use str built-in function" ,
25
+ "__bytes__" : "Use bytes built-in function" ,
26
+ "__format__" : "Use format built-in function, format string method, or f-string" ,
27
+ "__lt__" : "Use < operator" ,
28
+ "__le__" : "Use <= operator" ,
29
+ "__eq__" : "Use == operator" ,
30
+ "__ne__" : "Use != operator" ,
31
+ "__gt__" : "Use > operator" ,
32
+ "__ge__" : "Use >= operator" ,
33
+ "__hash__" : "Use hash built-in function" ,
34
+ "__bool__" : "Use bool built-in function" ,
35
+ "__getattr__" : "Access attribute directly or use getattr built-in function" ,
36
+ "__getattribute__" : "Access attribute directly or use getattr built-in function" ,
37
+ "__setattr__" : "Set attribute directly or use setattr built-in function" ,
38
+ "__delattr__" : "Use del keyword" ,
39
+ "__dir__" : "Use dir built-in function" ,
40
+ "__get__" : "Use get method" ,
41
+ "__set__" : "Use set method" ,
42
+ "__delete__" : "Use del keyword" ,
43
+ "__instancecheck__" : "Use isinstance built-in function" ,
44
+ "__subclasscheck__" : "Use issubclass built-in function" ,
45
+ "__call__" : "Invoke instance directly" ,
46
+ "__len__" : "Use len built-in function" ,
47
+ "__length_hint__" : "Use length_hint method" ,
48
+ "__getitem__" : "Access item via subscript" ,
49
+ "__setitem__" : "Set item via subscript" ,
50
+ "__delitem__" : "Use del keyword" ,
51
+ "__iter__" : "Use iter built-in function" ,
52
+ "__next__" : "Use next built-in function" ,
53
+ "__reversed__" : "Use reversed built-in function" ,
54
+ "__contains__" : "Use in keyword" ,
55
+ "__add__" : "Use + operator" ,
56
+ "__sub__" : "Use - operator" ,
57
+ "__mul__" : "Use * operator" ,
58
+ "__matmul__" : "Use @ operator" ,
59
+ "__truediv__" : "Use / operator" ,
60
+ "__floordiv__" : "Use // operator" ,
61
+ "__mod__" : "Use % operator" ,
62
+ "__divmod__" : "Use divmod built-in function" ,
63
+ "__pow__" : "Use ** operator or pow built-in function" ,
64
+ "__lshift__" : "Use << operator" ,
65
+ "__rshift__" : "Use >> operator" ,
66
+ "__and__" : "Use & operator" ,
67
+ "__xor__" : "Use ^ operator" ,
68
+ "__or__" : "Use | operator" ,
69
+ "__radd__" : "Use + operator" ,
70
+ "__rsub__" : "Use - operator" ,
71
+ "__rmul__" : "Use * operator" ,
72
+ "__rmatmul__" : "Use @ operator" ,
73
+ "__rtruediv__" : "Use / operator" ,
74
+ "__rfloordiv__" : "Use // operator" ,
75
+ "__rmod__" : "Use % operator" ,
76
+ "__rdivmod__" : "Use divmod built-in function" ,
77
+ "__rpow__" : "Use ** operator or pow built-in function" ,
78
+ "__rlshift__" : "Use << operator" ,
79
+ "__rrshift__" : "Use >> operator" ,
80
+ "__rand__" : "Use & operator" ,
81
+ "__rxor__" : "Use ^ operator" ,
82
+ "__ror__" : "Use | operator" ,
83
+ "__iadd__" : "Use += operator" ,
84
+ "__isub__" : "Use -= operator" ,
85
+ "__imul__" : "Use *= operator" ,
86
+ "__imatmul__" : "Use @= operator" ,
87
+ "__itruediv__" : "Use /= operator" ,
88
+ "__ifloordiv__" : "Use //= operator" ,
89
+ "__imod__" : "Use %= operator" ,
90
+ "__ipow__" : "Use **= operator" ,
91
+ "__ilshift__" : "Use <<= operator" ,
92
+ "__irshift__" : "Use >>= operator" ,
93
+ "__iand__" : "Use &= operator" ,
94
+ "__ixor__" : "Use ^= operator" ,
95
+ "__ior__" : "Use |= operator" ,
96
+ "__neg__" : "Multiply by -1 instead" ,
97
+ "__pos__" : "Multiply by +1 instead" ,
98
+ "__abs__" : "Use abs built-in function" ,
99
+ "__invert__" : "Use ~ operator" ,
100
+ "__complex__" : "Use complex built-in function" ,
101
+ "__int__" : "Use int built-in function" ,
102
+ "__float__" : "Use float built-in function" ,
103
+ "__index__" : "Use index method" ,
104
+ "__round__" : "Use round built-in function" ,
105
+ "__trunc__" : "Use math.trunc function" ,
106
+ "__floor__" : "Use math.floor function" ,
107
+ "__ceil__" : "Use math.ceil function" ,
108
+ "__enter__" : "Invoke context manager directly" ,
109
+ "__aenter__" : "Invoke context manager directly" ,
110
+ "__copy__" : "Use copy.copy function" ,
111
+ "__deepcopy__" : "Use copy.deepcopy function" ,
112
+ "__fspath__" : "Use os.fspath function instead" ,
113
+ },
114
+ (3 , 10 ): {
115
+ "__aiter__" : "Use aiter built-in function" ,
116
+ "__anext__" : "Use anext built-in function" ,
117
+ },
114
118
}
115
119
116
120
@@ -143,6 +147,12 @@ class DunderCallChecker(BaseChecker):
143
147
}
144
148
options = ()
145
149
150
+ def open (self ) -> None :
151
+ self ._dunder_methods : dict [str , str ] = {}
152
+ for since_vers , dunder_methods in DUNDER_METHODS .items ():
153
+ if since_vers <= self .linter .config .py_version :
154
+ self ._dunder_methods .update (dunder_methods )
155
+
146
156
@staticmethod
147
157
def within_dunder_def (node : nodes .NodeNG ) -> bool :
148
158
"""Check if dunder method call is within a dunder method definition."""
@@ -161,7 +171,7 @@ def visit_call(self, node: nodes.Call) -> None:
161
171
"""Check if method being called is an unnecessary dunder method."""
162
172
if (
163
173
isinstance (node .func , nodes .Attribute )
164
- and node .func .attrname in DUNDER_METHODS
174
+ and node .func .attrname in self . _dunder_methods
165
175
and not self .within_dunder_def (node )
166
176
and not (
167
177
isinstance (node .func .expr , nodes .Call )
@@ -177,7 +187,7 @@ def visit_call(self, node: nodes.Call) -> None:
177
187
self .add_message (
178
188
"unnecessary-dunder-call" ,
179
189
node = node ,
180
- args = (node .func .attrname , DUNDER_METHODS [node .func .attrname ]),
190
+ args = (node .func .attrname , self . _dunder_methods [node .func .attrname ]),
181
191
confidence = HIGH ,
182
192
)
183
193
0 commit comments