diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | checkers/classes.py | 41 | ||||
-rw-r--r-- | test/unittest_checker_classes.py | 16 |
3 files changed, 40 insertions, 20 deletions
@@ -16,6 +16,9 @@ ChangeLog for Pylint * Catch enchant errors and emit 'invalid-characters-in-docstring' when checking for spelling errors. Closes issue #469. + * Use all the inferred statements for the super-init-not-called + check. Closes issue #389. + 2015-01-16 -- 1.4.1 diff --git a/checkers/classes.py b/checkers/classes.py index 1a10c35..8e51a47 100644 --- a/checkers/classes.py +++ b/checkers/classes.py @@ -893,26 +893,27 @@ a metaclass class method.'} expr.expr.func.name == 'super': return try: - klass = next(expr.expr.infer()) - if klass is YES: - continue - # The infered klass can be super(), which was - # assigned to a variable and the `__init__` was called later. - # - # base = super() - # base.__init__(...) - - if (isinstance(klass, astroid.Instance) and - isinstance(klass._proxied, astroid.Class) and - is_builtin_object(klass._proxied) and - klass._proxied.name == 'super'): - return - try: - del not_called_yet[klass] - except KeyError: - if klass not in to_call: - self.add_message('non-parent-init-called', - node=expr, args=klass.name) + for klass in expr.expr.infer(): + if klass is YES: + continue + # The infered klass can be super(), which was + # assigned to a variable and the `__init__` + # was called later. + # + # base = super() + # base.__init__(...) + + if (isinstance(klass, astroid.Instance) and + isinstance(klass._proxied, astroid.Class) and + is_builtin_object(klass._proxied) and + klass._proxied.name == 'super'): + return + try: + del not_called_yet[klass] + except KeyError: + if klass not in to_call: + self.add_message('non-parent-init-called', + node=expr, args=klass.name) except astroid.InferenceError: continue for klass, method in six.iteritems(not_called_yet): diff --git a/test/unittest_checker_classes.py b/test/unittest_checker_classes.py index f35e5e3..f21cfc1 100644 --- a/test/unittest_checker_classes.py +++ b/test/unittest_checker_classes.py @@ -61,6 +61,22 @@ class VariablesCheckerTC(CheckerTestCase): with self.assertNoMessages(): self.checker.visit_function(node) + def test_super_init_not_called_regression(self): + # This should not emit a super-init-not-called + # warning. It previously did this, because + # ``next(node.infer())`` was used in that checker's + # logic and the first inferred node was an YES object, + # leading to this false positive. + node = test_utils.extract_node(""" + import ctypes + + class Foo(ctypes.BigEndianStructure): + def __init__(self): #@ + ctypes.BigEndianStructure.__init__(self) + """) + with self.assertNoMessages(): + self.checker.visit_function(node) + if __name__ == '__main__': unittest.main() |