Skip to content
This repository was archived by the owner on Sep 8, 2025. It is now read-only.

Commit 2d574f6

Browse files
authored
Merge pull request #133 from jepler/dethread-wwvbtk
No need for threading in wwvbtk
2 parents 636d2d8 + 1609077 commit 2d574f6

File tree

2 files changed

+23
-14
lines changed

2 files changed

+23
-14
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ dependencies = {file = "requirements.txt"}
1919
write_to = "src/wwvb/__version__.py"
2020
[tool.ruff.lint]
2121
select = ["E", "F", "D", "I", "N", "UP", "YTT", "BLE", "B", "FBT", "A", "COM", "C4", "DTZ", "FA", "ISC", "ICN", "PIE", "PYI", "Q", "RET", "SIM", "TID", "TCH", "ARG", "PTH", "C", "R", "W", "FLY", "RUF", "PL"]
22-
ignore = ["D203", "D213", "D400", "D415", "ISC001", "E741", "C901", "PLR0911", "PLR2004", "PLR0913"]
22+
ignore = ["D203", "D213", "D400", "D415", "ISC001", "E741", "C901", "PLR0911", "PLR2004", "PLR0913", "COM812"]
2323
[tool.ruff]
2424
line-length = 120
2525
[project]

src/wwvb/wwvbtk.py

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from __future__ import annotations
88

99
import functools
10-
import threading
1110
import time
1211
from tkinter import Canvas, TclError, Tk
1312
from typing import TYPE_CHECKING, Any
@@ -31,7 +30,7 @@ def validate_colors(ctx: Any, param: Any, value: str) -> list[str]: # noqa: ARG
3130
app = _app()
3231
colors = value.split()
3332
if len(colors) not in (2, 3, 4, 6):
34-
raise click.BadParameter(f"Give 2, 3, 4 or 6 colors (not {len(colors)}")
33+
raise click.BadParameter(f"Give 2, 3, 4 or 6 colors (not {len(colors)})")
3534
for c in colors:
3635
try:
3736
app.winfo_rgb(c)
@@ -53,19 +52,24 @@ def validate_colors(ctx: Any, param: Any, value: str) -> list[str]: # noqa: ARG
5352

5453

5554
@click.command
56-
@click.option("--colors", callback=validate_colors, default=DEFAULT_COLORS)
55+
@click.option(
56+
"--colors",
57+
callback=validate_colors,
58+
default=DEFAULT_COLORS,
59+
metavar="COLORS",
60+
help="2, 3, 4, or 6 Tk color values",
61+
)
5762
@click.option("--size", default=48)
5863
@click.option("--min-size", default=None)
5964
def main(colors: list[str], size: int, min_size: int | None) -> None: # noqa: PLR0915
6065
"""Visualize the WWVB signal in realtime"""
6166
if min_size is None:
6267
min_size = size
6368

64-
def sleep_deadline(deadline: float) -> None:
65-
"""Sleep until a deadline"""
69+
def deadline_ms(deadline: float) -> int:
70+
"""Compute the number of ms until a deadline"""
6671
now = time.time()
67-
if deadline > now:
68-
time.sleep(deadline - now)
72+
return int(max(0, deadline - now) * 1000)
6973

7074
def wwvbtick() -> Generator[tuple[float, wwvb.AmplitudeModulation], None, None]:
7175
"""Yield consecutive values of the WWVB amplitude signal, going from minute to minute"""
@@ -127,18 +131,23 @@ def led_off(i: int) -> None:
127131
"""Turn the canvas's virtual LED off"""
128132
canvas.itemconfigure(circle, fill=colors[i])
129133

130-
def thread_func() -> None:
131-
"""Update the canvas virtual LED"""
134+
def controller_func() -> Generator[int]:
135+
"""Update the canvas virtual LED, yielding the number of ms until the next change"""
132136
for stamp, code in wwvbsmarttick():
133-
sleep_deadline(stamp)
137+
yield deadline_ms(stamp)
134138
led_on(code)
135139
app.update()
136-
sleep_deadline(stamp + 0.2 + 0.3 * int(code))
140+
yield deadline_ms(stamp + 0.2 + 0.3 * int(code))
137141
led_off(code)
138142
app.update()
139143

140-
thread = threading.Thread(target=thread_func, daemon=True)
141-
thread.start()
144+
controller = controller_func().__next__
145+
146+
def after_func() -> None:
147+
"""Repeatedly run the controller after the desired interval"""
148+
app.after(controller(), after_func)
149+
150+
app.after_idle(after_func)
142151
app.mainloop()
143152

144153

0 commit comments

Comments
 (0)