Skip to content

Commit 512837b

Browse files
committed
Update release notes
Signed-off-by: Leandro Lucarella <[email protected]>
1 parent d46f36f commit 512837b

File tree

1 file changed

+80
-4
lines changed

1 file changed

+80
-4
lines changed

RELEASE_NOTES.md

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,92 @@
22

33
## Summary
44

5-
<!-- Here goes a general summary of what this release is about -->
5+
The minimum Python supported version was bumped to 3.11 and the `Select` class replaced by the new `Selector`.
66

77
## Upgrading
88

99
* The minimum supported Python version was bumped to 3.11, downstream projects will need to upgrade too to use this version.
1010

11+
* The `Select` class was replaced by a new `Selector` class, with the following improvements:
12+
13+
* Type-safe: proper type hinting by using the new helper type guard `selected_from()`.
14+
* Fixes potential starvation issues.
15+
* Simplifies the interface by providing values one-by-one.
16+
* Guarantees there are no dangling tasks left behind when used as an async context manager.
17+
18+
This new class acts as an [async context manager](https://docs.python.org/3/reference/datamodel.html#async-context-managers) and an [async iterator](https://docs.python.org/3.11/library/collections.abc.html#collections.abc.AsyncIterator), and makes sure no dangling tasks are left behind after a select loop is done.
19+
20+
Example:
21+
```python
22+
timer1 = Timer.periodic(datetime.timedelta(seconds=1))
23+
timer2 = Timer.timeout(datetime.timedelta(seconds=0.5))
24+
25+
async with Selector(timer1, timer2) as selector:
26+
async for selected in selector:
27+
if selected_from(selected, timer1):
28+
# Beware: `selected.value` might raise an exception, you can always
29+
# check for exceptions with `selected.exception` first or use
30+
# a try-except block. You can also quickly check if the receiver was
31+
# stopped and let any other unexpected exceptions bubble up.
32+
if selected.was_stopped():
33+
print("timer1 was stopped")
34+
continue
35+
print(f"timer1: now={datetime.datetime.now()} drift={selected.value}")
36+
timer2.stop()
37+
elif selected_from(selected, timer2):
38+
# Explicitly handling of exceptions
39+
match selected.exception:
40+
case ReceiverStoppedError():
41+
print("timer2 was stopped")
42+
case Exception() as exception:
43+
print(f"timer2: exception={exception}")
44+
case None:
45+
# All good, no exception, we can use `selected.value` safely
46+
print(
47+
f"timer2: now={datetime.datetime.now()} "
48+
f"drift={selected.value}"
49+
)
50+
case _ as unhanded:
51+
assert_never(unhanded)
52+
else:
53+
# This is not necessary, as select() will check for exhaustiveness, but
54+
# it is good practice to have it in case you forgot to handle a new
55+
# receiver added to `select()` at a later point in time.
56+
assert False
57+
```
58+
1159
## New Features
1260

13-
<!-- Here goes the main new features and examples or instructions on how to use them -->
61+
* A new `Selector` class was added, please look at the *Upgrading* section for details.
62+
63+
* A new `Event` utility receiver was added.
64+
65+
This receiver can be made ready manually. It is mainly useful for testing but can also become handy in scenarios where a simple, on-off signal needs to be sent to a select loop for example.
66+
67+
Example:
68+
69+
```python
70+
import asyncio
71+
from frequenz.channels import Receiver
72+
from frequenz.channels.util import Event, select, selected_from
73+
74+
other_receiver: Receiver[int] = ...
75+
exit_event = Event()
76+
77+
async def exit_after_10_seconds() -> None:
78+
asyncio.sleep(10)
79+
exit_event.set()
80+
81+
asyncio.ensure_future(exit_after_10_seconds())
1482

15-
## Bug Fixes
83+
async with Selector(exit_event, other_receiver) as selector:
84+
async for selected in selector:
85+
if selected_from(selected, exit_event):
86+
break
87+
if selected_from(selected, other_receiver):
88+
print(selected.value)
89+
else:
90+
assert False, "Unknow receiver selected"
91+
```
1692

17-
<!-- Here goes notable bug fixes that are worth a special mention or explanation -->
93+
* The `Timer` class now has more descriptive `__str__` and `__repr__` methods.

0 commit comments

Comments
 (0)