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?
Python Code can be dynamically imported and classes can be dynamically created at run-time. Classes can be dynamically created using the type() function in Python. The type() function is used to return the type of the object. The above syntax returns the type of object.
@abc. abstractmethod prevents any attempt to instantiate a subclass that doesn't override a particular method in the superclass.
The abc module defines ABCMeta class which is a metaclass for defining abstract base class. Following example defines Shape class as an abstract base class using ABCMeta. The shape class has area() method decorated by abstractmethod.
An abstract method is a method that is declared, but contains no implementation. Abstract classes cannot be instantiated, and require subclasses to provide implementations for the abstract methods.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With