Skip to content

Commit

Permalink
Fix a false negative for abstract-method when an abstract class i…
Browse files Browse the repository at this point in the history
…s the direct ancestor of a derived class.

Closes #9979
  • Loading branch information
mbyrnepr2 committed Sep 30, 2024
1 parent c0ecd70 commit fba14dd
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 3 deletions.
2 changes: 1 addition & 1 deletion doc/data/messages/a/abstract-method/bad/abstract_method.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import abc


class WildAnimal:
class WildAnimal(abc.ABC):
@abc.abstractmethod
def make_sound(self):
pass
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import abc


class WildAnimal:
class WildAnimal(abc.ABC):
@abc.abstractmethod
def make_sound(self):
pass
Expand Down
3 changes: 3 additions & 0 deletions doc/whatsnew/fragments/9979.false_negative
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix a false negative for ``abstract-method`` when an abstract class is the direct ancestor of a derived class.

Closes #9979
2 changes: 1 addition & 1 deletion pylint/checkers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1166,7 +1166,7 @@ def class_is_abstract(node: nodes.ClassDef) -> bool:
if meta.name == "ABCMeta" and meta.root().name in ABC_MODULES:
return True

for ancestor in node.ancestors():
for ancestor in node.ancestors(recurs=False):
if ancestor.name == "ABC" and ancestor.root().name in ABC_MODULES:
# abc.ABC inheritance
return True
Expand Down
15 changes: 15 additions & 0 deletions tests/functional/a/abstract/abstract_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,18 @@ class GoodComplexMRO(Container, Iterator, Sizable, Hashable):
# +1: [abstract-method, abstract-method, abstract-method]
class BadComplexMro(Container, Iterator, AbstractSizable):
pass


class Base(abc.ABC):
@abc.abstractmethod
def do_something(self):
pass


# +1: [abstract-method]
class Derived(Base):
""" Test that a class derived from an abstract class correctly triggers
`abstract-method`.
"""
def do_something_else(self):
pass
1 change: 1 addition & 0 deletions tests/functional/a/abstract/abstract_method.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ abstract-method:87:0:87:14:Iterator:Method '__len__' is abstract in class 'Struc
abstract-method:106:0:106:19:BadComplexMro:Method '__hash__' is abstract in class 'Structure' but is not overridden in child class 'BadComplexMro':INFERENCE
abstract-method:106:0:106:19:BadComplexMro:Method '__len__' is abstract in class 'AbstractSizable' but is not overridden in child class 'BadComplexMro':INFERENCE
abstract-method:106:0:106:19:BadComplexMro:Method 'length' is abstract in class 'AbstractSizable' but is not overridden in child class 'BadComplexMro':INFERENCE
abstract-method:117:0:117:13:Derived:Method 'do_something' is abstract in class 'Base' but is not overridden in child class 'Derived':INFERENCE

0 comments on commit fba14dd

Please sign in to comment.