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 a crash when looking up an __init__ method #7744

Merged
merged 7 commits into from Nov 12, 2022
3 changes: 3 additions & 0 deletions doc/whatsnew/fragments/7742.other
@@ -0,0 +1,3 @@
Fix a crash when a child class with an ``__init__`` method inherits from a parent class with an ``__init__`` class attribute.
mbyrnepr2 marked this conversation as resolved.
Show resolved Hide resolved

Closes #7742
6 changes: 4 additions & 2 deletions pylint/checkers/classes/class_checker.py
Expand Up @@ -2240,15 +2240,17 @@ def _is_mandatory_method_param(self, node: nodes.NodeNG) -> bool:


def _ancestors_to_call(
klass_node: nodes.ClassDef, method: str = "__init__"
klass_node: nodes.ClassDef, method_name: str = "__init__"
mbyrnepr2 marked this conversation as resolved.
Show resolved Hide resolved
) -> dict[nodes.ClassDef, bases.UnboundMethod]:
"""Return a dictionary where keys are the list of base classes providing
the queried method, and so that should/may be called from the method node.
"""
to_call: dict[nodes.ClassDef, bases.UnboundMethod] = {}
for base_node in klass_node.ancestors(recurs=False):
try:
init_node: bases.UnboundMethod = next(base_node.igetattr(method))
init_node = next(base_node.igetattr(method_name))
if not isinstance(init_node, astroid.UnboundMethod):
continue
if init_node.is_abstract():
continue
to_call[base_node] = init_node
Expand Down
11 changes: 11 additions & 0 deletions tests/functional/i/init_not_called.py
Expand Up @@ -84,3 +84,14 @@ def __init__(self, num: float):

def __init__(self, num):
super().__init__(round(num))


# https://github.com/PyCQA/pylint/issues/7742
# Crash when parent class has a class attribute named `__init__`
class NoInitMethod:
__init__ = 42


class ChildNoInitMethod(NoInitMethod):
def __init__(self):
...