From 73d35e35ecb3a1b0d2afc7d78b41cec2e5bb0308 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Mon, 5 Oct 2026 16:44:50 +0000 Subject: [PATCH 1/3] Pass channel names as keyword arguments in actor examples The `compose.py` and `select.py` examples in the actor module guide create `Broadcast` channels passing the name positionally, but `name` is a keyword-only argument in frequenz-channels v1, so the examples fail with a `TypeError`. These examples were never linted because their fences have a `title` option, which made the example linter skip them (frequenz-floss/frequenz-repo-config-python#652). Signed-off-by: Leandro Lucarella --- src/frequenz/sdk/actor/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/frequenz/sdk/actor/__init__.py b/src/frequenz/sdk/actor/__init__.py index 19615aa04..40dd6333e 100644 --- a/src/frequenz/sdk/actor/__init__.py +++ b/src/frequenz/sdk/actor/__init__.py @@ -380,9 +380,9 @@ async def _run(self) -> None: async def main() -> None: # (2)! # (4)! - input_channel: Broadcast[str] = Broadcast("Input to Actor1") - middle_channel: Broadcast[str] = Broadcast("Actor1 -> Actor2 stream") - output_channel: Broadcast[str] = Broadcast("Actor2 output") + input_channel: Broadcast[str] = Broadcast(name="Input to Actor1") + middle_channel: Broadcast[str] = Broadcast(name="Actor1 -> Actor2 stream") + output_channel: Broadcast[str] = Broadcast(name="Actor2 output") input_sender = input_channel.new_sender() output_receiver = output_channel.new_receiver() @@ -497,9 +497,9 @@ async def _run(self) -> None: # (2)! # (3)! -input_channel_1 = Broadcast[bool]("input_channel_1") -input_channel_2 = Broadcast[bool]("input_channel_2") -echo_channel = Broadcast[bool]("echo_channel") +input_channel_1 = Broadcast[bool](name="input_channel_1") +input_channel_2 = Broadcast[bool](name="input_channel_2") +echo_channel = Broadcast[bool](name="echo_channel") echo_actor = EchoActor( # (4)! input_channel_1.new_receiver(), From 51c37c553c9e84ba6a5adb9f49a8e82b431a33e3 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Mon, 5 Oct 2026 16:45:00 +0000 Subject: [PATCH 2/3] Update the select example to the frequenz-channels v1 API `select()` and `selected_from()` are now imported from `frequenz.channels` (`frequenz.channels.util` is gone), and `Selected` exposes the received message as `message` instead of `value`, so the example failed to import and, once fixed, raised an `AttributeError`. Signed-off-by: Leandro Lucarella --- src/frequenz/sdk/actor/__init__.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/frequenz/sdk/actor/__init__.py b/src/frequenz/sdk/actor/__init__.py index 40dd6333e..992acc2eb 100644 --- a/src/frequenz/sdk/actor/__init__.py +++ b/src/frequenz/sdk/actor/__init__.py @@ -460,8 +460,7 @@ async def main() -> None: # (2)! ```python title="select.py" import asyncio -from frequenz.channels import Broadcast, Receiver, Sender -from frequenz.channels.util import select, selected_from +from frequenz.channels import Broadcast, Receiver, Sender, select, selected_from from frequenz.sdk.actor import Actor, run @@ -481,14 +480,14 @@ def __init__( async def _run(self) -> None: # (2)! async for selected in select(self._receiver_1, self._receiver_2): # (10)! if selected_from(selected, self._receiver_1): # (11)! - print(f"Received from receiver_1: {selected.value}") - await self._output.send(selected.value) - if not selected.value: # (12)! + print(f"Received from receiver_1: {selected.message}") + await self._output.send(selected.message) + if not selected.message: # (12)! break elif selected_from(selected, self._receiver_2): # (13)! - print(f"Received from receiver_2: {selected.value}") - await self._output.send(selected.value) - if not selected.value: # (14)! + print(f"Received from receiver_2: {selected.message}") + await self._output.send(selected.message) + if not selected.message: # (14)! break else: assert False, "Unknown selected channel" @@ -558,20 +557,20 @@ async def main() -> None: # (6)! `input_channel_1` (`True`) and the second from `input_channel_1` (`False`). 11. The [`selected_from()`][frequenz.channels.selected_from] function will return - `True` for the `input_channel_1` receiver. `selected.value` holds the received + `True` for the `input_channel_1` receiver. `selected.message` holds the received message, so `"Received from receiver_1: True"` will be printed and `True` will be sent to the `output` channel. -12. Since `selected.value` is `True`, the loop will continue, going back to the +12. Since `selected.message` is `True`, the loop will continue, going back to the [`select()`][frequenz.channels.select] function. 13. The [`selected_from()`][frequenz.channels.selected_from] function will return `False` for the `input_channel_1` receiver and `True` for the `input_channel_2` - receiver. The message stored in `selected.value` will now be `False`, so + receiver. The message stored in `selected.message` will now be `False`, so `"Received from receiver_2: False"` will be printed and `False` will be sent to the `output` channel. -14. Since `selected.value` is `False`, the loop will break. +14. Since `selected.message` is `False`, the loop will break. 15. The [`_run()`][_run] method will finish normally and the actor will be stopped, so the [`run()`][frequenz.sdk.actor.run] function will return. From c42d2c43bd9c082c45573ef772c8d994691565a5 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Mon, 5 Oct 2026 16:45:12 +0000 Subject: [PATCH 3/3] Fix the select example's notes and expected output The notes said both messages come from `input_channel_1`, but the second one comes from `input_channel_2`. The expected output was also missing the `EchoActor finished` line the actor prints when it stops. Signed-off-by: Leandro Lucarella --- src/frequenz/sdk/actor/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/frequenz/sdk/actor/__init__.py b/src/frequenz/sdk/actor/__init__.py index 992acc2eb..854c9dda3 100644 --- a/src/frequenz/sdk/actor/__init__.py +++ b/src/frequenz/sdk/actor/__init__.py @@ -554,7 +554,7 @@ async def main() -> None: # (6)! 10. The [`select()`][frequenz.channels.select] function will get the first message available from the two channels. The order in which they will be handled is unknown, but in this example we assume that the first message will be from - `input_channel_1` (`True`) and the second from `input_channel_1` (`False`). + `input_channel_1` (`True`) and the second from `input_channel_2` (`False`). 11. The [`selected_from()`][frequenz.channels.selected_from] function will return `True` for the `input_channel_1` receiver. `selected.message` holds the received @@ -588,6 +588,7 @@ async def main() -> None: # (6)! ``` Received from receiver_1: True Received from receiver_2: False +EchoActor finished Received message=True Received message=False ```