Comment 0 for bug 2020379

Revision history for this message
NFSL2001 (nightfurysl2001) wrote :

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
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'
```