lxml-stubs
lxml-stubs copied to clipboard
NSMapArg type definition is incorrect.
nsmap argument of Element function is of type Optional[_NSMapArg] where _NSMapArg is Mapping[str, str].
But according to the documentation here namespace key for the default namespace supposed to be None:
...
>>> NSMAP = {None : XHTML_NAMESPACE} # the default namespace (no prefix)
>>> xhtml = etree.Element(XHTML + "html", nsmap=NSMAP) # lxml only!
...
So it seems like _NSMapArg should be Mapping[Optional[str], str]
I also just encountered this issue, and agree that the documentation disagrees with the type stubs.
According to this comment:
# See https://github.com/python/typing/pull/273
# Due to Mapping having invariant key types, Mapping[Union[A, B], ...]
# would fail to validate against either Mapping[A, ...] or Mapping[B, ...]
# Try to settle for simpler solution, encouraging use of empty string ('')
# as default namespace prefix. If too many people complain, it can be
# back-paddled as Mapping[Any, ...]
_NSMapArg = Mapping[str, str]
Mapping[Optional[str], str] doesn't work because of Mapping being invariant in key and the recommendation is to use an empty string as default namespace prefix.
Which is fine by me, except it doesn't work:
In [78]: etree.Element('{foo}test', nsmap={'': 'pr'})
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[78], line 1
----> 1 etree.Element('{foo}test', nsmap={'': 'pr'})
File src/lxml/etree.pyx:3092, in lxml.etree.Element()
File src/lxml/apihelpers.pxi:138, in lxml.etree._makeElement()
File src/lxml/apihelpers.pxi:125, in lxml.etree._makeElement()
File src/lxml/apihelpers.pxi:226, in lxml.etree._setNodeNamespaces()
File src/lxml/apihelpers.pxi:1746, in lxml.etree._prefixValidOrRaise()
ValueError: Invalid namespace prefix ''
Apparently the empty string only works for the find* functions, but not for element creation.
I am having exactly this problem as @danpascu as well. For now I'll have to settle with ignoring this (type: ignore[dict-item]).