v0.25.0
Frequenz Python SDK Release Notes
Summary
This release replaces the @actor
decorator with a new Actor
class.
Upgrading
-
The
frequenz.sdk.power
package contained the power distribution algorithm, which is for internal use in the sdk, and is no longer part of the public API. -
PowerDistributingActor
's result typeOutOfBound
has been renamed toOutOfBounds
, and its member variablebound
has been renamed tobounds
. -
The
@actor
decorator was replaced by the newActor
class. The main differences between the new class and the old decorator are:- It doesn't start automatically,
start()
needs to be called to start an actor (using thefrequenz.sdk.actor.run()
function is recommended). - The method to implement the main logic was renamed from
run()
to_run()
, as it is not intended to be run externally. - Actors can have an optional
name
(useful for debugging/logging purposes). - The actor will only be restarted if an unhandled
Exception
is raised by_run()
. It will not be restarted if the_run()
method finishes normally. If an unhandledBaseException
is raised instead, it will be re-raised. For normal cancellation the_run()
method should handleasyncio.CancelledError
if the cancellation shouldn't be propagated (this is the same as with the decorator). - The
_stop()
method is public (stop()
) and willcancel()
andawait
for the task to finish, catching theasyncio.CancelledError
. - The
join()
method is renamed towait()
, but they can also be awaited directly (await actor
). - For deterministic cleanup, actors can now be used as
async
context managers.
Most actors can be migrated following these steps:
- Remove the decorator
- Add
Actor
as a base class - Rename
run()
to_run()
- Forward the
name
argument (optional but recommended)
For example, this old actor:
from frequenz.sdk.actor import actor @actor class TheActor: def __init__(self, actor_args) -> None: # init code def run(self) -> None: # run code
Can be migrated as:
import asyncio from frequenz.sdk.actor import Actor class TheActor(Actor): def __init__(self, actor_args, *, name: str | None = None, ) -> None: super().__init__(name=name) # init code def _run(self) -> None: # run code
Then you can instantiate all your actors first and then run them using:
from frequenz.sdk.actor import run # Init code actor = TheActor() other_actor = OtherActor() # more setup await run(actor, other_actor) # Start and await for all the actors
- It doesn't start automatically,
-
The
MovingWindow
is now aBackgroundService
, so it needs to be started manually withwindow.start()
. It is recommended to use it as anasync
context manager if possible though:async with MovingWindow(...) as window: # The moving windows is started here use(window) # The moving window is stopped here
-
The base actors (
ConfigManagingActor
,ComponentMetricsResamplingActor
,DataSourcingActor
,PowerDistributingActor
) now inherit from the newActor
class, if you are using them directly, you need to start them manually withactor.start()
and you might need to do some other adjustments. -
The
BatteryPool.power_distribution_results
method has been enhanced to provide power distribution results in the form ofPower
objects, replacing the previous use offloat
values. -
In the
Request
class:- The attribute
request_timeout_sec
has been updated and is now namedrequest_timeout
and it is represented by atimedelta
object rather than afloat
. - The attribute
power
is now presented as aPower
object, as opposed to afloat
.
- The attribute
-
Within the
EVChargerPool.set_bounds
method, the parametermax_amps
has been redefined asmax_current
, and it is now represented using aCurrent
object instead of afloat
. -
The argument
nones_are_zeros
inFormulaEngine
and related classes and methods is now a keyword-only argument.
New Features
-
Added
DFS
to the component graph -
BackgroundService
: This new abstract base class can be used to write other classes that runs one or more tasks in the background. It provides a consistent API to start and stop these services and also takes care of the handling of the background tasks. It can also work as anasync
context manager, giving the service a deterministic lifetime and guaranteed cleanup.All classes spawning tasks that are expected to run for an indeterminate amount of time are likely good candidates to use this as a base class.
-
Actor
: This new class inherits fromBackgroundService
and it replaces the@actor
decorator. -
Newly added
min
andmax
functions for Formulas. They can be used as follows:formula1.min(formula2)
Bug Fixes
-
Fixes a bug in the ring buffer updating the end timestamp of gaps when they are outdated.
-
Properly handles PV configurations with no or only some meters before the PV component.
So far we only had configurations like this:
Meter -> Inverter -> PV
. However the scenario withInverter -> PV
is also possible and now handled correctly. -
Fix
consumer_power()
not working certain configurations.In microgrids without consumers and no main meter, the formula would never return any values.
-
Fix
pv_power
not working in setups with 2 grid meters by using a new reliable function to search for components in the components graph -
Fix
consumer_power
andproducer_power
similar topv_power
-
Zero value requests received by the
PowerDistributingActor
will now always be accepted, even when there are non-zero exclusion bounds. -
Hold on to a reference to all streaming tasks in the microgrid API client, so they don't get garbage collected.
What's Changed
- Fix ring buffer gap cleanup code by @matthias-wende-frequenz in #578
- Amend deficit calculation in the power distributor by @daniel-zullo-frequenz in #577
- Clear release notes by @llucax in #574
- Bump types-protobuf from 4.23.0.3 to 4.24.0.0 by @dependabot in #576
- Bump mypy from 1.4.1 to 1.5.0 by @dependabot in #580
- Support PV configurations with no or only some meters by @Marenz in #584
- Bump mypy from 1.5.0 to 1.5.1 by @dependabot in #585
- Bump types-protobuf from 4.24.0.0 to 4.24.0.1 by @dependabot in #581
- Bump time-machine from 2.11.0 to 2.12.0 by @dependabot in #582
- Some very small fixes by @Marenz in #590
- Bump mkdocs-material from 9.1.21 to 9.2.1 by @dependabot in #592
- Fix
consumer_power()
not working certain configurations. by @Marenz in #589 - Add depth first search for components by @matthias-wende-frequenz in #595
- [ci] Add test for installation in multiple architectures by @tiyash-basu-frequenz in #597
- Improve formula generators by @matthias-wende-frequenz in #599
- Forward zero power requests always to the microgrid API by @shsms in #591
- Implement BackgroundService and new Actor class by @llucax in #564
- Replace absolute imports with relative imports by @tiyash-basu-frequenz in #604
- Drop example to private PowerDistributor API by @christianparpart in #605
- Bump mkdocs-material from 9.2.1 to 9.2.5 by @dependabot in #608
- Improve consumer power formula by @matthias-wende-frequenz in #609
- Update high-level public interfaces to concrete types by @daniel-zullo-frequenz in #607
- Make nones_are_zeros a keyword-only parameter by @daniel-zullo-frequenz in #611
- Improve error message for incorrect component graphs by @tiyash-basu-frequenz in #602
- DataPipeline: Fix resampling/ds/power actors not started by @Marenz in #603
- Bump polars from 0.18.13 to 0.18.15 by @dependabot in #583
- Add module to easily create component graphs by @Marenz in #606
- Upgrade to repo-config v0.5.2 by @llucax in #587
- Store references to streaming tasks by @shsms in #615
- Add min and max operations to formula engine by @matthias-wende-frequenz in #561
New Contributors
- @tiyash-basu-frequenz made their first contribution in #597
Full Changelog: v0.24.0...v0.25.0