summaryrefslogtreecommitdiff
path: root/checkers/classes.py
diff options
context:
space:
mode:
authorClaudiu Popa <cpopa@cloudbasesolutions.com>2014-12-21 17:07:52 +0200
committerClaudiu Popa <cpopa@cloudbasesolutions.com>2014-12-21 17:07:52 +0200
commitfc12599809c8a7397bee2b49c8162b3c60e36db6 (patch)
tree271674821cebd7d0df96c4056f4e373cc38fae84 /checkers/classes.py
parent49da69cade967362dff9933929f82e5fe6890df4 (diff)
downloadpylint-fc12599809c8a7397bee2b49c8162b3c60e36db6.tar.gz
Use a mro traversal for finding abstract methods. Closes issue #415.
This patch adds a new unimplemented_abstract_methods in pylint.checkers.utils, which is used to obtain all the abstract methods which weren't implemented anywhere in the mro of a class. The code works now by traversing the mro, gathering all abstract methods encountered at each step and resolving the implemented ones through either definition or assignment. This disables a couple of false positives on classes with complex hierarchies.
Diffstat (limited to 'checkers/classes.py')
-rw-r--r--checkers/classes.py19
1 files changed, 13 insertions, 6 deletions
diff --git a/checkers/classes.py b/checkers/classes.py
index 030bee6..f7a344e 100644
--- a/checkers/classes.py
+++ b/checkers/classes.py
@@ -30,7 +30,7 @@ from pylint.checkers import BaseChecker
from pylint.checkers.utils import (
PYMETHODS, overrides_a_method, check_messages, is_attr_private,
is_attr_protected, node_frame_class, safe_infer, is_builtin_object,
- decorated_with_property)
+ decorated_with_property, unimplemented_abstract_methods)
import six
if sys.version_info >= (3, 0):
@@ -800,21 +800,28 @@ a metaclass class method.'}
"""check that the given class node implements abstract methods from
base classes
"""
+ def is_abstract(method):
+ return method.is_abstract(pass_is_abstract=False)
+
# check if this class abstract
if class_is_abstract(node):
return
- for method in node.methods():
+
+ methods = sorted(
+ unimplemented_abstract_methods(node, is_abstract).items(),
+ key=lambda item: item[0],
+ )
+ for name, method in methods:
owner = method.parent.frame()
if owner is node:
continue
# owner is not this class, it must be a parent class
# check that the ancestor's method is not abstract
- if method.name in node.locals:
+ if name in node.locals:
# it is redefined as an attribute or with a descriptor
continue
- if method.is_abstract(pass_is_abstract=False):
- self.add_message('abstract-method', node=node,
- args=(method.name, owner.name))
+ self.add_message('abstract-method', node=node,
+ args=(name, owner.name))
def _check_interfaces(self, node):
"""check that the given class node really implements declared