Skip to content

Conversation

@Marenz
Copy link
Contributor

@Marenz Marenz commented Jun 2, 2025

Blocked by:

  • The release of base-client v0.11
  • The release of microgrid client

@Copilot Copilot AI review requested due to automatic review settings June 2, 2025 16:54
@Marenz Marenz requested a review from a team as a code owner June 2, 2025 16:54
@Marenz Marenz requested review from ela-kotulska-frequenz and removed request for a team June 2, 2025 16:54
@github-actions github-actions bot added part:docs Affects the documentation part:tests Affects the unit, integration and performance (benchmarks) tests part:tooling Affects the development tooling (CI, deployment, dependency management, etc.) part:data-pipeline Affects the data pipeline part:microgrid Affects the interactions with the microgrid labels Jun 2, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR updates the microgrid client integration to the latest version by changing import paths and filtering out StreamEvents where necessary. It also updates dependency references and release notes accordingly.

  • Updated import locations for ComponentId across multiple modules.
  • Introduced filtering of stream events in various data stream receivers.
  • Adjusted dependency declaration in pyproject.toml and updated release notes.

Reviewed Changes

Copilot reviewed 69 out of 69 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/frequenz/sdk/microgrid/_power_distributing/request.py Updated import for ComponentId from the new location.
src/frequenz/sdk/microgrid/_power_distributing/power_distributing.py Adjusted ComponentId import and removed unused import items.
src/frequenz/sdk/microgrid/_power_distributing/_distribution_algorithm/_battery_distribution_algorithm.py Updated ComponentId import with consistent module path.
src/frequenz/sdk/microgrid/_power_distributing/_component_status/_pv_inverter_status_tracker.py Revised ComponentId import and added stream filtering for InverterData.
src/frequenz/sdk/microgrid/_power_distributing/_component_status/_ev_charger_status_tracker.py Updated imports and wrapped EVCharger receiver with filter_stream_events.
src/frequenz/sdk/microgrid/_power_distributing/_component_status/_component_status.py Updated ComponentId import.
src/frequenz/sdk/microgrid/_power_distributing/_component_status/_battery_status_tracker.py Applied filtering for battery and inverter receivers.
src/frequenz/sdk/microgrid/_power_distributing/_component_pool_status_tracker.py Updated ComponentId import.
src/frequenz/sdk/microgrid/_power_distributing/_component_managers/_pv_inverter_manager/_pv_inverter_manager.py Added filtering to inverter_data stream and updated ComponentId import.
src/frequenz/sdk/microgrid/_power_distributing/_component_managers/_ev_charger_manager/_states.py Updated import order for EVChargerData and ComponentId.
src/frequenz/sdk/microgrid/_power_distributing/_component_managers/_ev_charger_manager/_ev_charger_manager.py Updated import order, wrapped merged EVCharger stream with filter_stream_events.
src/frequenz/sdk/microgrid/_power_distributing/_component_managers/_ev_charger_manager/_config.py Updated ComponentId import.
src/frequenz/sdk/microgrid/_power_distributing/_component_managers/_component_manager.py Updated ComponentId import.
src/frequenz/sdk/microgrid/_power_distributing/_component_managers/_battery_manager.py Updated ComponentId import and applied filter_stream_events to data receivers.
src/frequenz/sdk/microgrid/_data_sourcing/microgrid_api_source.py Updated ComponentId import.
src/frequenz/sdk/microgrid/_data_sourcing/_component_metric_request.py Updated imports for ComponentId and ComponentMetricId.
src/frequenz/sdk/microgrid/_data_pipeline.py Updated ComponentId import and removed unneeded imports.
pyproject.toml Updated microgrid client dependency and frequencies channels version.
benchmarks/power_distribution/power_distributor.py Updated ComponentId import to reflect new module path.
RELEASE_NOTES.md Updated release notes to mention microgrid client dependency changes.

@Marenz Marenz added the status:blocked Other issues must be resolved before this can be worked on label Jun 2, 2025
@Marenz Marenz force-pushed the microgrid_client_update branch from b9cc2ff to 30b6d21 Compare June 11, 2025 09:59
@Marenz Marenz requested a review from llucax June 11, 2025 10:01
Comment on lines 182 to 190
filterwarnings = [
"error",
"once::DeprecationWarning",
"once::PendingDeprecationWarning",
# We use a raw string (single quote) to avoid the need to escape special
# chars as this is a regex
'ignore:Protobuf gencode version .*exactly one major version older.*:UserWarning',
]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if you added this just for consistency or if you are also getting protobuf warnings at this level 😱

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am getting warnings indeed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn, I didn't know they were so intrusive...

@Marenz Marenz force-pushed the microgrid_client_update branch from 30b6d21 to faf2087 Compare June 11, 2025 10:42
Signed-off-by: Mathias L. Baumann <[email protected]>
@Marenz Marenz force-pushed the microgrid_client_update branch from faf2087 to a3de905 Compare June 11, 2025 10:50
@Marenz Marenz enabled auto-merge June 11, 2025 10:50
@Marenz Marenz requested a review from llucax June 11, 2025 10:51
llucax
llucax previously approved these changes Jun 11, 2025
@Marenz Marenz added this pull request to the merge queue Jun 11, 2025
@github-project-automation github-project-automation bot moved this from To do to Review approved in Python SDK Roadmap Jun 11, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to no response for status checks Jun 11, 2025
@Marenz Marenz added this pull request to the merge queue Jun 11, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to no response for status checks Jun 11, 2025
@llucax
Copy link
Contributor

llucax commented Jun 12, 2025

Test with nox (amd64, ubuntu-24.04, 3.13, pytest_min) is consistently timing out due to some infinite loop while cleaning up for tests (tests finish, but the reporting of warnings, etc. is never ending) 😟

@llucax
Copy link
Contributor

llucax commented Jun 12, 2025

Not sure if it might be related or a similar issue to the time-machine update issues we had and @sahas-subramanian-frequenz fixed.

These are the logs after the tests finish
================= 425 passed, 4 warnings in 119.58s (0:01:59) ==================
Task was destroyed but it is pending!
task: <Task pending name='LatestValueCache«BatteryManager«0x7fd88c486350»:battery«CID9»»' coro=<LatestValueCache._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_latest_value_cache.py:107> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='LatestValueCache«BatteryManager«0x7fd88c486350»:inverter«CID8»»' coro=<LatestValueCache._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_latest_value_cache.py:107> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='LatestValueCache«BatteryManager«0x7fd88c486350»:battery«CID29»»' coro=<LatestValueCache._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_latest_value_cache.py:107> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='LatestValueCache«BatteryManager«0x7fd88c486350»:inverter«CID28»»' coro=<LatestValueCache._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_latest_value_cache.py:107> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='LatestValueCache«BatteryManager«0x7fd88c486350»:battery«CID19»»' coro=<LatestValueCache._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_latest_value_cache.py:107> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='LatestValueCache«BatteryManager«0x7fd88c486350»:inverter«CID18»»' coro=<LatestValueCache._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_latest_value_cache.py:107> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='LatestValueCache«BatteryManager«0x7fd88c773200»:inverter«CID48»»' coro=<LatestValueCache._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_latest_value_cache.py:107> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='#17' coro=<MetricFetcher.fetch_next() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/timeseries/formula_engine/_formula_steps.py:514> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='#7' coro=<MetricFetcher.fetch_next() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/timeseries/formula_engine/_formula_steps.py:514> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='#7' coro=<MetricFetcher.fetch_next() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/timeseries/formula_engine/_formula_steps.py:514> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='Task-18511' coro=<sleep() running at /opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/tasks.py:718> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='Task-18512' coro=<Event.wait() running at /opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/locks.py:213> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='Task-18750' coro=<Event.wait() running at /opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/locks.py:213> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='Task-18916' coro=<Event.wait() running at /opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/locks.py:213> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='Task-18948' coro=<Event.wait() running at /opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/locks.py:213> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='Task-18958' coro=<Event.wait() running at /opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/locks.py:213> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='Task-18960' coro=<Event.wait() running at /opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/locks.py:213> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Exception ignored in: <function BackgroundService.__del__ at 0x7fd88fb92980>
Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_background_service.py", line 276, in __del__
    self.cancel("{self!r} was deleted")
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_actor.py", line 148, in cancel
    return super().cancel(msg)
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_background_service.py", line 171, in cancel
    task.cancel(msg)
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 827, in call_soon
    self._check_closed()
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 550, in _check_closed
Error:     raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Exception ignored in: <function BackgroundService.__del__ at 0x7fd88fb92980>
Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_background_service.py", line 276, in __del__
    self.cancel("{self!r} was deleted")
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_background_service.py", line 171, in cancel
    task.cancel(msg)
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 827, in call_soon
    self._check_closed()
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 550, in _check_closed
Error:     raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Exception ignored in: <function BackgroundService.__del__ at 0x7fd88fb92980>
Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_background_service.py", line 276, in __del__
    self.cancel("{self!r} was deleted")
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_background_service.py", line 171, in cancel
    task.cancel(msg)
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 827, in call_soon
    self._check_closed()
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 550, in _check_closed
Error:     raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Exception ignored in: <function BackgroundService.__del__ at 0x7fd88fb92980>
Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_background_service.py", line 276, in __del__
    self.cancel("{self!r} was deleted")
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_background_service.py", line 171, in cancel
    task.cancel(msg)
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 827, in call_soon
    self._check_closed()
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 550, in _check_closed
Error:     raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Task was destroyed but it is pending!
task: <Task pending name='0' coro=<Receiver.__anext__() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_receiver.py:201> wait_for=<Future pending cb=[Task.task_wakeup()]> cb=[_wait.<locals>._on_completion() at /opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/tasks.py:521]>
Task was destroyed but it is pending!
task: <Task pending name='1' coro=<Receiver.__anext__() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_receiver.py:201> wait_for=<Future pending cb=[Task.task_wakeup()]> cb=[_wait.<locals>._on_completion() at /opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/tasks.py:521]>
Task was destroyed but it is pending!
task: <Task pending name='2' coro=<Receiver.__anext__() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_receiver.py:201> wait_for=<Future pending cb=[Task.task_wakeup()]> cb=[_wait.<locals>._on_completion() at /opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/tasks.py:521]>
Task was destroyed but it is pending!
task: <Task pending name='Task-24021' coro=<ComponentPoolStatusTracker._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/microgrid/_power_distributing/_component_pool_status_tracker.py:117> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task cancelling name='Task-24022' coro=<Actor._run_loop() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_actor.py:102> wait_for=<Future cancelled>>
Exception ignored in: <function BackgroundService.__del__ at 0x7fd88fb92980>
Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_background_service.py", line 276, in __del__
    self.cancel("{self!r} was deleted")
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_actor.py", line 148, in cancel
    return super().cancel(msg)
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_background_service.py", line 171, in cancel
    task.cancel(msg)
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 827, in call_soon
    self._check_closed()
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 550, in _check_closed
Error:     raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Task was destroyed but it is pending!
task: <Task cancelling name='Task-24023' coro=<Actor._run_loop() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_actor.py:102> wait_for=<Future cancelled>>
Task was destroyed but it is pending!
task: <Task cancelling name='Task-24025' coro=<BatteryStatusTracker._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/microgrid/_power_distributing/_component_status/_battery_status_tracker.py:267> wait_for=<Future cancelled>>
Task was destroyed but it is pending!
task: <Task cancelling name='Task-24026' coro=<BatteryStatusTracker._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/microgrid/_power_distributing/_component_status/_battery_status_tracker.py:267> wait_for=<Future cancelled>>
Task was destroyed but it is pending!
task: <Task cancelling name='Task-24027' coro=<BatteryStatusTracker._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/microgrid/_power_distributing/_component_status/_battery_status_tracker.py:267> wait_for=<Future cancelled>>
Task was destroyed but it is pending!
task: <Task pending name='LatestValueCache«BatteryManager«0x7fd88c7359d0»:battery«CID29»»' coro=<LatestValueCache._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_latest_value_cache.py:107> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='LatestValueCache«BatteryManager«0x7fd88c7359d0»:battery«CID19»»' coro=<LatestValueCache._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_latest_value_cache.py:107> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='LatestValueCache«BatteryManager«0x7fd88c7359d0»:inverter«CID48»»' coro=<LatestValueCache._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_latest_value_cache.py:107> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Task was destroyed but it is pending!
task: <Task pending name='LatestValueCache«BatteryManager«0x7fd88c7359d0»:inverter«CID38»»' coro=<LatestValueCache._run() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_latest_value_cache.py:107> wait_for=<Future pending cb=[Task.task_wakeup()]>>
Exception ignored in: <coroutine object ComponentPoolStatusTracker._run at 0x7fd88c07a940>
Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/microgrid/_power_distributing/_component_pool_status_tracker.py", line 112, in _run
    async with contextlib.AsyncExitStack() as stack:
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/contextlib.py", line 768, in __aexit__
    raise exc
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/contextlib.py", line 751, in __aexit__
    cb_suppress = await cb(*exc_details)
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_background_service.py", line 226, in __aexit__
    await self.stop()
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_background_service.py", line 190, in stop
    await self.wait()
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_background_service.py", line 241, in wait
    done, pending = await asyncio.wait(self._tasks)
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/tasks.py", line 450, in wait
    loop = events.get_running_loop()
RuntimeError: no running event loop
Actor PowerDistributingActor[140568046327552]: Raised a BaseException.
Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_actor.py", line 102, in _run_loop
    await self._run()
GeneratorExit
Actor PowerManagingActor[140568044333424]: Raised an unhandled exception during stop.
Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_select.py", line 438, in select
    done, pending = await asyncio.wait(
                    ^^^^^^^^^^^^^^^^^^^
        pending, return_when=asyncio.FIRST_COMPLETED
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
GeneratorExit

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/actor/_actor.py", line 102, in _run_loop
    await self._run()
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/microgrid/_power_managing/_power_managing_actor.py", line 224, in _run
    async for selected in select(
    ...<61 lines>...
            self._algorithm.drop_old_proposals(asyncio.get_event_loop().time())
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_select.py", line 470, in select
    await _stop_pending_tasks(pending)
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_select.py", line 484, in _stop_pending_tasks
    task.cancel()
    ~~~~~~~~~~~^^
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 827, in call_soon
    self._check_closed()
    ~~~~~~~~~~~~~~~~~~^^
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 550, in _check_closed
Error:     raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Task was destroyed but it is pending!
task: <Task cancelling name='8785502476025' coro=<_Receiver.ready() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_broadcast.py:475> wait_for=<Future cancelled>>
BatteryStatusTracker crashed with error: Event loop is closed
Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_select.py", line 438, in select
    done, pending = await asyncio.wait(
                    ^^^^^^^^^^^^^^^^^^^
        pending, return_when=asyncio.FIRST_COMPLETED
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
GeneratorExit

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/microgrid/_power_distributing/_component_status/_battery_status_tracker.py", line 267, in _run
    async for selected in select(
    ...<47 lines>...
            )
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_select.py", line 470, in select
    await _stop_pending_tasks(pending)
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_select.py", line 484, in _stop_pending_tasks
    task.cancel()
    ~~~~~~~~~~~^^
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 827, in call_soon
    self._check_closed()
    ~~~~~~~~~~~~~~~~~~^^
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 550, in _check_closed
Error:     raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
Task was destroyed but it is pending!
task: <Task cancelling name='8785502476039' coro=<_Receiver.ready() running at /home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_broadcast.py:475> wait_for=<Future cancelled>>
Exception ignored in: <coroutine object _Receiver.ready at 0x7fd88c0e0e40>
Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_broadcast.py", line 475, in ready
    await self._channel._recv_cv.wait()
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/locks.py", line 300, in wait
    self._notify(1)
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/locks.py", line 341, in _notify
    fut.set_result(False)
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 827, in call_soon
    self._check_closed()
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/base_events.py", line 550, in _check_closed
Error:     raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
BatteryStatusTracker crashed with error: no running event loop
Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/microgrid/_power_distributing/_component_status/_battery_status_tracker.py", line 267, in _run
    async for selected in select(
    ...<47 lines>...
            )
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_select.py", line 435, in select
    pending.add(asyncio.create_task(recv.ready(), name=name))
                ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/tasks.py", line 407, in create_task
    loop = events.get_running_loop()
RuntimeError: no running event loop
/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/microgrid/_power_distributing/_component_status/_battery_status_tracker.py:318: RuntimeWarning: coroutine '_Receiver.ready' was never awaited
  _logger.exception("BatteryStatusTracker crashed with error: %s", err)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
BatteryStatusTracker crashed with error: no running event loop
Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/microgrid/_power_distributing/_component_status/_battery_status_tracker.py", line 267, in _run
    async for selected in select(
    ...<47 lines>...
            )
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_select.py", line 435, in select
    pending.add(asyncio.create_task(recv.ready(), name=name))
                ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/tasks.py", line 407, in create_task
    loop = events.get_running_loop()
RuntimeError: no running event loop
BatteryStatusTracker crashed with error: no running event loop
Traceback (most recent call last):
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/microgrid/_power_distributing/_component_status/_battery_status_tracker.py", line 267, in _run
    async for selected in select(
    ...<47 lines>...
            )
  File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/.nox/pytest_min/lib/python3.13/site-packages/frequenz/channels/_select.py", line 435, in select
    pending.add(asyncio.create_task(recv.ready(), name=name))
                ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/asyncio/tasks.py", line 407, in create_task
    loop = events.get_running_loop()
RuntimeError: no running event loop

(keeps looping on the last runtime error in " File "/home/runner/work/frequenz-sdk-python/frequenz-sdk-python/src/frequenz/sdk/microgrid/_power_distributing/_component_status/_battery_status_tracker.py", line 267").

We have no guarantee that the event loop is still running at the time
the __del__ method is called. In fact we do see errors in the
in the test cleanup phase exactly because of this.

Signed-off-by: Mathias L. Baumann <[email protected]>
@Marenz Marenz dismissed stale reviews from ela-kotulska-frequenz and llucax via 45c4ad7 June 16, 2025 15:16
@github-actions github-actions bot added the part:actor Affects an actor ot the actors utilities (decorator, etc.) label Jun 16, 2025
@Marenz Marenz enabled auto-merge June 16, 2025 15:22
Comment on lines -271 to -277
def __del__(self) -> None:
"""Destroy this instance.
Cancel all running tasks spawned by this background service.
"""
self.cancel("{self!r} was deleted")

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the fix is to check if the event loop is running before calling cancel, because when the loop is there, we still want to cancel and cleanup.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about that, but I don't think we gain much from that tbh. Cleanup should not rely on del

@Marenz Marenz added this pull request to the merge queue Jun 16, 2025
Merged via the queue into frequenz-floss:v1.x.x with commit 7a26a31 Jun 16, 2025
5 checks passed
@Marenz Marenz deleted the microgrid_client_update branch June 16, 2025 15:38
@github-project-automation github-project-automation bot moved this from Review approved to Done in Python SDK Roadmap Jun 16, 2025
@llucax llucax added this to the v1.0.0-rc2100 milestone Jun 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

part:actor Affects an actor ot the actors utilities (decorator, etc.) part:data-pipeline Affects the data pipeline part:docs Affects the documentation part:microgrid Affects the interactions with the microgrid part:tests Affects the unit, integration and performance (benchmarks) tests part:tooling Affects the development tooling (CI, deployment, dependency management, etc.) status:blocked Other issues must be resolved before this can be worked on

Projects

Development

Successfully merging this pull request may close these issues.

4 participants