From 74f95688d9741324a8889f6dbcb4b1e4b2eaf4ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Bol=C3=ADvar?= Date: Tue, 13 Apr 2021 13:26:08 -0700 Subject: [PATCH] dtlib: add Type enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 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 --- .../python-devicetree/src/devicetree/dtlib.py | 112 +++++++++--------- .../src/devicetree/edtlib.py | 32 +++-- .../dts/python-devicetree/tests/test_dtlib.py | 48 ++++---- 3 files changed, 96 insertions(+), 96 deletions(-) diff --git a/scripts/dts/python-devicetree/src/devicetree/dtlib.py b/scripts/dts/python-devicetree/src/devicetree/dtlib.py index 37f7ade8be5..67c5c9866be 100644 --- a/scripts/dts/python-devicetree/src/devicetree/dtlib.py +++ b/scripts/dts/python-devicetree/src/devicetree/dtlib.py @@ -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): diff --git a/scripts/dts/python-devicetree/src/devicetree/edtlib.py b/scripts/dts/python-devicetree/src/devicetree/edtlib.py index fe70c99dcd1..a9785d3a2e0 100644 --- a/scripts/dts/python-devicetree/src/devicetree/edtlib.py +++ b/scripts/dts/python-devicetree/src/devicetree/edtlib.py @@ -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)) diff --git a/scripts/dts/python-devicetree/tests/test_dtlib.py b/scripts/dts/python-devicetree/tests/test_dtlib.py index ef8d2b2e741..16595550a09 100644 --- a/scripts/dts/python-devicetree/tests/test_dtlib.py +++ b/scripts/dts/python-devicetree/tests/test_dtlib.py @@ -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}()'''