Skip to content

Releases: frequenz-floss/frequenz-channels-python

v1.4.0

05 Dec 14:12
v1.4.0
f4a6642
Compare
Choose a tag to compare

Frequenz channels Release Notes

New Features

Experimental

  • A new composable predicate, WithPrevious, to filter messages based on the previous message.

What's Changed

  • Clear release notes by @llucax in #338
  • Bump the required group across 1 directory with 9 updates by @dependabot in #337
  • Add useful predicates to filter based on the previous value by @llucax in #341
  • Prepare release notes for v1.4.0 by @llucax in #346
  • Use a float for the tolerance in the timer tests by @llucax in #347
  • Update watchfiles requirement from <0.25.0,>=0.15.0 to >=0.15.0,<1.1.0 by @dependabot in #352
  • Bump setuptools from 68.1.0 to 75.6.0 by @dependabot in #351
  • Bump the required group with 7 updates by @dependabot in #349
  • Bump setuptools-scm[toml] from 7.1.0 to 8.1.0 by @dependabot in #350
  • Fix documentation Broadcast -> Anycast by @Marenz in #358
  • Rename OnlyIfPrevious to WithPrevious by @llucax in #357
  • Update files using repo-config-0.11 by @llucax in #353
  • Bump types-markdown from 3.7.0.20240822 to 3.7.0.20241204 by @dependabot in #359

Full Changelog: v1.3.0...v1.4.0

v1.3.0

19 Nov 13:36
v1.3.0
b3c98e5
Compare
Choose a tag to compare

Frequenz channels Release Notes

New Features

  • There is a new Receiver.triggered method that can be used instead of selected_from:

    async for selected in select(recv1, recv2):
        if recv1.triggered(selected):
            print('Received from recv1:', selected.message)
        if recv2.triggered(selected):
            print('Received from recv2:', selected.message)
  • Receiver.filter() can now properly handle TypeGuards. The resulting receiver will now have the narrowed type when a TypeGuard is used.

Bug Fixes

  • Fixed a memory leak in the timer.

What's Changed

Full Changelog: v1.2.0...v1.3.0

v1.2.1

18 Nov 09:57
v1.2.1
391fe11
Compare
Choose a tag to compare

Frequenz channels Release Notes

Bug Fixes

  • Fixed a memory leak in the timer.

What's Changed

Full Changelog: v1.2.0...v1.2.1

v1.2.0

25 Sep 09:39
v1.2.0
13cf174
Compare
Choose a tag to compare

Frequenz channels Release Notes

Upgrading

  • FileWatcher: The file polling mechanism is now forced by default. This provides reliable and consistent file monitoring on network file systems (e.g., CIFS). However, it may have a performance impact on local file systems or when monitoring a large number of files.
    • To disable file polling, set the force_polling parameter to False.
    • The polling_interval parameter defines the interval for polling changes. This is relevant only when polling is enabled and defaults to 1 second.

New Features

  • Timer.reset() now supports setting the interval and will restart the timer with the new interval.

Bug Fixes

  • FileWatcher:

    • Fixed ready() method to return False when an error occurs. Before this fix, select() (and other code using ready()) never detected the FileWatcher was stopped and the select() loop was continuously waking up to inform the receiver was ready.
    • Reports file events correctly on network file systems like CIFS.
  • Timer.stop() and Timer.reset() now immediately stop the timer if it is running. Before this fix, the timer would continue to run until the next interval.

What's Changed

Full Changelog: v1.1.2...v1.2.0

v1.1.2

13 Sep 12:42
v1.1.2
62c2248
Compare
Choose a tag to compare

Frequenz channels Release Notes

Bug Fixes

  • FileWatcher: Fixed ready() method to return False when an error occurs. Before this fix, select() (and other code using ready()) never detected the FileWatcher was stopped and the select() loop was continuously waking up to inform the receiver was ready.

What's Changed

Full Changelog: v1.1.1...v1.1.2

v1.1.1

18 Jul 08:22
v1.1.1
a8710e5
Compare
Choose a tag to compare

Frequenz channels Release Notes

Summary

This release improves the documentation on Receiver.filter.

What's Changed

Full Changelog: v1.1.0...v1.1.1

v1.1.0

09 Jul 12:39
v1.1.0
a1c2102
Compare
Choose a tag to compare

Frequenz channels Release Notes

Summary

In addition to the new LatestValueCache and the ability to filter messages on Receivers, this release introduces two "Experimental" features for providing interconnections between channels.

New Features

  • The LatestValueCache class, which used to be internal to the Frequenz SDK, is now available through the channels package.

  • Experimental: RelaySender, which is a Sender that forwards the messages sent to it, to multiple senders.

  • Experimental: Pipe, which provides a pipe between two channels, by connecting a Receiver to a Sender.

  • Receivers now have a filter method that applies a filter function on the messages on a receiver.

What's Changed

  • Clear release notes by @llucax in #296
  • Bump the required group with 10 updates by @dependabot in #299
  • Bump markdown-svgbob from 202112.1022 to 202406.1023 by @dependabot in #305
  • Bump the required group with 10 updates by @dependabot in #304
  • Import the LatestValueCache implementation from the Frequenz SDK by @shsms in #302
  • Bump the required group with 2 updates by @dependabot in #309
  • Bump brettcannon/check-for-changed-files from 1.2.0 to 1.2.1 by @dependabot in #308
  • Bump docker/build-push-action from 5 to 6 by @dependabot in #307
  • Add abstractions for sharing messages between channels by @shsms in #301
  • Support filtering the messages on a receiver by @shsms in #303
  • Prepare for release v1.1.0 by @shsms in #311

Full Changelog: v1.0.1...v1.1.0

v1.0.1

15 May 10:59
v1.0.1
da86ac6
Compare
Choose a tag to compare

Frequenz channels Release Notes

Enhancements

  • The API documentation now shows the type of symbol in the table of contents.

Bug Fixes

  • Fix logger for the Broadcast channel (the log messages were missing the level, timestamp, etc.).

What's Changed

Full Changelog: v1.0.0...v1.0.1

v1.0.0

02 Apr 17:40
v1.0.0
6be80c1
Compare
Choose a tag to compare

Frequenz channels Release Notes

Summary

This is the first stable release of the Frequenz channels library.

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:

There were no changes between 1.0.0-rc.1 and this 1.0.0 final release.

If you are upgrading from v0.16.x, please keep reading these release notes.

Upgrading

  • The following symbols were moved to the top-level frequenz.channels package:

    • Selected
    • SelectError
    • UnhandledSelectedError
    • select
    • selected_from
  • util

    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).

  • All exceptions that took Any as the message argument now take str instead.

    If you were passing a non-str value to an exception, you should convert it using str(value) before passing it to the exception.

  • Anycast

    • __init__: The maxsize argument was renamed to limit and made keyword-only and a new keyword-only name (required) argument was added.

      You should instantiate using Anycast(name=..., limit=...) (or Anycast(name=...) if the default limit is enough) instead of Anycast(...) or Anycast(maxsize=...).

    • The following properties were changed:

      • limit: is now read-only.
      • closed: is now named is_closed and read-only.
    • new_sender and new_receiver: They now return a base Sender and Receiver class (respectively) instead of a channel-specific Sender or Receiver subclass.

      This means users now don't have access to the internals to the channel-specific Sender and Receiver subclasses.

  • Broadcast

    • __init__: The name and resend_latest arguments were made keyword-only.

      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).

    • The following properties were changed:

      • limit: is now read-only.
      • closed: is now named is_closed and read-only.
    • 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.

      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).

    • new_sender and new_receiver now return a base Sender and Receiver class (respectively) instead of a channel-specific Sender or Receiver subclass.

      This means users now don't have access to the internals to the channel-specific Sender and Receiver subclasses.

  • Event

    • Moved from frequenz.channels.util to frequenz.channels.event.

    • __init__: The name argument was made keyword-only. The default was changed to a more readable version of id(self).

      You should instantiate using Event(name=...) instead of Event(...).

  • FileWatcher

    • Moved from frequenz.channels.util to frequenz.channels.file_watcher.

    • 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).

  • Receiver

    • 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).
  • SelectError now inherits from channels.Error instead of BaseException, so you should be able to catch it with except Exception: or except channels.Error:.

  • Selected

    • The value property was renamed to message.
    • was_stopped is now a property, you need to replace selected.was_stopped() with selected.was_stopped.
  • Sender

    • 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).
  • Timer and support classes

    • Moved from frequenz.channels.util to frequenz.channels.timer.

Removals

  • Anycast

    • The following public properties were removed (made private): deque, send_cv, recv_cv.
  • Bidirectional

    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.

  • Broadcast

    • The following public properties were removed (made private): recv_cv, receivers.
    • new_peekable() was removed because Peekable was removed.
  • Merge

    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.

    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.

  • MergeNamed

    This class was redundant, use either the new merge() function or select() instead.

  • Peekable

    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.

    You can replace it with a task that receives and retains the last message.

  • Receiver.into_peekable() was removed because Peekable was removed.

  • ReceiverInvalidatedError was removed because it was only used when converting to a Peekable and Peekable was removed.

  • 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.

  • Timer:

    • 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:

      • Timer.periodic(interval) / Timer.periodic(interval, skip_missed_ticks=True) -> Timer(interval, TriggerAllMissed())
      • Timer.periodic(interval, skip_missed_ticks=False) -> Timer(interval, SkipMissedAndResync())
      • Timer.timeout(interval) -> Timer(interval, SkipMissedAndDrift())

New Features

  • A new Broadcast.resend_latest read-write property was added to get/set whether the latest message should be resent to new receivers.

  • Timer() and Timer.reset() now take an optional start_delay option to make the timer start after some delay.

    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.

Improvements

  • The arm64 architecture is now officially supported.

  • A new User's Guide was added to the documentation and the documentation was greately improved in general.

  • A new merge() function was added to replace Merge.

  • A warning will be logged by Anycast channels if senders are blocked because the channel buffer is full.

  • 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.

  • Sender now uses a contravariant generic type, which allows the generic type to be narrower than the required type.

  • ChannelError is now generic, so when accessing the channel attribute, the type of the channel is preserved.

  • Most classes have now a better implementation of __str__ and __repr__.

Bug Fixes

  • Timer: Fix bug that was causing calls to reset() to not reset the timer, if the timer was already being awaited.

What's Changed

Read more

v1.0.0-rc.1

07 Mar 13:05
v1.0.0-rc.1
c6c92ac
Compare
Choose a tag to compare
v1.0.0-rc.1 Pre-release
Pre-release

Frequenz channels Release Notes

Summary

This is the first release candidate for version 1.0. It includes few new features and a lot of cleanups and API improvements and polishing. Because of this, there are a lot of breaking changes too, but they should be easy to fix, as they ae mostly renames and reorganizations.

We hope this is the final pre-release before the final 1.0 release, and we don't expect to introduce any further breaking changes. Because of this we encourage you to test it and report any issues you find. You can also use a version constraint like >= 1.0.0-rc.1, < 2.0.0 as the final version should be compatible.

Upgrading

  • Anycast

    • __init__: The maxsize argument was renamed to limit and made keyword-only and a new keyword-only name argument was added.

      You should instantiate using Anycast(name=..., limit=...) (or Anycast(name=...) if the default limit is enough) instead of Anycast(...) or Anycast(maxsize=...).

    • new_sender and new_receiver: They now return a base Sender and Receiver class (respectively) instead of a channel-specific Sender or Receiver subclass.

      This means users now don't have access to the internals to the channel-specific Sender and Receiver subclasses.

  • Broadcast

    • __init__: The name argument was made optional and keyword-only; resend_latest was also made keyword-only. If a name is not specified, it will be generated from the id() of the instance.

      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).

    • 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.

      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).

    • new_sender and new_receiver now return a base Sender and Receiver class (respectively) instead of a channel-specific Sender or Receiver subclass.

      This means users now don't have access to the internals to the channel-specific Sender and Receiver subclasses.

  • Event

    • __init__: The name argument was made keyword-only. The default was changed to a more readable version of id(self).

      You should instantiate using Event(name=...) instead of Event(...).

    • Moved from frequenz.channels.util to frequenz.channels.event.

  • FileWatcher

    • Moved from frequenz.channels.util to frequenz.channels.file_watcher.

    • 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).

  • Receiver

    • 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).
  • SelectError now inherits from channels.Error instead of BaseException, so you should be able to catch it with except Exception: or except channels.Error:.

  • Selected

    • The value property was renamed to message.
    • was_stopped is now a property, you need to replace selected.was_stopped() with selected.was_stopped.
  • Sender

    • 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).
  • Timer and support classes

    • Moved from frequenz.channels.util to frequenz.channels.timer.
  • All exceptions that took Any as the message argument now take str instead.

    If you were passing a non-str value to an exception, you should convert it using str(value) before passing it to the exception.

  • The following symbols were moved to the top-level frequenz.channels package:

    • Selected
    • SelectError
    • UnhandledSelectedError
    • select
    • selected_from

Removals

  • Bidirectional

    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.

  • Merge

    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.

    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.

  • MergeNamed

    This class was redundant, use either the new merge() function or select() instead.

  • Peekable

    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.

    You can replace it with a task that receives and retains the last message.

  • Broadcast.new_peekable()

    This was removed alongside Peekable.

  • Receiver.into_peekable()

    This was removed alongside Peekable.

  • ReceiverInvalidatedError

    This was removed alongside Peekable (it was only raised when using a Receiver that was converted into a Peekable).

  • 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.

  • Timer:

    • 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:

      • Timer.periodic(interval) / Timer.periodic(interval, skip_missed_ticks=True) -> Timer(interval, TriggerAllMissed())
      • Timer.periodic(interval, skip_missed_ticks=False) -> Timer(interval, SkipMissedAndResync())
      • Timer.timeout(interval) -> Timer(interval, SkipMissedAndDrift())
  • util

    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).

New Features

  • A new User's Guide was added to the documentation and the documentation was greately improved in general.

  • A new merge() function was added to replace Merge.

  • Anycast

    • The following new read-only properties were added:

      • name: The name of the channel.
      • limit: The maximum number of messages that can be sent to the channel.
      • is_closed: Whether the channel is closed.
    • A more useful implementation of __str__ and repr` were added for the channel and its senders and receivers.

    • A warning will be logged if senders are blocked because the channel buffer is full.

  • Bidirectional

    • The following new read-only properties were added:

      • name: The name of the channel (read-only).
      • is_closed: Whether the channel is closed (read-only).
    • A more useful implementation of __str__ and repr` were added for the channel and the client and service handles.

  • Broadcast

    • The following new read-only properties were added:

      • name: The name of the channel.
      • is_closed: Whether the channel is closed.
    • A more useful implementation of __str__ and repr` were added for the channel and the client and service handles.

  • FileWatcher

    • A more useful implementation of __str__ and repr` were added.
  • Peekable

    • A more useful implementation of __str__ and repr` were added.
  • Receiver

    • map(): The returned map object now has a more useful implementation of __str__ and repr`.

Improvements

  • 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.

  • Sender now uses a contravariant generic type, which allows the generic type to be narrower than the required type.

  • ChannelError is now generic, so when accessing the channel attribute, the type of the channel is preserved.

  • The generated documentation / website was greatly improved, both in content and looks.

Bug Fixes

  • Timer: Fix bug that was causing calls to reset() to not reset the timer, if the timer was already being awaited.

What's Changed

  • Update to repo-config v0.7.2 by @llucax in #230
  • Bump the optional group with 5 updates by @dependabot in #229
  • Clean up and improve the code and public interface by @llucax in #231
  • Revamp modules structure by @llucax in #235
  • Replace Merge and MergeNamed with merge() by @llucax in #238
  • Clear release notes by @llucax in #240
  • Fix timer reset() while it is being waited on by @llucax in #241
  • Fix typo in comment by @llucax in #247
  • Make Merge public again and rename it to Merger by @llucax in h...
Read more