diff options
author | Claudiu Popa <cpopa@cloudbasesolutions.com> | 2014-12-21 17:07:52 +0200 |
---|---|---|
committer | Claudiu Popa <cpopa@cloudbasesolutions.com> | 2014-12-21 17:07:52 +0200 |
commit | c7ac191d9e45d693afc173c29bc3ea1b735d6c3e (patch) | |
tree | 669e0f8a6fc3701f0093d10958e4b4bfe3f79ea6 /checkers/classes.py | |
parent | cc33f030cebc46e77961c499f2565d43618618c5 (diff) | |
download | pylint-git-c7ac191d9e45d693afc173c29bc3ea1b735d6c3e.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.py | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/checkers/classes.py b/checkers/classes.py index 030bee614..f7a344ea9 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 |