From 6f4a8b07c5b2c40a379cb66a3105d64106e6f752 Mon Sep 17 00:00:00 2001 From: Nathaniel Graff Date: Fri, 8 Nov 2019 10:27:42 -0800 Subject: [PATCH 1/2] Fix get_by_path parsing unit-address as decimal instead of hex Signed-off-by: Nathaniel Graff --- pydevicetree/ast/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydevicetree/ast/node.py b/pydevicetree/ast/node.py index 46a5b2e..1d80411 100644 --- a/pydevicetree/ast/node.py +++ b/pydevicetree/ast/node.py @@ -195,7 +195,7 @@ def __get_child_by_handle(self, handle: str) -> Optional['Node']: """Get a child node by name or name and unit address""" if '@' in handle: name, addr_s = handle.split('@') - address = int(addr_s) + address = int(addr_s, base=16) nodes = list(filter(lambda n: n.name == name and n.address == address, self.children)) else: name = handle From bde2f327c057537156f8eb8858333e1f068db47d Mon Sep 17 00:00:00 2001 From: Nathaniel Graff Date: Fri, 8 Nov 2019 10:19:18 -0800 Subject: [PATCH 2/2] Create Nodes from source After parsing a tree, you can now create nodes by writing the source for the Node you want and calling Node.from_dts(). Then that node can be added to the tree by calling Node.add_child(). Signed-off-by: Nathaniel Graff --- pydevicetree/ast/node.py | 14 ++++++++++++++ pydevicetree/source/__init__.py | 2 +- pydevicetree/source/parser.py | 4 ++++ tests/test_devicetree.py | 25 +++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/pydevicetree/ast/node.py b/pydevicetree/ast/node.py index 1d80411..9f00f66 100644 --- a/pydevicetree/ast/node.py +++ b/pydevicetree/ast/node.py @@ -103,6 +103,20 @@ def __eq__(self, other) -> bool: def __hash__(self): return hash((self.name, self.address)) + @staticmethod + def from_dts(source: str) -> 'Node': + """Create a node from Devicetree Source""" + # pylint: disable=import-outside-toplevel,cyclic-import + from pydevicetree.source import parseNode + return parseNode(source) + + def add_child(self, node: 'Node', merge: bool = True): + """Add a child node and merge it into the tree""" + node.parent = self + self.children.append(node) + if merge: + self.merge_tree() + def to_dts(self, level: int = 0) -> str: """Format the subtree starting at the node as Devicetree Source""" out = "" diff --git a/pydevicetree/source/__init__.py b/pydevicetree/source/__init__.py index 5ac3ff8..0440733 100644 --- a/pydevicetree/source/__init__.py +++ b/pydevicetree/source/__init__.py @@ -2,4 +2,4 @@ # Copyright (c) 2019 SiFive Inc. # SPDX-License-Identifier: Apache-2.0 -from pydevicetree.source.parser import parseTree +from pydevicetree.source.parser import parseTree, parseNode diff --git a/pydevicetree/source/parser.py b/pydevicetree/source/parser.py index ec2602f..857f1fa 100644 --- a/pydevicetree/source/parser.py +++ b/pydevicetree/source/parser.py @@ -144,6 +144,10 @@ def parseTree(dts, pwd="", followIncludes=False): """Parses a string into a full Devicetree""" return Devicetree(parseElements(dts, pwd, followIncludes)) +def parseNode(dts): + """Parses a string into a Devictreee Node""" + return grammar.node_definition.parseString(dts)[0] + if __name__ == "__main__": import sys if len(sys.argv) > 1: diff --git a/tests/test_devicetree.py b/tests/test_devicetree.py index 85bf8ed..8912619 100644 --- a/tests/test_devicetree.py +++ b/tests/test_devicetree.py @@ -137,5 +137,30 @@ def func(values): self.assertEqual(cpu.get_path(), "/cpus/cpu@0") self.assertEqual(cpu.get_field("reg"), 0) + def test_node_from_dts(self): + node = Node.from_dts("uart0: uart@10013000 { compatible = \"sifive,uart0\"; };") + + self.assertEqual(type(node), Node) + self.assertEqual(node.label, "uart0") + self.assertEqual(node.name, "uart") + self.assertEqual(node.address, 0x10013000) + self.assertEqual(node.get_field("compatible"), "sifive,uart0") + + def test_add_child(self): + tree = parseTree(self.source) + + new_node = Node.from_dts("uart0: uart@10013000 { compatible = \"sifive,uart0\"; };") + + soc = tree.get_by_path("/soc") + soc.add_child(new_node) + + uart = tree.get_by_path("/soc/uart@10013000") + self.assertEqual(type(uart), Node) + self.assertEqual(uart.label, "uart0") + self.assertEqual(uart.name, "uart") + self.assertEqual(uart.address, 0x10013000) + self.assertEqual(uart.get_field("compatible"), "sifive,uart0") + + if __name__ == "__main__": unittest.main()