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>
This commit is contained in:
parent
9a85a89313
commit
74f95688d9
3 changed files with 96 additions and 96 deletions
|
@ -17,6 +17,7 @@ files.
|
|||
"""
|
||||
|
||||
import collections
|
||||
import enum
|
||||
import errno
|
||||
import os
|
||||
import re
|
||||
|
@ -1336,23 +1337,23 @@ class Property:
|
|||
|
||||
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 @@ class Property:
|
|||
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 @@ class Property:
|
|||
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 @@ class Property:
|
|||
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 @@ class Property:
|
|||
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 @@ class Property:
|
|||
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 @@ class Property:
|
|||
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 @@ class Property:
|
|||
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 @@ class Property:
|
|||
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 @@ class Property:
|
|||
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 @@ class Property:
|
|||
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 @@ class Property:
|
|||
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 @@ def to_nums(data, length=4, signed=False):
|
|||
#
|
||||
|
||||
# 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):
|
||||
|
|
|
@ -81,10 +81,7 @@ try:
|
|||
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 @@ class Node:
|
|||
}
|
||||
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 @@ class Node:
|
|||
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 @@ class Node:
|
|||
# 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 @@ def _check_dt(dt):
|
|||
|
||||
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))
|
||||
|
|
|
@ -1538,30 +1538,30 @@ def test_prop_type():
|
|||
};
|
||||
""")
|
||||
|
||||
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}()'''
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue