Skip to content

Commit b9bc2c2

Browse files
authored
Always require a priority argument in calls to microgrid.*_pool methods (#944)
This PR also makes the methods accept only keyword arguments. Closes #916
2 parents 8abd544 + dec16b1 commit b9bc2c2

File tree

17 files changed

+108
-81
lines changed

17 files changed

+108
-81
lines changed

RELEASE_NOTES.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
## Upgrading
88

9-
<!-- Here goes notes on how to upgrade from previous versions, including deprecations and what they should be replaced with -->
9+
- Calls to `microgrid.*_pool` methods now always need to specified a priority value, corresponding to the requirements/priority of the actor making the call.
10+
11+
- The `microgrid.*_pool` methods would only accept keyword arguments from now on.
1012

1113
## New Features
1214

benchmarks/power_distribution/power_distributor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ async def send_requests(batteries: set[int], request_num: int) -> list[Result]:
5050
Returns:
5151
List of the results from the PowerDistributingActor.
5252
"""
53-
battery_pool = microgrid.battery_pool(batteries)
53+
battery_pool = microgrid.battery_pool(priority=5, component_ids=batteries)
5454
results_rx = battery_pool.power_status.new_receiver()
5555
result: list[Any] = []
5656
for _ in range(request_num):

examples/battery_pool.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ async def main() -> None:
2828
resampler_config=ResamplerConfig(resampling_period=timedelta(seconds=1.0)),
2929
)
3030

31-
battery_pool = microgrid.battery_pool()
31+
battery_pool = microgrid.battery_pool(priority=5)
3232
receivers = [
3333
battery_pool.soc.new_receiver(limit=1),
3434
battery_pool.capacity.new_receiver(limit=1),

src/frequenz/sdk/actor/_power_managing/_power_managing_actor.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import asyncio
99
import logging
10+
import sys
1011
import typing
1112
from datetime import datetime, timedelta, timezone
1213

@@ -146,16 +147,22 @@ def _add_bounds_tracker(self, component_ids: frozenset[int]) -> None:
146147
bounds_receiver: Receiver[SystemBounds]
147148
# pylint: disable=protected-access
148149
if self._component_category is ComponentCategory.BATTERY:
149-
battery_pool = microgrid.battery_pool(component_ids)
150+
battery_pool = microgrid.battery_pool(
151+
priority=-sys.maxsize - 1, component_ids=component_ids
152+
)
150153
bounds_receiver = battery_pool._system_power_bounds.new_receiver()
151154
elif self._component_category is ComponentCategory.EV_CHARGER:
152-
ev_charger_pool = microgrid.ev_charger_pool(component_ids)
155+
ev_charger_pool = microgrid.ev_charger_pool(
156+
priority=-sys.maxsize - 1, component_ids=component_ids
157+
)
153158
bounds_receiver = ev_charger_pool._system_power_bounds.new_receiver()
154159
elif (
155160
self._component_category is ComponentCategory.INVERTER
156161
and self._component_type is InverterType.SOLAR
157162
):
158-
pv_pool = microgrid.pv_pool(component_ids)
163+
pv_pool = microgrid.pv_pool(
164+
priority=-sys.maxsize - 1, component_ids=component_ids
165+
)
159166
bounds_receiver = pv_pool._system_power_bounds.new_receiver()
160167
# pylint: enable=protected-access
161168
else:

src/frequenz/sdk/microgrid/_data_pipeline.py

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from __future__ import annotations
1212

1313
import logging
14-
import sys
1514
import typing
1615
from collections import abc
1716
from dataclasses import dataclass
@@ -185,21 +184,22 @@ def producer(self) -> Producer:
185184

186185
def ev_charger_pool(
187186
self,
188-
ev_charger_ids: abc.Set[int] | None = None,
187+
*,
188+
priority: int,
189+
component_ids: abc.Set[int] | None = None,
189190
name: str | None = None,
190-
priority: int = -sys.maxsize - 1,
191191
) -> EVChargerPool:
192192
"""Return the corresponding EVChargerPool instance for the given ids.
193193
194194
If an EVChargerPool instance for the given ids doesn't exist, a new one is
195195
created and returned.
196196
197197
Args:
198-
ev_charger_ids: Optional set of IDs of EV Chargers to be managed by the
198+
priority: The priority of the actor making the call.
199+
component_ids: Optional set of IDs of EV Chargers to be managed by the
199200
EVChargerPool.
200201
name: An optional name used to identify this instance of the pool or a
201202
corresponding actor in the logs.
202-
priority: The priority of the actor making the call.
203203
204204
Returns:
205205
An EVChargerPool instance.
@@ -214,8 +214,8 @@ def ev_charger_pool(
214214

215215
# We use frozenset to make a hashable key from the input set.
216216
ref_store_key: frozenset[int] = frozenset()
217-
if ev_charger_ids is not None:
218-
ref_store_key = frozenset(ev_charger_ids)
217+
if component_ids is not None:
218+
ref_store_key = frozenset(component_ids)
219219

220220
pool_key = f"{ref_store_key}-{priority}"
221221
if pool_key in self._known_pool_keys:
@@ -226,7 +226,7 @@ def ev_charger_pool(
226226
"consider reusing the same instance."
227227
"\n Hint: If the instances are created from different actors, "
228228
"consider using different priorities to distinguish them.",
229-
ev_charger_ids,
229+
component_ids,
230230
priority,
231231
)
232232
else:
@@ -246,7 +246,7 @@ def ev_charger_pool(
246246
power_manager_bounds_subs_sender=(
247247
self._ev_power_wrapper.bounds_subscription_channel.new_sender()
248248
),
249-
component_ids=ev_charger_ids,
249+
component_ids=component_ids,
250250
)
251251
)
252252
return EVChargerPool(
@@ -255,21 +255,22 @@ def ev_charger_pool(
255255

256256
def pv_pool(
257257
self,
258-
pv_inverter_ids: abc.Set[int] | None = None,
258+
*,
259+
priority: int,
260+
component_ids: abc.Set[int] | None = None,
259261
name: str | None = None,
260-
priority: int = -sys.maxsize - 1,
261262
) -> PVPool:
262263
"""Return a new `PVPool` instance for the given ids.
263264
264265
If a `PVPoolReferenceStore` instance for the given PV inverter ids doesn't
265266
exist, a new one is created and used for creating the `PVPool`.
266267
267268
Args:
268-
pv_inverter_ids: Optional set of IDs of PV inverters to be managed by the
269+
priority: The priority of the actor making the call.
270+
component_ids: Optional set of IDs of PV inverters to be managed by the
269271
`PVPool`.
270272
name: An optional name used to identify this instance of the pool or a
271273
corresponding actor in the logs.
272-
priority: The priority of the actor making the call.
273274
274275
Returns:
275276
A `PVPool` instance.
@@ -282,8 +283,8 @@ def pv_pool(
282283

283284
# We use frozenset to make a hashable key from the input set.
284285
ref_store_key: frozenset[int] = frozenset()
285-
if pv_inverter_ids is not None:
286-
ref_store_key = frozenset(pv_inverter_ids)
286+
if component_ids is not None:
287+
ref_store_key = frozenset(component_ids)
287288

288289
pool_key = f"{ref_store_key}-{priority}"
289290
if pool_key in self._known_pool_keys:
@@ -294,7 +295,7 @@ def pv_pool(
294295
"consider reusing the same instance."
295296
"\n Hint: If the instances are created from different actors, "
296297
"consider using different priorities to distinguish them.",
297-
pv_inverter_ids,
298+
component_ids,
298299
priority,
299300
)
300301
else:
@@ -313,7 +314,7 @@ def pv_pool(
313314
power_manager_bounds_subs_sender=(
314315
self._pv_power_wrapper.bounds_subscription_channel.new_sender()
315316
),
316-
component_ids=pv_inverter_ids,
317+
component_ids=component_ids,
317318
)
318319

319320
return PVPool(self._pv_pool_reference_stores[ref_store_key], name, priority)
@@ -331,21 +332,22 @@ def grid(self) -> Grid:
331332

332333
def battery_pool(
333334
self,
334-
battery_ids: abc.Set[int] | None = None,
335+
*,
336+
priority: int,
337+
component_ids: abc.Set[int] | None = None,
335338
name: str | None = None,
336-
priority: int = -sys.maxsize - 1,
337339
) -> BatteryPool:
338340
"""Return a new `BatteryPool` instance for the given ids.
339341
340-
If a `BatteryPoolReferenceStore` instance for the given battery ids doesn't exist,
341-
a new one is created and used for creating the `BatteryPool`.
342+
If a `BatteryPoolReferenceStore` instance for the given battery ids doesn't
343+
exist, a new one is created and used for creating the `BatteryPool`.
342344
343345
Args:
344-
battery_ids: Optional set of IDs of batteries to be managed by the
346+
priority: The priority of the actor making the call.
347+
component_ids: Optional set of IDs of batteries to be managed by the
345348
`BatteryPool`.
346349
name: An optional name used to identify this instance of the pool or a
347350
corresponding actor in the logs.
348-
priority: The priority of the actor making the call.
349351
350352
Returns:
351353
A `BatteryPool` instance.
@@ -360,8 +362,8 @@ def battery_pool(
360362

361363
# We use frozenset to make a hashable key from the input set.
362364
ref_store_key: frozenset[int] = frozenset()
363-
if battery_ids is not None:
364-
ref_store_key = frozenset(battery_ids)
365+
if component_ids is not None:
366+
ref_store_key = frozenset(component_ids)
365367

366368
pool_key = f"{ref_store_key}-{priority}"
367369
if pool_key in self._known_pool_keys:
@@ -372,7 +374,7 @@ def battery_pool(
372374
"consider reusing the same instance."
373375
"\n Hint: If the instances are created from different actors, "
374376
"consider using different priorities to distinguish them.",
375-
battery_ids,
377+
component_ids,
376378
priority,
377379
)
378380
else:
@@ -393,7 +395,7 @@ def battery_pool(
393395
self._battery_power_wrapper.bounds_subscription_channel.new_sender()
394396
),
395397
min_update_interval=self._resampler_config.resampling_period,
396-
batteries_id=battery_ids,
398+
batteries_id=component_ids,
397399
)
398400
)
399401

@@ -505,9 +507,10 @@ def producer() -> Producer:
505507

506508

507509
def ev_charger_pool(
508-
ev_charger_ids: abc.Set[int] | None = None,
510+
*,
511+
priority: int,
512+
component_ids: abc.Set[int] | None = None,
509513
name: str | None = None,
510-
priority: int = -sys.maxsize - 1,
511514
) -> EVChargerPool:
512515
"""Return a new `EVChargerPool` instance for the given parameters.
513516
@@ -528,23 +531,26 @@ def ev_charger_pool(
528531
power.
529532
530533
Args:
531-
ev_charger_ids: Optional set of IDs of EV Chargers to be managed by the
534+
priority: The priority of the actor making the call.
535+
component_ids: Optional set of IDs of EV Chargers to be managed by the
532536
EVChargerPool. If not specified, all EV Chargers available in the
533537
component graph are used.
534538
name: An optional name used to identify this instance of the pool or a
535539
corresponding actor in the logs.
536-
priority: The priority of the actor making the call.
537540
538541
Returns:
539542
An `EVChargerPool` instance.
540543
"""
541-
return _get().ev_charger_pool(ev_charger_ids, name, priority)
544+
return _get().ev_charger_pool(
545+
priority=priority, component_ids=component_ids, name=name
546+
)
542547

543548

544549
def battery_pool(
545-
battery_ids: abc.Set[int] | None = None,
550+
*,
551+
priority: int,
552+
component_ids: abc.Set[int] | None = None,
546553
name: str | None = None,
547-
priority: int = -sys.maxsize - 1,
548554
) -> BatteryPool:
549555
"""Return a new `BatteryPool` instance for the given parameters.
550556
@@ -565,22 +571,26 @@ def battery_pool(
565571
power.
566572
567573
Args:
568-
battery_ids: Optional set of IDs of batteries to be managed by the `BatteryPool`.
569-
If not specified, all batteries available in the component graph are used.
574+
priority: The priority of the actor making the call.
575+
component_ids: Optional set of IDs of batteries to be managed by the
576+
`BatteryPool`. If not specified, all batteries available in the component
577+
graph are used.
570578
name: An optional name used to identify this instance of the pool or a
571579
corresponding actor in the logs.
572-
priority: The priority of the actor making the call.
573580
574581
Returns:
575582
A `BatteryPool` instance.
576583
"""
577-
return _get().battery_pool(battery_ids, name, priority)
584+
return _get().battery_pool(
585+
priority=priority, component_ids=component_ids, name=name
586+
)
578587

579588

580589
def pv_pool(
581-
pv_inverter_ids: abc.Set[int] | None = None,
590+
*,
591+
priority: int,
592+
component_ids: abc.Set[int] | None = None,
582593
name: str | None = None,
583-
priority: int = -sys.maxsize - 1,
584594
) -> PVPool:
585595
"""Return a new `PVPool` instance for the given parameters.
586596
@@ -601,17 +611,17 @@ def pv_pool(
601611
power.
602612
603613
Args:
604-
pv_inverter_ids: Optional set of IDs of PV inverters to be managed by the
614+
priority: The priority of the actor making the call.
615+
component_ids: Optional set of IDs of PV inverters to be managed by the
605616
`PVPool`. If not specified, all PV inverters available in the component
606617
graph are used.
607618
name: An optional name used to identify this instance of the pool or a
608619
corresponding actor in the logs.
609-
priority: The priority of the actor making the call.
610620
611621
Returns:
612622
A `PVPool` instance.
613623
"""
614-
return _get().pv_pool(pv_inverter_ids, name, priority)
624+
return _get().pv_pool(priority=priority, component_ids=component_ids, name=name)
615625

616626

617627
def grid() -> Grid:

src/frequenz/sdk/timeseries/battery_pool/_result_types.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ def adjust_to_bounds(self, power: Power) -> tuple[Power | None, Power | None]:
6666
```python
6767
from frequenz.sdk import microgrid
6868
69-
power_status_rx = microgrid.battery_pool().power_status.new_receiver()
69+
power_status_rx = microgrid.battery_pool(
70+
priority=5,
71+
).power_status.new_receiver()
7072
power_status = await power_status_rx.receive()
7173
desired_power = Power.from_watts(1000.0)
7274

src/frequenz/sdk/timeseries/formula_engine/_formula_engine.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ class FormulaEngine(
253253
```python
254254
from frequenz.sdk import microgrid
255255
256-
battery_pool = microgrid.battery_pool()
256+
battery_pool = microgrid.battery_pool(priority=5)
257257
258258
async for power in battery_pool.power.new_receiver():
259259
print(f"{power=}")
@@ -277,8 +277,8 @@ class FormulaEngine(
277277
from frequenz.sdk import microgrid
278278
279279
logical_meter = microgrid.logical_meter()
280-
battery_pool = microgrid.battery_pool()
281-
ev_charger_pool = microgrid.ev_charger_pool()
280+
battery_pool = microgrid.battery_pool(priority=5)
281+
ev_charger_pool = microgrid.ev_charger_pool(priority=5)
282282
grid = microgrid.grid()
283283
284284
# apply operations on formula engines to create a formula engine that would
@@ -459,7 +459,7 @@ class FormulaEngine3Phase(
459459
```python
460460
from frequenz.sdk import microgrid
461461
462-
ev_charger_pool = microgrid.ev_charger_pool()
462+
ev_charger_pool = microgrid.ev_charger_pool(priority=5)
463463
464464
async for sample in ev_charger_pool.current.new_receiver():
465465
print(f"Current: {sample}")
@@ -474,7 +474,7 @@ class FormulaEngine3Phase(
474474
from frequenz.sdk import microgrid
475475
476476
logical_meter = microgrid.logical_meter()
477-
ev_charger_pool = microgrid.ev_charger_pool()
477+
ev_charger_pool = microgrid.ev_charger_pool(priority=5)
478478
grid = microgrid.grid()
479479
480480
# Calculate grid consumption current that's not used by the EV chargers

src/frequenz/sdk/timeseries/logical_meter/_logical_meter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class LogicalMeter:
4242
)
4343
4444
logical_meter = microgrid.logical_meter()
45-
pv_pool = microgrid.pv_pool()
45+
pv_pool = microgrid.pv_pool(priority=5)
4646
grid = microgrid.grid()
4747
4848
# Get a receiver for a builtin formula

0 commit comments

Comments
 (0)