diff options
author | Claudiu Popa <cpopa@cloudbasesolutions.com> | 2015-02-05 01:15:17 +0200 |
---|---|---|
committer | Claudiu Popa <cpopa@cloudbasesolutions.com> | 2015-02-05 01:15:17 +0200 |
commit | 0963c1ff552782a9e4d18d653c330ea58937d47d (patch) | |
tree | a753c86e725039c17e12ea5ece64bd5f262d6822 | |
parent | 2e1f5afab2497baf2a9e1fe47fed62482da3cfcc (diff) | |
download | pylint-0963c1ff552782a9e4d18d653c330ea58937d47d.tar.gz |
Look all the methods from ancestors for too-few-public-methods.
This patch uses two counters for too-few-public-methods and too-many-public-methods.
In order to avoid false positives, too-many-public-methods check is looking
only for methods defined in the current class. On the other hand, too-few-public-methods
should look in ancestors as well, since most of the time this check is useful only
for simple classes, without many public methods.
Closes issue #471.
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | checkers/design_analysis.py | 35 | ||||
-rw-r--r-- | test/input/func_r0903.py | 16 |
3 files changed, 40 insertions, 14 deletions
@@ -10,6 +10,9 @@ ChangeLog for Pylint an attribute access ('{0.__class__}'). Closes issue #463. + * Take in account all the methods from the ancestors + when checking for too-few-public-methods. Closes issue #471. + 2015-01-16 -- 1.4.1 diff --git a/checkers/design_analysis.py b/checkers/design_analysis.py index 0a7a307..e361cca 100644 --- a/checkers/design_analysis.py +++ b/checkers/design_analysis.py @@ -234,28 +234,35 @@ class MisdesignChecker(BaseChecker): except KeyError: self._used_abstracts[parent] = 1 - @check_messages('too-many-ancestors', 'too-many-instance-attributes', - 'too-few-public-methods', 'too-many-public-methods', - 'abstract-class-not-used', 'abstract-class-little-used', - 'interface-not-implemented') + @check_messages('too-few-public-methods', 'too-many-public-methods') def leave_class(self, node): """check number of public methods""" - nb_public_methods = 0 - for method in node.mymethods(): - if not method.name.startswith('_'): - nb_public_methods += 1 - # Does the class contain less than 20 public methods ? - if nb_public_methods > self.config.max_public_methods: + my_methods = sum(1 for method in node.mymethods() + if not method.name.startswith('_')) + all_methods = sum(1 for method in node.methods() + if not method.name.startswith('_')) + + # Does the class contain less than n public methods ? + # This checks only the methods defined in the current class, + # since the user might not have control over the classes + # from the ancestors. It avoids some false positives + # for classes such as unittest.TestCase, which provides + # a lot of assert methods. It doesn't make sense to warn + # when the user subclasses TestCase to add his own tests. + if my_methods > self.config.max_public_methods: self.add_message('too-many-public-methods', node=node, - args=(nb_public_methods, + args=(my_methods, self.config.max_public_methods)) # stop here for exception, metaclass and interface classes if node.type != 'class': return - # Does the class contain more than 5 public methods ? - if nb_public_methods < self.config.min_public_methods: + + # Does the class contain more than n public methods ? + # This checks all the methods defined by ancestors and + # by the current class. + if all_methods < self.config.min_public_methods: self.add_message('too-few-public-methods', node=node, - args=(nb_public_methods, + args=(all_methods, self.config.min_public_methods)) @check_messages('too-many-return-statements', 'too-many-branches', diff --git a/test/input/func_r0903.py b/test/input/func_r0903.py index 917b0ea..49008f9 100644 --- a/test/input/func_r0903.py +++ b/test/input/func_r0903.py @@ -12,3 +12,19 @@ class Aaaa(object): def _dontcount(self): """not public""" print(self) + + +# Don't emit for these cases. +class Klass(object): + """docstring""" + + def meth1(self): + """first""" + + def meth2(self): + """second""" + + +class EnoughPublicMethods(Klass): + """We shouldn't emit too-few-public-methods for this.""" + |