Skip to content
Snippets Groups Projects
Commit eb803a0e authored by Jon Parise's avatar Jon Parise
Browse files

Consider all metaclass methods to be class methods

It's a widely used (but perhaps not official?) convention to consider a
metaclass's methods to be class methods and to use `cls` as the first
argument (rather than `self`).

Use the simple heuristic of "class inherits from `type`" to identify
metaclasses and mark all of their methods as CLASSMETHOD.
parent c45970d9
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -180,13 +180,16 @@ class NamingChecker(object):
if isinstance(meth, ast.Name):
late_decoration[meth.id] = self.decorator_to_type[func_name]
 
# If this class inherits from `type`, it's a metaclass, and we'll
# consider all of it's methods to be classmethods.
ismetaclass = any(name for name in cls_node.bases if name.id == 'type')
# iterate over all functions and tag them
for node in iter_child_nodes(cls_node):
if not isinstance(node, ast.FunctionDef):
continue
node.function_type = _FunctionType.METHOD
if node.name in ('__new__', '__init_subclass__'):
if node.name in ('__new__', '__init_subclass__') or ismetaclass:
node.function_type = _FunctionType.CLASSMETHOD
if node.name in late_decoration:
node.function_type = late_decoration[node.name]
Loading
Loading
Loading
Loading
@@ -19,3 +19,11 @@ class NewClassIsRequired(object):
@cool
def test(self, sy):
pass
#: N804
class Meta(type):
def __new__(self, name, bases, attrs):
pass
#: Okay
class MetaMethod(type):
def test(cls):
pass
Loading
Loading
@@ -30,6 +30,12 @@ class Foo(object):
class Foo(object):
def __init_subclass__(cls):
pass
#: Okay
class Meta(type):
def __new__(cls, name, bases, attrs):
pass
def test(cls):
pass
#: Okay(--classmethod-decorators=clazzy,cool)
class NewClassmethodDecorators(object):
@clazzy
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment