I am trying to implement an abstract superclass (Base) with an abstract method (addfeature), which the Child class will override.
from lxml.builder import ElementMaker
from abc import ABCMeta, abstractmethod
class Base(object):
__metaclass__ = ABCMeta
ns = "http://www.foo.com/bar"
em = ElementMaker(namespace=ns, nsmap={'bar': ns})
@abstractmethod
def addfeature(self):
pass
class Child(Base):
def addfeature(self):
pass
child_instance = Child()
This code fails however with
"TypeError: Can't instantiate abstract class Child with abstract methods em"
Why? em is supposed to be a class attribute, not a method (and surely not an abstract method)
ABCMeta
check whether the method is abstract or not by using __isabstractmethod__
attribute. The lxml.builder.ElementMaker
dynamically generate a method (using __getattr__
); access to __isabstractmethod__
confuse the ABCMeta
.
>>> ns = "http://www.foo.com/bar"
>>> em = ElementMaker(namespace=ns, nsmap={'bar': ns})
>>> em.child_element
<functools.partial object at 0x0000000002B55598>
>>> em.child_element()
<Element {http://www.foo.com/bar}child_element at 0x27a8828>
>>> em.__isabstractmethod__
<functools.partial object at 0x0000000002B55598>
>>> bool(em.__isabstractmethod__)
True
By assigning __isabstractmethod__
as a False
, you can work around it.
class Base(object):
__metaclass__ = ABCMeta
ns = "http://www.foo.com/bar"
em = ElementMaker(namespace=ns, nsmap={'bar': ns})
em.__isabstractmethod__ = False # <-----
@abstractmethod
def addfeature(self):
pass