11"""Checker of PEP-8 Naming Conventions."""
22import ast
3+ import enum
34from ast import iter_child_nodes
45from collections import deque
5- from collections .abc import Iterable , Sequence
6+ from collections .abc import Iterable , Iterator , Sequence
67from fnmatch import fnmatchcase
78from functools import partial
89from itertools import chain
@@ -69,7 +70,8 @@ def __contains__(self, item: object, /) -> bool:
6970 return super ().__contains__ (item )
7071
7172
72- class _FunctionType :
73+ @enum .unique
74+ class FunctionType (enum .Enum ):
7375 CLASSMETHOD = 'classmethod'
7476 STATICMETHOD = 'staticmethod'
7577 FUNCTION = 'function'
@@ -94,11 +96,11 @@ class _FunctionType:
9496
9597
9698def _build_decorator_to_type (classmethod_decorators , staticmethod_decorators ):
97- decorator_to_type = {}
99+ decorator_to_type : dict [ str , FunctionType ] = {}
98100 for decorator in classmethod_decorators :
99- decorator_to_type [decorator ] = _FunctionType .CLASSMETHOD
101+ decorator_to_type [decorator ] = FunctionType .CLASSMETHOD
100102 for decorator in staticmethod_decorators :
101- decorator_to_type [decorator ] = _FunctionType .STATICMETHOD
103+ decorator_to_type [decorator ] = FunctionType .STATICMETHOD
102104 return decorator_to_type
103105
104106
@@ -188,7 +190,7 @@ def tag_class_functions(self, cls_node):
188190 """Tag functions if they are methods, classmethods, staticmethods"""
189191 # tries to find all 'old style decorators' like
190192 # m = staticmethod(m)
191- late_decoration = {}
193+ late_decoration : dict [ str , FunctionType ] = {}
192194 for node in iter_child_nodes (cls_node ):
193195 if not (isinstance (node , ast .Assign ) and
194196 isinstance (node .value , ast .Call ) and
@@ -213,24 +215,31 @@ def tag_class_functions(self, cls_node):
213215 self .set_function_nodes_types (
214216 iter_child_nodes (cls_node ), ismetaclass , late_decoration )
215217
216- def set_function_nodes_types (self , nodes , ismetaclass , late_decoration ):
218+ def set_function_nodes_types (
219+ self ,
220+ nodes : Iterator [ast .AST ],
221+ ismetaclass : bool ,
222+ late_decoration : dict [str , FunctionType ],
223+ ):
217224 # iterate over all functions and tag them
218225 for node in nodes :
219226 if type (node ) in METHOD_CONTAINER_NODES :
220227 self .set_function_nodes_types (
221228 iter_child_nodes (node ), ismetaclass , late_decoration )
222229 if not isinstance (node , FUNC_NODES ):
223230 continue
224- node . function_type = _FunctionType .METHOD
231+ setattr ( node , ' function_type' , FunctionType .METHOD )
225232 if node .name in CLASS_METHODS or ismetaclass :
226- node . function_type = _FunctionType .CLASSMETHOD
233+ setattr ( node , ' function_type' , FunctionType .CLASSMETHOD )
227234 if node .name in late_decoration :
228- node . function_type = late_decoration [node .name ]
235+ setattr ( node , ' function_type' , late_decoration [node .name ])
229236 elif node .decorator_list :
230237 for d in node .decorator_list :
231238 name = self .find_decorator_name (d )
232- if name in self .decorator_to_type :
233- node .function_type = self .decorator_to_type [name ]
239+ if name is None :
240+ continue
241+ if function_type := self .decorator_to_type .get (name ):
242+ setattr (node , 'function_type' , function_type )
234243 break
235244
236245 @classmethod
@@ -320,18 +329,18 @@ def has_override_decorator(node):
320329 return False
321330
322331 def visit_functiondef (self , node , parents : Sequence , ignored : NameSet ):
323- function_type = getattr (node , 'function_type' , _FunctionType .FUNCTION )
332+ function_type = getattr (node , 'function_type' , FunctionType .FUNCTION )
324333 name = node .name
325334 if name in ignored :
326335 return
327336 if name in ('__dir__' , '__getattr__' ):
328337 return
329- if (function_type != _FunctionType .FUNCTION
338+ if (function_type != FunctionType .FUNCTION
330339 and self .has_override_decorator (node )):
331340 return
332341 if name .lower () != name :
333342 yield self .err (node , 'N802' , name = name )
334- if (function_type == _FunctionType .FUNCTION
343+ if (function_type == FunctionType .FUNCTION
335344 and name [:2 ] == '__' and name [- 2 :] == '__' ):
336345 yield self .err (node , 'N807' , name = name )
337346
@@ -363,9 +372,9 @@ def visit_functiondef(self, node, parents: Sequence, ignored: NameSet):
363372 # for backwards compatibility.
364373 if args and (name := args [0 ].arg ) and name not in ignored :
365374 function_type = getattr (node , 'function_type' , None )
366- if function_type == _FunctionType .METHOD and name != 'self' :
375+ if function_type == FunctionType .METHOD and name != 'self' :
367376 yield self .err (args [0 ], 'N805' )
368- elif function_type == _FunctionType .CLASSMETHOD and name != 'cls' :
377+ elif function_type == FunctionType .CLASSMETHOD and name != 'cls' :
369378 yield self .err (args [0 ], 'N804' )
370379
371380 # Also add the special *arg and **kwarg arguments for the rest of the
0 commit comments