From 110526ec0ef8ff1d6e72a2cd7330b9b951148697 Mon Sep 17 00:00:00 2001 From: Ulf Magnusson Date: Sat, 21 Sep 2019 04:14:33 +0200 Subject: [PATCH] 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 --- scripts/dts/edtlib.py | 21 ++++++++++++++++++--- scripts/dts/test.dts | 13 +++++++++++++ scripts/dts/testdtlib.py | 5 ++--- scripts/dts/testedtlib.py | 33 ++++++++++++++++++++++++++------- 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/scripts/dts/edtlib.py b/scripts/dts/edtlib.py index 728d9541c9f..241ca9b5781 100644 --- a/scripts/dts/edtlib.py +++ b/scripts/dts/edtlib.py @@ -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" diff --git a/scripts/dts/test.dts b/scripts/dts/test.dts index b3292f3e1bc..6b30bb78329 100644 --- a/scripts/dts/test.dts +++ b/scripts/dts/test.dts @@ -273,6 +273,19 @@ }; }; + // + // For testing Device.parent and Device.children + // + + parent { + child-1 { + }; + child-2 { + grandchild { + }; + }; + }; + // // For testing 'include:' // diff --git a/scripts/dts/testdtlib.py b/scripts/dts/testdtlib.py index e763d9778a0..af753d4d670 100755 --- a/scripts/dts/testdtlib.py +++ b/scripts/dts/testdtlib.py @@ -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 diff --git a/scripts/dts/testedtlib.py b/scripts/dts/testedtlib.py index 39c84c7c5dd..04de564e6a1 100755 --- a/scripts/dts/testedtlib.py +++ b/scripts/dts/testedtlib.py @@ -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, "[]") + # + # Test Device.parent and Device.children + # + + verify_eq(edt.get_dev("/").parent, None) + + verify_streq(edt.get_dev("/parent/child-1").parent, + "") + + verify_streq(edt.get_dev("/parent/child-2/grandchild").parent, + "") + + verify_streq(edt.get_dev("/parent").children, + "{'child-1': , 'child-2': }") + + verify_eq(edt.get_dev("/parent/child-1").children, {}) + # # Test 'include:' and the legacy 'inherits: !include ...' #