QName can't ingest bytearray parameters

Bug #2172456 reported by masklinn
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
lxml
Confirmed
Low
Unassigned

Bug Description

Trying to fix up typing on a codebase, types-lxml specs `_Element.tag` as `str | bytes | bytearray | QName`, which seems correct -- even if anything but `str` requires the `tag` to be set manually after the fact. I figured I could use `QName` to normalize the tag name, however while it works perfectly for an str, bytes, or a QName:

    >>> QName("foo").localname
    'foo'
    >>> QName(b"foo").localname
    'foo'
    >>> QName(QName("foo")).localname
    'foo'

bytearray input fails:

    >>> QName(bytearray(b"foo")).localname
    Traceback (most recent call last):
      File "<python-input-25>", line 1, in <module>
        QName(bytearray(b"foo")).localname
        ~~~~~^^^^^^^^^^^^^^^^^^^
      File "src/lxml/etree.pyx", line 1968, in lxml.etree.QName.__init__
      File "src/lxml/apihelpers.pxi", line 1739, in lxml.etree._tagValidOrRaise
    ValueError: Invalid tag name "bytearray(b'foo')"

even though it's possible to set `_Element.tag` to a bytearray:

    >>> e = Element('x')
    >>> e.tag = bytearray(b'x')
    >>> e.tag
    bytearray(b'foo')

so there are edge cases where this can fail at runtime. The stubs are both helpful and frustrating here, because they surface this edge case and result in a type error when writing `QName(e.tag)`. However if one finds out that `QName(_Element)` is also valid, and happen to have this condition happen at runtime, everything typechecks but results in an error:

    >>> QName(e)
    Traceback (most recent call last):
      File "<python-input-34>", line 1, in <module>
        QName(e)
        ~~~~~^^^
      File "src/lxml/etree.pyx", line 1954, in lxml.etree.QName.__init__
    ValueError: Invalid input tag of type <class 'bytearray'>

I think it would make sense for `QName(bytearray)` to be valid resolving these concerns (then the stubs can be updated to match).

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

Revision history for this message
scoder (scoder) wrote :

That looks like a relict from the times when bytearray didn't exist. It should be allowed everywhere where bytes is allowed.

This should be implemented in the respective input conversion/validation functions in "apihelpers.pxi". They should probably just copy the value into a bytes object if there isn't an obvious quicker way to handle them.

Happy to receive a PR.

Changed in lxml:
importance: Undecided → Low
status: New → Confirmed
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.