v0.25.0
Frequenz Python SDK Release Notes
Summary
This release replaces the @actor decorator with a new Actor class.
Upgrading
-
The
frequenz.sdk.powerpackage 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 typeOutOfBoundhas been renamed toOutOfBounds, and its member variableboundhas been renamed tobounds. -
The
@actordecorator was replaced by the newActorclass. 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
Exceptionis raised by_run(). It will not be restarted if the_run()method finishes normally. If an unhandledBaseExceptionis raised instead, it will be re-raised. For normal cancellation the_run()method should handleasyncio.CancelledErrorif the cancellation shouldn't be propagated (this is the same as with the decorator). - The
_stop()method is public (stop()) and willcancel()andawaitfor 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
asynccontext managers.
Most actors can be migrated following these steps:
- Remove the decorator
- Add
Actoras a base class - Rename
run()to_run() - Forward the
nameargument (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
MovingWindowis now aBackgroundService, so it needs to be started manually withwindow.start(). It is recommended to use it as anasynccontext 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 newActorclass, 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_resultsmethod has been enhanced to provide power distribution results in the form ofPowerobjects, replacing the previous use offloatvalues. -
In the
Requestclass:- The attribute
request_timeout_sechas been updated and is now namedrequest_timeoutand it is represented by atimedeltaobject rather than afloat. - The attribute
poweris now presented as aPowerobject, as opposed to afloat.
- The attribute
-
Within the
EVChargerPool.set_boundsmethod, the parametermax_ampshas been redefined asmax_current, and it is now represented using aCurrentobject instead of afloat. -
The argument
nones_are_zerosinFormulaEngineand related classes and methods is now a keyword-only argument.
New Features
-
Added
DFSto 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 anasynccontext 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 fromBackgroundServiceand it replaces the@actordecorator. -
Newly added
minandmaxfunctions 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 -> PVis 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_powernot working in setups with 2 grid meters by using a new reliable function to search for components in the components graph -
Fix
consumer_powerandproducer_powersimilar topv_power -
Zero value requests received by the
PowerDistributingActorwill 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