diff --git a/lib/hidapi/hidconsole.py b/lib/hidapi/hidconsole.py index 48296b61ef..74dc25a01f 100644 --- a/lib/hidapi/hidconsole.py +++ b/lib/hidapi/hidconsole.py @@ -155,7 +155,7 @@ def matchfn(bid, vid, pid, _a, _b): print(".. Opening device", device) handle = _hid.open_path(device) if not handle: - sys.exit("!! Failed to open %s, aborting." % device) + sys.exit(f"!! Failed to open {device}, aborting.") print( ".. Opened handle %r, vendor %r product %r serial %r." % (handle, _hid.get_manufacturer(handle), _hid.get_product(handle), _hid.get_serial(handle)) @@ -243,7 +243,7 @@ def main(): time.sleep(1) finally: - print(".. Closing handle %r" % handle) + print(f".. Closing handle {handle!r}") _hid.close(handle) if interactive: readline.write_history_file(args.history) diff --git a/lib/logitech_receiver/base.py b/lib/logitech_receiver/base.py index 42fbb0424f..03699c0126 100644 --- a/lib/logitech_receiver/base.py +++ b/lib/logitech_receiver/base.py @@ -273,7 +273,7 @@ def check_message(data): if report_lengths.get(report_id) == len(data): return True else: - logger.warning("unexpected message size: report_id %02X message %s" % (report_id, _strhex(data))) + logger.warning(f"unexpected message size: report_id {report_id:02X} message {_strhex(data)}") return False diff --git a/lib/logitech_receiver/common.py b/lib/logitech_receiver/common.py index 0c3d0ccb7b..8f617743a3 100644 --- a/lib/logitech_receiver/common.py +++ b/lib/logitech_receiver/common.py @@ -413,7 +413,7 @@ def flag_names(self, value): yield str(self._indexed[k]) if unknown_bits: - yield "unknown:%06X" % unknown_bits + yield f"unknown:{unknown_bits:06X}" def _sort_values(self): self._values = sorted(self._values) @@ -501,7 +501,7 @@ def __len__(self): return len(self._values) def __repr__(self): - return "NamedInts(%s)" % ", ".join(repr(v) for v in self._values) + return f"NamedInts({', '.join(repr(v) for v in self._values)})" def __or__(self, other): return NamedInts(**self.__dict__, **other.__dict__) diff --git a/lib/logitech_receiver/descriptors.py b/lib/logitech_receiver/descriptors.py index 47d7862416..3548b2fd76 100644 --- a/lib/logitech_receiver/descriptors.py +++ b/lib/logitech_receiver/descriptors.py @@ -85,18 +85,18 @@ def _D( if "Trackball" in name else None ) - assert kind is not None, "descriptor for %s does not have kind set" % name + assert kind is not None, f"descriptor for {name} does not have kind set" if protocol is not None: if wpid: for w in wpid if isinstance(wpid, tuple) else (wpid,): if protocol > 1.0: - assert w[0:1] == "4", "%s has protocol %0.1f, wpid %s" % (name, protocol, w) + assert w[0:1] == "4", f"{name} has protocol {protocol:0.1f}, wpid {w}" else: if w[0:1] == "1": - assert kind == _DK.mouse, "%s has protocol %0.1f, wpid %s" % (name, protocol, w) + assert kind == _DK.mouse, f"{name} has protocol {protocol:0.1f}, wpid {w}" elif w[0:1] == "2": - assert kind in (_DK.keyboard, _DK.numpad), "%s has protocol %0.1f, wpid %s" % (name, protocol, w) + assert kind in (_DK.keyboard, _DK.numpad), f"{name} has protocol {protocol:0.1f}, wpid {w}" device_descriptor = _DeviceDescriptor( name=name, @@ -112,18 +112,18 @@ def _D( if usbid: found = get_usbid(usbid) - assert found is None, "duplicate usbid in device descriptors: %s" % (found,) + assert found is None, f"duplicate usbid in device descriptors: {found}" if btid: found = get_btid(btid) - assert found is None, "duplicate btid in device descriptors: %s" % (found,) + assert found is None, f"duplicate btid in device descriptors: {found}" - assert codename not in DEVICES, "duplicate codename in device descriptors: %s" % (DEVICES[codename],) + assert codename not in DEVICES, f"duplicate codename in device descriptors: {DEVICES[codename]}" if codename: DEVICES[codename] = device_descriptor if wpid: for w in wpid if isinstance(wpid, tuple) else (wpid,): - assert w not in DEVICES_WPID, "duplicate wpid in device descriptors: %s" % (DEVICES_WPID[w],) + assert w not in DEVICES_WPID, f"duplicate wpid in device descriptors: {DEVICES_WPID[w]}" DEVICES_WPID[w] = device_descriptor diff --git a/lib/logitech_receiver/diversion.py b/lib/logitech_receiver/diversion.py index 17c90476cc..88b0e34756 100644 --- a/lib/logitech_receiver/diversion.py +++ b/lib/logitech_receiver/diversion.py @@ -493,7 +493,7 @@ def __init__(self, args, source=None, warn=True): def __str__(self): source = "(" + self.source + ")" if self.source else "" - return "Rule%s[%s]" % (source, ", ".join([c.__str__() for c in self.components])) + return f"Rule{source}[{', '.join([c.__str__() for c in self.components])}]" def evaluate(self, feature, notification, device, last_result): if logger.isEnabledFor(logging.DEBUG): @@ -832,16 +832,16 @@ def __init__(self, args, warn=True): if not args or not isinstance(args, (list, str)): if warn: - logger.warning("rule Key arguments unknown: %s" % args) + logger.warning(f"rule Key arguments unknown: {args}") key = default_key action = default_action elif isinstance(args, str): - logger.debug('rule Key assuming action "%s" for "%s"' % (default_action, args)) + logger.debug(f'rule Key assuming action "{default_action}" for "{args}"') key = args action = default_action elif isinstance(args, list): if len(args) == 1: - logger.debug('rule Key assuming action "%s" for "%s"' % (default_action, args)) + logger.debug(f'rule Key assuming action "{default_action}" for "{args}"') key, action = args[0], default_action elif len(args) >= 2: key, action = args[:2] @@ -850,18 +850,18 @@ def __init__(self, args, warn=True): self.key = _CONTROL[key] else: if warn: - logger.warning("rule Key key name not name of a Logitech key: %s" % key) + logger.warning(f"rule Key key name not name of a Logitech key: {key}") self.key = default_key if isinstance(action, str) and action in (self.DOWN, self.UP): self.action = action else: if warn: - logger.warning("rule Key action unknown: %s, assuming %s" % (action, default_action)) + logger.warning(f"rule Key action unknown: {action}, assuming {default_action}") self.action = default_action def __str__(self): - return "Key: %s (%s)" % ((str(self.key) if self.key else "None"), self.action) + return f"Key: {str(self.key) if self.key else 'None'} ({self.action})" def evaluate(self, feature, notification, device, last_result): if logger.isEnabledFor(logging.DEBUG): @@ -880,7 +880,7 @@ def __init__(self, args, warn=True): if not args or not isinstance(args, str): if warn: - logger.warning("rule KeyDown arguments unknown: %s" % args) + logger.warning(f"rule KeyDown arguments unknown: {args}") key = default_key elif isinstance(args, str): key = args @@ -889,11 +889,11 @@ def __init__(self, args, warn=True): self.key = _CONTROL[key] else: if warn: - logger.warning("rule Key key name not name of a Logitech key: %s" % key) + logger.warning(f"rule Key key name not name of a Logitech key: {key}") self.key = default_key def __str__(self): - return "KeyIsDown: %s" % (str(self.key) if self.key else "None") + return f"KeyIsDown: {str(self.key) if self.key else 'None'}" def evaluate(self, feature, notification, device, last_result): if logger.isEnabledFor(logging.DEBUG): diff --git a/lib/logitech_receiver/hidpp10.py b/lib/logitech_receiver/hidpp10.py index 3c3dd483e8..b46f7ff40a 100644 --- a/lib/logitech_receiver/hidpp10.py +++ b/lib/logitech_receiver/hidpp10.py @@ -32,14 +32,14 @@ def read_register(device, register_number, *params): - assert device is not None, "tried to read register %02X from invalid device %s" % (register_number, device) + assert device is not None, f"tried to read register {register_number:02X} from invalid device {device}" # support long registers by adding a 2 in front of the register number request_id = 0x8100 | (int(register_number) & 0x2FF) return device.request(request_id, *params) def write_register(device, register_number, *value): - assert device is not None, "tried to write register %02X to invalid device %s" % (register_number, device) + assert device is not None, f"tried to write register {register_number:02X} to invalid device {device}" # support long registers by adding a 2 in front of the register number request_id = 0x8000 | (int(register_number) & 0x2FF) return device.request(request_id, *value) @@ -87,7 +87,7 @@ def get_firmware(self, device): return fw_version = _strhex(reply[1:3]) - fw_version = "%s.%s" % (fw_version[0:2], fw_version[2:4]) + fw_version = f"{fw_version[0:2]}.{fw_version[2:4]}" reply = read_register(device, REGISTERS.firmware, 0x02) if reply: fw_version += ".B" + _strhex(reply[1:3]) @@ -97,14 +97,14 @@ def get_firmware(self, device): reply = read_register(device, REGISTERS.firmware, 0x04) if reply: bl_version = _strhex(reply[1:3]) - bl_version = "%s.%s" % (bl_version[0:2], bl_version[2:4]) + bl_version = f"{bl_version[0:2]}.{bl_version[2:4]}" bl = _FirmwareInfo(FIRMWARE_KIND.Bootloader, "", bl_version, None) firmware[1] = bl reply = read_register(device, REGISTERS.firmware, 0x03) if reply: o_version = _strhex(reply[1:3]) - o_version = "%s.%s" % (o_version[0:2], o_version[2:4]) + o_version = f"{o_version[0:2]}.{o_version[2:4]}" o = _FirmwareInfo(FIRMWARE_KIND.Other, "", o_version, None) firmware[2] = o diff --git a/lib/logitech_receiver/hidpp20.py b/lib/logitech_receiver/hidpp20.py index 7747a985dd..b420d1ed51 100644 --- a/lib/logitech_receiver/hidpp20.py +++ b/lib/logitech_receiver/hidpp20.py @@ -577,7 +577,7 @@ def _query_key(self, index: int): RatioZone=3, # 4 bytes, left, bottom, width, height; unit 1/240 pad size ScaleFactor=4, # 2-byte integer, with 256 as normal scale ) -PARAM._fallback = lambda x: "unknown:%04X" % x +PARAM._fallback = lambda x: f"unknown:{x:04X}" class SubParam: @@ -627,7 +627,7 @@ def __repr__(self): finger_force=9, zone=10, ) -SPEC._fallback = lambda x: "unknown:%04X" % x +SPEC._fallback = lambda x: f"unknown:{x:04X}" # Action Ids for feature GESTURE_2 ACTION_ID = _NamedInts( @@ -644,7 +644,7 @@ def __repr__(self): ScrollHorizontalOnly=11, ScrollVerticalOnly=12, ) -ACTION_ID._fallback = lambda x: "unknown:%04X" % x +ACTION_ID._fallback = lambda x: f"unknown:{x:04X}" class Gesture: @@ -1396,9 +1396,9 @@ def get_firmware(self, device): level = ord(fw_info[:1]) & 0x0F if level == 0 or level == 1: name, version_major, version_minor, build = _unpack("!3sBBH", fw_info[1:8]) - version = "%02X.%02X" % (version_major, version_minor) + version = f"{version_major:02X}.{version_minor:02X}" if build: - version += ".B%04X" % build + version += f".B{build:04X}" extras = fw_info[9:].rstrip(b"\x00") or None fw_info = _FirmwareInfo(FIRMWARE_KIND[level], name.decode("ascii"), version, extras) elif level == FIRMWARE_KIND.Hardware: @@ -1716,7 +1716,7 @@ def get_remaining_pairing(self, device): result = feature_request(device, FEATURE.REMAINING_PAIRING, 0x0) if result: result = _unpack("!B", result[:1])[0] - FEATURE._fallback = lambda x: "unknown:%04X" % x + FEATURE._fallback = lambda x: f"unknown:{x:04X}" return result def config_change(self, device, configuration, no_reply=False): diff --git a/lib/logitech_receiver/hidpp20_constants.py b/lib/logitech_receiver/hidpp20_constants.py index d5f314d455..69fc8b95ca 100644 --- a/lib/logitech_receiver/hidpp20_constants.py +++ b/lib/logitech_receiver/hidpp20_constants.py @@ -145,7 +145,7 @@ # Fake features for Solaar internal use MOUSE_GESTURE=0xFE00, ) -FEATURE._fallback = lambda x: "unknown:%04X" % x +FEATURE._fallback = lambda x: f"unknown:{x:04X}" FEATURE_FLAG = NamedInts(internal=0x20, hidden=0x40, obsolete=0x80) @@ -238,7 +238,7 @@ Finger10=99, DeviceSpecificRawData=100, ) -GESTURE._fallback = lambda x: "unknown:%04X" % x +GESTURE._fallback = lambda x: f"unknown:{x:04X}" # Param Ids for feature GESTURE_2 PARAM = NamedInts( @@ -247,4 +247,4 @@ RatioZone=3, # 4 bytes, left, bottom, width, height; unit 1/240 pad size ScaleFactor=4, # 2-byte integer, with 256 as normal scale ) -PARAM._fallback = lambda x: "unknown:%04X" % x +PARAM._fallback = lambda x: f"unknown:{x:04X}" diff --git a/lib/logitech_receiver/listener.py b/lib/logitech_receiver/listener.py index 4898d67708..4de7386436 100644 --- a/lib/logitech_receiver/listener.py +++ b/lib/logitech_receiver/listener.py @@ -91,7 +91,7 @@ def __str__(self): return str(int(self)) def __repr__(self): - return "<_ThreadedHandle(%s)>" % self.path + return f"<_ThreadedHandle({self.path})>" def __bool__(self): return bool(self._local) diff --git a/lib/logitech_receiver/receiver.py b/lib/logitech_receiver/receiver.py index c3ac47d858..30f82a5fb7 100644 --- a/lib/logitech_receiver/receiver.py +++ b/lib/logitech_receiver/receiver.py @@ -312,7 +312,7 @@ def _unpair_device(self, key, force=False): logger.info("%s unpaired device %s", self, dev) else: logger.error("%s failed to unpair device %s", self, dev) - raise Exception("failed to unpair device %s: %s" % (dev.name, key)) + raise Exception(f"failed to unpair device {dev.name}: {key}") def _unpair_device_per_receiver(self, key): """Receiver specific unpairing.""" diff --git a/lib/logitech_receiver/settings.py b/lib/logitech_receiver/settings.py index f6e3ee7517..800e7675c6 100644 --- a/lib/logitech_receiver/settings.py +++ b/lib/logitech_receiver/settings.py @@ -220,7 +220,7 @@ def __str__(self): self.name, self._value, ) - return "" % (self._rw.kind, self._validator.kind if self._validator else None, self.name) + return f"" __repr__ = __str__ @@ -747,7 +747,7 @@ def __init__( assert fv & mv == fv self.needs_current_value = any(m != 0xFF for m in mask) else: - raise Exception("invalid mask '%r', type %s" % (mask, type(mask))) + raise Exception(f"invalid mask '{mask!r}', type {type(mask)}") self.true_value = true_value self.false_value = false_value @@ -795,7 +795,7 @@ def prepare_write(self, new_value, current_value=None): if new_value is None: new_value = False else: - assert isinstance(new_value, bool), "New value %s for boolean setting is not a boolean" % new_value + assert isinstance(new_value, bool), f"New value {new_value} for boolean setting is not a boolean" to_write = self.true_value if new_value else self.false_value @@ -1033,7 +1033,7 @@ def to_string(self, value): def validate_read(self, reply_bytes): reply_value = _bytes2int(reply_bytes[self._read_skip_byte_count : self._read_skip_byte_count + self._byte_count]) valid_value = self.choices[reply_value] - assert valid_value is not None, "%s: failed to validate read value %02X" % (self.__class__.__name__, reply_value) + assert valid_value is not None, f"{self.__class__.__name__}: failed to validate read value {reply_value:02X}" return valid_value def prepare_write(self, new_value, current_value=None): @@ -1042,7 +1042,7 @@ def prepare_write(self, new_value, current_value=None): else: value = self.choice(new_value) if value is None: - raise ValueError("invalid choice %r" % new_value) + raise ValueError(f"invalid choice {new_value!r}") assert isinstance(value, _NamedInt) return self._write_prefix_bytes + value.bytes(self._byte_count) @@ -1191,13 +1191,13 @@ def __init__(self, min_value=0, max_value=255, byte_count=1): def validate_read(self, reply_bytes): reply_value = _bytes2int(reply_bytes[: self._byte_count]) - assert reply_value >= self.min_value, "%s: failed to validate read value %02X" % (self.__class__.__name__, reply_value) - assert reply_value <= self.max_value, "%s: failed to validate read value %02X" % (self.__class__.__name__, reply_value) + assert reply_value >= self.min_value, f"{self.__class__.__name__}: failed to validate read value {reply_value:02X}" + assert reply_value <= self.max_value, f"{self.__class__.__name__}: failed to validate read value {reply_value:02X}" return reply_value def prepare_write(self, new_value, current_value=None): if new_value < self.min_value or new_value > self.max_value: - raise ValueError("invalid choice %r" % new_value) + raise ValueError(f"invalid choice {new_value!r}") current_value = self.validate_read(current_value) if current_value is not None else None to_write = _int2bytes(new_value, self._byte_count) # current value is known and same as value to be written return None to signal not to write it @@ -1276,16 +1276,16 @@ def validate_read(self, reply_bytes): for n in range(self.count) } for n in range(self.count): - assert rvs[n] >= self.min_value, "%s: failed to validate read value %02X" % (self.__class__.__name__, rvs[n]) - assert rvs[n] <= self.max_value, "%s: failed to validate read value %02X" % (self.__class__.__name__, rvs[n]) + assert rvs[n] >= self.min_value, f"{self.__class__.__name__}: failed to validate read value {rvs[n]:02X}" + assert rvs[n] <= self.max_value, f"{self.__class__.__name__}: failed to validate read value {rvs[n]:02X}" return rvs def prepare_write(self, new_values): if len(new_values) != self.count: - raise ValueError("wrong number of values %r" % new_values) + raise ValueError(f"wrong number of values {new_values!r}") for new_value in new_values: if new_value < self.min_value or new_value > self.max_value: - raise ValueError("invalid value %r" % new_value) + raise ValueError(f"invalid value {new_value!r}") bytes = self.write_prefix_bytes + b"".join(_int2bytes(new_values[n], self.bc, signed=True) for n in range(self.count)) return bytes diff --git a/lib/logitech_receiver/settings_templates.py b/lib/logitech_receiver/settings_templates.py index c63fecbbc8..edbb9701ed 100644 --- a/lib/logitech_receiver/settings_templates.py +++ b/lib/logitech_receiver/settings_templates.py @@ -972,12 +972,12 @@ def build(cls, setting_class, device): if val == 0: break if val >> 13 == 0b111: - assert step is None and len(dpi_list) == 1, "Invalid DPI list item: %r" % val + assert step is None and len(dpi_list) == 1, f"Invalid DPI list item: {val!r}" step = val & 0x1FFF else: dpi_list.append(val) if step: - assert len(dpi_list) == 2, "Invalid DPI list range: %r" % dpi_list + assert len(dpi_list) == 2, f"Invalid DPI list range: {dpi_list!r}" dpi_list = range(dpi_list[0], dpi_list[1] + 1, step) return cls(choices=_NamedInts.list(dpi_list), byte_count=3) if dpi_list else None @@ -986,7 +986,7 @@ def validate_read(self, reply_bytes): # special validator to use default DPI if if reply_value == 0: # use default value instead reply_value = _bytes2int(reply_bytes[3:5]) valid_value = self.choices[reply_value] - assert valid_value is not None, "%s: failed to validate read value %02X" % (self.__class__.__name__, reply_value) + assert valid_value is not None, f"{self.__class__.__name__}: failed to validate read value {reply_value:02X}" return valid_value diff --git a/lib/logitech_receiver/special_keys.py b/lib/logitech_receiver/special_keys.py index 88f6017b8e..149bcb6ecb 100644 --- a/lib/logitech_receiver/special_keys.py +++ b/lib/logitech_receiver/special_keys.py @@ -312,7 +312,7 @@ CONTROL[0x1100 + i] = "M" + str(i) CONTROL[0x1200] = "MR" # add in MR key - this is not really a Logitech Control -CONTROL._fallback = lambda x: "unknown:%04X" % x +CONTROL._fallback = lambda x: f"unknown:{x:04X}" # --help`." ) subparsers = parser.add_subparsers(title="actions", help="optional action to perform") @@ -117,7 +117,7 @@ def _receivers(dev_path=None): yield r except Exception as e: logger.exception("opening " + str(dev_info)) - _sys.exit("%s: error: %s" % (NAME.lower(), str(e))) + _sys.exit(f"{NAME.lower()}: error: {str(e)}") def _receivers_and_devices(dev_path=None): @@ -136,7 +136,7 @@ def _receivers_and_devices(dev_path=None): yield d except Exception as e: logger.exception("opening " + str(dev_info)) - _sys.exit("%s: error: %s" % (NAME.lower(), str(e))) + _sys.exit(f"{NAME.lower()}: error: {str(e)}") def _find_receiver(receivers, name): @@ -201,7 +201,7 @@ def run(cli_args=None, hidraw_path=None): # http://bugs.python.org/issue16308 if "cmd" not in args: _cli_parser.print_usage(_sys.stderr) - _sys.stderr.write("%s: error: too few arguments\n" % NAME.lower()) + _sys.stderr.write(f"{NAME.lower()}: error: too few arguments\n") _sys.exit(2) action = args.action assert action in actions @@ -221,4 +221,4 @@ def run(cli_args=None, hidraw_path=None): tb_last = extract_tb(_sys.exc_info()[2])[-1] _sys.exit("%s: assertion failed: %s line %d" % (NAME.lower(), tb_last[0], tb_last[1])) except Exception: - _sys.exit("%s: error: %s" % (NAME.lower(), format_exc())) + _sys.exit(f"{NAME.lower()}: error: {format_exc()}") diff --git a/lib/solaar/cli/config.py b/lib/solaar/cli/config.py index 44b3eca255..d6acbbe0e6 100644 --- a/lib/solaar/cli/config.py +++ b/lib/solaar/cli/config.py @@ -97,7 +97,7 @@ def select_choice(value, choices, setting, key): elif lvalue in ("higher", "lower"): old_value = setting.read() if key is None else setting.read_key(key) if old_value is None: - raise Exception("%s: could not read current value" % setting.name) + raise Exception(f"{setting.name}: could not read current value") if lvalue == "lower": lower_values = choices[:old_value] value = lower_values[-1] if lower_values else choices[:][0] @@ -109,7 +109,7 @@ def select_choice(value, choices, setting, key): elif lvalue in ("lowest", "min", "last"): value = choices[:][0] else: - raise Exception("%s: possible values are [%s]" % (setting.name, ", ".join(str(v) for v in choices))) + raise Exception(f"{setting.name}: possible values are [{', '.join(str(v) for v in choices)}]") return value @@ -125,7 +125,7 @@ def select_toggle(value, setting, key=None): elif value.lower() in ("false", "no", "off", "f", "n"): value = False else: - raise Exception("%s: don't know how to interpret '%s' as boolean" % (setting.name, value)) from exc + raise Exception(f"{setting.name}: don't know how to interpret '{value}' as boolean") from exc return value @@ -133,10 +133,10 @@ def select_range(value, setting): try: value = int(value) except ValueError as exc: - raise Exception("%s: can't interpret '%s' as integer" % (setting.name, value)) from exc + raise Exception(f"{setting.name}: can't interpret '{value}' as integer") from exc min, max = setting.range if value < min or value > max: - raise Exception("%s: value '%s' out of bounds" % (setting.name, value)) + raise Exception(f"{setting.name}: value '{value}' out of bounds") return value @@ -153,14 +153,14 @@ def run(receivers, args, find_receiver, find_device): dev = None if not dev: - raise Exception("no online device found matching '%s'" % device_name) + raise Exception(f"no online device found matching '{device_name}'") if not args.setting: # print all settings, so first set them all up if not dev.settings: - raise Exception("no settings for %s" % dev.name) + raise Exception(f"no settings for {dev.name}") _configuration.attach_to(dev) # _settings.apply_all_settings(dev) - print(dev.name, "(%s) [%s:%s]" % (dev.codename, dev.wpid, dev.serial)) + print(dev.name, f"({dev.codename}) [{dev.wpid}:{dev.serial}]") for s in dev.settings: print("") _print_setting(s) @@ -176,7 +176,7 @@ def run(receivers, args, find_receiver, find_device): except Exception: setting = None if setting is None: - raise Exception("no setting '%s' for %s" % (args.setting, dev.name)) + raise Exception(f"no setting '{args.setting}' for {dev.name}") if args.value_key is None: # setting.apply() @@ -203,7 +203,7 @@ def run(receivers, args, find_receiver, find_device): if message is not None: print(message) if result is None: - raise Exception("%s: failed to set value '%s' [%r]" % (setting.name, str(value), value)) + raise Exception(f"{setting.name}: failed to set value '{str(value)}' [{value!r}]") # if the Solaar UI is running tell it to also perform the set, otherwise save the change in the configuration file if remote: @@ -219,19 +219,19 @@ def set(dev, setting, args, save): if setting.kind == _settings.KIND.toggle: value = select_toggle(args.value_key, setting) args.value_key = value - message = "Setting %s of %s to %s" % (setting.name, dev.name, value) + message = f"Setting {setting.name} of {dev.name} to {value}" result = setting.write(value, save=save) elif setting.kind == _settings.KIND.range: value = select_range(args.value_key, setting) args.value_key = value - message = "Setting %s of %s to %s" % (setting.name, dev.name, value) + message = f"Setting {setting.name} of {dev.name} to {value}" result = setting.write(value, save=save) elif setting.kind == _settings.KIND.choice: value = select_choice(args.value_key, setting.choices, setting, None) args.value_key = int(value) - message = "Setting %s of %s to %s" % (setting.name, dev.name, value) + message = f"Setting {setting.name} of {dev.name} to {value}" result = setting.write(value, save=save) elif setting.kind == _settings.KIND.map_choice: @@ -248,8 +248,8 @@ def set(dev, setting, args, save): args.extra_subkey = int(value) args.value_key = str(int(k)) else: - raise Exception("%s: key '%s' not in setting" % (setting.name, key)) - message = "Setting %s of %s key %r to %r" % (setting.name, dev.name, k, value) + raise Exception(f"{setting.name}: key '{key}' not in setting") + message = f"Setting {setting.name} of {dev.name} key {k!r} to {value!r}" result = setting.write_key_value(int(k), value, save=save) elif setting.kind == _settings.KIND.multiple_toggle: @@ -267,18 +267,18 @@ def set(dev, setting, args, save): args.extra_subkey = value args.value_key = str(int(k)) else: - raise Exception("%s: key '%s' not in setting" % (setting.name, key)) - message = "Setting %s key %r to %r" % (setting.name, k, value) + raise Exception(f"{setting.name}: key '{key}' not in setting") + message = f"Setting {setting.name} key {k!r} to {value!r}" result = setting.write_key_value(str(int(k)), value, save=save) elif setting.kind == _settings.KIND.multiple_range: if args.extra_subkey is None: - raise Exception("%s: setting needs both key and value to set" % (setting.name)) + raise Exception(f"{setting.name}: setting needs both key and value to set") key = args.value_key all_keys = getattr(setting, "choices_universe", None) ikey = all_keys[int(key) if key.isdigit() else key] if isinstance(all_keys, _NamedInts) else to_int(key) if args.extra2 is None or to_int(args.extra2) is None: - raise Exception("%s: setting needs an integer value, not %s" % (setting.name, args.extra2)) + raise Exception(f"{setting.name}: setting needs an integer value, not {args.extra2}") if not setting._value: # ensure that there are values to look through setting.read() k = next((k for k in setting._value if key == ikey or key.isdigit() and ikey == int(key)), None) @@ -289,8 +289,8 @@ def set(dev, setting, args, save): item[args.extra_subkey] = to_int(args.extra2) args.value_key = str(int(k)) else: - raise Exception("%s: key '%s' not in setting" % (setting.name, key)) - message = "Setting %s key %s parameter %s to %r" % (setting.name, k, args.extra_subkey, item[args.extra_subkey]) + raise Exception(f"{setting.name}: key '{key}' not in setting") + message = f"Setting {setting.name} key {k} parameter {args.extra_subkey} to {item[args.extra_subkey]!r}" result = setting.write_key_value(int(k), item, save=save) value = item diff --git a/lib/solaar/cli/pair.py b/lib/solaar/cli/pair.py index 1a9543cdb8..d8379fa792 100644 --- a/lib/solaar/cli/pair.py +++ b/lib/solaar/cli/pair.py @@ -32,7 +32,7 @@ def run(receivers, args, find_receiver, _ignore): receiver_name = args.receiver.lower() receiver = find_receiver(receivers, receiver_name) if not receiver: - raise Exception("no receiver found matching '%s'" % receiver_name) + raise Exception(f"no receiver found matching '{receiver_name}'") else: receiver = receivers[0] @@ -131,6 +131,6 @@ def notifications_hook(self, n): else: error = receiver.pairing.error if error: - raise Exception("pairing failed: %s" % error) + raise Exception(f"pairing failed: {error}") else: print("Paired device") # this is better than an error diff --git a/lib/solaar/cli/probe.py b/lib/solaar/cli/probe.py index 5b4c4cf612..3a2e349144 100644 --- a/lib/solaar/cli/probe.py +++ b/lib/solaar/cli/probe.py @@ -30,7 +30,7 @@ def run(receivers, args, find_receiver, _ignore): receiver_name = args.receiver.lower() receiver = find_receiver(receivers, receiver_name) if not receiver: - raise Exception("no receiver found matching '%s'" % receiver_name) + raise Exception(f"no receiver found matching '{receiver_name}'") else: receiver = receivers[0] diff --git a/lib/solaar/cli/profiles.py b/lib/solaar/cli/profiles.py index 4d99e00c6e..91cb09e8eb 100644 --- a/lib/solaar/cli/profiles.py +++ b/lib/solaar/cli/profiles.py @@ -36,7 +36,7 @@ def run(receivers, args, find_receiver, find_device): dev = None if not dev: - raise Exception("no online device found matching '%s'" % device_name) + raise Exception(f"no online device found matching '{device_name}'") if not (dev.online and dev.profiles): print(f"Device {dev.name} is either offline or has no onboard profiles") diff --git a/lib/solaar/cli/show.py b/lib/solaar/cli/show.py index 4f0e64e9e7..555fba4eec 100644 --- a/lib/solaar/cli/show.py +++ b/lib/solaar/cli/show.py @@ -33,11 +33,11 @@ def _print_receiver(receiver): print(receiver.name) print(" Device path :", receiver.path) - print(" USB id : 046d:%s" % receiver.product_id) + print(f" USB id : 046d:{receiver.product_id}") print(" Serial :", receiver.serial) pending = _hidpp10.get_configuration_pending_flags(receiver) if pending: - print(" C Pending : %02x" % pending) + print(f" C Pending : {pending:02x}") if receiver.firmware: for f in receiver.firmware: print(" %-11s: %s" % (f.kind, f.version)) @@ -50,7 +50,7 @@ def _print_receiver(receiver): if notification_flags is not None: if notification_flags: notification_names = _hidpp10_constants.NOTIFICATION_FLAG.flag_names(notification_flags) - print(" Notifications: %s (0x%06X)" % (", ".join(notification_names), notification_flags)) + print(f" Notifications: {', '.join(notification_names)} (0x{notification_flags:06X})") else: print(" Notifications: (none)") @@ -76,9 +76,9 @@ def _battery_line(dev): level, nextLevel, status, voltage = battery.level, battery.next_level, battery.status, battery.voltage text = _battery_text(level) if voltage is not None: - text = text + (" %smV " % voltage) + text = text + f" {voltage}mV " nextText = "" if nextLevel is None else ", next level " + _battery_text(nextLevel) - print(" Battery: %s, %s%s." % (text, status, nextText)) + print(f" Battery: {text}, {status}{nextText}.") else: print(" Battery status unavailable.") @@ -89,22 +89,22 @@ def _print_device(dev, num=None): try: dev.ping() except exceptions.NoSuchDevice: - print(" %s: Device not found" % num or dev.number) + print(f" {num}: Device not found" or dev.number) return if num or dev.number < 8: print(" %d: %s" % (num or dev.number, dev.name)) else: - print("%s" % dev.name) + print(f"{dev.name}") print(" Device path :", dev.path) if dev.wpid: - print(" WPID : %s" % dev.wpid) + print(f" WPID : {dev.wpid}") if dev.product_id: - print(" USB id : 046d:%s" % dev.product_id) + print(f" USB id : 046d:{dev.product_id}") print(" Codename :", dev.codename) print(" Kind :", dev.kind) if dev.protocol: - print(" Protocol : HID++ %1.1f" % dev.protocol) + print(f" Protocol : HID++ {dev.protocol:1.1f}") else: print(" Protocol : unknown (device is offline)") if dev.polling_rate: @@ -119,26 +119,26 @@ def _print_device(dev, num=None): print(" %11s:" % fw.kind, (fw.name + " " + fw.version).strip()) if dev.power_switch_location: - print(" The power switch is located on the %s." % dev.power_switch_location) + print(f" The power switch is located on the {dev.power_switch_location}.") if dev.online: notification_flags = _hidpp10.get_notification_flags(dev) if notification_flags is not None: if notification_flags: notification_names = _hidpp10_constants.NOTIFICATION_FLAG.flag_names(notification_flags) - print(" Notifications: %s (0x%06X)." % (", ".join(notification_names), notification_flags)) + print(f" Notifications: {', '.join(notification_names)} (0x{notification_flags:06X}).") else: print(" Notifications: (none).") device_features = _hidpp10.get_device_features(dev) if device_features is not None: if device_features: device_features_names = _hidpp10_constants.DEVICE_FEATURES.flag_names(device_features) - print(" Features: %s (0x%06X)" % (", ".join(device_features_names), device_features)) + print(f" Features: {', '.join(device_features_names)} (0x{device_features:06X})") else: print(" Features: (none)") if dev.online and dev.features: - print(" Supports %d HID++ 2.0 features:" % len(dev.features)) + print(f" Supports {len(dev.features)} HID++ 2.0 features:") dev_settings = [] _settings_templates.check_feature_settings(dev, dev_settings) for feature, index in dev.features.enumerate(): @@ -152,7 +152,7 @@ def _print_device(dev, num=None): wheel = _hidpp20.get_hires_wheel(dev) if wheel: multi, has_invert, has_switch, inv, res, target, ratchet = wheel - print(" Multiplier: %s" % multi) + print(f" Multiplier: {multi}") if has_invert: print(" Has invert:", "Inverse wheel motion" if inv else "Normal wheel motion") if has_switch: @@ -168,8 +168,8 @@ def _print_device(dev, num=None): elif feature == _hidpp20_constants.FEATURE.MOUSE_POINTER: mouse_pointer = _hidpp20.get_mouse_pointer_info(dev) if mouse_pointer: - print(" DPI: %s" % mouse_pointer["dpi"]) - print(" Acceleration: %s" % mouse_pointer["acceleration"]) + print(f" DPI: {mouse_pointer['dpi']}") + print(f" Acceleration: {mouse_pointer['acceleration']}") if mouse_pointer["suggest_os_ballistics"]: print(" Use OS ballistics") else: @@ -181,9 +181,9 @@ def _print_device(dev, num=None): elif feature == _hidpp20_constants.FEATURE.VERTICAL_SCROLLING: vertical_scrolling_info = _hidpp20.get_vertical_scrolling_info(dev) if vertical_scrolling_info: - print(" Roller type: %s" % vertical_scrolling_info["roller"]) - print(" Ratchet per turn: %s" % vertical_scrolling_info["ratchet"]) - print(" Scroll lines: %s" % vertical_scrolling_info["lines"]) + print(f" Roller type: {vertical_scrolling_info['roller']}") + print(f" Ratchet per turn: {vertical_scrolling_info['ratchet']}") + print(f" Scroll lines: {vertical_scrolling_info['lines']}") elif feature == _hidpp20_constants.FEATURE.HI_RES_SCROLLING: scrolling_mode, scrolling_resolution = _hidpp20.get_hi_res_scrolling_info(dev) if scrolling_mode: @@ -191,15 +191,15 @@ def _print_device(dev, num=None): else: print(" Hi-res scrolling disabled") if scrolling_resolution: - print(" Hi-res scrolling multiplier: %s" % scrolling_resolution) + print(f" Hi-res scrolling multiplier: {scrolling_resolution}") elif feature == _hidpp20_constants.FEATURE.POINTER_SPEED: pointer_speed = _hidpp20.get_pointer_speed_info(dev) if pointer_speed: - print(" Pointer Speed: %s" % pointer_speed) + print(f" Pointer Speed: {pointer_speed}") elif feature == _hidpp20_constants.FEATURE.LOWRES_WHEEL: wheel_status = _hidpp20.get_lowres_wheel_status(dev) if wheel_status: - print(" Wheel Reports: %s" % wheel_status) + print(f" Wheel Reports: {wheel_status}") elif feature == _hidpp20_constants.FEATURE.NEW_FN_INVERSION: inversion = _hidpp20.get_new_fn_inversion(dev) if inversion: @@ -209,28 +209,28 @@ def _print_device(dev, num=None): elif feature == _hidpp20_constants.FEATURE.HOSTS_INFO: host_names = _hidpp20.get_host_names(dev) for host, (paired, name) in host_names.items(): - print(" Host %s (%s): %s" % (host, "paired" if paired else "unpaired", name)) + print(f" Host {host} ({'paired' if paired else 'unpaired'}): {name}") elif feature == _hidpp20_constants.FEATURE.DEVICE_NAME: - print(" Name: %s" % _hidpp20.get_name(dev)) - print(" Kind: %s" % _hidpp20.get_kind(dev)) + print(f" Name: {_hidpp20.get_name(dev)}") + print(f" Kind: {_hidpp20.get_kind(dev)}") elif feature == _hidpp20_constants.FEATURE.DEVICE_FRIENDLY_NAME: - print(" Friendly Name: %s" % _hidpp20.get_friendly_name(dev)) + print(f" Friendly Name: {_hidpp20.get_friendly_name(dev)}") elif feature == _hidpp20_constants.FEATURE.DEVICE_FW_VERSION: for fw in _hidpp20.get_firmware(dev): extras = _strhex(fw.extras) if fw.extras else "" - print(" Firmware: %s %s %s %s" % (fw.kind, fw.name, fw.version, extras)) + print(f" Firmware: {fw.kind} {fw.name} {fw.version} {extras}") ids = _hidpp20.get_ids(dev) if ids: unitId, modelId, tid_map = ids - print(" Unit ID: %s Model ID: %s Transport IDs: %s" % (unitId, modelId, tid_map)) + print(f" Unit ID: {unitId} Model ID: {modelId} Transport IDs: {tid_map}") elif ( feature == _hidpp20_constants.FEATURE.REPORT_RATE or feature == _hidpp20_constants.FEATURE.EXTENDED_ADJUSTABLE_REPORT_RATE ): - print(" Report Rate: %s" % _hidpp20.get_polling_rate(dev)) + print(f" Report Rate: {_hidpp20.get_polling_rate(dev)}") elif feature == _hidpp20_constants.FEATURE.CONFIG_CHANGE: response = dev.feature_request(_hidpp20_constants.FEATURE.CONFIG_CHANGE, 0x10) - print(" Configuration: %s" % response.hex()) + print(f" Configuration: {response.hex()}") elif feature == _hidpp20_constants.FEATURE.REMAINING_PAIRING: print(" Remaining Pairings: %d" % _hidpp20.get_remaining_pairing(dev)) elif feature == _hidpp20_constants.FEATURE.ONBOARD_PROFILES: @@ -238,7 +238,7 @@ def _print_device(dev, num=None): mode = "Host" else: mode = "On-Board" - print(" Device Mode: %s" % mode) + print(f" Device Mode: {mode}") elif hidpp20.battery_functions.get(feature, None): print("", end=" ") _battery_line(dev) @@ -250,17 +250,17 @@ def _print_device(dev, num=None): and setting._device.persister.get(setting.name) is not None ): v = setting.val_to_string(setting._device.persister.get(setting.name)) - print(" %s (saved): %s" % (setting.label, v)) + print(f" {setting.label} (saved): {v}") try: v = setting.val_to_string(setting.read(False)) except exceptions.FeatureCallError as e: v = "HID++ error " + str(e) except AssertionError as e: v = "AssertionError " + str(e) - print(" %s : %s" % (setting.label, v)) + print(f" {setting.label} : {v}") if dev.online and dev.keys: - print(" Has %d reprogrammable keys:" % len(dev.keys)) + print(f" Has {len(dev.keys)} reprogrammable keys:") for k in dev.keys: # TODO: add here additional variants for other REPROG_CONTROLS if dev.keys.keyversion == _hidpp20_constants.FEATURE.REPROG_CONTROLS_V2: @@ -272,9 +272,9 @@ def _print_device(dev, num=None): print(" %s, pos:%d, group:%1d, group mask:%s" % (", ".join(k.flags), k.pos, k.group, gmask_fmt)) report_fmt = ", ".join(k.mapping_flags) report_fmt = report_fmt if report_fmt else "default" - print(" reporting: %s" % (report_fmt)) + print(f" reporting: {report_fmt}") if dev.online and dev.remap_keys: - print(" Has %d persistent remappable keys:" % len(dev.remap_keys)) + print(f" Has {len(dev.remap_keys)} persistent remappable keys:") for k in dev.remap_keys: print(" %2d: %-26s => %s%s" % (k.index, k.key, k.action, " (remapped)" if k.cidStatus else "")) if dev.online and dev.gestures: @@ -301,7 +301,7 @@ def run(devices, args, find_receiver, find_device): assert devices assert args.device - print("%s version %s" % (NAME.lower(), __version__)) + print(f"{NAME.lower()} version {__version__}") print("") device_name = args.device.lower() @@ -331,6 +331,6 @@ def run(devices, args, find_receiver, find_device): dev = next(find_device(devices, device_name), None) if not dev: - raise Exception("no device found matching '%s'" % device_name) + raise Exception(f"no device found matching '{device_name}'") _print_device(dev) diff --git a/lib/solaar/cli/unpair.py b/lib/solaar/cli/unpair.py index cc2ece848a..bd6e8faa1f 100644 --- a/lib/solaar/cli/unpair.py +++ b/lib/solaar/cli/unpair.py @@ -22,7 +22,7 @@ def run(receivers, args, find_receiver, find_device): device_name = args.device.lower() dev = next(find_device(receivers, device_name), None) if not dev: - raise Exception("no device found matching '%s'" % device_name) + raise Exception(f"no device found matching '{device_name}'") if not dev.receiver.may_unpair: print( diff --git a/lib/solaar/gtk.py b/lib/solaar/gtk.py index b4cb72023f..3451000a94 100755 --- a/lib/solaar/gtk.py +++ b/lib/solaar/gtk.py @@ -51,7 +51,7 @@ def _require(module, os_package, gi=None, gi_package=None, gi_version=None): gi.require_version(gi_package, gi_version) return importlib.import_module(module) except (ImportError, ValueError): - sys.exit("%s: missing required system package %s" % (NAME.lower(), os_package)) + sys.exit(f"{NAME.lower()}: missing required system package {os_package}") battery_icons_style = "regular" @@ -134,7 +134,7 @@ def _handlesig(signl, stack): if signl == int(signal.SIGINT): if logger.isEnabledFor(logging.INFO): faulthandler.dump_traceback() - sys.exit("%s: exit due to keyboard interrupt" % (NAME.lower())) + sys.exit(f"{NAME.lower()}: exit due to keyboard interrupt") else: sys.exit(0) @@ -180,7 +180,7 @@ def main(): # main UI event loop _ui.run_loop(_listener.start_all, _listener.stop_all, args.window != "only", args.window != "hide") except Exception: - sys.exit("%s: error: %s" % (NAME.lower(), format_exc())) + sys.exit(f"{NAME.lower()}: error: {format_exc()}") temp.close() diff --git a/lib/solaar/listener.py b/lib/solaar/listener.py index da09bca897..649bd420c8 100644 --- a/lib/solaar/listener.py +++ b/lib/solaar/listener.py @@ -89,7 +89,7 @@ def has_stopped(self): try: r.close() except Exception: - logger.exception("closing receiver %s" % r.path) + logger.exception(f"closing receiver {r.path}") self.status_changed_callback(r) def _status_changed(self, device, alert=None, reason=None): @@ -226,7 +226,7 @@ def _notifications_handler(self, n): dev.ping() def __str__(self): - return "" % (self.receiver.path, self.receiver.handle) + return f"" _all_listeners = {} # all known receiver listeners, listeners that stop on their own may remain here diff --git a/lib/solaar/ui/diversion_rules.py b/lib/solaar/ui/diversion_rules.py index 2aecf2c968..15685adea2 100644 --- a/lib/solaar/ui/diversion_rules.py +++ b/lib/solaar/ui/diversion_rules.py @@ -1283,7 +1283,7 @@ def left_label(cls, component): @classmethod def right_label(cls, component): - return "%s (%04X)" % (str(component.feature), int(component.feature or 0)) + return f"{str(component.feature)} ({int(component.feature or 0):04X})" class ReportUI(ConditionUI): @@ -1407,7 +1407,7 @@ def left_label(cls, component): @classmethod def right_label(cls, component): - return "%s (%04X) (%s)" % (str(component.key), int(component.key), _(component.action)) if component.key else "None" + return f"{str(component.key)} ({int(component.key):04X}) ({_(component.action)})" if component.key else "None" class KeyIsDownUI(ConditionUI): @@ -1448,7 +1448,7 @@ def left_label(cls, component): @classmethod def right_label(cls, component): - return "%s (%04X)" % (str(component.key), int(component.key)) if component.key else "None" + return f"{str(component.key)} ({int(component.key):04X})" if component.key else "None" class TestUI(ConditionUI): diff --git a/lib/solaar/ui/pair_window.py b/lib/solaar/ui/pair_window.py index 5e8e2256cf..b1386893ef 100644 --- a/lib/solaar/ui/pair_window.py +++ b/lib/solaar/ui/pair_window.py @@ -220,7 +220,7 @@ def _pairing_succeeded(assistant, receiver, device): page.pack_start(device_icon, True, True, 0) device_label = Gtk.Label() - device_label.set_markup("%s" % device.name) + device_label.set_markup(f"{device.name}") device_label.set_alignment(0.5, 0) page.pack_start(device_label, True, True, 0) diff --git a/lib/solaar/ui/tray.py b/lib/solaar/ui/tray.py index 88ab364e6c..47a74a9a40 100644 --- a/lib/solaar/ui/tray.py +++ b/lib/solaar/ui/tray.py @@ -160,7 +160,7 @@ def _scroll(tray_icon, event, direction=None): raise ImportError from exc if logger.isEnabledFor(logging.DEBUG): - logger.debug("using %sAppIndicator3" % ("Ayatana " if ayatana_appindicator_found else "")) + logger.debug(f"using {'Ayatana ' if ayatana_appindicator_found else ''}AppIndicator3") # Defense against AppIndicator3 bug that treats files in current directory as icon files # https://bugs.launchpad.net/ubuntu/+source/libappindicator/+bug/1363277 @@ -200,7 +200,7 @@ def _update_tray_icon(): battery_level = device.battery_info.level if device.battery_info is not None else None battery_charging = device.battery_info.charging() if device.battery_info is not None else None tray_icon_name = _icons.battery(battery_level, battery_charging) - description = "%s: %s" % (name, device.status_string()) + description = f"{name}: {device.status_string()}" else: # there may be a receiver, but no peripherals tray_icon_name = _icons.TRAY_OKAY if _devices_info else _icons.TRAY_INIT @@ -290,7 +290,7 @@ def attention(reason=None): def _generate_tooltip_lines(): if not _devices_info: - yield "%s: " % NAME + _("no receiver") + yield f"{NAME}: " + _("no receiver") return yield from _generate_description_lines() @@ -307,16 +307,16 @@ def _generate_description_lines(): p = device.status_string() if p: # does it have any properties to print? - yield "%s" % name + yield f"{name}" if device.online: - yield "\t%s" % p + yield f"\t{p}" else: - yield "\t%s (" % p + _("offline") + ")" + yield f"\t{p} (" + _("offline") + ")" else: if device.online: - yield "%s (" % name + _("no status") + ")" + yield f"{name} (" + _("no status") + ")" else: - yield "%s (" % name + _("offline") + ")" + yield f"{name} (" + _("offline") + ")" def _pick_device_with_lowest_battery(): diff --git a/lib/solaar/ui/window.py b/lib/solaar/ui/window.py index bac0442d51..eba142a1a7 100644 --- a/lib/solaar/ui/window.py +++ b/lib/solaar/ui/window.py @@ -555,7 +555,7 @@ def _details_items(device, read_all=False): if device.product_id: yield (_("Product ID"), "046d:" + device.product_id) hid_version = device.protocol - yield (_("Protocol"), "HID++ %1.1f" % hid_version if hid_version else _("Unknown")) + yield (_("Protocol"), f"HID++ {hid_version:1.1f}" if hid_version else _("Unknown")) if read_all and device.polling_rate: yield (_("Polling rate"), device.polling_rate) @@ -571,12 +571,12 @@ def _details_items(device, read_all=False): for fw in list(device.firmware): yield (" " + _(str(fw.kind)), (fw.name + " " + fw.version).strip()) elif device.kind is None or device.online: - yield (" %s" % _("Firmware"), "...") + yield (f" {_('Firmware')}", "...") flag_bits = device.notification_flags if flag_bits is not None: flag_names = ( - ("(%s)" % _("none"),) if flag_bits == 0 else _hidpp10_constants.NOTIFICATION_FLAG.flag_names(flag_bits) + (f"({_('none')})",) if flag_bits == 0 else _hidpp10_constants.NOTIFICATION_FLAG.flag_names(flag_bits) ) yield (_("Notifications"), ("\n%15s" % " ").join(flag_names)) @@ -638,7 +638,7 @@ def _update_receiver_panel(receiver, panel, buttons, full=False): % {"max_count": receiver.max_devices} ) elif devices_count > 0: - paired_text += "\n\n%s" % _("Only one device can be paired to this receiver.") + paired_text += f"\n\n{_('Only one device can be paired to this receiver.')}" pairings = receiver.remaining_pairings() if pairings is not None and pairings >= 0: paired_text += "\n%s" % ( @@ -718,9 +718,9 @@ def _update_device_panel(device, panel, buttons, full=False): tooltip_text = tooltip_text + _(" and next level to be reported.") if is_online: if charging: - text += " (%s)" % _("charging") + text += f" ({_('charging')})" else: - text += " (%s)" % _("last known") + text += f" ({_('last known')})" panel._battery._text.set_markup(text) panel._battery.set_tooltip_text(tooltip_text) @@ -746,7 +746,7 @@ def _update_device_panel(device, panel, buttons, full=False): else: panel._secure.set_visible(True) panel._secure._icon.set_visible(False) - panel._secure._text.set_markup("%s" % _("offline")) + panel._secure._text.set_markup(f"{_('offline')}") panel._secure.set_tooltip_text("") if is_online: @@ -782,7 +782,7 @@ def _update_info_panel(device, full=False): # a device must be paired assert device - _info._title.set_markup("%s" % device.name) + _info._title.set_markup(f"{device.name}") icon_name = _icons.device_icon_name(device.name, device.kind) _info._icon.set_from_icon_name(icon_name, _DEVICE_ICON_SIZE)