tostring() ignores tag attribute

Bug #1780950 reported by James Pic on 2018-07-10
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
lxml
Undecided
Unassigned

Bug Description

Python : sys.version_info(major=3, minor=6, micro=6, releaselevel='final', serial=0)
lxml.etree : (4, 2, 3, 0)
libxml used : (2, 9, 8)
libxml compiled : (2, 9, 8)
libxslt used : (1, 1, 32)
libxslt compiled : (1, 1, 32)

Test script:

from lxml import etree

class Component(etree.ElementBase):
    pass

class Div(Component):
    tag = 'div'

class Col(Div):
    def __init__(self, l=None):
        self.l = l
        super().__init__()

    def _init(self):
        super()._init()
        if 'class' not in self.attrib:
            self.attrib['class'] = 'col'
        else:
            self.attrib['class'] += ' col'

        if self.l:
            self.attrib['class'] += ' l{}'.format(self.l)

el = Col(l=2)
el.tag = 'div'
print('el repr', el)
print('expected: ', b'<div class="col l2"/>')
print('result: ', etree.tostring(el))

Result:

el repr <Element div at 0x7fe6923ada48>
expected: b'<div class="col l2"/>'
result: b'<Col class="col l2"/>'

As you can see, tostring enforces the class name instead of using the tag attribute, like repr does.

scoder (scoder) wrote :

Element classes are not relevant for serialisation. As documented, all state must be stored in the tree, not in the element classes. If you set "self.tag" from your class, you will get the expected result.

Changed in lxml:
status: New → Won't Fix
James Pic (jpic) wrote :

What about: repr output is incorrect, and setting tag should raise an exception since it's useless ?

scoder (scoder) wrote :

It could be considered acceptable to duplicate the code to read the tag name in a couple of more places, including "__repr__()", rather than resorting to the simple "self.tag". PR welcome.

I don't under your comment regarding an exception when setting the tag. What do you mean here?

James Pic (jpic) wrote :

I think the tag attribute should be read only, if we can't change it ?

It's really too bad, Python almost had a perfect component based HTML refactoring pattern like React...

scoder (scoder) wrote :

The tag property is writable, but you cannot override it in subclasses (and why would you do that?).

Can't you use a factory function instead of the "Col" class in your example?

Just because I wanted to use inheritance I guess. We can still use lxml but
i thought it would be cool to start from existing lxml components

But right now we're making a function based poc, thanks for your reply,
will keep you in such if you see fit.

Best regards

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers