scripts: edtlib: child binding compatibles match parents

Fixes: #29758

Commit 7165b77a81 ("scripts: edtlib:
refactor for first class bindings") introduced a Binding class.

Its child_binding instance attribute has a compatible which can be
None. Adjust this behavior so the child Binding object has the same
compatible as the parent binding which ultimately has a compatible.

Without this, sanitycheck's expr_parser is doing some matching on
compatibles in child nodes that is producing unexpected results.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This commit is contained in:
Martí Bolívar 2020-11-03 08:34:04 -08:00 committed by Kumar Gala
commit 0d4dca10b2
2 changed files with 19 additions and 4 deletions

View file

@ -1390,9 +1390,10 @@ class Binding:
The free-form description of the binding. The free-form description of the binding.
compatible: compatible:
The compatible string the binding matches. This may be None if the The compatible string the binding matches. This is None if the Binding is
Binding object is a child binding or if it's inferred from node inferred from node properties. If the Binding is a child binding, then
properties. this will be inherited from the parent binding unless the child binding
explicitly sets its own compatible.
prop2specs: prop2specs:
A collections.OrderedDict mapping property names to PropertySpec objects A collections.OrderedDict mapping property names to PropertySpec objects
@ -1508,6 +1509,14 @@ class Binding:
if key.endswith("-cells"): if key.endswith("-cells"):
self.specifier2cells[key[:-len("-cells")]] = val self.specifier2cells[key[:-len("-cells")]] = val
# Make child binding compatibles match ours if they are missing.
if self.compatible is not None:
child = self.child_binding
while child is not None:
if child.compatible is None:
child.compatible = self.compatible
child = child.child_binding
# Drop the reference to the open warn file. This is necessary # Drop the reference to the open warn file. This is necessary
# to make this object pickleable, but also allows it to get # to make this object pickleable, but also allows it to get
# garbage collected and closed if nobody else is using it. # garbage collected and closed if nobody else is using it.
@ -1528,8 +1537,15 @@ class Binding:
@property @property
def compatible(self): def compatible(self):
"See the class docstring" "See the class docstring"
if hasattr(self, '_compatible'):
return self._compatible
return self.raw.get('compatible') return self.raw.get('compatible')
@compatible.setter
def compatible(self, compatible):
"See the class docstring"
self._compatible = compatible
@property @property
def bus(self): def bus(self):
"See the class docstring" "See the class docstring"

View file

@ -137,7 +137,6 @@ def test_bus():
assert str(edt.get_node("/buses/foo-bus/node/nested").binding_path) == \ assert str(edt.get_node("/buses/foo-bus/node/nested").binding_path) == \
hpath("test-bindings/device-on-foo-bus.yaml") hpath("test-bindings/device-on-foo-bus.yaml")
@pytest.mark.xfail
def test_child_binding(): def test_child_binding():
'''Test 'child-binding:' in bindings''' '''Test 'child-binding:' in bindings'''
edt = edtlib.EDT("test.dts", ["test-bindings"]) edt = edtlib.EDT("test.dts", ["test-bindings"])