Skip to content

Commit

Permalink
Merge pull request #12 from sifive/split-up-ast-module
Browse files Browse the repository at this point in the history
Split up the pydevicetree.ast module for maintainability
  • Loading branch information
nategraff-sifive authored Nov 7, 2019
2 parents 1d27842 + 0a5f1f4 commit e10cf0b
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 137 deletions.
4 changes: 3 additions & 1 deletion pydevicetree/ast/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
# Copyright (c) 2019 SiFive Inc.
# SPDX-License-Identifier: Apache-2.0

from pydevicetree.ast.classes import *
from pydevicetree.ast.property import PropertyValues, Bytestring, CellArray, StringList, Property
from pydevicetree.ast.directive import Directive
from pydevicetree.ast.node import Node, NodeReference, Devicetree
23 changes: 23 additions & 0 deletions pydevicetree/ast/directive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env python3
# Copyright (c) 2019 SiFive Inc.
# SPDX-License-Identifier: Apache-2.0

from typing import List, Any

from pydevicetree.ast.helpers import formatLevel

class Directive:
def __init__(self, directive: str, options: List[Any] = None):
self.directive = directive
self.options = options

def __repr__(self) -> str:
return "<Directive %s>" % self.directive

def __str__(self) -> str:
return self.to_dts()

def to_dts(self, level: int = 0) -> str:
if self.options:
return formatLevel(level, "%s %s;\n" % (self.directive, self.options))
return formatLevel(level, "%s;\n" % self.directive)
25 changes: 25 additions & 0 deletions pydevicetree/ast/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env python3
# Copyright (c) 2019 SiFive Inc.
# SPDX-License-Identifier: Apache-2.0

from typing import List, Any

def formatLevel(level: int, s: str) -> str:
return "\t" * level + s

def wrapStrings(values: List[Any], formatHex: bool = False) -> List[Any]:
wrapped = []
for v in values:
if isinstance(v, str):
if v[0] != '&':
wrapped.append("\"%s\"" % v)
else:
wrapped.append(v)
elif isinstance(v, int):
if formatHex:
wrapped.append("0x%x" % v)
else:
wrapped.append(str(v))
else:
wrapped.append(str(v))
return wrapped
130 changes: 9 additions & 121 deletions pydevicetree/ast/classes.py → pydevicetree/ast/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,132 +2,20 @@
# Copyright (c) 2019 SiFive Inc.
# SPDX-License-Identifier: Apache-2.0

import os
import re
import os
from typing import List, Union, Optional, Iterable, Callable, Any, cast, Pattern

from typing import List, Union, Optional, Iterable, Callable, cast, Any, Pattern
from pydevicetree.ast.helpers import formatLevel
from pydevicetree.ast.property import Property, PropertyValues
from pydevicetree.ast.directive import Directive

# These names are just used in the constructors for these clasess
ElementList = Iterable[Union['Node', 'Property', 'Directive']]
DirectiveOption = List[Any]
# Type signature for elements passed to Devicetree constructor
ElementList = Iterable[Union['Node', Property, Directive]]

# Callback isinstance signatures for Devicetree.match() and Devicetree.chosen()
# Callback type signatures for Devicetree.match() and Devicetree.chosen()
MatchCallback = Optional[Callable[['Node'], None]]
ChosenCallback = Optional[Callable[['PropertyValues'], None]]

def formatLevel(level: int, s: str) -> str:
return "\t" * level + s

def wrapStrings(values: List[Any], formatHex: bool = False) -> List[Any]:
wrapped = []
for v in values:
if isinstance(v, str):
if v[0] != '&':
wrapped.append("\"%s\"" % v)
else:
wrapped.append(v)
elif isinstance(v, int):
if formatHex:
wrapped.append("0x%x" % v)
else:
wrapped.append(str(v))
else:
wrapped.append(str(v))
return wrapped

class PropertyValues:
def __init__(self, values: List[Any] = None):
self.values = values

def __repr__(self) -> str:
return "<PropertyValues " + self.values.__repr__() + ">"

def __str__(self) -> str:
return self.to_dts()

def __iter__(self):
return iter(self.values)

def __len__(self) -> int:
return len(self.values)

def to_dts(self, formatHex: bool = False) -> str:
return " ".join(wrapStrings(self.values, formatHex))

def __getitem__(self, key) -> Any:
return self.values[key]

def __eq__(self, other) -> bool:
if isinstance(other, PropertyValues):
return self.values == other.values
return self.values == other

class Bytestring(PropertyValues):
def __init__(self, bytelist: List[int] = None):
PropertyValues.__init__(self, bytearray(bytelist))

def __repr__(self) -> str:
return "<Bytestring " + str(self.values) + ">"

def to_dts(self, formatHex: bool = False) -> str:
return "[" + " ".join("%02x" % v for v in self.values) + "]"

class CellArray(PropertyValues):
def __init__(self, cells: List[Any] = None):
PropertyValues.__init__(self, cells)

def __repr__(self) -> str:
return "<CellArray " + self.values.__repr__() + ">"

def to_dts(self, formatHex: bool = False) -> str:
return "<" + " ".join(wrapStrings(self.values, formatHex)) + ">"

class StringList(PropertyValues):
def __init__(self, strings: List[str] = None):
PropertyValues.__init__(self, strings)

def __repr__(self) -> str:
return "<StringList " + self.values.__repr__() + ">"

def to_dts(self, formatHex: bool = False) -> str:
return ", ".join(wrapStrings(self.values))

class Property:
def __init__(self, name: str, values: PropertyValues):
self.name = name
self.values = values

def __repr__(self) -> str:
return "<Property %s>" % self.name

def __str__(self) -> str:
return self.to_dts()

def to_dts(self, level: int = 0) -> str:
if self.name in ["reg", "ranges"]:
value = self.values.to_dts(formatHex=True)
else:
value = self.values.to_dts(formatHex=False)

if value != "":
return formatLevel(level, "%s = %s;\n" % (self.name, value))
return formatLevel(level, "%s;\n" % self.name)

class Directive:
def __init__(self, directive: str, options: DirectiveOption = None):
self.directive = directive
self.options = options

def __repr__(self) -> str:
return "<Directive %s>" % self.directive

def __str__(self) -> str:
return self.to_dts()

def to_dts(self, level: int = 0) -> str:
if self.options:
return formatLevel(level, "%s %s;\n" % (self.directive, self.options))
return formatLevel(level, "%s;\n" % self.directive)
ChosenCallback = Optional[Callable[[PropertyValues], None]]

class Node:
# pylint: disable=too-many-arguments
Expand Down
85 changes: 85 additions & 0 deletions pydevicetree/ast/property.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/env python3
# Copyright (c) 2019 SiFive Inc.
# SPDX-License-Identifier: Apache-2.0

from typing import List, Any

from pydevicetree.ast.helpers import wrapStrings, formatLevel

class PropertyValues:
def __init__(self, values: List[Any] = None):
self.values = values

def __repr__(self) -> str:
return "<PropertyValues " + self.values.__repr__() + ">"

def __str__(self) -> str:
return self.to_dts()

def __iter__(self):
return iter(self.values)

def __len__(self) -> int:
return len(self.values)

def to_dts(self, formatHex: bool = False) -> str:
return " ".join(wrapStrings(self.values, formatHex))

def __getitem__(self, key) -> Any:
return self.values[key]

def __eq__(self, other) -> bool:
if isinstance(other, PropertyValues):
return self.values == other.values
return self.values == other

class Bytestring(PropertyValues):
def __init__(self, bytelist: List[int] = None):
PropertyValues.__init__(self, bytearray(bytelist))

def __repr__(self) -> str:
return "<Bytestring " + str(self.values) + ">"

def to_dts(self, formatHex: bool = False) -> str:
return "[" + " ".join("%02x" % v for v in self.values) + "]"

class CellArray(PropertyValues):
def __init__(self, cells: List[Any] = None):
PropertyValues.__init__(self, cells)

def __repr__(self) -> str:
return "<CellArray " + self.values.__repr__() + ">"

def to_dts(self, formatHex: bool = False) -> str:
return "<" + " ".join(wrapStrings(self.values, formatHex)) + ">"

class StringList(PropertyValues):
def __init__(self, strings: List[str] = None):
PropertyValues.__init__(self, strings)

def __repr__(self) -> str:
return "<StringList " + self.values.__repr__() + ">"

def to_dts(self, formatHex: bool = False) -> str:
return ", ".join(wrapStrings(self.values))

class Property:
def __init__(self, name: str, values: PropertyValues):
self.name = name
self.values = values

def __repr__(self) -> str:
return "<Property %s>" % self.name

def __str__(self) -> str:
return self.to_dts()

def to_dts(self, level: int = 0) -> str:
if self.name in ["reg", "ranges"]:
value = self.values.to_dts(formatHex=True)
else:
value = self.values.to_dts(formatHex=False)

if value != "":
return formatLevel(level, "%s = %s;\n" % (self.name, value))
return formatLevel(level, "%s;\n" % self.name)
2 changes: 1 addition & 1 deletion pydevicetree/source/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
# Copyright (c) 2019 SiFive Inc.
# SPDX-License-Identifier: Apache-2.0

from pydevicetree.source.parser import *
from pydevicetree.source.parser import parseTree
22 changes: 11 additions & 11 deletions pydevicetree/source/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from itertools import chain

from pydevicetree.source.grammar import *
from pydevicetree.source import grammar
from pydevicetree.ast import *

def transformNode(string, location, tokens):
Expand Down Expand Up @@ -60,15 +60,15 @@ def transformBytestring(string, location, tokens):
def transformCellArray(string, location, tokens):
return CellArray(tokens.asList())

node_definition.setParseAction(transformNode)
property_assignment.setParseAction(transformPropertyAssignment)
directive.setParseAction(transformDirective)
arith_expr.setParseAction(evaluateArithExpr)
ternary_expr.setParseAction(transformTernary)
stringlist.setParseAction(transformStringList)
bytestring.setParseAction(transformBytestring)
cell_array.setParseAction(transformCellArray)
property_values.setParseAction(transformPropertyValues)
grammar.node_definition.setParseAction(transformNode)
grammar.property_assignment.setParseAction(transformPropertyAssignment)
grammar.directive.setParseAction(transformDirective)
grammar.arith_expr.setParseAction(evaluateArithExpr)
grammar.ternary_expr.setParseAction(transformTernary)
grammar.stringlist.setParseAction(transformStringList)
grammar.bytestring.setParseAction(transformBytestring)
grammar.cell_array.setParseAction(transformCellArray)
grammar.property_values.setParseAction(transformPropertyValues)

def printTree(tree, level=0):
def printlevel(level, s):
Expand Down Expand Up @@ -121,7 +121,7 @@ def recurseIncludeFiles(elements, pwd):
elements += parseElements(contents)

def parseElements(dts, pwd="", followIncludes=False):
elements = devicetree.parseString(dts)
elements = grammar.devicetree.parseString(dts)
parentNodes(elements)
if followIncludes:
recurseIncludeFiles(elements, pwd)
Expand Down
6 changes: 3 additions & 3 deletions tests/test_grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def test_cell_array(self):
self.assertEqual(cell_array.parseString("<1 2 label: 3>")[0], [1, 2, 3])

def test_prop_value_comma_separated(self):
from pydevicetree.ast.classes import PropertyValues, CellArray, StringList
from pydevicetree.ast import PropertyValues, CellArray, StringList
# this test taken straight from the Devicetree v0.2 specification page 52
teststring = "example = <0xf00f0000 19>, \"a strange property format\";"

Expand All @@ -47,7 +47,7 @@ def test_prop_value_comma_separated(self):
self.assertEqual(prop.values[1][0], "a strange property format")

def test_node_definition(self):
from pydevicetree.ast.classes import Node
from pydevicetree.ast import Node
node = node_definition.parseString("label: my-node@DEADBEEF { my-property; compatible = \"my-node\"; };")[0]

self.assertEqual(type(node), Node)
Expand All @@ -59,7 +59,7 @@ def test_node_definition(self):
self.assertEqual(node.children, [])

def test_directive(self):
from pydevicetree.ast.classes import Directive
from pydevicetree.ast import Directive
dtsv1 = directive.parseString("/dts-v1/;")[0]

self.assertEqual(type(dtsv1), Directive)
Expand Down

0 comments on commit e10cf0b

Please sign in to comment.