Skip to content

require-explicit-contract-implementation

Require owned substitutes to inherit an injected nominal abstract contract.

Why

An ABC is a nominal contract: inheriting it makes its abstract operations enforceable at instantiation. Protocols intentionally use structural typing and do not require inheritance.

Fix

Make the owned implementation inherit the nominal ABC expected by the consumer.

Examples

Before — flagged A fake is supplied without inheriting its nominal ABC
app/__init__.py
# package
app/consumer.py
from abc import ABC, abstractmethod
class Publisher(ABC):
@abstractmethod
def publish(self) -> None: ...
class Consumer:
def __init__(self, publisher: Publisher) -> None:
self.publisher = publisher
app/fake.py
class FakePublisher:
def publish(self) -> None: ...
app/usage.py
from app.consumer import Consumer
from app.fake import FakePublisher
def setup() -> None:
Consumer(publisher=FakePublisher())
After — preferred The fake declares the actual contract
app/__init__.py
# package
app/consumer.py
from abc import ABC, abstractmethod
class Publisher(ABC):
@abstractmethod
def publish(self) -> None: ...
class Consumer:
def __init__(self, publisher: Publisher) -> None:
self.publisher = publisher
app/fake.py
from app.consumer import Publisher
class FakePublisher(Publisher):
def publish(self) -> None: ...
app/usage.py
from app.consumer import Consumer
from app.fake import FakePublisher
def setup() -> None:
Consumer(publisher=FakePublisher())