v0.16.0
Frequenz Channels Release Notes
Summary
The minimum Python supported version was bumped to 3.11 and the Select
class replaced by the new select()
function.
Upgrading
-
The minimum supported Python version was bumped to 3.11, downstream projects will need to upgrade too to use this version.
-
The
Select
class was replaced by a newselect()
function, with the following improvements:- Type-safe: proper type hinting by using the new helper type guard
selected_from()
. - Fixes potential starvation issues.
- Simplifies the interface by providing values one-by-one.
- Guarantees there are no dangling tasks left behind when used as an async context manager.
This new function is an async iterator, and makes sure no dangling tasks are left behind after a select loop is done.
Example:
timer1 = Timer.periodic(datetime.timedelta(seconds=1)) timer2 = Timer.timeout(datetime.timedelta(seconds=0.5)) async for selected in select(timer1, timer2): if selected_from(selected, timer1): # Beware: `selected.value` might raise an exception, you can always # check for exceptions with `selected.exception` first or use # a try-except block. You can also quickly check if the receiver was # stopped and let any other unexpected exceptions bubble up. if selected.was_stopped(): print("timer1 was stopped") continue print(f"timer1: now={datetime.datetime.now()} drift={selected.value}") timer2.stop() elif selected_from(selected, timer2): # Explicitly handling of exceptions match selected.exception: case ReceiverStoppedError(): print("timer2 was stopped") case Exception() as exception: print(f"timer2: exception={exception}") case None: # All good, no exception, we can use `selected.value` safely print( f"timer2: now={datetime.datetime.now()} " f"drift={selected.value}" ) case _ as unhanded: assert_never(unhanded) else: # This is not necessary, as select() will check for exhaustiveness, but # it is good practice to have it in case you forgot to handle a new # receiver added to `select()` at a later point in time. assert False
- Type-safe: proper type hinting by using the new helper type guard
New Features
-
A new
select()
function was added, please look at the Upgrading section for details. -
A new
Event
utility receiver was added.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.
Example:
import asyncio from frequenz.channels import Receiver from frequenz.channels.util import Event, select, selected_from other_receiver: Receiver[int] = ... exit_event = Event() async def exit_after_10_seconds() -> None: asyncio.sleep(10) exit_event.set() asyncio.ensure_future(exit_after_10_seconds()) async for selected in select(exit_event, other_receiver): if selected_from(selected, exit_event): break if selected_from(selected, other_receiver): print(selected.value) else: assert False, "Unknow receiver selected"
-
The
Timer
class now has more descriptive__str__
and__repr__
methods.
What's Changed
- Clear release notes by @leandro-lucarella-frequenz in #106
- Enable merge queue by @leandro-lucarella-frequenz in #108
- Bump actions/labeler from 4.0.3 to 4.0.4 by @dependabot in #110
- Add possible values to timer missed_tick_policy parameter documentation by @Marenz in #109
- Bump mkdocstrings[python] from 0.21.2 to 0.22.0 by @dependabot in #111
- Bump mkdocs-material from 9.1.14 to 9.1.15 by @dependabot in #112
- Bump the minimum Python supported version to 3.11 by @leandro-lucarella-frequenz in #113
- Bump actions/labeler from 4.0.4 to 4.1.0 by @dependabot in #115
- Bump mkdocs-material from 9.1.15 to 9.1.16 by @dependabot in #117
- Bump mkdocs-material from 9.1.16 to 9.1.17 by @dependabot in #118
- Bump actions/labeler from 4.1.0 to 4.2.0 by @dependabot in #119
- Replace
Select
withselect()
, a type-safe async iterator by @leandro-lucarella-frequenz in #114 - Fix broken cross-reference in docs by @llucax in #120
- Fix typo in release notes example by @llucax in #121
- Run CI for tags too by @llucax in #122
New Contributors
Full Changelog: v0.15.1...v0.16.0