diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 34cef0f7a..4241c66de 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -6,7 +6,7 @@ ## Upgrading - +- The minimum required version of `frequenz-microgrid-component-graph` is now `0.3.4`. ## New Features diff --git a/pyproject.toml b/pyproject.toml index 70a9c9b63..c3b49f107 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,7 @@ dependencies = [ # changing the version # (plugins.mkdocstrings.handlers.python.import) "frequenz-client-microgrid >= 0.18.1, < 0.19.0", - "frequenz-microgrid-component-graph >= 0.3.2, < 0.4", + "frequenz-microgrid-component-graph >= 0.3.4, < 0.4", "frequenz-client-common >= 0.3.6, < 0.4.0", "frequenz-channels >= 1.6.1, < 2.0.0", "frequenz-quantities[marshmallow] >= 1.0.0, < 2.0.0", diff --git a/tests/timeseries/_battery_pool/test_battery_pool.py b/tests/timeseries/_battery_pool/test_battery_pool.py index b39b2c663..783fedb6c 100644 --- a/tests/timeseries/_battery_pool/test_battery_pool.py +++ b/tests/timeseries/_battery_pool/test_battery_pool.py @@ -21,16 +21,7 @@ import time_machine from frequenz.channels import Receiver, Sender from frequenz.client.common.microgrid.components import ComponentId -from frequenz.client.microgrid.component import ( - Battery, - Component, - ComponentCategory, - InverterType, -) -from frequenz.microgrid_component_graph import ( - FormulaGenerationError, - InvalidGraphError, -) +from frequenz.client.microgrid.component import Battery, Component from frequenz.quantities import Energy, Percentage, Power, Temperature from pytest_mock import MockerFixture @@ -46,7 +37,6 @@ from frequenz.sdk.timeseries import Bounds, ResamplerConfig2, Sample from frequenz.sdk.timeseries._base_types import SystemBounds from frequenz.sdk.timeseries.battery_pool import BatteryPool -from tests.utils.graph_generator import GraphGenerator from ...timeseries.mock_microgrid import MockMicrogrid from ...utils.component_data_streamer import MockComponentDataStreamer @@ -503,10 +493,6 @@ async def run_test_battery_status_channel( compare_messages(msg, all_pool_result) -@pytest.mark.skip( - reason="Needs to be adapted to the new component graph behavior, see " - "https://github.com/frequenz-floss/frequenz-sdk-python/issues/1345" -) async def test_battery_pool_power(mocker: MockerFixture) -> None: """Test `BatteryPool.power` method.""" mockgrid = MockMicrogrid(grid_meter=True, mocker=mocker) @@ -518,165 +504,9 @@ async def test_battery_pool_power(mocker: MockerFixture) -> None: power_receiver = battery_pool.power.new_receiver() # send meter power [grid_meter, battery1_meter, battery2_meter] - await mockgrid.mock_resampler.send_meter_power([100.0, 2.0, 3.0]) - await mockgrid.mock_resampler.send_bat_inverter_power([20.0, 30.0]) + await mockgrid.mock_resampler.send_meter_power([100.0, 20.0, 30.0]) assert (await power_receiver.receive()).value == Power.from_watts(50.0) - await mockgrid.mock_resampler.send_meter_power([100.0, -2.0, -5.0]) - await mockgrid.mock_resampler.send_bat_inverter_power([-20.0, -50.0]) - assert (await power_receiver.receive()).value == Power.from_watts(-70.0) - - await mockgrid.mock_resampler.send_meter_power([100.0, 2.0, -5.0]) - await mockgrid.mock_resampler.send_bat_inverter_power([20.0, -50.0]) - assert (await power_receiver.receive()).value == Power.from_watts(-30.0) - - -@pytest.mark.skip( - reason="Needs to be adapted to the new component graph behavior, see " - "https://github.com/frequenz-floss/frequenz-sdk-python/issues/1345" -) -async def test_battery_pool_power_two_inverters_per_battery( - mocker: MockerFixture, -) -> None: - """Test power method with two inverters per battery.""" - gen = GraphGenerator() - bat = gen.component(ComponentCategory.BATTERY) - mockgrid = MockMicrogrid( - graph=gen.to_graph( - (ComponentCategory.METER, gen.battery_with_inverter(bat, 2)) - ), - mocker=mocker, - ) - async with mockgrid, AsyncExitStack() as stack: - battery_pool = microgrid.new_battery_pool(priority=5) - stack.push_async_callback(battery_pool.stop) - power_receiver = battery_pool.power.new_receiver() - - # send meter power [grid_meter, battery1_meter] - # Fallback formula - use only meter power, inverter and batteries are not used. - await mockgrid.mock_resampler.send_meter_power([100.0, 2.0]) - await mockgrid.mock_resampler.send_bat_inverter_power([20.0, 30.0]) - assert (await power_receiver.receive()).value == Power.from_watts(50.0) - - await mockgrid.mock_resampler.send_meter_power([100.0, -5.0]) - await mockgrid.mock_resampler.send_bat_inverter_power([-20.0, -50.0]) - assert (await power_receiver.receive()).value == Power.from_watts(-70.0) - - await mockgrid.mock_resampler.send_meter_power([100.0, -5.0]) - await mockgrid.mock_resampler.send_bat_inverter_power([20.0, -50.0]) - assert (await power_receiver.receive()).value == Power.from_watts(-30.0) - - -@pytest.mark.skip( - reason="Needs to be adapted to the new component graph behavior, see " - "https://github.com/frequenz-floss/frequenz-sdk-python/issues/1345" -) -async def test_batter_pool_power_two_batteries_per_inverter( - mocker: MockerFixture, -) -> None: - """Test power method with two batteries per inverter.""" - gen = GraphGenerator() - mockgrid = MockMicrogrid( - graph=gen.to_graph( - [ - ( - ComponentCategory.METER, - ( - ComponentCategory.INVERTER, - [ComponentCategory.BATTERY, ComponentCategory.BATTERY], - ), - ), - ( - ComponentCategory.METER, - ( - ComponentCategory.INVERTER, - [ComponentCategory.BATTERY, ComponentCategory.BATTERY], - ), - ), - ] - ), - mocker=mocker, - ) - - async with mockgrid, AsyncExitStack() as stack: - battery_pool = microgrid.new_battery_pool(priority=5) - stack.push_async_callback(battery_pool.stop) - power_receiver = battery_pool.power.new_receiver() - - # send meter power [battery1_meter, battery2_meter] - # Fallback formula - use only meter power, inverter and batteries are not used. - await mockgrid.mock_resampler.send_meter_power([100.0, 3.0]) - await mockgrid.mock_resampler.send_bat_inverter_power([20.0, 30.0]) - assert (await power_receiver.receive()).value == Power.from_watts(50.0) - - await mockgrid.mock_resampler.send_meter_power([100.0, -5.0]) - await mockgrid.mock_resampler.send_bat_inverter_power([-20.0, -50.0]) - assert (await power_receiver.receive()).value == Power.from_watts(-70.0) - - await mockgrid.mock_resampler.send_meter_power([3.0, -5.0]) - await mockgrid.mock_resampler.send_bat_inverter_power([20.0, -50.0]) - assert (await power_receiver.receive()).value == Power.from_watts(-30.0) - - -async def test_batter_pool_power_no_batteries(mocker: MockerFixture) -> None: - """Test power method with no batteries.""" - graph_gen = GraphGenerator() - mockgrid = MockMicrogrid( - graph=graph_gen.to_graph( - ( - ComponentCategory.METER, - [ - graph_gen.component(ComponentCategory.INVERTER, InverterType.SOLAR), - graph_gen.component(ComponentCategory.INVERTER, InverterType.SOLAR), - ], - ) - ) - ) - await mockgrid.start(mocker) - battery_pool = microgrid.new_battery_pool(priority=5) - power_receiver = battery_pool.power.new_receiver() - - await mockgrid.mock_resampler.send_non_existing_component_value() - assert (await power_receiver.receive()).value == Power.from_watts(0) - - -async def test_battery_pool_power_with_no_inverters(mocker: MockerFixture) -> None: - """Test power method with no inverters.""" - with pytest.raises(InvalidGraphError): - mockgrid = MockMicrogrid( - graph=GraphGenerator().to_graph( - (ComponentCategory.METER, ComponentCategory.BATTERY) - ) - ) - await mockgrid.start(mocker) - - -async def test_battery_pool_power_incomplete_bat_request(mocker: MockerFixture) -> None: - """Test power method when not all requested ids are behind the same inverter.""" - gen = GraphGenerator() - bats = gen.components( - ComponentCategory.BATTERY, ComponentCategory.BATTERY, ComponentCategory.BATTERY - ) - - mockgrid = MockMicrogrid( - graph=gen.to_graph( - ( - ComponentCategory.METER, - gen.batteries_with_inverter(bats, 2), - ) - ) - ) - await mockgrid.start(mocker) - - with pytest.raises(FormulaGenerationError): - # Request only two of the three batteries behind the inverters - battery_pool = microgrid.new_battery_pool( - priority=5, component_ids=set([bats[1].id, bats[0].id]) - ) - power_receiver = battery_pool.power.new_receiver() - await mockgrid.mock_resampler.send_bat_inverter_power([2.0]) - assert (await power_receiver.receive()).value == Power.from_watts(2.0) - async def run_capacity_test( # pylint: disable=too-many-locals fake_time: time_machine.Coordinates, setup_args: SetupArgs diff --git a/tests/timeseries/_ev_charger_pool/test_ev_charger_pool.py b/tests/timeseries/_ev_charger_pool/test_ev_charger_pool.py index a2b4a73fb..113908923 100644 --- a/tests/timeseries/_ev_charger_pool/test_ev_charger_pool.py +++ b/tests/timeseries/_ev_charger_pool/test_ev_charger_pool.py @@ -4,7 +4,6 @@ """Tests for the `EVChargerPool`.""" -import pytest from frequenz.quantities import Power from pytest_mock import MockerFixture @@ -15,10 +14,6 @@ class TestEVChargerPool: """Tests for the `EVChargerPool`.""" - @pytest.mark.skip( - reason="Needs to be adapted to the new component graph behavior, see " - "https://github.com/frequenz-floss/frequenz-sdk-python/issues/1345" - ) async def test_ev_power( # pylint: disable=too-many-locals self, mocker: MockerFixture, @@ -31,10 +26,5 @@ async def test_ev_power( # pylint: disable=too-many-locals ev_pool = microgrid.new_ev_charger_pool(priority=5) power_receiver = ev_pool.power.new_receiver() - await mockgrid.mock_resampler.send_meter_power([None]) - await mockgrid.mock_resampler.send_evc_power([2.0, 4.0, 10.0]) + await mockgrid.mock_resampler.send_meter_power([16.0]) assert (await power_receiver.receive()).value == Power.from_watts(16.0) - - await mockgrid.mock_resampler.send_meter_power([None]) - await mockgrid.mock_resampler.send_evc_power([2.0, 4.0, -10.0]) - assert (await power_receiver.receive()).value == Power.from_watts(-4.0) diff --git a/tests/timeseries/_formulas/test_formula_composition.py b/tests/timeseries/_formulas/test_formula_composition.py index d490bc8f7..cb72f222a 100644 --- a/tests/timeseries/_formulas/test_formula_composition.py +++ b/tests/timeseries/_formulas/test_formula_composition.py @@ -206,10 +206,6 @@ async def test_formula_composition_missing_bat(self, mocker: MockerFixture) -> N assert count == 10 - @pytest.mark.skip( - reason="Needs to be adapted to the new component graph behavior, see " - "https://github.com/frequenz-floss/frequenz-sdk-python/issues/1345" - ) async def test_formula_composition_min_max(self, mocker: MockerFixture) -> None: """Test the composition of formulas with the min and max.""" mockgrid = MockMicrogrid(grid_meter=True, mocker=mocker, num_namespaces=2) @@ -237,13 +233,13 @@ async def test_formula_composition_min_max(self, mocker: MockerFixture) -> None: assert ( str(formula_min) == "[grid_power_min](" - + "MIN([grid_power](COALESCE(#4, #7)), [chp_power](COALESCE(#5, #7, 0.0)))" + + "MIN([grid_power](#4), [chp_power](COALESCE(#7, #5, 0.0)))" + ")" ) assert ( str(formula_max) == "[grid_power_max](" - + "MAX([grid_power](COALESCE(#4, #7)), [chp_power](COALESCE(#5, #7, 0.0)))" + + "MAX([grid_power](#4), [chp_power](COALESCE(#7, #5, 0.0)))" + ")" ) diff --git a/tests/timeseries/test_logical_meter.py b/tests/timeseries/test_logical_meter.py index 95245f1d4..1ac0b8d49 100644 --- a/tests/timeseries/test_logical_meter.py +++ b/tests/timeseries/test_logical_meter.py @@ -6,7 +6,6 @@ from contextlib import AsyncExitStack -import pytest from frequenz.quantities import Power from pytest_mock import MockerFixture @@ -41,10 +40,6 @@ async def test_chp_power(self, mocker: MockerFixture) -> None: await mockgrid.mock_resampler.send_chp_power([-12.0]) assert (await chp_power_receiver.receive()).value == Power.from_watts(-12.0) - @pytest.mark.skip( - reason="Needs to be adapted to the new component graph behavior, see " - "https://github.com/frequenz-floss/frequenz-sdk-python/issues/1345" - ) async def test_pv_power(self, mocker: MockerFixture) -> None: """Test the pv power formula.""" mockgrid = MockMicrogrid(grid_meter=False, mocker=mocker) @@ -55,32 +50,5 @@ async def test_pv_power(self, mocker: MockerFixture) -> None: stack.push_async_callback(pv_pool.stop) pv_power_receiver = pv_pool.power.new_receiver() - await mockgrid.mock_resampler.send_meter_power([-1.0, -2.0]) - await mockgrid.mock_resampler.send_pv_inverter_power([-10.0, -20.0]) + await mockgrid.mock_resampler.send_meter_power([-10.0, -20.0]) assert (await pv_power_receiver.receive()).value == Power.from_watts(-30.0) - - async def test_pv_power_no_meter(self, mocker: MockerFixture) -> None: - """Test the pv power formula.""" - mockgrid = MockMicrogrid(grid_meter=False, mocker=mocker) - mockgrid.add_solar_inverters(2, no_meter=True) - - async with mockgrid, AsyncExitStack() as stack: - pv_pool = microgrid.new_pv_pool(priority=5) - stack.push_async_callback(pv_pool.stop) - pv_power_receiver = pv_pool.power.new_receiver() - - await mockgrid.mock_resampler.send_pv_inverter_power([-1.0, -2.0]) - assert (await pv_power_receiver.receive()).value == Power.from_watts(-3.0) - - async def test_pv_power_no_pv_components(self, mocker: MockerFixture) -> None: - """Test the pv power formula without having any pv components.""" - async with ( - MockMicrogrid(grid_meter=True, mocker=mocker) as mockgrid, - AsyncExitStack() as stack, - ): - pv_pool = microgrid.new_pv_pool(priority=5) - stack.push_async_callback(pv_pool.stop) - pv_power_receiver = pv_pool.power.new_receiver() - - await mockgrid.mock_resampler.send_non_existing_component_value() - assert (await pv_power_receiver.receive()).value == Power.zero()