Skip to content

Commit f8d60f8

Browse files
committed
Leveraged str.format and str.format_map methods to substitute values in labels
- Replaced all the instances of str.replace to substitute appropriate data in labels with str.format and str.format_map methods
1 parent a2cfd14 commit f8d60f8

27 files changed

Lines changed: 373 additions & 406 deletions

src/core/widgets/glazewm/binding_mode.py

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -107,34 +107,29 @@ def _reload_css(self, label: QLabel):
107107
def _update_label(self):
108108
active_widgets = self._widgets_alt if self._show_alt_label else self._widgets
109109
active_label_content = self._label_alt_content if self._show_alt_label else self._label_content
110+
111+
active_label_content = active_label_content.format(
112+
binding_mode=(
113+
self._active_binding_mode.display_name or self._active_binding_mode.name or self._label_if_no_active
114+
),
115+
icon=self._icons.get(self._active_binding_mode.name or "none", self._default_icon),
116+
)
117+
110118
label_parts = re.split("(<span.*?>.*?</span>)", active_label_content)
111-
label_parts = [part for part in label_parts if part]
112119
widget_index = 0
113120

114-
label_options = {
115-
"{binding_mode}": self._active_binding_mode.display_name
116-
or self._active_binding_mode.name
117-
or self._label_if_no_active,
118-
"{icon}": self._icons.get(self._active_binding_mode.name or "none", self._default_icon),
119-
}
120121
for part in label_parts:
121122
part = part.strip()
122123
if part and widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel):
123-
formatted_text = part
124-
for option, value in label_options.items():
125-
formatted_text = formatted_text.replace(option, str(value))
126124
if "<span" in part and "</span>" in part:
127-
icon = re.sub(r"<span.*?>|</span>", "", part).strip()
128-
if icon in label_options:
129-
active_widgets[widget_index].setProperty(
130-
"class", f"icon {self._active_binding_mode.name or 'none'}"
131-
)
132-
active_widgets[widget_index].setText(formatted_text)
133-
else:
134-
active_widgets[widget_index].setText(icon)
125+
part = re.sub(r"<span.*?>|</span>", "", part).strip()
126+
active_widgets[widget_index].setProperty(
127+
"class", f"icon {self._active_binding_mode.name or 'none'}"
128+
)
129+
active_widgets[widget_index].setText(part)
135130
else:
136131
if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel):
137-
active_widgets[widget_index].setText(formatted_text)
132+
active_widgets[widget_index].setText(part)
138133
if active_widgets[widget_index].property("class") == "label-offline":
139134
active_widgets[widget_index].setProperty("class", "label")
140135
if not self._active_binding_mode.name:

src/core/widgets/yasb/battery.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,8 @@ def _charging_blink(self):
144144
def _update_label(self):
145145
active_widgets = self._widgets_alt if self._show_alt_label else self._widgets
146146
active_label_content = self._label_alt_content if self._show_alt_label else self._label_content
147-
label_parts = re.split("(<span.*?>.*?</span>)", active_label_content)
148-
label_parts = [part for part in label_parts if part]
149147
widget_index = 0
148+
150149
self._battery_state = psutil.sensors_battery()
151150

152151
if self._battery_state is None:
@@ -155,8 +154,13 @@ def _update_label(self):
155154
self.timer.stop()
156155
return
157156

157+
label_parts = re.split("(<span.*?>.*?</span>)", active_label_content)
158+
158159
for part in label_parts:
159160
part = part.strip()
161+
if not part:
162+
continue
163+
160164
if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel):
161165
if "<span" in part and "</span>" in part:
162166
active_widgets[widget_index].hide()
@@ -170,19 +174,21 @@ def _update_label(self):
170174
is_charging_str = "yes" if self._battery_state.power_plugged else "no"
171175
charging_icon = self._get_charging_icon(original_threshold)
172176

177+
active_label_content = active_label_content.format(
178+
percent=str(self._battery_state.percent),
179+
time_remaining=time_remaining,
180+
is_charging=is_charging_str,
181+
icon=charging_icon,
182+
)
183+
label_parts = re.split("(<span.*?>.*?</span>)", active_label_content)
184+
173185
for part in label_parts:
174186
part = part.strip()
175187
if part and widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel):
176-
battery_status = (
177-
part.replace("{percent}", str(self._battery_state.percent))
178-
.replace("{time_remaining}", time_remaining)
179-
.replace("{is_charging}", is_charging_str)
180-
.replace("{icon}", charging_icon)
181-
)
182-
if "<span" in battery_status and "</span>" in battery_status:
188+
if "<span" in part and "</span>" in part:
183189
# icon-only QLabel
184190
widget_label = active_widgets[widget_index]
185-
icon = re.sub(r"<span.*?>|</span>", "", battery_status).strip()
191+
icon = re.sub(r"<span.*?>|</span>", "", part).strip()
186192
widget_label.setText(icon)
187193
# apply status‐class
188194
existing_classes = widget_label.property("class")
@@ -207,8 +213,7 @@ def _update_label(self):
207213
refresh_widget_style(widget_label)
208214
else:
209215
alt_class = "alt" if self._show_alt_label else ""
210-
formatted_text = battery_status.format(battery_status)
211-
active_widgets[widget_index].setText(formatted_text)
216+
active_widgets[widget_index].setText(part)
212217
active_widgets[widget_index].setProperty("class", f"label {alt_class} status-{threshold}")
213218
refresh_widget_style(active_widgets[widget_index])
214219
widget_index += 1

src/core/widgets/yasb/bluetooth.py

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,6 @@ def _toggle_label(self):
310310
def _update_label(self, icon, connected_devices=None):
311311
active_widgets = self._widgets_alt if self._show_alt_label else self._widgets
312312
active_label_content = self._label_alt_content if self._show_alt_label else self._label_content
313-
label_parts = re.split("(<span.*?>.*?</span>)", active_label_content)
314-
label_parts = [part for part in label_parts if part]
315313
widget_index = 0
316314

317315
if connected_devices:
@@ -333,26 +331,25 @@ def _update_label(self, icon, connected_devices=None):
333331
device_names = self._label_no_device
334332
tooltip_text = self._label_no_device
335333

336-
label_options = {
337-
"{icon}": icon,
338-
"{device_name}": device_names,
339-
"{device_count}": len(connected_devices) if connected_devices else 0,
340-
}
334+
active_label_content = active_label_content.format(
335+
icon=icon,
336+
device_name=device_names,
337+
device_count=len(connected_devices) if connected_devices else 0,
338+
)
339+
340+
label_parts = re.split("(<span.*?>.*?</span>)", active_label_content)
341341

342342
for part in label_parts:
343343
part = part.strip()
344344
if part:
345-
formatted_text = part
346-
for option, value in label_options.items():
347-
formatted_text = formatted_text.replace(option, str(value))
348345
if "<span" in part and "</span>" in part:
349346
if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel):
350-
active_widgets[widget_index].setText(formatted_text)
347+
active_widgets[widget_index].setText(part)
351348
else:
352-
if self._max_length and len(formatted_text) > self._max_length:
353-
formatted_text = formatted_text[: self._max_length] + self._max_length_ellipsis
349+
if self._max_length and len(part) > self._max_length:
350+
part = part[: self._max_length] + self._max_length_ellipsis
354351
if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel):
355-
active_widgets[widget_index].setText(formatted_text)
352+
active_widgets[widget_index].setText(part)
356353
widget_index += 1
357354

358355
if self._tooltip:

src/core/widgets/yasb/brightness.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,7 @@ def _toggle_brightness_menu(self):
158158
def _update_label(self):
159159
active_widgets = self._widgets_alt if self._show_alt_label else self._widgets
160160
active_label_content = self._label_alt_content if self._show_alt_label else self._label_content
161-
label_parts = re.split("(<span.*?>.*?</span>)", active_label_content)
162-
label_parts = [part for part in label_parts if part]
163-
widget_index = 0
161+
164162
try:
165163
percent = self.get_brightness()
166164
if percent is None:
@@ -176,7 +174,9 @@ def _update_label(self):
176174
except Exception:
177175
percent, icon = 0, "not supported"
178176

179-
label_options = {"{icon}": icon, "{percent}": percent}
177+
active_label_content = active_label_content.format(icon=icon, percent=percent)
178+
label_parts = re.split("(<span.*?>.*?</span>)", active_label_content)
179+
widget_index = 0
180180

181181
if self._progress_bar["enabled"] and self.progress_widget:
182182
if self._widget_container_layout.indexOf(self.progress_widget) == -1:
@@ -189,15 +189,12 @@ def _update_label(self):
189189
for part in label_parts:
190190
part = part.strip()
191191
if part:
192-
formatted_text = part
193-
for option, value in label_options.items():
194-
formatted_text = formatted_text.replace(option, str(value))
195192
if "<span" in part and "</span>" in part:
196193
if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel):
197-
active_widgets[widget_index].setText(formatted_text)
194+
active_widgets[widget_index].setText(part)
198195
else:
199196
if widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel):
200-
active_widgets[widget_index].setText(formatted_text)
197+
active_widgets[widget_index].setText(part)
201198
widget_index += 1
202199

203200
def show_brightness_menu(self):

src/core/widgets/yasb/clock.py

Lines changed: 60 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -511,16 +511,33 @@ def _update_label(self):
511511
# Choose which label set to update (primary or alternate)
512512
active_widgets = self._widgets_alt if self._show_alt_label else self._widgets
513513
active_label_content = self._label_alt_content if self._show_alt_label else self._label_content
514-
label_parts = re.split("(<span.*?>.*?</span>)", active_label_content)
515-
label_parts = [part for part in label_parts if part]
516514
widget_index = 0
515+
517516
now = datetime.now(ZoneInfo(self._active_tz)) if self._active_tz else datetime.now().astimezone()
517+
518+
# Finding the datetime format string in the label using keyerror exception.
519+
try:
520+
active_label_content.format(icon="", alarm="", timedata=now)
521+
except KeyError as ke:
522+
# Remove the quotes around the exception message to get the datetime format.
523+
datetime_format = str(ke)[1:-1]
524+
525+
datetime_format_idx = active_label_content.find(datetime_format)
526+
closing_braces_idx = active_label_content.find("}", datetime_format_idx + len(datetime_format))
527+
528+
datetime_format = active_label_content[datetime_format_idx:closing_braces_idx]
529+
active_label_content = active_label_content.replace(
530+
"{" + datetime_format + "}", now.strftime(datetime_format)
531+
)
532+
518533
current_hour = f"{now.hour:02d}"
519534
current_minute = f"{now.minute:02d}"
520535
hour_changed = self._current_hour != current_hour
521536
minute_changed = self._current_minute != current_minute
537+
522538
if hour_changed:
523539
self._current_hour = current_hour
540+
524541
if minute_changed:
525542
self._current_minute = current_minute
526543

@@ -539,72 +556,53 @@ def _update_label(self):
539556
self._timer_label.hide()
540557
self._timer_visible = False
541558

559+
clock_icon = self._get_icon_for_hour(now.hour)
560+
hour_class = f"clock_{current_hour}"
561+
alarm_icon = alarm_class = ""
562+
563+
if self._shared_state._snoozed_alarms:
564+
alarm_class = "icon alarm snooze"
565+
alarm_icon = self._alarm_icons["snooze"]
566+
567+
elif self._has_enabled_alarms():
568+
alarm_icon = self._alarm_icons["enabled"]
569+
alarm_class = "icon alarm"
570+
571+
# The icon place holders are replaced with a span tag of the icon string, with all of its appropriate classes
572+
# assigned to it.
573+
label_content_values = {
574+
"icon": f'<span class="{hour_class}">{clock_icon}</span>',
575+
"alarm": f'<span class="{alarm_class}">{alarm_icon}</span>',
576+
"timedata": now,
577+
}
578+
579+
active_label_content = active_label_content.format_map(label_content_values)
580+
581+
# If any of the icon placeholders are already in a span tag, then flatten the 2 layers of nested span tags, and
582+
# merge their classes into one span tag, before sending them for parsing.
583+
active_label_content = re.sub(
584+
r'<span(?: class=([\'"])(?P<class_name>[\w -]*)\1)?><span class=([\'"])(?P<class_name2>[\w -]*)\3>(?P<label_name>.*?)</span></span>',
585+
r'<span class="\g<class_name> \g<class_name2>">\g<label_name></span>',
586+
active_label_content,
587+
)
588+
589+
label_parts = re.split("(<span.*?>.*?</span>)", active_label_content)
590+
542591
for part in label_parts:
543592
part = part.strip()
544593
if part and widget_index < len(active_widgets) and isinstance(active_widgets[widget_index], QLabel):
545594
if "<span" in part and "</span>" in part:
595+
match = re.search(r'<span class=([\'"])(?P<class_name>[\w -]*)\1>[^>]*</span>', part)
596+
classes = match.group("class_name") or ""
597+
546598
icon_placeholder = re.sub(r"<span.*?>|</span>", "", part).strip()
547-
if icon_placeholder == "{icon}":
548-
if hour_changed:
549-
icon = self._get_icon_for_hour(now.hour)
550-
active_widgets[widget_index].setText(icon)
551-
hour_class = f"clock_{current_hour}"
552-
active_widgets[widget_index].setProperty("class", f"icon {hour_class}")
553-
refresh_widget_style(active_widgets[widget_index])
554-
elif icon_placeholder == "{alarm}":
555-
if self._shared_state._snoozed_alarms:
556-
active_widgets[widget_index].setText(self._alarm_icons["snooze"])
557-
active_widgets[widget_index].setProperty("class", "icon alarm snooze")
558-
active_widgets[widget_index].setVisible(True)
559-
refresh_widget_style(active_widgets[widget_index])
560-
elif self._has_enabled_alarms():
561-
active_widgets[widget_index].setText(self._alarm_icons["enabled"])
562-
active_widgets[widget_index].setProperty("class", "icon alarm")
563-
active_widgets[widget_index].setVisible(True)
564-
refresh_widget_style(active_widgets[widget_index])
565-
else:
566-
active_widgets[widget_index].setText("")
567-
active_widgets[widget_index].setVisible(False)
568-
569-
else:
570-
active_widgets[widget_index].setText(icon_placeholder)
571-
else:
572-
has_alarm = "{alarm}" in part and (self._shared_state._snoozed_alarms or self._has_enabled_alarms())
573-
574-
if "{icon}" in part:
575-
icon = self._get_icon_for_hour(now.hour)
576-
part = part.replace("{icon}", icon)
577-
578-
if "{alarm}" in part:
579-
if self._shared_state._snoozed_alarms:
580-
part = part.replace("{alarm}", self._alarm_icons["snooze"])
581-
elif self._has_enabled_alarms():
582-
part = part.replace("{alarm}", self._alarm_icons["enabled"])
583-
else:
584-
part = part.replace("{alarm}", "")
585-
try:
586-
datetime_format_search = re.search(r"\{(.*)}", part)
587-
datetime_format_str = datetime_format_search.group()
588-
datetime_format = datetime_format_search.group(1)
589-
format_label_content = part.replace(datetime_format_str, now.strftime(datetime_format))
590-
except Exception:
591-
format_label_content = part
592-
593-
active_widgets[widget_index].setText(format_label_content)
594-
595-
alarm_state_changed = has_alarm != self._previous_alarm_state
596-
if has_alarm:
597-
if self._shared_state._snoozed_alarms:
598-
active_widgets[widget_index].setProperty("class", "label alarm snooze")
599-
else:
600-
active_widgets[widget_index].setProperty("class", "label alarm")
601-
refresh_widget_style(active_widgets[widget_index])
602-
else:
603-
hour_class = f"clock_{current_hour}"
604-
active_widgets[widget_index].setProperty("class", f"label {hour_class}")
605-
if hour_changed or alarm_state_changed:
606-
refresh_widget_style(active_widgets[widget_index])
599+
active_widgets[widget_index].setText(icon_placeholder)
600+
active_widgets[widget_index].setProperty("class", classes.strip())
601+
refresh_widget_style(active_widgets[widget_index])
607602

603+
else:
604+
active_widgets[widget_index].setText(part)
605+
has_alarm = self._shared_state._snoozed_alarms or self._has_enabled_alarms()
608606
self._previous_alarm_state = has_alarm
609607
widget_index += 1
610608

src/core/widgets/yasb/cpu.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,10 @@ def _update_label(self, cpu_freq, cpu_stats, current_perc, cores_perc, cpu_cores
164164

165165
active_widgets = self._widgets_alt if self._show_alt_label else self._widgets
166166
active_label_content = self._label_alt_content if self._show_alt_label else self._label_content
167+
active_label_content = active_label_content.format(info=cpu_info)
168+
cpu_threshold_class = self._get_cpu_threshold(current_perc)
169+
167170
label_parts = re.split("(<span.*?>.*?</span>)", active_label_content)
168-
label_parts = [part for part in label_parts if part]
169171
widget_index = 0
170172

171173
if self._progress_bar["enabled"] and self.progress_widget:
@@ -184,12 +186,8 @@ def _update_label(self, cpu_freq, cpu_stats, current_perc, cores_perc, cpu_cores
184186
active_widgets[widget_index].setText(icon)
185187
else:
186188
label_class = "label alt" if self._show_alt_label else "label"
187-
formatted_text = part.format(info=cpu_info)
188-
active_widgets[widget_index].setText(formatted_text)
189-
active_widgets[widget_index].setProperty("class", label_class)
190-
active_widgets[widget_index].setProperty(
191-
"class", f"{label_class} status-{self._get_cpu_threshold(current_perc)}"
192-
)
189+
active_widgets[widget_index].setText(part)
190+
active_widgets[widget_index].setProperty("class", f"{label_class} status-{cpu_threshold_class}")
193191
refresh_widget_style(active_widgets[widget_index])
194192
widget_index += 1
195193

0 commit comments

Comments
 (0)