Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bad-super-call for non-direct parents #6956

Merged
merged 7 commits into from Jun 16, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion doc/data/messages/b/bad-super-call/bad.py
Expand Up @@ -2,6 +2,11 @@ class Animal:
pass


class Fish:
DanielNoord marked this conversation as resolved.
Show resolved Hide resolved
pass


class Cat(Animal):
def __init__(self):
super(Animal, self).__init__() # [bad-super-call]
super(Fish, self).__init__() # [bad-super-call]
DanielNoord marked this conversation as resolved.
Show resolved Hide resolved
super(Animal, self).__init__()
3 changes: 3 additions & 0 deletions doc/data/messages/b/bad-super-call/details.rst
Expand Up @@ -2,3 +2,6 @@ In Python 2.7, ``super()`` has to be called with its own class and ``self`` as a
lead to a mix up of parent and child class in the code.

In Python 3 the recommended way is to call ``super()`` without arguments (see also ``super-with-arguments``).

One exception is calling ``super()`` on a non-direct parent class. This can be used to get a method other than the default
method returned by the ``mro()``.
6 changes: 5 additions & 1 deletion doc/data/messages/b/bad-super-call/good.py
Expand Up @@ -2,6 +2,10 @@ class Animal:
pass


class Fish:
DanielNoord marked this conversation as resolved.
Show resolved Hide resolved
pass


class Cat(Animal):
def __init__(self):
super().__init__()
super(Animal, self).__init__()
4 changes: 4 additions & 0 deletions doc/whatsnew/2/2.14/full.rst
Expand Up @@ -5,6 +5,10 @@ What's New in Pylint 2.14.3?
----------------------------
Release date: TBA

* Fixed two false positives for ``bad-super-call`` for calls that refer to a non-direct parent.

Closes #4922, Closes #2903

* Fixed a false positive for ``useless-super-delegation`` for subclasses that specify the number of
of parameters against a parent that uses a variadic argument.

Expand Down
4 changes: 3 additions & 1 deletion pylint/checkers/newstyle.py
Expand Up @@ -108,7 +108,9 @@ def visit_functiondef(self, node: nodes.FunctionDef) -> None:
except astroid.InferenceError:
continue

if klass is not supcls:
# If the supcls is in the ancestors of klass super can be used to skip
# a step in the mro() and get a method from a higher parent
if klass is not supcls and all(i != supcls for i in klass.ancestors()):
name = None
# if supcls is not Uninferable, then supcls was inferred
# and use its name. Otherwise, try to look
Expand Down
35 changes: 33 additions & 2 deletions tests/functional/s/super/super_checks.py
Expand Up @@ -29,7 +29,7 @@ def __init__(self):
class Py3kWrongSuper(Py3kAaaa):
"""new style"""
def __init__(self):
super(NewAaaa, self).__init__() # [bad-super-call]
super(NewAaaa, self).__init__()

class WrongNameRegression(Py3kAaaa):
""" test a regression with the message """
Expand Down Expand Up @@ -59,7 +59,7 @@ class FalsePositive(Empty):
"""The following super is in another scope than `test`."""
def __init__(self, arg):
super(FalsePositive, self).__init__(arg)
super(object, 1).__init__() # [bad-super-call]
super(object, 1).__init__()


class UnknownBases(Missing):
Expand Down Expand Up @@ -123,3 +123,34 @@ class SuperWithSelfClass(object):
"""self.__class__ may lead to recursion loop in derived classes"""
def __init__(self):
super(self.__class__, self).__init__() # [bad-super-call]


# Reported in https://github.com/PyCQA/pylint/issues/2903
class Parent:
def method(self):
print()


class Child(Parent):
def method(self):
print("Child")
super().method()

class Niece(Parent):
def method(self):
print("Niece")
super().method()

class GrandChild(Child):
def method(self):
print("Grandchild")
super(GrandChild, self).method()
super(Child, self).method()
super(Niece, self).method() # [bad-super-call]


# Reported in https://github.com/PyCQA/pylint/issues/4922
class AlabamaCousin(Child, Niece):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, that's very funny πŸ˜„ CarlosTwoOfSpain works too if we want to keep the goodwill of alabamians πŸ˜›

def method(self):
print("AlabamaCousin")
super(Child, self).method()
3 changes: 1 addition & 2 deletions tests/functional/s/super/super_checks.txt
@@ -1,10 +1,8 @@
no-member:10:8:10:29:Aaaa.hop:Super of 'Aaaa' has no 'hop' member:INFERENCE
no-member:19:8:19:32:NewAaaa.hop:Super of 'NewAaaa' has no 'hop' member:INFERENCE
bad-super-call:22:8:22:25:NewAaaa.__init__:Bad first argument 'Aaaa' given to super():UNDEFINED
bad-super-call:32:8:32:28:Py3kWrongSuper.__init__:Bad first argument 'NewAaaa' given to super():UNDEFINED
bad-super-call:37:8:37:28:WrongNameRegression.__init__:Bad first argument 'Missing' given to super():UNDEFINED
bad-super-call:46:8:46:33:CrashSuper.__init__:Bad first argument 'NewAaaa' given to super():UNDEFINED
bad-super-call:62:8:62:24:SuperDifferentScope.test:Bad first argument 'object' given to super():UNDEFINED
bad-super-call:70:8:70:28:UnknownBases.__init__:Bad first argument 'Missing' given to super():UNDEFINED
not-callable:89:8:89:54:InvalidSuperChecks.__init__:super(InvalidSuperChecks, self).not_a_method is not callable:UNDEFINED
no-member:90:8:90:55:InvalidSuperChecks.__init__:Super of 'InvalidSuperChecks' has no 'attribute_error' member:INFERENCE
Expand All @@ -15,3 +13,4 @@ unexpected-keyword-arg:95:8:95:57:InvalidSuperChecks.__init__:Unexpected keyword
no-member:98:8:98:55:InvalidSuperChecks.__init__:Super of 'InvalidSuperChecks' has no 'attribute_error' member:INFERENCE
bad-super-call:120:8:120:31:SuperWithType.__init__:Bad first argument 'type' given to super():UNDEFINED
bad-super-call:125:8:125:35:SuperWithSelfClass.__init__:Bad first argument 'self.__class__' given to super():UNDEFINED
bad-super-call:149:8:149:26:GrandChild.method:Bad first argument 'Niece' given to super():UNDEFINED