Skip to content

Commit d9b7d22

Browse files
authored
Update release notes for the 1.0.0 final release (#288)
2 parents 1afcf80 + 7e67716 commit d9b7d22

File tree

1 file changed

+162
-4
lines changed

1 file changed

+162
-4
lines changed

RELEASE_NOTES.md

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

33
## Summary
44

5-
<!-- Here goes a general summary of what this release is about -->
5+
This is the first stable release of the Frequenz channels library.
6+
7+
If you are **upgrading from the previous 1.0.0 pre-releases**, please look into the release notes for those versions to see the changes and upgrade instructions:
8+
9+
* [1.0.0-rc.1](https://github.com/frequenz-floss/frequenz-channels-python/releases/tag/v1.0.0-rc.1)
10+
* [1.0.0-beta.2](https://github.com/frequenz-floss/frequenz-channels-python/releases/tag/v1.0.0-beta.2)
11+
* [1.0.0-beta.1](https://github.com/frequenz-floss/frequenz-channels-python/releases/tag/v1.0.0-beta.1)
12+
13+
There were no changes between 1.0.0-rc.1 and this 1.0.0 final release.
14+
15+
If you are **upgrading from v0.16.x**, please keep reading these release notes.
616

717
## Upgrading
818

9-
<!-- Here goes notes on how to upgrade from previous versions, including deprecations and what they should be replaced with -->
19+
* The following symbols were moved to the top-level `frequenz.channels` package:
20+
21+
- `Selected`
22+
- `SelectError`
23+
- `UnhandledSelectedError`
24+
- `select`
25+
- `selected_from`
26+
27+
* `util`
28+
29+
The entire `util` package was removed and its symbols were either moved to the top-level package or to their own public modules (as noted above).
30+
31+
* All exceptions that took `Any` as the `message` argument now take `str` instead.
32+
33+
If you were passing a non-`str` value to an exception, you should convert it using `str(value)` before passing it to the exception.
34+
35+
* `Anycast`
36+
37+
- `__init__`: The `maxsize` argument was renamed to `limit` and made keyword-only and a new keyword-only `name` (required) argument was added.
38+
39+
You should instantiate using `Anycast(name=..., limit=...)` (or `Anycast(name=...)` if the default `limit` is enough) instead of `Anycast(...)` or `Anycast(maxsize=...)`.
40+
41+
- The following properties were changed:
42+
43+
- `limit`: is now read-only.
44+
- `closed`: is now named `is_closed` and read-only.
45+
46+
- `new_sender` and `new_receiver`: They now return a base `Sender` and `Receiver` class (respectively) instead of a channel-specific `Sender` or `Receiver` subclass.
47+
48+
This means users now don't have access to the internals to the channel-specific `Sender` and `Receiver` subclasses.
49+
50+
* `Broadcast`
51+
52+
- `__init__`: The `name` and `resend_latest` arguments were made keyword-only.
53+
54+
You should instantiate using `Broadcast(name=name, resend_latest=resend_latest)` (or `Broadcast()` if the defaults are enough) instead of `Broadcast(name)` or `Broadcast(name, resend_latest)`.
55+
56+
- The following properties were changed:
57+
58+
- `limit`: is now read-only.
59+
- `closed`: is now named `is_closed` and read-only.
60+
61+
- `new_receiver`: The `maxsize` argument was renamed to `limit` and made keyword-only; the `name` argument was also made keyword-only. If a `name` is not specified, it will be generated from the `id()` of the instance instead of a random UUID.
62+
63+
You should use `.new_receiver(name=name, limit=limit)` (or `.new_receiver()` if the defaults are enough) instead of `.new_receiver(name)` or `.new_receiver(name, maxsize)`.
64+
65+
- `new_sender` and `new_receiver` now return a base `Sender` and `Receiver` class (respectively) instead of a channel-specific `Sender` or `Receiver` subclass.
66+
67+
This means users now don't have access to the internals to the channel-specific `Sender` and `Receiver` subclasses.
68+
69+
* `Event`
70+
71+
- Moved from `frequenz.channels.util` to `frequenz.channels.event`.
72+
73+
- `__init__`: The `name` argument was made keyword-only. The default was changed to a more readable version of `id(self)`.
74+
75+
You should instantiate using `Event(name=...)` instead of `Event(...)`.
76+
77+
* `FileWatcher`
78+
79+
- Moved from `frequenz.channels.util` to `frequenz.channels.file_watcher`.
80+
81+
- 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`).
82+
83+
* `Receiver`
84+
85+
- 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)`.
86+
87+
* `SelectError` now inherits from `channels.Error` instead of `BaseException`, so you should be able to catch it with `except Exception:` or `except channels.Error:`.
88+
89+
* `Selected`
90+
91+
- The `value` property was renamed to `message`.
92+
- `was_stopped` is now a property, you need to replace `selected.was_stopped()` with `selected.was_stopped`.
93+
94+
* `Sender`
95+
96+
- 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)`.
97+
98+
* `Timer` and support classes
99+
100+
- Moved from `frequenz.channels.util` to `frequenz.channels.timer`.
101+
102+
### Removals
103+
104+
* `Anycast`
105+
106+
- The following public properties were removed (made private): `deque`, `send_cv`, `recv_cv`.
107+
108+
* `Bidirectional`
109+
110+
This channel was removed as it is not recommended practice and was a niche use case. If you need to use it, you can set up two channels or copy the `Bidirectional` class from the previous version to your project.
111+
112+
* `Broadcast`
113+
114+
- The following public properties were removed (made private): `recv_cv`, `receivers`.
115+
- `new_peekable()` was removed because `Peekable` was removed.
116+
117+
* `Merge`
118+
119+
Replaced by the new `merge()` function. When replacing `Merge` with `merge()` please keep in mind that this new function will raise a `ValueError` if no receivers are passed to it.
120+
121+
Please note that the old `Merge` class is still also available but it was renamed to `Merger` to avoid confusion with the new `merge()` function, but it is only present for typing reasons and should not be used directly.
122+
123+
* `MergeNamed`
124+
125+
This class was redundant, use either the new `merge()` function or `select()` instead.
126+
127+
* `Peekable`
128+
129+
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.
130+
131+
You can replace it with a task that receives and retains the last message.
132+
133+
* `Receiver.into_peekable()` was removed because `Peekable` was removed.
134+
135+
* `ReceiverInvalidatedError` was removed because it was only used when converting to a `Peekable` and `Peekable` was removed.
136+
137+
* `SelectErrorGroup` was removed, a Python built-in `BaseExceptionGroup` is raised instead in case of unexpected errors while finalizing a `select()` loop, which will be automatically converted to a simple `ExceptionGroup` when no exception in the groups is a `BaseException`.
138+
139+
- `Timer`:
140+
141+
- `periodic()` and `timeout()`: The names proved to be too confusing, please use `Timer()` and pass a missing ticks policy explicitly instead. In general you can update your code by doing:
142+
143+
* `Timer.periodic(interval)` / `Timer.periodic(interval, skip_missed_ticks=True)` -> `Timer(interval, TriggerAllMissed())`
144+
* `Timer.periodic(interval, skip_missed_ticks=False)` -> `Timer(interval, SkipMissedAndResync())`
145+
* `Timer.timeout(interval)` -> `Timer(interval, SkipMissedAndDrift())`
10146

11147
## New Features
12148

13-
<!-- Here goes the main new features and examples or instructions on how to use them -->
149+
* A new `Broadcast.resend_latest` read-write property was added to get/set whether the latest message should be resent to new receivers.
150+
151+
* `Timer()` and `Timer.reset()` now take an optional `start_delay` option to make the timer start after some delay.
152+
153+
This can be useful, for example, if the timer needs to be *aligned* to a particular time. The alternative to this would be to `sleep()` for the time needed to align the timer, but if the `sleep()` call gets delayed because the event loop is busy, then a re-alignment is needed and this could go on for a while. The only way to guarantee a certain alignment (with a reasonable precision) is to delay the timer start.
154+
155+
## Improvements
156+
157+
* The arm64 architecture is now officially supported.
158+
159+
* A new User's Guide was added to the documentation and the documentation was greately improved in general.
160+
161+
* A new `merge()` function was added to replace `Merge`.
162+
163+
* A warning will be logged by `Anycast` channels if senders are blocked because the channel buffer is full.
164+
165+
* `Receiver`, `merge`/`Merger`, `Error` and its derived classes now use a covariant generic type, which allows the generic type to be broader than the actual type.
166+
167+
* `Sender` now uses a contravariant generic type, which allows the generic type to be narrower than the required type.
168+
169+
* `ChannelError` is now generic, so when accessing the `channel` attribute, the type of the channel is preserved.
170+
171+
* Most classes have now a better implementation of `__str__` and `__repr__`.
14172

15173
## Bug Fixes
16174

17-
<!-- Here goes notable bug fixes that are worth a special mention or explanation -->
175+
* `Timer`: Fix bug that was causing calls to `reset()` to not reset the timer, if the timer was already being awaited.

0 commit comments

Comments
 (0)