I'm writing an plugin framework and I want to be able to write a decorator interface
, which will convert user class to ABC class and substitute all methods with abstractmethods. I cannot get it working and I suppose the problem is connected with wrong mro, but I can be wrong.
I basically need to be albe to write:
@interface
class X:
def test(self):
pass
x = X() # should fail, because test will be abstract method.
substituting methods with their abstract versions is straightforward (you have to iterate over func's and replace them with abc.abstractmethod(func)
), but I've got problem with creating dynamic type, which will be an ABCmeta
metaclass.
Right now I've got something like:
from abc import ABCMeta
class Interface(metaclass=ABCMeta):
pass
def interface(cls):
newcls = type(cls.__name__, (Interface, cls), {})
# substitute all methods with abstract ones
for name, func in inspect.getmembers(newcls, predicate=inspect.isfunction):
setattr(newcls, name, abstractmethod(func))
return newcls
but it doesnot work - Ican initialize class X without errors.
With standard usage of ABC in Python, we can write:
class X(metaclass=ABCMeta):
@abstractmethod
def test(self):
pass
x = X() # it will fail
How can I create dynamic type in Python3, which will behave like it will have metaclass ABCmeta
and will substitute all functions with abstract ones?
The trick is not to use setattr
to reset each of the attributes, but instead to pass those modified attributes to the type
function as a dictionary:
import inspect
from abc import ABCMeta, abstractmethod
class Interface(metaclass=ABCMeta):
pass
def interface(cls):
attrs = {n: abstractmethod(f)
for n, f in inspect.getmembers(cls, predicate=inspect.isfunction)}
return type(cls.__name__, (Interface, cls), attrs)
@interface
class X(metaclass=ABCMeta):
def test(self):
pass
x = X()
# does fail:
# Traceback (most recent call last):
# File "test.py", line 19, in <module>
# x = X() # should fail, because test will be abstract method.
# TypeError: Can't instantiate abstract class X with abstract methods test