Skip to content

Commit e7b98d1

Browse files
authored
Rename "value" to "message" and other minor breaking changes (#281)
This PR replaces the term "value" with "message" as "value" is too generic and used in many other contexts. It also makes `Selected.was_stopped` a property and make some function taking only one obvious argument positional-only, to avoid having the argument name being part of the interface (we actually renamed those arguments too, but that's not included in the release notes as they are not part of the public API any more anyways). We also do some other minor internal renaming and changing of arguments to positional-or-keyword-only.
2 parents 7a7c823 + d946c94 commit e7b98d1

21 files changed

+282
-277
lines changed

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ async def main() -> None:
7676
receiver = hello_channel.new_receiver()
7777

7878
await sender.send("Hello World!")
79-
msg = await receiver.receive()
80-
print(msg)
79+
message = await receiver.receive()
80+
print(message)
8181

8282

8383
asyncio.run(main())
@@ -141,8 +141,8 @@ async def send(
141141
await sender.send(f"{sender}: {counter}")
142142
counter += 1
143143
elif selected_from(selected, control_command):
144-
print(f"{sender}: Received command: {selected.value.name}")
145-
match selected.value:
144+
print(f"{sender}: Received command: {selected.message.name}")
145+
match selected.message:
146146
case Command.STOP_SENDER:
147147
print(f"{sender}: Stopping")
148148
break
@@ -166,13 +166,13 @@ async def receive(
166166
merged = merge(*receivers)
167167
async for selected in select(merged, timer, control_command):
168168
if selected_from(selected, merged):
169-
message = selected.value
169+
message = selected.message
170170
print(f"receive: Received {message=}")
171171
timer.reset()
172172
print(f"{timer=}")
173173
elif selected_from(selected, control_command):
174-
print(f"receive: received command: {selected.value.name}")
175-
match selected.value:
174+
print(f"receive: received command: {selected.message.name}")
175+
match selected.message:
176176
case Command.PING:
177177
print("receive: Ping received, reply with pong")
178178
await control_reply.send(Reply(ReplyCommand.PONG, "receive"))
@@ -181,7 +181,7 @@ async def receive(
181181
case _ as unknown:
182182
assert_never(unknown)
183183
elif selected_from(selected, timer):
184-
drift = selected.value
184+
drift = selected.message
185185
print(
186186
f"receive: No data received for {timer.interval + drift} seconds, "
187187
"giving up"

RELEASE_NOTES.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,19 @@
4444

4545
- Support classes are no longer nested inside `FileWatcher`. They are now top-level classes within the new `frequenz.channels.file_watcher` module (e.g., `frequenz.channels.util.FileWatcher.EventType` -> `frequenz.channels.file_watcher.EventType`, `frequenz.channels.util.FileWatcher.Event` -> `frequenz.channels.file_watcher.Event`).
4646

47+
* `Receiver`
48+
49+
- The `map()` function now takes a positional-only argument, if you were using `receiver.map(call=fun)` you should replace it with `receiver.map(func)`.
50+
51+
* `Selected`
52+
53+
- The `value` property was renamed to `message`.
54+
- `was_stopped` is now a property, you need to replace `selected.was_stopped()` with `selected.was_stopped`.
55+
56+
* `Sender`
57+
58+
- The `send` method now takes a positional-only argument, if you were using `sender.send(msg=message)` you should replace it with `sender.send(message)`.
59+
4760
* `Timer` and support classes
4861

4962
- Moved from `frequenz.channels.util` to `frequenz.channels.timer`.
@@ -79,9 +92,9 @@
7992

8093
* `Peekable`
8194

82-
This class was removed because it was merely a shortcut to a receiver that caches the last value received. It did not fit the channel abstraction well and was infrequently used.
95+
This class was removed because it was merely a shortcut to a receiver that caches the last message received. It did not fit the channel abstraction well and was infrequently used.
8396

84-
You can replace it with a task that receives and retains the last value.
97+
You can replace it with a task that receives and retains the last message.
8598

8699
* `Broadcast.new_peekable()`
87100

docs/_scripts/macros.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ def _slugify(text: str) -> str:
3030
Returns:
3131
The slugified text.
3232
"""
33-
# The type of the return value is not defined for the markdown library.
34-
# Also for some reason `mypy` thinks the `toc` module doesn't have a
35-
# `slugify_unicode` function, but it definitely does.
3633
return toc.slugify_unicode(text, "-")
3734

3835

docs/user-guide/receiving/synchronization/index.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ not work:
99
receiver1: Receiver[int] = channel1.new_receiver()
1010
receiver2: Receiver[int] = channel2.new_receiver()
1111

12-
msg = await receiver1.receive()
13-
print(f"Received from channel1: {msg}")
12+
message = await receiver1.receive()
13+
print(f"Received from channel1: {message}")
1414

15-
msg = await receiver2.receive()
16-
print(f"Received from channel2: {msg}")
15+
message = await receiver2.receive()
16+
print(f"Received from channel2: {message}")
1717
```
1818

1919
The problem is that if the first message is not available in `channel1` but in

src/frequenz/channels/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
* [merge][frequenz.channels.merge]: Merge messages coming from multiple receivers into
3333
a single stream.
3434
35-
* [select][frequenz.channels.select]: Iterate over the values of all
36-
[receivers][frequenz.channels.Receiver] as new values become available.
35+
* [select][frequenz.channels.select]: Iterate over the messages of all
36+
[receivers][frequenz.channels.Receiver] as new messages become available.
3737
3838
Exception classes:
3939

src/frequenz/channels/_anycast.py

Lines changed: 57 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class Anycast(Generic[_T]):
7979
When the channel is not needed anymore, it should be closed with the
8080
[`close()`][frequenz.channels.Anycast.close] method. This will prevent further
8181
attempts to [`send()`][frequenz.channels.Sender.send] data. Receivers will still be
82-
able to drain the pending values on the channel, but after that, subsequent
82+
able to drain the pending messages on the channel, but after that, subsequent
8383
[`receive()`][frequenz.channels.Receiver.receive] calls will raise a
8484
[`ReceiverStoppedError`][frequenz.channels.ReceiverStoppedError] exception.
8585
@@ -101,9 +101,9 @@ class Anycast(Generic[_T]):
101101
102102
103103
async def send(sender: Sender[int]) -> None:
104-
for msg in range(3):
105-
print(f"sending {msg}")
106-
await sender.send(msg)
104+
for message in range(3):
105+
print(f"sending {message}")
106+
await sender.send(message)
107107
108108
109109
async def main() -> None:
@@ -115,8 +115,8 @@ async def main() -> None:
115115
async with asyncio.TaskGroup() as task_group:
116116
task_group.create_task(send(sender))
117117
for _ in range(3):
118-
msg = await receiver.receive()
119-
print(f"received {msg}")
118+
message = await receiver.receive()
119+
print(f"received {message}")
120120
await asyncio.sleep(0.1) # sleep (or work) with the data
121121
122122
@@ -146,15 +146,15 @@ async def main() -> None:
146146
147147
148148
async def send(name: str, sender: Sender[int], start: int, stop: int) -> None:
149-
for msg in range(start, stop):
150-
print(f"{name} sending {msg}")
151-
await sender.send(msg)
149+
for message in range(start, stop):
150+
print(f"{name} sending {message}")
151+
await sender.send(message)
152152
153153
154154
async def recv(name: str, receiver: Receiver[int]) -> None:
155155
try:
156-
async for msg in receiver:
157-
print(f"{name} received {msg}")
156+
async for message in receiver:
157+
print(f"{name} received {message}")
158158
await asyncio.sleep(0.1) # sleep (or work) with the data
159159
except ReceiverStoppedError:
160160
pass
@@ -181,15 +181,15 @@ async def main() -> None:
181181
sender_1 sending 11
182182
sender_1 sending 12
183183
Anycast channel [Anycast:numbers:_Sender] is full, blocking sender until a receiver
184-
consumes a value
184+
consumes a message
185185
sender_2 sending 20
186186
Anycast channel [Anycast:numbers:_Sender] is full, blocking sender until a receiver
187-
consumes a value
187+
consumes a message
188188
receiver_1 received 10
189189
receiver_1 received 11
190190
sender_2 sending 21
191191
Anycast channel [Anycast:numbers:_Sender] is full, blocking sender until a receiver
192-
consumes a value
192+
consumes a message
193193
receiver_1 received 12
194194
receiver_1 received 20
195195
receiver_1 received 21
@@ -219,16 +219,16 @@ def __init__(self, *, name: str, limit: int = 10) -> None:
219219
self._send_cv: Condition = Condition()
220220
"""The condition to wait for free space in the channel's buffer.
221221
222-
If the channel's buffer is full, then the sender waits for values to
222+
If the channel's buffer is full, then the sender waits for messages to
223223
get consumed using this condition until there's some free space
224224
available in the channel's buffer.
225225
"""
226226

227227
self._recv_cv: Condition = Condition()
228-
"""The condition to wait for values in the channel's buffer.
228+
"""The condition to wait for messages in the channel's buffer.
229229
230-
If the channel's buffer is empty, then the receiver waits for values
231-
using this condition until there's a value available in the channel's
230+
If the channel's buffer is empty, then the receiver waits for messages
231+
using this condition until there's a message available in the channel's
232232
buffer.
233233
"""
234234

@@ -255,11 +255,11 @@ def is_closed(self) -> bool:
255255

256256
@property
257257
def limit(self) -> int:
258-
"""The maximum number of values that can be stored in the channel's buffer.
258+
"""The maximum number of messages that can be stored in the channel's buffer.
259259
260260
If the length of channel's buffer reaches the limit, then the sender
261261
blocks at the [send()][frequenz.channels.Sender.send] method until
262-
a value is consumed.
262+
a message is consumed.
263263
"""
264264
maxlen = self._deque.maxlen
265265
assert maxlen is not None
@@ -271,7 +271,7 @@ async def close(self) -> None:
271271
Any further attempts to [send()][frequenz.channels.Sender.send] data
272272
will return `False`.
273273
274-
Receivers will still be able to drain the pending values on the channel,
274+
Receivers will still be able to drain the pending messages on the channel,
275275
but after that, subsequent
276276
[receive()][frequenz.channels.Receiver.receive] calls will return `None`
277277
immediately.
@@ -309,16 +309,16 @@ class _Sender(Sender[_T]):
309309
method.
310310
"""
311311

312-
def __init__(self, chan: Anycast[_T]) -> None:
312+
def __init__(self, channel: Anycast[_T], /) -> None:
313313
"""Initialize this sender.
314314
315315
Args:
316-
chan: A reference to the channel that this sender belongs to.
316+
channel: A reference to the channel that this sender belongs to.
317317
"""
318-
self._chan: Anycast[_T] = chan
318+
self._channel: Anycast[_T] = channel
319319
"""The channel that this sender belongs to."""
320320

321-
async def send(self, msg: _T) -> None:
321+
async def send(self, message: _T, /) -> None:
322322
"""Send a message across the channel.
323323
324324
To send, this method inserts the message into the Anycast channel's
@@ -327,47 +327,47 @@ async def send(self, msg: _T) -> None:
327327
message will be received by exactly one receiver.
328328
329329
Args:
330-
msg: The message to be sent.
330+
message: The message to be sent.
331331
332332
Raises:
333333
SenderError: If the underlying channel was closed.
334334
A [ChannelClosedError][frequenz.channels.ChannelClosedError] is
335335
set as the cause.
336336
"""
337337
# pylint: disable=protected-access
338-
if self._chan._closed:
338+
if self._channel._closed:
339339
raise SenderError("The channel was closed", self) from ChannelClosedError(
340-
self._chan
340+
self._channel
341341
)
342-
if len(self._chan._deque) == self._chan._deque.maxlen:
342+
if len(self._channel._deque) == self._channel._deque.maxlen:
343343
_logger.warning(
344344
"Anycast channel [%s] is full, blocking sender until a receiver "
345-
"consumes a value",
345+
"consumes a message",
346346
self,
347347
)
348-
while len(self._chan._deque) == self._chan._deque.maxlen:
349-
async with self._chan._send_cv:
350-
await self._chan._send_cv.wait()
348+
while len(self._channel._deque) == self._channel._deque.maxlen:
349+
async with self._channel._send_cv:
350+
await self._channel._send_cv.wait()
351351
_logger.info(
352352
"Anycast channel [%s] has space again, resuming the blocked sender",
353353
self,
354354
)
355-
self._chan._deque.append(msg)
356-
async with self._chan._recv_cv:
357-
self._chan._recv_cv.notify(1)
355+
self._channel._deque.append(message)
356+
async with self._channel._recv_cv:
357+
self._channel._recv_cv.notify(1)
358358
# pylint: enable=protected-access
359359

360360
def __str__(self) -> str:
361361
"""Return a string representation of this sender."""
362-
return f"{self._chan}:{type(self).__name__}"
362+
return f"{self._channel}:{type(self).__name__}"
363363

364364
def __repr__(self) -> str:
365365
"""Return a string representation of this sender."""
366-
return f"{type(self).__name__}({self._chan!r})"
366+
return f"{type(self).__name__}({self._channel!r})"
367367

368368

369369
class _Empty:
370-
"""A sentinel value to indicate that a value has not been set."""
370+
"""A sentinel to indicate that a message has not been set."""
371371

372372

373373
class _Receiver(Receiver[_T]):
@@ -377,21 +377,21 @@ class _Receiver(Receiver[_T]):
377377
method.
378378
"""
379379

380-
def __init__(self, chan: Anycast[_T]) -> None:
380+
def __init__(self, channel: Anycast[_T], /) -> None:
381381
"""Initialize this receiver.
382382
383383
Args:
384-
chan: A reference to the channel that this receiver belongs to.
384+
channel: A reference to the channel that this receiver belongs to.
385385
"""
386-
self._chan: Anycast[_T] = chan
386+
self._channel: Anycast[_T] = channel
387387
"""The channel that this receiver belongs to."""
388388

389389
self._next: _T | type[_Empty] = _Empty
390390

391391
async def ready(self) -> bool:
392-
"""Wait until the receiver is ready with a value or an error.
392+
"""Wait until the receiver is ready with a message or an error.
393393
394-
Once a call to `ready()` has finished, the value should be read with
394+
Once a call to `ready()` has finished, the message should be read with
395395
a call to `consume()` (`receive()` or iterated over). The receiver will
396396
remain ready (this method will return immediately) until it is
397397
consumed.
@@ -404,31 +404,31 @@ async def ready(self) -> bool:
404404
return True
405405

406406
# pylint: disable=protected-access
407-
while len(self._chan._deque) == 0:
408-
if self._chan._closed:
407+
while len(self._channel._deque) == 0:
408+
if self._channel._closed:
409409
return False
410-
async with self._chan._recv_cv:
411-
await self._chan._recv_cv.wait()
412-
self._next = self._chan._deque.popleft()
413-
async with self._chan._send_cv:
414-
self._chan._send_cv.notify(1)
410+
async with self._channel._recv_cv:
411+
await self._channel._recv_cv.wait()
412+
self._next = self._channel._deque.popleft()
413+
async with self._channel._send_cv:
414+
self._channel._send_cv.notify(1)
415415
# pylint: enable=protected-access
416416
return True
417417

418418
def consume(self) -> _T:
419-
"""Return the latest value once `ready()` is complete.
419+
"""Return the latest message once `ready()` is complete.
420420
421421
Returns:
422-
The next value that was received.
422+
The next message that was received.
423423
424424
Raises:
425425
ReceiverStoppedError: If the receiver stopped producing messages.
426426
ReceiverError: If there is some problem with the receiver.
427427
"""
428428
if ( # pylint: disable=protected-access
429-
self._next is _Empty and self._chan._closed
429+
self._next is _Empty and self._channel._closed
430430
):
431-
raise ReceiverStoppedError(self) from ChannelClosedError(self._chan)
431+
raise ReceiverStoppedError(self) from ChannelClosedError(self._channel)
432432

433433
assert (
434434
self._next is not _Empty
@@ -442,8 +442,8 @@ def consume(self) -> _T:
442442

443443
def __str__(self) -> str:
444444
"""Return a string representation of this receiver."""
445-
return f"{self._chan}:{type(self).__name__}"
445+
return f"{self._channel}:{type(self).__name__}"
446446

447447
def __repr__(self) -> str:
448448
"""Return a string representation of this receiver."""
449-
return f"{type(self).__name__}({self._chan!r})"
449+
return f"{type(self).__name__}({self._channel!r})"

0 commit comments

Comments
 (0)