ElementMaker as class variables are interpreted as abstract methods
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
lxml |
Triaged
|
Undecided
|
Unassigned |
Bug Description
So this is kind of a fun one:
>>> import abc
>>> from lxml.builder import ElementMaker
>>> EM = ElementMaker()
>>> EM.foo()
<Element foo at 0x11066a388>
>>> class C(metaclass=
... x = EM
>>> C()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class C with abstract methods x
Can't instantiate abstract class C with abstract methods x
Details:
Python : sys.version_
lxml.etree : (3, 8, 0, 0)
libxml used : (2, 9, 4)
libxml compiled : (2, 9, 4)
libxslt used : (1, 1, 29)
libxslt compiled : (1, 1, 29)
Let me know if you need more information. :)
Yes, a lovely one. Thanks for sharing. ;)
The reason is in ABCMeta.__new__():
abstracts = {name
for name, value in namespace.items()
if getattr(value, "__isabstractme thod__" , False)}
Calling getattr() on the ElementMaker will not raise an AttributeError, but return a partial( ElementMaker) that creates "__isabstractme thod__" tags. That partial object resolves to true in the code abode and ABCMeta considers that enough to assume it's an actual abstract method. :)
I'd rather not restrict the (valid) tag names that ElementMaker is allowed to create - imagine a user wants to write an XML serialiser for Python class definitions. That could actually benefit from an XML tag name "__isabstractme thod__" .
In short - I'm not sure if this is worth fixing. What do you think?