Проверяем был ли метод декорирован с помощью специального атрибута wrapped.
Мы добавляем его вручную, но вроде бы он проставляется автоматически если использовать functools.wraps
import abc
class C(abc.ABC):
@abc.abstractmethod
def method_one(self, *args, **kwargs):
"""Abstract method one"""
@abc.abstractmethod
def method_two(self, *args, **kwargs):
"""Abstract method two"""
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
# Проверяем, что методы подкласса декорированы
for method_name in ['method_one', 'method_two']:
method = getattr(cls, method_name, None)
if method is None:
raise TypeError(f"{cls.__name__} must implement {method_name}")
if not hasattr(method, "__wrapped__"):
raise TypeError(f"{cls.__name__}.{method_name} must be decorated with a decorator")
def some_decorator(func):
def wrapper(*args, **kwargs):
print(f"Executing {func.__name__} with decorator")
return func(*args, **kwargs)
wrapper.__wrapped__ = func
return wrapper
class D(C):
@some_decorator
def method_one(self, *args, **kwargs):
print("Executing method_one")
@some_decorator
def method_two(self, *args, **kwargs):
print("Executing method_two")
# Пример некорректного использования (вызывает TypeError)
class E(C):
def method_one(self, *args, **kwargs): # Метод не декорирован
print("Executing method_one")
@some_decorator
def method_two(self, *args, **kwargs):
print("Executing method_two")
d = D() # Работает без ошибок
try:
e = E() # Ошибка
except TypeError as e:
print(e)