Code reports error when given attribute names starting with dash

Bug #2020379 reported by NFSL2001
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
lxml
New
Undecided
Unassigned

Bug Description

When using `picosvg` on https://github.com/googlefonts/picosvg (a Python module dealing with SVGs), there is a weird bug that when given an attribute name starting with dash (e.g. "-inkscape-stroke"), the lxml etree raises an attribute error as below.

Minimal recreate code (after installing picosvg):
```py
from picosvg.svg import SVG

text_svg = SVG.fromstring("""
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" style="enable-background:new 0 0 128 128;">
  <rect width="10" height="10"/>
  <path d="M2,2 v6 h6 v-6 h-6 z" style="stroke:#FF0000;stroke-width:0.5;fill:none;-inkscape-font-specification:'Roboto'"/>
</svg>
            """)
print(text_svg.topicosvg(allow_text=True).tostring())
```

Traceback code:
```py
def parse_css_declarations(
    style: str,
    output: MutableMapping[str, Any],
    property_names: Optional[Container[str]] = None,
) -> str:
    """Parse CSS declaration list into {property: value} dict.

    Args:
        style: CSS declaration list without the enclosing braces,
            as found in an SVG element's "style" attribute.
        output: a dictionary where to store the parsed properties.
        property_names: optional set of property names to limit the declarations
            to be parsed; if not provided, all will be parsed.

    Returns:
        A string containing the unparsed style declarations, if any.

    Raises:
        ValueError if CSS declaration is invalid and can't be parsed.

    References:
    https://www.w3.org/TR/SVG/styling.html#ElementSpecificStyling
    https://www.w3.org/TR/2013/REC-css-style-attr-20131107/#syntax
    """
    unparsed = []
    for declaration in style.split(";"):
        if declaration.count(":") == 1:
            property_name, value = declaration.split(":")
            property_name = property_name.strip()
            if property_names is None or property_name in property_names:
                output[property_name] = value.strip()
            else:
                unparsed.append(declaration.strip())
        elif declaration.strip():
            raise ValueError(f"Invalid CSS declaration syntax: {declaration}")
    return "; ".join(unparsed) + ";" if unparsed else ""
```
where `output` is given a dictionary of attributes:
```py
def _apply_styles(self, el: etree.Element):
    parse_css_declarations(el.attrib.pop("style", ""), el.attrib)
```

Error:
```
Traceback (most recent call last):
  File "d:\Desktop\coding\svg2font\picosvgtest.py", line 15, in <module>
    print(text_svg.topicosvg(allow_text=True).tostring())
  File "D:\Desktop\coding\svg2font\kivy_venv\lib\site-packages\picosvg\svg.py", line 1343, in topicosvg
    svg.topicosvg(ndigits=ndigits, inplace=True, allow_text=allow_text)
  File "D:\Desktop\coding\svg2font\kivy_venv\lib\site-packages\picosvg\svg.py", line 1356, in topicosvg
    self.apply_style_attributes(inplace=True)
  File "D:\Desktop\coding\svg2font\kivy_venv\lib\site-packages\picosvg\svg.py", line 471, in apply_style_attributes
    self._apply_styles(el)
  File "D:\Desktop\coding\svg2font\kivy_venv\lib\site-packages\picosvg\svg.py", line 454, in _apply_styles
    parse_css_declarations(el.attrib.pop("style", ""), el.attrib)
  File "D:\Desktop\coding\svg2font\kivy_venv\lib\site-packages\picosvg\svg_meta.py", line 170, in parse_css_declarations
    output[property_name] = value.strip()
  File "src\lxml\etree.pyx", line 2447, in lxml.etree._Attrib.__setitem__
  File "src\lxml\apihelpers.pxi", line 586, in lxml.etree._setAttributeValue
  File "src\lxml\apihelpers.pxi", line 1764, in lxml.etree._attributeValidOrRaise
ValueError: Invalid attribute name '-inkscape-font-specification'
```

description: updated
Revision history for this message
NFSL2001 (nightfurysl2001) wrote (last edit ):

Related bug report and workaround: https://github.com/googlefonts/picosvg/pull/295

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.