In issue #829 Andy Lewis has reported a problem with HTML and SVG attributes. Trying to solve this issue made me realize that the way Brython manages attributes should be improved.
Background : attributes and propertiesThis is what I understand after reading things on the Internet (
this post on stackoverflow in particular). Please correct me if I'm wrong.
While Python defines object attributes, that are managed by the syntax "
element.attr_name", the DOM defines two different concepts for elements :
- attributes, which are defined in the HTML (or SVG) tag : <img src="icon.png"> defines the attribute "src". The DOM specification defines a set of methods to manage attributes : getAttribute(name), setAttribute(name, value), etc.
- properties, managed by the same dotted syntax as Python : element.attr_name
To make things more obscure, there is a link between
some attributes and
some properties. Generally, for the attributes that are expected for a given tag (eg "id" or "class" for any kind of tag, "src" for IMG tags, "href" for A, etc), when the attribute is set, the property is also set. Most of the time, the property name is the same as the attribute name, but there are exceptions : the property for the attribute "class" is "className". Generally, the property value is the same as the attribute value, but not always : for instance, for an element defined by
<INPUT type="checkbox" checked="checked">, the value of attribute "checked" is "checked", and the value of property "checked" is the boolean "true".
Besides the attributes defined by the specification for a given tag, custom attributes can be defined (template engine use this a lot) ; for these attributes, the property of the same name is not set. Custom properties can also be defined for an element, and this doesn't set the attribute of the same name.
Attribute values are always strings, while property values can be of any type. Attributes are case-insensitive for HTML elements and case-sensitive for SVG elements ; properties are always case-sensitive.
Management in BrythonSo far, the DOM API in Brython tries to manage both attributes and properties with the same syntax : "
element.attr_name = value" or "
value = attribute.name". Depending on the case, it's sometimes the attribute or the property which is set or read. Since the attributes or properties that are the most often used are "reflected" in each other, the confusion has little consequences, and in more than 5 years, few issues have been reported, but this lack of control on what is managed by the program is not a good thing.
ProposalAfter a few experiments, the current development version proposes to manage properties with the syntax "
element.attr_name", and attributes with a new attribute of DOMNode instances : "
element.attrs". This attribute is a dict-like object:
element.attrs[name] = value
value = element.attrs[name]
delete element.attrs[name]
for name, value in element.attrs:
...
This proposal would certainly break existing code in some cases : for instance, setting the attribute "stroke" of an SVG element was possible with "
element.stoke = value" and would now require "
element.attrs["stroke"] = value". But in practise, all the examples in the gallery and the demo work unmodified, so the consequences should be limited.
You can test this modified API by cloning the repository. Feedback is appreciated !