Consider the following set of classes:
from abc import ABC, abstractmethod
class GrandParent(ABC):
@abstractmethod
def foo(self):
raise NotImplementedError()
@abstractmethod
def bar(self):
raise NotImplementedError()
class Parent1(GrandParent):
def foo(self):
print("Parent 1")
class Parent2(GrandParent):
def foo(self):
print("Parent 2")
class Child1A(Parent1):
def bar(self):
print("Child 1A")
class Child1B(Parent1):
def bar(self):
print("Child 1B")
Here GrandParent,
Parent1
and Parent2
are abstract classes, and the only concrete ones are Child1A
and Child1B
. However, pylint
complains about Parent
s that:
W0223: Method 'bar' is abstract in class 'GrandParent' but is not overridden (abstract-method)
I can understand the reason is that by looking at the class definition itself one cannot understand that it is supposed to be an abstract class. I wonder if there is a decorator or something that I need to use to indicate this explicitly?
One obvious way would be to re-define an abstract bar
method in Parent1
and Parent2
but that does not sounds reasonable to me (what if there were 10 other abstract methods in GrandParent
that the children need to override?, should all 10 of them be copy-pasted in Parent
s?)
Update
It was suggested in the comments that this is a pylint
-specific behavior that intermediate implicit ABCs are not supported yet. To get rid of the warning (without disabling it) it is sufficient to redefine one of the abstract methods of GrandParent
in Parent1
using @abstractmethod
decorator. Indeed this solves the issue, but will cause problems in multiple-inheritance scenarios:
from abc import ABC, abstractmethod
class Base(ABC):
@abstractmethod
def foo(self):
raise NotImplementedError()
@abstractmethod
def bar(self):
raise NotImplementedError()
def baz(self):
return 'baz'
def qux(self):
return 'qux'
class C1(Base):
def qux(self):
return super().qux().upper()
# @abstractmethod
# def bar(self):
# raise NotImplementedError()
class C2(Base):
def foo(self):
return 'FOO'
def bar(self):
return 'BAR'
class D(C1, C2):
pass
Here C1
is an intermediate implicit ABC, hence pylint
warns. Yet, D
is a concrete class. To get rid of the pylint
warning we can uncomment the redefinition of bar
in C1
. But then D
cannot be instantiated --- Python complains that bar
is abstract in C1
and not defined in D
.