dtlib: use f-strings where it makes sense
The library was originally developed before Python 3.6 was the minimum supported version. Use f-strings now that we can do that, as they tend to be easier to read. There are a few places where str.format() makes sense to preserve, specifically where the same argument is used multiple times; leave those alone. Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
This commit is contained in:
parent
a61517b58e
commit
66ee3d291c
1 changed files with 66 additions and 74 deletions
|
@ -159,7 +159,7 @@ class Node:
|
||||||
"""
|
"""
|
||||||
s = "".join(label + ": " for label in self.labels)
|
s = "".join(label + ": " for label in self.labels)
|
||||||
|
|
||||||
s += "{} {{\n".format(self.name)
|
s += f"{self.name} {{\n"
|
||||||
|
|
||||||
for prop in self.props.values():
|
for prop in self.props.values():
|
||||||
s += "\t" + str(prop) + "\n"
|
s += "\t" + str(prop) + "\n"
|
||||||
|
@ -176,8 +176,7 @@ class Node:
|
||||||
Returns some information about the Node instance. Called automatically
|
Returns some information about the Node instance. Called automatically
|
||||||
if the Node instance is evaluated.
|
if the Node instance is evaluated.
|
||||||
"""
|
"""
|
||||||
return "<Node {} in '{}'>" \
|
return f"<Node {self.path} in '{self.dt.filename}'>"
|
||||||
.format(self.path, self.dt.filename)
|
|
||||||
|
|
||||||
# See Property.type
|
# See Property.type
|
||||||
class Type(enum.IntEnum):
|
class Type(enum.IntEnum):
|
||||||
|
@ -381,9 +380,9 @@ class Property:
|
||||||
try:
|
try:
|
||||||
ret = self.value.decode("utf-8")[:-1] # Strip null
|
ret = self.value.decode("utf-8")[:-1] # Strip null
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
_err("value of property '{}' ({!r}) on {} in {} is not valid UTF-8"
|
_err(f"value of property '{self.name}' ({self.value!r}) "
|
||||||
.format(self.name, self.value, self.node.path,
|
f"on {self.node.path} in {self.node.dt.filename} "
|
||||||
self.node.dt.filename))
|
"is not valid UTF-8")
|
||||||
|
|
||||||
return ret # The separate 'return' appeases the type checker.
|
return ret # The separate 'return' appeases the type checker.
|
||||||
|
|
||||||
|
@ -407,9 +406,9 @@ class Property:
|
||||||
try:
|
try:
|
||||||
ret = self.value.decode("utf-8").split("\0")[:-1]
|
ret = self.value.decode("utf-8").split("\0")[:-1]
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
_err("value of property '{}' ({!r}) on {} in {} is not valid UTF-8"
|
_err(f"value of property '{self.name}' ({self.value!r}) "
|
||||||
.format(self.name, self.value, self.node.path,
|
f"on {self.node.path} in {self.node.dt.filename} "
|
||||||
self.node.dt.filename))
|
"is not valid UTF-8")
|
||||||
|
|
||||||
return ret # The separate 'return' appeases the type checker.
|
return ret # The separate 'return' appeases the type checker.
|
||||||
|
|
||||||
|
@ -479,16 +478,16 @@ class Property:
|
||||||
try:
|
try:
|
||||||
path = self.value.decode("utf-8")[:-1]
|
path = self.value.decode("utf-8")[:-1]
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
_err("value of property '{}' ({!r}) on {} in {} is not valid UTF-8"
|
_err(f"value of property '{self.name}' ({self.value!r}) "
|
||||||
.format(self.name, self.value, self.node.path,
|
f"on {self.node.path} in {self.node.dt.filename} "
|
||||||
self.node.dt.filename))
|
"is not valid UTF-8")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ret = self.node.dt.get_node(path)
|
ret = self.node.dt.get_node(path)
|
||||||
except DTError:
|
except DTError:
|
||||||
_err("property '{}' on {} in {} points to the non-existent node "
|
_err(f"property '{self.name}' on {self.node.path} in "
|
||||||
"\"{}\"".format(self.name, self.node.path,
|
f"{self.node.dt.filename} points to the non-existent node "
|
||||||
self.node.dt.filename, path))
|
f'"{path}"')
|
||||||
|
|
||||||
return ret # The separate 'return' appeases the type checker.
|
return ret # The separate 'return' appeases the type checker.
|
||||||
|
|
||||||
|
@ -552,8 +551,7 @@ class Property:
|
||||||
|
|
||||||
if marker_type is _MarkerType.STRING:
|
if marker_type is _MarkerType.STRING:
|
||||||
# end - 1 to strip off the null terminator
|
# end - 1 to strip off the null terminator
|
||||||
s += ' "{}"'.format(_decode_and_escape(
|
s += f' "{_decode_and_escape(self.value[pos:end - 1])}"'
|
||||||
self.value[pos:end - 1]))
|
|
||||||
if end != len(self.value):
|
if end != len(self.value):
|
||||||
s += ","
|
s += ","
|
||||||
elif marker_type is _MarkerType.PATH:
|
elif marker_type is _MarkerType.PATH:
|
||||||
|
@ -564,7 +562,7 @@ class Property:
|
||||||
# <> or []
|
# <> or []
|
||||||
|
|
||||||
if marker_type is _MarkerType.LABEL:
|
if marker_type is _MarkerType.LABEL:
|
||||||
s += " {}:".format(ref)
|
s += f" {ref}:"
|
||||||
elif marker_type is _MarkerType.PHANDLE:
|
elif marker_type is _MarkerType.PHANDLE:
|
||||||
s += " &" + ref
|
s += " &" + ref
|
||||||
pos += 4
|
pos += 4
|
||||||
|
@ -578,9 +576,9 @@ class Property:
|
||||||
num = int.from_bytes(self.value[pos:pos + elm_size],
|
num = int.from_bytes(self.value[pos:pos + elm_size],
|
||||||
"big")
|
"big")
|
||||||
if elm_size == 1:
|
if elm_size == 1:
|
||||||
s += " {:02X}".format(num)
|
s += f" {num:02X}"
|
||||||
else:
|
else:
|
||||||
s += " " + hex(num)
|
s += f" {hex(num)}"
|
||||||
|
|
||||||
pos += elm_size
|
pos += elm_size
|
||||||
|
|
||||||
|
@ -596,8 +594,8 @@ class Property:
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<Property '{}' at '{}' in '{}'>" \
|
return f"<Property '{self.name}' at '{self.node.path}' in " \
|
||||||
.format(self.name, self.node.path, self.node.dt.filename)
|
f"'{self.node.dt.filename}'>"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Internal functions
|
# Internal functions
|
||||||
|
@ -796,8 +794,8 @@ class DT:
|
||||||
# Path does not start with '/'. First component must be an alias.
|
# Path does not start with '/'. First component must be an alias.
|
||||||
alias, _, rest = path.partition("/")
|
alias, _, rest = path.partition("/")
|
||||||
if alias not in self.alias2node:
|
if alias not in self.alias2node:
|
||||||
_err("no alias '{}' found -- did you forget the leading '/' in "
|
_err(f"no alias '{alias}' found -- did you forget the leading "
|
||||||
"the node path?".format(alias))
|
"'/' in the node path?")
|
||||||
|
|
||||||
return _root_and_path_to_node(self.alias2node[alias], rest, path)
|
return _root_and_path_to_node(self.alias2node[alias], rest, path)
|
||||||
|
|
||||||
|
@ -835,9 +833,8 @@ class DT:
|
||||||
for labels, address, offset in self.memreserves:
|
for labels, address, offset in self.memreserves:
|
||||||
# List the labels in a consistent order to help with testing
|
# List the labels in a consistent order to help with testing
|
||||||
for label in labels:
|
for label in labels:
|
||||||
s += label + ": "
|
s += f"{label}: "
|
||||||
s += "/memreserve/ {:#018x} {:#018x};\n" \
|
s += f"/memreserve/ {address:#018x} {offset:#018x};\n"
|
||||||
.format(address, offset)
|
|
||||||
s += "\n"
|
s += "\n"
|
||||||
|
|
||||||
return s + str(self.root)
|
return s + str(self.root)
|
||||||
|
@ -847,8 +844,8 @@ class DT:
|
||||||
Returns some information about the DT instance. Called automatically if
|
Returns some information about the DT instance. Called automatically if
|
||||||
the DT instance is evaluated.
|
the DT instance is evaluated.
|
||||||
"""
|
"""
|
||||||
return "DT(filename='{}', include_path={})" \
|
return f"DT(filename='{self.filename}', " \
|
||||||
.format(self.filename, self._include_path)
|
f"include_path={self._include_path})"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Parsing
|
# Parsing
|
||||||
|
@ -1119,8 +1116,8 @@ class DT:
|
||||||
# Try again as a signed number, in case it's negative
|
# Try again as a signed number, in case it's negative
|
||||||
prop.value += num.to_bytes(n_bytes, "big", signed=True)
|
prop.value += num.to_bytes(n_bytes, "big", signed=True)
|
||||||
except OverflowError:
|
except OverflowError:
|
||||||
self._parse_error("{} does not fit in {} bits"
|
self._parse_error(
|
||||||
.format(num, 8*n_bytes))
|
f"{num} does not fit in {8*n_bytes} bits")
|
||||||
|
|
||||||
def _parse_bytes(self, prop):
|
def _parse_bytes(self, prop):
|
||||||
# Parses '[ ... ]'
|
# Parses '[ ... ]'
|
||||||
|
@ -1178,8 +1175,7 @@ class DT:
|
||||||
f.seek(offset)
|
f.seek(offset)
|
||||||
prop.value += f.read(size)
|
prop.value += f.read(size)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
self._parse_error("could not read '{}': {}"
|
self._parse_error(f"could not read '{filename}': {e}")
|
||||||
.format(filename, e))
|
|
||||||
|
|
||||||
def _parse_value_labels(self, prop):
|
def _parse_value_labels(self, prop):
|
||||||
# _parse_assignment() helper for parsing labels before/after each
|
# _parse_assignment() helper for parsing labels before/after each
|
||||||
|
@ -1465,8 +1461,7 @@ class DT:
|
||||||
|
|
||||||
tok = self._next_token()
|
tok = self._next_token()
|
||||||
if tok.val != tok_val:
|
if tok.val != tok_val:
|
||||||
self._parse_error("expected '{}', not '{}'"
|
self._parse_error(f"expected '{tok_val}', not '{tok.val}'")
|
||||||
.format(tok_val, tok.val))
|
|
||||||
|
|
||||||
return tok
|
return tok
|
||||||
|
|
||||||
|
@ -1479,12 +1474,12 @@ class DT:
|
||||||
return tok.val
|
return tok.val
|
||||||
|
|
||||||
def _parse_error(self, s):
|
def _parse_error(self, s):
|
||||||
_err("{}:{} (column {}): parse error: {}".format(
|
# This works out for the first line of the file too, where rfind()
|
||||||
self.filename, self._lineno,
|
# returns -1
|
||||||
# This works out for the first line of the file too, where rfind()
|
column = self._tok_i - self._file_contents.rfind("\n", 0,
|
||||||
# returns -1
|
self._tok_i + 1)
|
||||||
self._tok_i - self._file_contents.rfind("\n", 0, self._tok_i + 1),
|
_err(f"{self.filename}:{self._lineno} (column {column}): "
|
||||||
s))
|
f"parse error: {s}")
|
||||||
|
|
||||||
def _enter_file(self, filename):
|
def _enter_file(self, filename):
|
||||||
# Enters the /include/d file 'filename', remembering the position in
|
# Enters the /include/d file 'filename', remembering the position in
|
||||||
|
@ -1511,8 +1506,8 @@ class DT:
|
||||||
for i, parent in enumerate(self._filestack):
|
for i, parent in enumerate(self._filestack):
|
||||||
if filename == parent[0]:
|
if filename == parent[0]:
|
||||||
self._parse_error("recursive /include/:\n" + " ->\n".join(
|
self._parse_error("recursive /include/:\n" + " ->\n".join(
|
||||||
["{}:{}".format(parent[0], parent[1])
|
[f"{parent[0]}:{parent[1]}"
|
||||||
for parent in self._filestack[i:]] +
|
for parent in self._filestack[i:]] +
|
||||||
[filename]))
|
[filename]))
|
||||||
|
|
||||||
self.filename = f.name
|
self.filename = f.name
|
||||||
|
@ -1546,7 +1541,7 @@ class DT:
|
||||||
# Path reference (&{/foo/bar})
|
# Path reference (&{/foo/bar})
|
||||||
path = s[1:-1]
|
path = s[1:-1]
|
||||||
if not path.startswith("/"):
|
if not path.startswith("/"):
|
||||||
_err("node path '{}' does not start with '/'".format(path))
|
_err(f"node path '{path}' does not start with '/'")
|
||||||
# Will raise DTError if the path doesn't exist
|
# Will raise DTError if the path doesn't exist
|
||||||
return _root_and_path_to_node(self.root, path, path)
|
return _root_and_path_to_node(self.root, path, path)
|
||||||
|
|
||||||
|
@ -1558,7 +1553,7 @@ class DT:
|
||||||
if s in node.labels:
|
if s in node.labels:
|
||||||
return node
|
return node
|
||||||
|
|
||||||
_err("undefined node label '{}'".format(s))
|
_err(f"undefined node label '{s}'")
|
||||||
|
|
||||||
#
|
#
|
||||||
# Post-processing
|
# Post-processing
|
||||||
|
@ -1575,8 +1570,8 @@ class DT:
|
||||||
phandle = node.props.get("phandle")
|
phandle = node.props.get("phandle")
|
||||||
if phandle:
|
if phandle:
|
||||||
if len(phandle.value) != 4:
|
if len(phandle.value) != 4:
|
||||||
_err("{}: bad phandle length ({}), expected 4 bytes"
|
_err(f"{node.path}: bad phandle length "
|
||||||
.format(node.path, len(phandle.value)))
|
f"({len(phandle.value)}), expected 4 bytes")
|
||||||
|
|
||||||
is_self_referential = False
|
is_self_referential = False
|
||||||
for marker in phandle._markers:
|
for marker in phandle._markers:
|
||||||
|
@ -1591,8 +1586,8 @@ class DT:
|
||||||
is_self_referential = True
|
is_self_referential = True
|
||||||
break
|
break
|
||||||
|
|
||||||
_err("{}: {} refers to another node"
|
_err(f"{node.path}: {phandle.name} "
|
||||||
.format(node.path, phandle.name))
|
"refers to another node")
|
||||||
|
|
||||||
# Could put on else on the 'for' above too, but keep it
|
# Could put on else on the 'for' above too, but keep it
|
||||||
# somewhat readable
|
# somewhat readable
|
||||||
|
@ -1600,13 +1595,13 @@ class DT:
|
||||||
phandle_val = int.from_bytes(phandle.value, "big")
|
phandle_val = int.from_bytes(phandle.value, "big")
|
||||||
|
|
||||||
if phandle_val in {0, 0xFFFFFFFF}:
|
if phandle_val in {0, 0xFFFFFFFF}:
|
||||||
_err("{}: bad value {:#010x} for {}"
|
_err(f"{node.path}: bad value {phandle_val:#010x} "
|
||||||
.format(node.path, phandle_val, phandle.name))
|
f"for {phandle.name}")
|
||||||
|
|
||||||
if phandle_val in self.phandle2node:
|
if phandle_val in self.phandle2node:
|
||||||
_err("{}: duplicated phandle {:#x} (seen before at {})"
|
_err(f"{node.path}: duplicated phandle {phandle_val:#x} "
|
||||||
.format(node.path, phandle_val,
|
"(seen before at "
|
||||||
self.phandle2node[phandle_val].path))
|
f"{self.phandle2node[phandle_val].path})")
|
||||||
|
|
||||||
self.phandle2node[phandle_val] = node
|
self.phandle2node[phandle_val] = node
|
||||||
|
|
||||||
|
@ -1649,7 +1644,7 @@ class DT:
|
||||||
try:
|
try:
|
||||||
ref_node = self._ref2node(ref)
|
ref_node = self._ref2node(ref)
|
||||||
except DTError as e:
|
except DTError as e:
|
||||||
_err("{}: {}".format(prop.node.path, e))
|
_err(f"{prop.node.path}: {e}")
|
||||||
|
|
||||||
# For /omit-if-no-ref/
|
# For /omit-if-no-ref/
|
||||||
ref_node._is_referenced = True
|
ref_node._is_referenced = True
|
||||||
|
@ -1681,8 +1676,8 @@ class DT:
|
||||||
if aliases:
|
if aliases:
|
||||||
for prop in aliases.props.values():
|
for prop in aliases.props.values():
|
||||||
if not alias_re.match(prop.name):
|
if not alias_re.match(prop.name):
|
||||||
_err("/aliases: alias property name '{}' should include "
|
_err(f"/aliases: alias property name '{prop.name}' "
|
||||||
"only characters from [0-9a-z-]".format(prop.name))
|
"should include only characters from [0-9a-z-]")
|
||||||
|
|
||||||
# Property.to_path() checks that the node exists, has
|
# Property.to_path() checks that the node exists, has
|
||||||
# the right type, etc. Swallow errors for invalid
|
# the right type, etc. Swallow errors for invalid
|
||||||
|
@ -1739,21 +1734,20 @@ class DT:
|
||||||
strings = []
|
strings = []
|
||||||
for thing in things:
|
for thing in things:
|
||||||
if isinstance(thing, Node):
|
if isinstance(thing, Node):
|
||||||
strings.append("on " + thing.path)
|
strings.append(f"on {thing.path}")
|
||||||
elif isinstance(thing, Property):
|
elif isinstance(thing, Property):
|
||||||
strings.append("on property '{}' of node {}"
|
strings.append(f"on property '{thing.name}' "
|
||||||
.format(thing.name, thing.node.path))
|
f"of node {thing.node.path}")
|
||||||
else:
|
else:
|
||||||
# Label within property value
|
# Label within property value
|
||||||
strings.append("in the value of property '{}' of node {}"
|
strings.append("in the value of property "
|
||||||
.format(thing[0].name,
|
f"'{thing[0].name}' of node "
|
||||||
thing[0].node.path))
|
f"{thing[0].node.path}")
|
||||||
|
|
||||||
# Give consistent error messages to help with testing
|
# Give consistent error messages to help with testing
|
||||||
strings.sort()
|
strings.sort()
|
||||||
|
|
||||||
_err("Label '{}' appears ".format(label) +
|
_err(f"Label '{label}' appears " + " and ".join(strings))
|
||||||
" and ".join(strings))
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1817,7 +1811,7 @@ class DT:
|
||||||
self._parse_error(e)
|
self._parse_error(e)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self._parse_error("'{}' could not be found".format(filename))
|
self._parse_error(f"'{filename}' could not be found")
|
||||||
|
|
||||||
#
|
#
|
||||||
# Public functions
|
# Public functions
|
||||||
|
@ -1840,8 +1834,7 @@ def to_num(data: bytes, length: Optional[int] = None,
|
||||||
if length is not None:
|
if length is not None:
|
||||||
_check_length_positive(length)
|
_check_length_positive(length)
|
||||||
if len(data) != length:
|
if len(data) != length:
|
||||||
_err("{!r} is {} bytes long, expected {}"
|
_err(f"{data!r} is {len(data)} bytes long, expected {length}")
|
||||||
.format(data, len(data), length))
|
|
||||||
|
|
||||||
return int.from_bytes(data, "big", signed=signed)
|
return int.from_bytes(data, "big", signed=signed)
|
||||||
|
|
||||||
|
@ -1854,8 +1847,8 @@ def to_nums(data: bytes, length: int = 4, signed: bool = False) -> List[int]:
|
||||||
_check_length_positive(length)
|
_check_length_positive(length)
|
||||||
|
|
||||||
if len(data) % length:
|
if len(data) % length:
|
||||||
_err("{!r} is {} bytes long, expected a length that's a a multiple of {}"
|
_err(f"{data!r} is {len(data)} bytes long, "
|
||||||
.format(data, len(data), length))
|
f"expected a length that's a a multiple of {length}")
|
||||||
|
|
||||||
return [int.from_bytes(data[i:i + length], "big", signed=signed)
|
return [int.from_bytes(data[i:i + length], "big", signed=signed)
|
||||||
for i in range(0, len(data), length)]
|
for i in range(0, len(data), length)]
|
||||||
|
@ -1866,8 +1859,7 @@ def to_nums(data: bytes, length: int = 4, signed: bool = False) -> List[int]:
|
||||||
|
|
||||||
def _check_is_bytes(data):
|
def _check_is_bytes(data):
|
||||||
if not isinstance(data, bytes):
|
if not isinstance(data, bytes):
|
||||||
_err("'{}' has type '{}', expected 'bytes'"
|
_err(f"'{data}' has type '{type(data).__name__}', expected 'bytes'")
|
||||||
.format(data, type(data).__name__))
|
|
||||||
|
|
||||||
def _check_length_positive(length):
|
def _check_length_positive(length):
|
||||||
if length < 1:
|
if length < 1:
|
||||||
|
@ -1905,8 +1897,8 @@ def _root_and_path_to_node(cur, path, fullpath):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if component not in cur.nodes:
|
if component not in cur.nodes:
|
||||||
_err("component '{}' in path '{}' does not exist"
|
_err(f"component '{component}' in path '{fullpath}' "
|
||||||
.format(component, fullpath))
|
"does not exist")
|
||||||
|
|
||||||
cur = cur.nodes[component]
|
cur = cur.nodes[component]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue