Python currently lacks a built-in mechanism to enforce method signatures in interfaces. While the abc module allows for abstract base classes (ABCs), it does not verify method signatures, leading to potential runtime errors when method signatures do not match expectations.
A new Interface class could be introduced, using the InterfaceMeta metaclass. Any class inheriting from Interface must implement all defined methods with the same signature.
The code:
from abc import ABCMeta
import inspect
class InterfaceMeta(ABCMeta):
"""Metaclass to force implementation of methods in derived classes with the same signature."""
def __new__(mcs, name, bases, namespace):
if bases: # Ensure we are checking derived classes, not the base interface
for base in bases:
if isinstance(base, InterfaceMeta):
for attr_name, attr_value in base.__dict__.items():
if callable(attr_value) and not attr_name.startswith('__'):
if attr_name not in namespace:
raise TypeError(
f"Class '{name}' must implement method '{attr_name}' of interface '{base.__name__}'"
)
base_signature = inspect.signature(attr_value)
derived_signature = inspect.signature(namespace[attr_name])
if base_signature != derived_signature:
raise TypeError(
f"Method '{attr_name}' in class '{name}' does not match the interface signature.\n"
f"Expected: {base_signature}\n"
f"Got: {derived_signature}"
)
return super().__new__(mcs, name, bases, namespace)
class Interface(metaclass=InterfaceMeta):
"""Base class for all interfaces."""
pass
Example Usage
class MyInterface(Interface):
def method(self, x: int) -> str:
pass
class ValidImplementation(MyInterface):
def method(self, x: int) -> str:
return str(x)
class InvalidImplementation(MyInterface):
def method(self, x): # Missing return annotation
return str(x)
# Raises TypeError: "Method 'method' in class 'InvalidImplementation' does not match the interface signature."
# Expected: (self, x: int) -> str
# Got: (self, x)
Performance Impact
Minimal, as the verification occurs only at class definition time.
I created a project on Pypi with this code for personal use.I leave it here in case you want to see it: Client Challenge