scripts: edtlib: Add a Device.children attribute with child Devices

API oversight. This was meant to be there all along together with
Device.parent, for navigating the devicetree, but since a need for it
never came up in gen_defines.py, it got overlooked.

Devices are just devicetree nodes augmented with binding information and
some interpretation of devicetree properties. I wonder if the name
should be changed to something like edtlib.Node to make that clearer.
Calling something like a flash partition a "device" is a bit weird, as
Galak pointed out.

I think I went with Device originally to avoid confusion with
dtlib.Node, but since edtlib users don't directly interact with dtlib,
it might not be that confusing in practice.

Piggyback some documentation clarifications.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
This commit is contained in:
Ulf Magnusson 2019-09-21 04:14:33 +02:00 committed by Kumar Gala
commit 110526ec0e
4 changed files with 59 additions and 13 deletions

View file

@ -333,8 +333,9 @@ class EDT:
class Device:
"""
Represents a device. There's a one-to-one correspondence between device
tree nodes and Devices.
Represents a device, which is a devicetree node augmented with information
from bindings and some interpretation of devicetree properties. There's a
one-to-one correspondence between device tree nodes and Devices.
These attributes are available on Device objects:
@ -357,7 +358,12 @@ class Device:
if the node has no 'label'
parent:
The parent Device, or None if there is no parent
The Device instance for the devicetree parent of the Device, or None if
there is no parent
children:
A dictionary with the Device instances for the devicetree children of the
Device, indexed by name
enabled:
True unless the device's node has 'status = "disabled"'
@ -479,6 +485,15 @@ class Device:
"See the class docstring"
return self.edt._node2dev.get(self._node.parent)
@property
def children(self):
"See the class docstring"
# Could be initialized statically too to preserve identity, but not
# sure if needed. Parent Devices being initialized before their
# children would need to be kept in mind.
return {name: self.edt._node2dev[node]
for name, node in self._node.nodes.items()}
@property
def enabled(self):
"See the class docstring"

View file

@ -273,6 +273,19 @@
};
};
//
// For testing Device.parent and Device.children
//
parent {
child-1 {
};
child-2 {
grandchild {
};
};
};
//
// For testing 'include:'
//

View file

@ -9,10 +9,9 @@ import sys
import dtlib
# Test suite for dtlib.py. Can be run directly as an executable.
# Test suite for dtlib.py. Run it directly as an executable, in this directory:
#
# This script expects to be run from the directory its in. This simplifies
# things, as paths in the output can be assumed below.
# $ ./testdtlib.py
# TODO: Factor out common code from error tests

View file

@ -7,13 +7,13 @@ import sys
import edtlib
# Test suite for edtlib.py. Mostly uses string comparisons via the various
# __repr__() methods. Can be run directly as an executable.
# Test suite for edtlib.py. Run it directly as an executable, in this
# directory:
#
# This script expects to be run from the directory its in. This simplifies
# things, as paths in the output can be assumed below.
# $ ./testedtlib.py
#
# test.dts is the test file, and test-bindings/ has bindings.
# test.dts is the test file. test-bindings/ has bindings. The tests mostly use
# string comparisons via the various __repr__() methods.
def run():
@ -25,13 +25,15 @@ def run():
def fail(msg):
sys.exit("test failed: " + msg)
def verify_streq(actual, expected):
actual = str(actual)
def verify_eq(actual, expected):
if actual != expected:
# Put values on separate lines to make it easy to spot differences
fail("not equal (expected value last):\n'{}'\n'{}'"
.format(actual, expected))
def verify_streq(actual, expected):
verify_eq(str(actual), expected)
edt = edtlib.EDT("test.dts", ["test-bindings"])
#
@ -97,6 +99,23 @@ def run():
verify_streq(edt.get_dev("/reg-nested-ranges/grandparent/parent/node").regs,
"[<Register, addr: 0x30000000200000001, size: 0x1>]")
#
# Test Device.parent and Device.children
#
verify_eq(edt.get_dev("/").parent, None)
verify_streq(edt.get_dev("/parent/child-1").parent,
"<Device /parent in 'test.dts', no binding>")
verify_streq(edt.get_dev("/parent/child-2/grandchild").parent,
"<Device /parent/child-2 in 'test.dts', no binding>")
verify_streq(edt.get_dev("/parent").children,
"{'child-1': <Device /parent/child-1 in 'test.dts', no binding>, 'child-2': <Device /parent/child-2 in 'test.dts', no binding>}")
verify_eq(edt.get_dev("/parent/child-1").children, {})
#
# Test 'include:' and the legacy 'inherits: !include ...'
#