Skip to content

Commit 98283a2

Browse files
sveinseerlend-aaslandacolomb
authored
Cleanup f-strings, logging and formats (#443)
* Change old-style % formatting to f-strings * Change str.format() to f-strings * Harmonize logging function to use % formatting and arguments. * Consistently print OD index and subindex in 0x01AB:0C notation. * Introduce helper function pretty_index() for the latter usage. Co-authored-by: Erlend E. Aasland <[email protected]> Co-authored-by: André Colomb <[email protected]>
1 parent 6b0c7cf commit 98283a2

25 files changed

+189
-155
lines changed

canopen/emcy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def get_desc(self) -> str:
130130
return ""
131131

132132
def __str__(self):
133-
text = "Code 0x{:04X}".format(self.code)
133+
text = f"Code 0x{self.code:04X}"
134134
description = self.get_desc()
135135
if description:
136136
text = text + ", " + description

canopen/lss.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ def __send_configure(self, req_cs, value1=0, value2=0):
353353
raise LssError("Response message is not for the request")
354354

355355
if error_code != ERROR_NONE:
356-
error_msg = "LSS Error: %d" % error_code
356+
error_msg = f"LSS Error: {error_code}"
357357
raise LssError(error_msg)
358358

359359
def __send_command(self, message):
@@ -368,9 +368,7 @@ def __send_command(self, message):
368368
:rtype: bytes
369369
"""
370370

371-
message_str = " ".join(["{:02x}".format(x) for x in message])
372-
logger.info(
373-
"Sending LSS message {}".format(message_str))
371+
logger.info("Sending LSS message %s", message.hex(" ").upper())
374372

375373
response = None
376374
if not self.responses.empty():

canopen/node/local.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def get_data(
8686
return obj.encode_raw(obj.default)
8787

8888
# Resource not available
89-
logger.info("Resource unavailable for 0x%X:%d", index, subindex)
89+
logger.info("Resource unavailable for 0x%04X:%02X", index, subindex)
9090
raise SdoAbortedError(0x060A0023)
9191

9292
def set_data(

canopen/node/remote.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -122,18 +122,13 @@ def __load_configuration_helper(self, index, subindex, name, value):
122122
"""
123123
try:
124124
if subindex is not None:
125-
logger.info(str('SDO [{index:#06x}][{subindex:#06x}]: {name}: {value:#06x}'.format(
126-
index=index,
127-
subindex=subindex,
128-
name=name,
129-
value=value)))
125+
logger.info('SDO [0x%04X][0x%02X]: %s: %#06x',
126+
index, subindex, name, value)
130127
self.sdo[index][subindex].raw = value
131128
else:
132129
self.sdo[index].raw = value
133-
logger.info(str('SDO [{index:#06x}]: {name}: {value:#06x}'.format(
134-
index=index,
135-
name=name,
136-
value=value)))
130+
logger.info('SDO [0x%04X]: %s: %#06x',
131+
index, name, value)
137132
except SdoCommunicationError as e:
138133
logger.warning(str(e))
139134
except SdoAbortedError as e:
@@ -142,7 +137,8 @@ def __load_configuration_helper(self, index, subindex, name, value):
142137
if e.code != 0x06010002:
143138
# Abort codes other than "Attempt to write a read-only object"
144139
# should still be reported.
145-
logger.warning('[ERROR SETTING object {0:#06x}:{1:#06x}] {2}'.format(index, subindex, str(e)))
140+
logger.warning('[ERROR SETTING object 0x%04X:%02X] %s',
141+
index, subindex, e)
146142
raise
147143

148144
def load_configuration(self):

canopen/objectdictionary/__init__.py

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from canopen.objectdictionary.datatypes import *
1010
from canopen.objectdictionary.datatypes_24bit import Integer24, Unsigned24
11+
from canopen.utils import pretty_index
1112

1213
logger = logging.getLogger(__name__)
1314

@@ -108,8 +109,7 @@ def __getitem__(
108109
if isinstance(index, str) and '.' in index:
109110
idx, sub = index.split('.', maxsplit=1)
110111
return self[idx][sub]
111-
name = "0x%X" % index if isinstance(index, int) else index
112-
raise KeyError("%s was not found in Object Dictionary" % name)
112+
raise KeyError(f"{pretty_index(index)} was not found in Object Dictionary")
113113
return item
114114

115115
def __setitem__(
@@ -180,12 +180,12 @@ def __init__(self, name: str, index: int):
180180
self.names = {}
181181

182182
def __repr__(self) -> str:
183-
return f"<{type(self).__qualname__} {self.name!r} at 0x{self.index:04X}>"
183+
return f"<{type(self).__qualname__} {self.name!r} at {pretty_index(self.index)}>"
184184

185185
def __getitem__(self, subindex: Union[int, str]) -> "ODVariable":
186186
item = self.names.get(subindex) or self.subindices.get(subindex)
187187
if item is None:
188-
raise KeyError("Subindex %s was not found" % subindex)
188+
raise KeyError(f"Subindex {pretty_index(None, subindex)} was not found")
189189
return item
190190

191191
def __setitem__(self, subindex: Union[int, str], var: "ODVariable"):
@@ -239,7 +239,7 @@ def __init__(self, name: str, index: int):
239239
self.names = {}
240240

241241
def __repr__(self) -> str:
242-
return f"<{type(self).__qualname__} {self.name!r} at 0x{self.index:04X}>"
242+
return f"<{type(self).__qualname__} {self.name!r} at {pretty_index(self.index)}>"
243243

244244
def __getitem__(self, subindex: Union[int, str]) -> "ODVariable":
245245
var = self.names.get(subindex) or self.subindices.get(subindex)
@@ -249,7 +249,7 @@ def __getitem__(self, subindex: Union[int, str]) -> "ODVariable":
249249
elif isinstance(subindex, int) and 0 < subindex < 256:
250250
# Create a new variable based on first array item
251251
template = self.subindices[1]
252-
name = "%s_%x" % (template.name, subindex)
252+
name = f"{template.name}_{subindex:x}"
253253
var = ODVariable(name, self.index, subindex)
254254
var.parent = self
255255
for attr in ("data_type", "unit", "factor", "min", "max", "default",
@@ -258,7 +258,7 @@ def __getitem__(self, subindex: Union[int, str]) -> "ODVariable":
258258
if attr in template.__dict__:
259259
var.__dict__[attr] = template.__dict__[attr]
260260
else:
261-
raise KeyError("Could not find subindex %r" % subindex)
261+
raise KeyError(f"Could not find subindex {pretty_index(None, subindex)}")
262262
return var
263263

264264
def __len__(self) -> int:
@@ -337,8 +337,8 @@ def __init__(self, name: str, index: int, subindex: int = 0):
337337
self.pdo_mappable = False
338338

339339
def __repr__(self) -> str:
340-
suffix = f":{self.subindex:02X}" if isinstance(self.parent, (ODRecord, ODArray)) else ""
341-
return f"<{type(self).__qualname__} {self.qualname!r} at 0x{self.index:04X}{suffix}>"
340+
subindex = self.subindex if isinstance(self.parent, (ODRecord, ODArray)) else None
341+
return f"<{type(self).__qualname__} {self.qualname!r} at {pretty_index(self.index, subindex)}>"
342342

343343
@property
344344
def qualname(self) -> str:
@@ -417,8 +417,7 @@ def encode_raw(self, value: Union[int, float, str, bytes, bytearray]) -> bytes:
417417
if self.max is not None and value > self.max:
418418
logger.warning(
419419
"Value %d is greater than max value %d",
420-
value,
421-
self.max)
420+
value, self.max)
422421
try:
423422
return self.STRUCT_TYPES[self.data_type].pack(value)
424423
except struct.error:
@@ -427,8 +426,7 @@ def encode_raw(self, value: Union[int, float, str, bytes, bytearray]) -> bytes:
427426
raise ObjectDictionaryError("Data type has not been specified")
428427
else:
429428
raise TypeError(
430-
"Do not know how to encode %r to data type %Xh" % (
431-
value, self.data_type))
429+
f"Do not know how to encode {value!r} to data type 0x{self.data_type:X}")
432430

433431
def decode_phys(self, value: int) -> Union[int, bool, float, str, bytes]:
434432
if self.data_type in INTEGER_TYPES:
@@ -446,7 +444,7 @@ def decode_desc(self, value: int) -> str:
446444
raise ObjectDictionaryError("No value descriptions exist")
447445
elif value not in self.value_descriptions:
448446
raise ObjectDictionaryError(
449-
"No value description exists for %d" % value)
447+
f"No value description exists for {value}")
450448
else:
451449
return self.value_descriptions[value]
452450

@@ -458,8 +456,8 @@ def encode_desc(self, desc: str) -> int:
458456
if description == desc:
459457
return value
460458
valid_values = ", ".join(self.value_descriptions.values())
461-
error_text = "No value corresponds to '%s'. Valid values are: %s"
462-
raise ValueError(error_text % (desc, valid_values))
459+
raise ValueError(
460+
f"No value corresponds to '{desc}'. Valid values are: {valid_values}")
463461

464462
def decode_bits(self, value: int, bits: List[int]) -> int:
465463
try:

canopen/objectdictionary/eds.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def import_eds(source, node_id):
4343
if eds.has_section("Comments"):
4444
linecount = int(eds.get("Comments", "Lines"), 0)
4545
od.comments = '\n'.join([
46-
eds.get("Comments", "Line%i" % line)
46+
eds.get("Comments", f"Line{line}")
4747
for line in range(1, linecount+1)
4848
])
4949

@@ -52,7 +52,7 @@ def import_eds(source, node_id):
5252
else:
5353
for rate in [10, 20, 50, 125, 250, 500, 800, 1000]:
5454
baudPossible = int(
55-
eds.get("DeviceInfo", "BaudRate_%i" % rate, fallback='0'), 0)
55+
eds.get("DeviceInfo", f"BaudRate_{rate}", fallback='0'), 0)
5656
if baudPossible != 0:
5757
od.device_information.allowed_baudrates.add(rate*1000)
5858

@@ -93,7 +93,7 @@ def import_eds(source, node_id):
9393
match = re.match(r"^[Dd]ummy[Uu]sage$", section)
9494
if match is not None:
9595
for i in range(1, 8):
96-
key = "Dummy%04d" % i
96+
key = f"Dummy{i:04d}"
9797
if eds.getint(section, key) == 1:
9898
var = objectdictionary.ODVariable(key, i, 0)
9999
var.data_type = i
@@ -239,7 +239,7 @@ def _revert_variable(var_type, value):
239239
elif var_type in datatypes.FLOAT_TYPES:
240240
return value
241241
else:
242-
return "0x%02X" % value
242+
return f"0x{value:02X}"
243243

244244

245245
def build_variable(eds, section, node_id, index, subindex=0):
@@ -264,9 +264,9 @@ def build_variable(eds, section, node_id, index, subindex=0):
264264
# The eds.get function gives us 0x00A0 now convert to String without hex representation and upper case
265265
# The sub2 part is then the section where the type parameter stands
266266
try:
267-
var.data_type = int(eds.get("%Xsub1" % var.data_type, "DefaultValue"), 0)
267+
var.data_type = int(eds.get(f"{var.data_type:X}sub1", "DefaultValue"), 0)
268268
except NoSectionError:
269-
logger.warning("%s has an unknown or unsupported data type (%X)", name, var.data_type)
269+
logger.warning("%s has an unknown or unsupported data type (0x%X)", name, var.data_type)
270270
# Assume DOMAIN to force application to interpret the byte data
271271
var.data_type = datatypes.DOMAIN
272272

@@ -354,15 +354,15 @@ def export_common(var, eds, section):
354354
def export_variable(var, eds):
355355
if isinstance(var.parent, ObjectDictionary):
356356
# top level variable
357-
section = "%04X" % var.index
357+
section = f"{var.index:04X}"
358358
else:
359359
# nested variable
360-
section = "%04Xsub%X" % (var.index, var.subindex)
360+
section = f"{var.index:04X}sub{var.subindex:X}"
361361

362362
export_common(var, eds, section)
363-
eds.set(section, "ObjectType", "0x%X" % VAR)
363+
eds.set(section, "ObjectType", f"0x{VAR:X}")
364364
if var.data_type:
365-
eds.set(section, "DataType", "0x%04X" % var.data_type)
365+
eds.set(section, "DataType", f"0x{var.data_type:04X}")
366366
if var.access_type:
367367
eds.set(section, "AccessType", var.access_type)
368368

@@ -379,7 +379,7 @@ def export_variable(var, eds):
379379
eds.set(section, "ParameterValue",
380380
_revert_variable(var.data_type, var.value))
381381

382-
eds.set(section, "DataType", "0x%04X" % var.data_type)
382+
eds.set(section, "DataType", f"0x{var.data_type:04X}")
383383
eds.set(section, "PDOMapping", hex(var.pdo_mappable))
384384

385385
if getattr(var, 'min', None) is not None:
@@ -395,11 +395,11 @@ def export_variable(var, eds):
395395
eds.set(section, "Unit", var.unit)
396396

397397
def export_record(var, eds):
398-
section = "%04X" % var.index
398+
section = f"{var.index:04X}"
399399
export_common(var, eds, section)
400-
eds.set(section, "SubNumber", "0x%X" % len(var.subindices))
400+
eds.set(section, "SubNumber", f"0x{len(var.subindices):X}")
401401
ot = RECORD if isinstance(var, objectdictionary.ODRecord) else ARR
402-
eds.set(section, "ObjectType", "0x%X" % ot)
402+
eds.set(section, "ObjectType", f"0x{ot:X}")
403403
for i in var:
404404
export_variable(var[i], eds)
405405

@@ -461,7 +461,7 @@ def export_record(var, eds):
461461
for rate in od.device_information.allowed_baudrates.union(
462462
{10e3, 20e3, 50e3, 125e3, 250e3, 500e3, 800e3, 1000e3}):
463463
eds.set(
464-
"DeviceInfo", "BaudRate_%i" % (rate/1000),
464+
"DeviceInfo", f"BaudRate_{rate//1000}",
465465
int(rate in od.device_information.allowed_baudrates))
466466

467467
if device_commisioning and (od.bitrate or od.node_id):
@@ -475,12 +475,12 @@ def export_record(var, eds):
475475
i = 0
476476
for line in od.comments.splitlines():
477477
i += 1
478-
eds.set("Comments", "Line%i" % i, line)
478+
eds.set("Comments", f"Line{i}", line)
479479
eds.set("Comments", "Lines", i)
480480

481481
eds.add_section("DummyUsage")
482482
for i in range(1, 8):
483-
key = "Dummy%04d" % i
483+
key = f"Dummy{i:04d}"
484484
eds.set("DummyUsage", key, 1 if (key in od) else 0)
485485

486486
def mandatory_indices(x):
@@ -504,7 +504,7 @@ def add_list(section, list):
504504
eds.add_section(section)
505505
eds.set(section, "SupportedObjects", len(list))
506506
for i in range(0, len(list)):
507-
eds.set(section, (i + 1), "0x%04X" % list[i])
507+
eds.set(section, (i + 1), f"0x{list[i]:04X}")
508508
for index in list:
509509
export_object(od[index], eds)
510510

canopen/pdo/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class RPDO(PdoBase):
3939
def __init__(self, node):
4040
super(RPDO, self).__init__(node)
4141
self.map = PdoMaps(0x1400, 0x1600, self, 0x200)
42-
logger.debug('RPDO Map as {0}'.format(len(self.map)))
42+
logger.debug('RPDO Map as %d', len(self.map))
4343

4444
def stop(self):
4545
"""Stop transmission of all RPDOs.
@@ -64,7 +64,7 @@ class TPDO(PdoBase):
6464
def __init__(self, node):
6565
super(TPDO, self).__init__(node)
6666
self.map = PdoMaps(0x1800, 0x1A00, self, 0x180)
67-
logger.debug('TPDO Map as {0}'.format(len(self.map)))
67+
logger.debug('TPDO Map as %d', len(self.map))
6868

6969
def stop(self):
7070
"""Stop transmission of all TPDOs.

canopen/pdo/base.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def __getitem__(self, key):
4242
except KeyError:
4343
# ignore if one specific PDO does not have the key and try the next one
4444
continue
45-
raise KeyError("PDO: {0} was not found in any map".format(key))
45+
raise KeyError(f"PDO: {key} was not found in any map")
4646

4747
def __len__(self):
4848
return len(self.map)
@@ -201,8 +201,8 @@ def __getitem_by_index(self, value):
201201
valid_values.append(var.index)
202202
if var.index == value:
203203
return var
204-
raise KeyError('{0} not found in map. Valid entries are {1}'.format(
205-
value, ', '.join(str(v) for v in valid_values)))
204+
raise KeyError(f"{value} not found in map. Valid entries are "
205+
f"{', '.join(str(v) for v in valid_values)}")
206206

207207
def __getitem_by_name(self, value):
208208
valid_values = []
@@ -211,8 +211,8 @@ def __getitem_by_name(self, value):
211211
valid_values.append(var.name)
212212
if var.name == value:
213213
return var
214-
raise KeyError('{0} not found in map. Valid entries are {1}'.format(
215-
value, ', '.join(valid_values)))
214+
raise KeyError(f"{value} not found in map. Valid entries are "
215+
f"{', '.join(valid_values)}")
216216

217217
def __getitem__(self, key: Union[int, str]) -> "PdoVariable":
218218
var = None
@@ -272,7 +272,7 @@ def name(self) -> str:
272272
if direction == "Rx":
273273
map_id -= 1
274274
node_id = self.cob_id & 0x7F
275-
return "%sPDO%d_node%d" % (direction, map_id, node_id)
275+
return f"{direction}PDO{map_id}_node{node_id}"
276276

277277
@property
278278
def is_periodic(self) -> bool:
@@ -398,7 +398,7 @@ def save(self) -> None:
398398
self._fill_map(self.map_array[0].raw)
399399
subindex = 1
400400
for var in self.map:
401-
logger.info("Writing %s (0x%X:%d, %d bits) to PDO map",
401+
logger.info("Writing %s (0x%04X:%02X, %d bits) to PDO map",
402402
var.name, var.index, var.subindex, var.length)
403403
if hasattr(self.pdo_node.node, "curtis_hack") and self.pdo_node.node.curtis_hack: # Curtis HACK: mixed up field order
404404
self.map_array[subindex].raw = (var.index |
@@ -467,7 +467,7 @@ def add_variable(
467467
# We want to see the bit fields within the PDO
468468
start_bit = var.offset
469469
end_bit = start_bit + var.length - 1
470-
logger.info("Adding %s (0x%X:%d) at bits %d - %d to PDO map",
470+
logger.info("Adding %s (0x%04X:%02X) at bits %d - %d to PDO map",
471471
var.name, var.index, var.subindex, start_bit, end_bit)
472472
self.map.append(var)
473473
self.length += var.length

0 commit comments

Comments
 (0)