dtlib: add Type enum
Instead of hard-coding constants, use an IntEnum.
These is still a subclass of 'int', but is both easier to import and
easier to read during debugging.
For example, compare:
>>> Type.BYTES
<Type.BYTES: 1>
with:
>>> TYPE_BYTES
1
However, 'Type.BYTES == 1' is still True, and the enum values
otherwise behave like you would expect.
Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
diff --git a/scripts/dts/python-devicetree/src/devicetree/dtlib.py b/scripts/dts/python-devicetree/src/devicetree/dtlib.py
index 37f7ade..67c5c98 100644
--- a/scripts/dts/python-devicetree/src/devicetree/dtlib.py
+++ b/scripts/dts/python-devicetree/src/devicetree/dtlib.py
@@ -17,6 +17,7 @@
"""
import collections
+import enum
import errno
import os
import re
@@ -1336,23 +1337,23 @@
Assignment | Property.type
----------------------------+------------------------
- foo; | dtlib.TYPE_EMPTY
- foo = []; | dtlib.TYPE_BYTES
- foo = [01 02]; | dtlib.TYPE_BYTES
- foo = /bits/ 8 <1>; | dtlib.TYPE_BYTES
- foo = <1>; | dtlib.TYPE_NUM
- foo = <>; | dtlib.TYPE_NUMS
- foo = <1 2 3>; | dtlib.TYPE_NUMS
- foo = <1 2>, <3>; | dtlib.TYPE_NUMS
- foo = "foo"; | dtlib.TYPE_STRING
- foo = "foo", "bar"; | dtlib.TYPE_STRINGS
- foo = <&l>; | dtlib.TYPE_PHANDLE
- foo = <&l1 &l2 &l3>; | dtlib.TYPE_PHANDLES
- foo = <&l1 &l2>, <&l3>; | dtlib.TYPE_PHANDLES
- foo = <&l1 1 2 &l2 3 4>; | dtlib.TYPE_PHANDLES_AND_NUMS
- foo = <&l1 1 2>, <&l2 3 4>; | dtlib.TYPE_PHANDLES_AND_NUMS
- foo = &l; | dtlib.TYPE_PATH
- *Anything else* | dtlib.TYPE_COMPOUND
+ foo; | dtlib.Type.EMPTY
+ foo = []; | dtlib.Type.BYTES
+ foo = [01 02]; | dtlib.Type.BYTES
+ foo = /bits/ 8 <1>; | dtlib.Type.BYTES
+ foo = <1>; | dtlib.Type.NUM
+ foo = <>; | dtlib.Type.NUMS
+ foo = <1 2 3>; | dtlib.Type.NUMS
+ foo = <1 2>, <3>; | dtlib.Type.NUMS
+ foo = "foo"; | dtlib.Type.STRING
+ foo = "foo", "bar"; | dtlib.Type.STRINGS
+ foo = <&l>; | dtlib.Type.PHANDLE
+ foo = <&l1 &l2 &l3>; | dtlib.Type.PHANDLES
+ foo = <&l1 &l2>, <&l3>; | dtlib.Type.PHANDLES
+ foo = <&l1 1 2 &l2 3 4>; | dtlib.Type.PHANDLES_AND_NUMS
+ foo = <&l1 1 2>, <&l2 3 4>; | dtlib.Type.PHANDLES_AND_NUMS
+ foo = &l; | dtlib.Type.PATH
+ *Anything else* | dtlib.Type.COMPOUND
*Anything else* includes properties mixing phandle (<&label>) and node
path (&label) references with other data.
@@ -1404,7 +1405,7 @@
Returns the value of the property as a number.
Raises DTError if the property was not assigned with this syntax (has
- Property.type TYPE_NUM):
+ Property.type Type.NUM):
foo = < 1 >;
@@ -1412,7 +1413,7 @@
If True, the value will be interpreted as signed rather than
unsigned.
"""
- if self.type is not TYPE_NUM:
+ if self.type is not Type.NUM:
_err("expected property '{0}' on {1} in {2} to be assigned with "
"'{0} = < (number) >;', not '{3}'"
.format(self.name, self.node.path, self.node.dt.filename,
@@ -1425,7 +1426,7 @@
Returns the value of the property as a list of numbers.
Raises DTError if the property was not assigned with this syntax (has
- Property.type TYPE_NUM or TYPE_NUMS):
+ Property.type Type.NUM or Type.NUMS):
foo = < 1 2 ... >;
@@ -1433,7 +1434,7 @@
If True, the values will be interpreted as signed rather than
unsigned.
"""
- if self.type not in (TYPE_NUM, TYPE_NUMS):
+ if self.type not in (Type.NUM, Type.NUMS):
_err("expected property '{0}' on {1} in {2} to be assigned with "
"'{0} = < (number) (number) ... >;', not '{3}'"
.format(self.name, self.node.path, self.node.dt.filename,
@@ -1448,11 +1449,11 @@
Property.value, except with added type checking.
Raises DTError if the property was not assigned with this syntax (has
- Property.type TYPE_BYTES):
+ Property.type Type.BYTES):
foo = [ 01 ... ];
"""
- if self.type is not TYPE_BYTES:
+ if self.type is not Type.BYTES:
_err("expected property '{0}' on {1} in {2} to be assigned with "
"'{0} = [ (byte) (byte) ... ];', not '{3}'"
.format(self.name, self.node.path, self.node.dt.filename,
@@ -1465,14 +1466,14 @@
Returns the value of the property as a string.
Raises DTError if the property was not assigned with this syntax (has
- Property.type TYPE_STRING):
+ Property.type Type.STRING):
foo = "string";
This function might also raise UnicodeDecodeError if the string is
not valid UTF-8.
"""
- if self.type is not TYPE_STRING:
+ if self.type is not Type.STRING:
_err("expected property '{0}' on {1} in {2} to be assigned with "
"'{0} = \"string\";', not '{3}'"
.format(self.name, self.node.path, self.node.dt.filename,
@@ -1490,13 +1491,13 @@
Returns the value of the property as a list of strings.
Raises DTError if the property was not assigned with this syntax (has
- Property.type TYPE_STRING or TYPE_STRINGS):
+ Property.type Type.STRING or Type.STRINGS):
foo = "string", "string", ... ;
Also raises DTError if any of the strings are not valid UTF-8.
"""
- if self.type not in (TYPE_STRING, TYPE_STRINGS):
+ if self.type not in (Type.STRING, Type.STRINGS):
_err("expected property '{0}' on {1} in {2} to be assigned with "
"'{0} = \"string\", \"string\", ... ;', not '{3}'"
.format(self.name, self.node.path, self.node.dt.filename,
@@ -1514,11 +1515,11 @@
Returns the Node the phandle in the property points to.
Raises DTError if the property was not assigned with this syntax (has
- Property.type TYPE_PHANDLE).
+ Property.type Type.PHANDLE).
foo = < &bar >;
"""
- if self.type is not TYPE_PHANDLE:
+ if self.type is not Type.PHANDLE:
_err("expected property '{0}' on {1} in {2} to be assigned with "
"'{0} = < &foo >;', not '{3}'"
.format(self.name, self.node.path, self.node.dt.filename,
@@ -1539,10 +1540,10 @@
foo = < &bar ... >, < &baz ... >;
"""
def type_ok():
- if self.type in (TYPE_PHANDLE, TYPE_PHANDLES):
+ if self.type in (Type.PHANDLE, Type.PHANDLES):
return True
# Also accept 'foo = < >;'
- return self.type is TYPE_NUMS and not self.value
+ return self.type is Type.NUMS and not self.value
if not type_ok():
_err("expected property '{0}' on {1} in {2} to be assigned with "
@@ -1559,14 +1560,14 @@
Returns the Node referenced by the path stored in the property.
Raises DTError if the property was not assigned with either of these
- syntaxes (has Property.type TYPE_PATH or TYPE_STRING):
+ syntaxes (has Property.type Type.PATH or Type.STRING):
foo = &bar;
foo = "/bar";
For the second case, DTError is raised if the path does not exist.
"""
- if self.type not in (TYPE_PATH, TYPE_STRING):
+ if self.type not in (Type.PATH, Type.STRING):
_err("expected property '{0}' on {1} in {2} to be assigned with "
"either '{0} = &foo' or '{0} = \"/path/to/node\"', not '{3}'"
.format(self.name, self.node.path, self.node.dt.filename,
@@ -1597,35 +1598,35 @@
if marker[1] != _REF_LABEL]
if not types:
- return TYPE_EMPTY
+ return Type.EMPTY
if types == [_TYPE_UINT8]:
- return TYPE_BYTES
+ return Type.BYTES
if types == [_TYPE_UINT32]:
- return TYPE_NUM if len(self.value) == 4 else TYPE_NUMS
+ return Type.NUM if len(self.value) == 4 else Type.NUMS
- # Treat 'foo = <1 2 3>, <4 5>, ...' as TYPE_NUMS too
+ # Treat 'foo = <1 2 3>, <4 5>, ...' as Type.NUMS too
if set(types) == {_TYPE_UINT32}:
- return TYPE_NUMS
+ return Type.NUMS
if set(types) == {_TYPE_STRING}:
- return TYPE_STRING if len(types) == 1 else TYPE_STRINGS
+ return Type.STRING if len(types) == 1 else Type.STRINGS
if types == [_REF_PATH]:
- return TYPE_PATH
+ return Type.PATH
if types == [_TYPE_UINT32, _REF_PHANDLE] and len(self.value) == 4:
- return TYPE_PHANDLE
+ return Type.PHANDLE
if set(types) == {_TYPE_UINT32, _REF_PHANDLE}:
if len(self.value) == 4*types.count(_REF_PHANDLE):
# Array with just phandles in it
- return TYPE_PHANDLES
+ return Type.PHANDLES
# Array with both phandles and numbers
- return TYPE_PHANDLES_AND_NUMS
+ return Type.PHANDLES_AND_NUMS
- return TYPE_COMPOUND
+ return Type.COMPOUND
def __str__(self):
s = "".join(label + ": " for label in self.labels) + self.name
@@ -1761,17 +1762,18 @@
#
# See Property.type
-TYPE_EMPTY = 0
-TYPE_BYTES = 1
-TYPE_NUM = 2
-TYPE_NUMS = 3
-TYPE_STRING = 4
-TYPE_STRINGS = 5
-TYPE_PATH = 6
-TYPE_PHANDLE = 7
-TYPE_PHANDLES = 8
-TYPE_PHANDLES_AND_NUMS = 9
-TYPE_COMPOUND = 10
+class Type(enum.IntEnum):
+ EMPTY = 0
+ BYTES = 1
+ NUM = 2
+ NUMS = 3
+ STRING = 4
+ STRINGS = 5
+ PATH = 6
+ PHANDLE = 7
+ PHANDLES = 8
+ PHANDLES_AND_NUMS = 9
+ COMPOUND = 10
def _check_is_bytes(data):
diff --git a/scripts/dts/python-devicetree/src/devicetree/edtlib.py b/scripts/dts/python-devicetree/src/devicetree/edtlib.py
index fe70c99..a9785d3 100644
--- a/scripts/dts/python-devicetree/src/devicetree/edtlib.py
+++ b/scripts/dts/python-devicetree/src/devicetree/edtlib.py
@@ -81,10 +81,7 @@
except ImportError:
from yaml import Loader
-from devicetree.dtlib import \
- DT, DTError, to_num, to_nums, TYPE_EMPTY, TYPE_BYTES, \
- TYPE_NUM, TYPE_NUMS, TYPE_STRING, TYPE_STRINGS, \
- TYPE_PHANDLE, TYPE_PHANDLES, TYPE_PHANDLES_AND_NUMS
+from devicetree.dtlib import DT, DTError, to_num, to_nums, Type
from devicetree.grutils import Graph
@@ -823,26 +820,27 @@
}
for name, prop in self._node.props.items():
pp = OrderedDict()
- if prop.type == TYPE_EMPTY:
+ if prop.type == Type.EMPTY:
pp["type"] = "boolean"
- elif prop.type == TYPE_BYTES:
+ elif prop.type == Type.BYTES:
pp["type"] = "uint8-array"
- elif prop.type == TYPE_NUM:
+ elif prop.type == Type.NUM:
pp["type"] = "int"
- elif prop.type == TYPE_NUMS:
+ elif prop.type == Type.NUMS:
pp["type"] = "array"
- elif prop.type == TYPE_STRING:
+ elif prop.type == Type.STRING:
pp["type"] = "string"
- elif prop.type == TYPE_STRINGS:
+ elif prop.type == Type.STRINGS:
pp["type"] = "string-array"
- elif prop.type == TYPE_PHANDLE:
+ elif prop.type == Type.PHANDLE:
pp["type"] = "phandle"
- elif prop.type == TYPE_PHANDLES:
+ elif prop.type == Type.PHANDLES:
pp["type"] = "phandles"
- elif prop.type == TYPE_PHANDLES_AND_NUMS:
+ elif prop.type == Type.PHANDLES_AND_NUMS:
pp["type"] = "phandle-array"
else:
- _err(f"cannot infer binding from property: {prop}")
+ _err(f"cannot infer binding from property: {prop} "
+ f"with type {prop.type}")
raw['properties'][name] = pp
# Set up Node state.
@@ -1007,7 +1005,7 @@
return False if prop_type == "boolean" else None
if prop_type == "boolean":
- if prop.type is not TYPE_EMPTY:
+ if prop.type is not Type.EMPTY:
_err("'{0}' in {1!r} is defined with 'type: boolean' in {2}, "
"but is assigned a value ('{3}') instead of being empty "
"('{0};')".format(name, node, self.binding_path, prop))
@@ -1038,7 +1036,7 @@
# This type is a bit high-level for dtlib as it involves
# information from bindings and *-names properties, so there's no
# to_phandle_array() in dtlib. Do the type check ourselves.
- if prop.type not in (TYPE_PHANDLE, TYPE_PHANDLES, TYPE_PHANDLES_AND_NUMS):
+ if prop.type not in (Type.PHANDLE, Type.PHANDLES, Type.PHANDLES_AND_NUMS):
_err(f"expected property '{name}' in {node.path} in "
f"{node.dt.filename} to be assigned "
f"with '{name} = < &foo ... &bar 1 ... &baz 2 3 >' "
@@ -2655,7 +2653,7 @@
ranges_prop = node.props.get("ranges")
if ranges_prop:
- if ranges_prop.type not in (TYPE_EMPTY, TYPE_NUMS):
+ if ranges_prop.type not in (Type.EMPTY, Type.NUMS):
_err("expected 'ranges = < ... >;' in {} in {}, not '{}' "
"(see the devicetree specification)"
.format(node.path, node.dt.filename, ranges_prop))
diff --git a/scripts/dts/python-devicetree/tests/test_dtlib.py b/scripts/dts/python-devicetree/tests/test_dtlib.py
index ef8d2b2..1659555 100644
--- a/scripts/dts/python-devicetree/tests/test_dtlib.py
+++ b/scripts/dts/python-devicetree/tests/test_dtlib.py
@@ -1538,30 +1538,30 @@
};
""")
- verify_type("empty", dtlib.TYPE_EMPTY)
- verify_type("bytes1", dtlib.TYPE_BYTES)
- verify_type("bytes2", dtlib.TYPE_BYTES)
- verify_type("bytes3", dtlib.TYPE_BYTES)
- verify_type("bytes4", dtlib.TYPE_BYTES)
- verify_type("bytes5", dtlib.TYPE_BYTES)
- verify_type("num", dtlib.TYPE_NUM)
- verify_type("nums1", dtlib.TYPE_NUMS)
- verify_type("nums2", dtlib.TYPE_NUMS)
- verify_type("nums3", dtlib.TYPE_NUMS)
- verify_type("nums4", dtlib.TYPE_NUMS)
- verify_type("string", dtlib.TYPE_STRING)
- verify_type("strings", dtlib.TYPE_STRINGS)
- verify_type("phandle1", dtlib.TYPE_PHANDLE)
- verify_type("phandle2", dtlib.TYPE_PHANDLE)
- verify_type("phandles1", dtlib.TYPE_PHANDLES)
- verify_type("phandles2", dtlib.TYPE_PHANDLES)
- verify_type("phandle-and-nums-1", dtlib.TYPE_PHANDLES_AND_NUMS)
- verify_type("phandle-and-nums-2", dtlib.TYPE_PHANDLES_AND_NUMS)
- verify_type("phandle-and-nums-3", dtlib.TYPE_PHANDLES_AND_NUMS)
- verify_type("path1", dtlib.TYPE_PATH)
- verify_type("path2", dtlib.TYPE_PATH)
- verify_type("compound1", dtlib.TYPE_COMPOUND)
- verify_type("compound2", dtlib.TYPE_COMPOUND)
+ verify_type("empty", dtlib.Type.EMPTY)
+ verify_type("bytes1", dtlib.Type.BYTES)
+ verify_type("bytes2", dtlib.Type.BYTES)
+ verify_type("bytes3", dtlib.Type.BYTES)
+ verify_type("bytes4", dtlib.Type.BYTES)
+ verify_type("bytes5", dtlib.Type.BYTES)
+ verify_type("num", dtlib.Type.NUM)
+ verify_type("nums1", dtlib.Type.NUMS)
+ verify_type("nums2", dtlib.Type.NUMS)
+ verify_type("nums3", dtlib.Type.NUMS)
+ verify_type("nums4", dtlib.Type.NUMS)
+ verify_type("string", dtlib.Type.STRING)
+ verify_type("strings", dtlib.Type.STRINGS)
+ verify_type("phandle1", dtlib.Type.PHANDLE)
+ verify_type("phandle2", dtlib.Type.PHANDLE)
+ verify_type("phandles1", dtlib.Type.PHANDLES)
+ verify_type("phandles2", dtlib.Type.PHANDLES)
+ verify_type("phandle-and-nums-1", dtlib.Type.PHANDLES_AND_NUMS)
+ verify_type("phandle-and-nums-2", dtlib.Type.PHANDLES_AND_NUMS)
+ verify_type("phandle-and-nums-3", dtlib.Type.PHANDLES_AND_NUMS)
+ verify_type("path1", dtlib.Type.PATH)
+ verify_type("path2", dtlib.Type.PATH)
+ verify_type("compound1", dtlib.Type.COMPOUND)
+ verify_type("compound2", dtlib.Type.COMPOUND)
def test_prop_type_casting():
'''Test Property.to_{num,nums,string,strings,node}()'''