frequenz-dispatch 0.6.0__tar.gz → 0.6.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. {frequenz_dispatch-0.6.0/src/frequenz_dispatch.egg-info → frequenz_dispatch-0.6.2}/PKG-INFO +21 -20
  2. frequenz_dispatch-0.6.2/RELEASE_NOTES.md +18 -0
  3. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/pyproject.toml +26 -21
  4. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/src/frequenz/dispatch/_actor_dispatcher.py +37 -19
  5. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2/src/frequenz_dispatch.egg-info}/PKG-INFO +21 -20
  6. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/src/frequenz_dispatch.egg-info/requires.txt +18 -18
  7. frequenz_dispatch-0.6.0/RELEASE_NOTES.md +0 -70
  8. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/LICENSE +0 -0
  9. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/MANIFEST.in +0 -0
  10. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/README.md +0 -0
  11. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/setup.cfg +0 -0
  12. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/src/frequenz/dispatch/__init__.py +0 -0
  13. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/src/frequenz/dispatch/_bg_service.py +0 -0
  14. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/src/frequenz/dispatch/_dispatch.py +0 -0
  15. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/src/frequenz/dispatch/_dispatcher.py +0 -0
  16. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/src/frequenz/dispatch/_event.py +0 -0
  17. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/src/frequenz/dispatch/_merge_strategies.py +0 -0
  18. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/src/frequenz/dispatch/conftest.py +0 -0
  19. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/src/frequenz/dispatch/py.typed +0 -0
  20. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/src/frequenz_dispatch.egg-info/SOURCES.txt +0 -0
  21. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/src/frequenz_dispatch.egg-info/dependency_links.txt +0 -0
  22. {frequenz_dispatch-0.6.0 → frequenz_dispatch-0.6.2}/src/frequenz_dispatch.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: frequenz-dispatch
3
- Version: 0.6.0
3
+ Version: 0.6.2
4
4
  Summary: A highlevel interface for the dispatch API
5
5
  Author-email: Frequenz Energy-as-a-Service GmbH <floss@frequenz.com>
6
6
  License: MIT
@@ -20,51 +20,52 @@ Classifier: Typing :: Typed
20
20
  Requires-Python: <4,>=3.11
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: typing-extensions<5.0.0,>=4.11.0
24
- Requires-Dist: frequenz-sdk<1.0.0-rc1800,>=1.0.0-rc1302
23
+ Requires-Dist: typing-extensions<5.0.0,>=4.13.0
24
+ Requires-Dist: frequenz-sdk<1.0.0-rc1900,>=1.0.0-rc1302
25
25
  Requires-Dist: frequenz-channels<2.0.0,>=1.6.1
26
26
  Requires-Dist: frequenz-client-dispatch<0.9.0,>=0.8.4
27
27
  Provides-Extra: dev-flake8
28
- Requires-Dist: flake8==7.1.1; extra == "dev-flake8"
28
+ Requires-Dist: flake8==7.2.0; extra == "dev-flake8"
29
29
  Requires-Dist: flake8-docstrings==1.7.0; extra == "dev-flake8"
30
30
  Requires-Dist: flake8-pyproject==1.2.3; extra == "dev-flake8"
31
- Requires-Dist: pydoclint==0.6.0; extra == "dev-flake8"
31
+ Requires-Dist: pydoclint==0.6.4; extra == "dev-flake8"
32
32
  Requires-Dist: pydocstyle==6.3.0; extra == "dev-flake8"
33
33
  Provides-Extra: dev-formatting
34
34
  Requires-Dist: black==25.1.0; extra == "dev-formatting"
35
- Requires-Dist: isort==6.0.0; extra == "dev-formatting"
35
+ Requires-Dist: isort==6.0.1; extra == "dev-formatting"
36
36
  Provides-Extra: dev-mkdocs
37
37
  Requires-Dist: black==25.1.0; extra == "dev-mkdocs"
38
38
  Requires-Dist: Markdown==3.7; extra == "dev-mkdocs"
39
39
  Requires-Dist: mike==2.1.3; extra == "dev-mkdocs"
40
40
  Requires-Dist: mkdocs-gen-files==0.5.0; extra == "dev-mkdocs"
41
- Requires-Dist: mkdocs-literate-nav==0.6.1; extra == "dev-mkdocs"
41
+ Requires-Dist: mkdocs-literate-nav==0.6.2; extra == "dev-mkdocs"
42
42
  Requires-Dist: mkdocs-macros-plugin==1.3.7; extra == "dev-mkdocs"
43
- Requires-Dist: mkdocs-material==9.6.1; extra == "dev-mkdocs"
44
- Requires-Dist: mkdocstrings[python]==0.27.0; extra == "dev-mkdocs"
45
- Requires-Dist: mkdocstrings-python==1.13.0; extra == "dev-mkdocs"
46
- Requires-Dist: frequenz-repo-config[lib]==0.11.0; extra == "dev-mkdocs"
43
+ Requires-Dist: mkdocs-material==9.6.11; extra == "dev-mkdocs"
44
+ Requires-Dist: mkdocstrings[python]==0.29.1; extra == "dev-mkdocs"
45
+ Requires-Dist: mkdocstrings-python==1.16.8; extra == "dev-mkdocs"
46
+ Requires-Dist: frequenz-repo-config[lib]==0.13.1; extra == "dev-mkdocs"
47
47
  Provides-Extra: dev-mypy
48
- Requires-Dist: mypy==1.14.1; extra == "dev-mypy"
48
+ Requires-Dist: mypy==1.15.0; extra == "dev-mypy"
49
49
  Requires-Dist: grpc-stubs==1.53.0.5; extra == "dev-mypy"
50
- Requires-Dist: types-Markdown==3.7.0.20241204; extra == "dev-mypy"
50
+ Requires-Dist: types-Markdown==3.7.0.20250322; extra == "dev-mypy"
51
51
  Requires-Dist: frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-mypy"
52
52
  Provides-Extra: dev-noxfile
53
- Requires-Dist: uv==0.5.26; extra == "dev-noxfile"
53
+ Requires-Dist: uv==0.6.11; extra == "dev-noxfile"
54
54
  Requires-Dist: nox==2025.2.9; extra == "dev-noxfile"
55
- Requires-Dist: frequenz-repo-config[lib]==0.11.0; extra == "dev-noxfile"
55
+ Requires-Dist: frequenz-repo-config[lib]==0.13.1; extra == "dev-noxfile"
56
56
  Provides-Extra: dev-pylint
57
- Requires-Dist: pylint==3.3.4; extra == "dev-pylint"
57
+ Requires-Dist: pylint==3.3.6; extra == "dev-pylint"
58
58
  Requires-Dist: frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-pylint"
59
59
  Provides-Extra: dev-pytest
60
- Requires-Dist: pytest==8.3.4; extra == "dev-pytest"
61
- Requires-Dist: frequenz-repo-config[extra-lint-examples]==0.11.0; extra == "dev-pytest"
60
+ Requires-Dist: pytest==8.3.5; extra == "dev-pytest"
61
+ Requires-Dist: frequenz-repo-config[extra-lint-examples]==0.13.1; extra == "dev-pytest"
62
62
  Requires-Dist: pytest-mock==3.14.0; extra == "dev-pytest"
63
- Requires-Dist: pytest-asyncio==0.25.3; extra == "dev-pytest"
63
+ Requires-Dist: pytest-asyncio==0.26.0; extra == "dev-pytest"
64
64
  Requires-Dist: async-solipsism==0.7; extra == "dev-pytest"
65
65
  Requires-Dist: time-machine==2.16.0; extra == "dev-pytest"
66
66
  Provides-Extra: dev
67
67
  Requires-Dist: frequenz-dispatch[dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]; extra == "dev"
68
+ Dynamic: license-file
68
69
 
69
70
  # Dispatch Highlevel Interface
70
71
 
@@ -0,0 +1,18 @@
1
+ # Dispatch Highlevel Interface Release Notes
2
+
3
+ ## Summary
4
+
5
+ <!-- Here goes a general summary of what this release is about -->
6
+
7
+ ## Upgrading
8
+
9
+ <!-- Here goes notes on how to upgrade from previous versions, including deprecations and what they should be replaced with -->
10
+
11
+ ## New Features
12
+
13
+ <!-- Here goes the main new features and examples or instructions on how to use them -->
14
+
15
+ ## Bug Fixes
16
+
17
+ * ActorDispatcher: Fix that every actor instance wrongly received all updates for their dispatch type. This is only relevant to you if your actor has more than one running instance at any time.
18
+
@@ -3,9 +3,9 @@
3
3
 
4
4
  [build-system]
5
5
  requires = [
6
- "setuptools == 75.8.0",
7
- "setuptools_scm[toml] == 8.1.0",
8
- "frequenz-repo-config[lib] == 0.11.0",
6
+ "setuptools == 78.1.0",
7
+ "setuptools_scm[toml] == 8.2.0",
8
+ "frequenz-repo-config[lib] == 0.13.1",
9
9
  ]
10
10
  build-backend = "setuptools.build_meta"
11
11
 
@@ -34,11 +34,11 @@ classifiers = [
34
34
  ]
35
35
  requires-python = ">= 3.11, < 4"
36
36
  dependencies = [
37
- "typing-extensions >= 4.11.0, < 5.0.0",
37
+ "typing-extensions >= 4.13.0, < 5.0.0",
38
38
  # Make sure to update the version for cross-referencing also in the
39
39
  # mkdocs.yml file when changing the version here (look for the config key
40
40
  # plugins.mkdocstrings.handlers.python.import)
41
- "frequenz-sdk >= 1.0.0-rc1302, < 1.0.0-rc1800",
41
+ "frequenz-sdk >= 1.0.0-rc1302, < 1.0.0-rc1900",
42
42
  "frequenz-channels >= 1.6.1, < 2.0.0",
43
43
  "frequenz-client-dispatch >= 0.8.4, < 0.9.0",
44
44
  ]
@@ -50,48 +50,48 @@ email = "floss@frequenz.com"
50
50
 
51
51
  [project.optional-dependencies]
52
52
  dev-flake8 = [
53
- "flake8 == 7.1.1",
53
+ "flake8 == 7.2.0",
54
54
  "flake8-docstrings == 1.7.0",
55
55
  "flake8-pyproject == 1.2.3", # For reading the flake8 config from pyproject.toml
56
- "pydoclint == 0.6.0",
56
+ "pydoclint == 0.6.4",
57
57
  "pydocstyle == 6.3.0",
58
58
  ]
59
- dev-formatting = ["black == 25.1.0", "isort == 6.0.0"]
59
+ dev-formatting = ["black == 25.1.0", "isort == 6.0.1"]
60
60
  dev-mkdocs = [
61
61
  "black == 25.1.0",
62
62
  "Markdown==3.7",
63
63
  "mike == 2.1.3",
64
64
  "mkdocs-gen-files == 0.5.0",
65
- "mkdocs-literate-nav == 0.6.1",
65
+ "mkdocs-literate-nav == 0.6.2",
66
66
  "mkdocs-macros-plugin == 1.3.7",
67
- "mkdocs-material == 9.6.1",
68
- "mkdocstrings[python] == 0.27.0",
69
- "mkdocstrings-python == 1.13.0",
70
- "frequenz-repo-config[lib] == 0.11.0",
67
+ "mkdocs-material == 9.6.11",
68
+ "mkdocstrings[python] == 0.29.1",
69
+ "mkdocstrings-python == 1.16.8",
70
+ "frequenz-repo-config[lib] == 0.13.1",
71
71
  ]
72
72
  dev-mypy = [
73
- "mypy == 1.14.1",
73
+ "mypy == 1.15.0",
74
74
  # This dependency introduces breaking changes in patch releases
75
75
  "grpc-stubs == 1.53.0.5",
76
- "types-Markdown == 3.7.0.20241204",
76
+ "types-Markdown == 3.7.0.20250322",
77
77
  # For checking the noxfile, docs/ script, and tests
78
78
  "frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]",
79
79
  ]
80
80
  dev-noxfile = [
81
- "uv == 0.5.26",
81
+ "uv == 0.6.11",
82
82
  "nox == 2025.2.9",
83
- "frequenz-repo-config[lib] == 0.11.0",
83
+ "frequenz-repo-config[lib] == 0.13.1",
84
84
  ]
85
85
  dev-pylint = [
86
- "pylint == 3.3.4",
86
+ "pylint == 3.3.6",
87
87
  # For checking the noxfile, docs/ script, and tests
88
88
  "frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]",
89
89
  ]
90
90
  dev-pytest = [
91
- "pytest == 8.3.4",
92
- "frequenz-repo-config[extra-lint-examples] == 0.11.0",
91
+ "pytest == 8.3.5",
92
+ "frequenz-repo-config[extra-lint-examples] == 0.13.1",
93
93
  "pytest-mock == 3.14.0",
94
- "pytest-asyncio == 0.25.3",
94
+ "pytest-asyncio == 0.26.0",
95
95
  "async-solipsism == 0.7",
96
96
  "time-machine == 2.16.0",
97
97
  ]
@@ -164,6 +164,11 @@ disable = [
164
164
  ]
165
165
 
166
166
  [tool.pytest.ini_options]
167
+ # Ideally we should treat warnings as errors, but we have too many warnings
168
+ # coming for external dependencies that are hard to address here, once this is
169
+ # fixed, we can add the following options:
170
+ # -Werror -Wdefault::DeprecationWarning -Wdefault::PendingDeprecationWarning
171
+ addopts = "-W=all -vv"
167
172
  testpaths = ["tests", "src"]
168
173
  asyncio_mode = "auto"
169
174
  asyncio_default_fixture_loop_scope = "function"
@@ -10,7 +10,7 @@ from dataclasses import dataclass
10
10
  from datetime import timedelta
11
11
  from typing import Any, Awaitable
12
12
 
13
- from frequenz.channels import Broadcast, Receiver, select
13
+ from frequenz.channels import Broadcast, Receiver, Sender, select
14
14
  from frequenz.client.dispatch.types import TargetComponents
15
15
  from frequenz.sdk.actor import Actor, BackgroundService
16
16
 
@@ -32,6 +32,9 @@ class DispatchInfo:
32
32
  options: dict[str, Any]
33
33
  """Additional options."""
34
34
 
35
+ _src: Dispatch
36
+ """The dispatch that triggered this update."""
37
+
35
38
 
36
39
  class ActorDispatcher(BackgroundService):
37
40
  """Helper class to manage actors based on dispatches.
@@ -186,6 +189,19 @@ class ActorDispatcher(BackgroundService):
186
189
  _logger.info("Retrying dispatch %s now", dispatch.id)
187
190
  await self._sender.send(dispatch)
188
191
 
192
+ @dataclass(frozen=True, kw_only=True)
193
+ class ActorAndChannel:
194
+ """Actor and its sender."""
195
+
196
+ actor: Actor
197
+ """The actor."""
198
+
199
+ channel: Broadcast[DispatchInfo]
200
+ """The channel for dispatch updates."""
201
+
202
+ sender: Sender[DispatchInfo]
203
+ """The sender for dispatch updates."""
204
+
189
205
  def __init__( # pylint: disable=too-many-arguments, too-many-positional-arguments
190
206
  self,
191
207
  actor_factory: Callable[
@@ -212,11 +228,8 @@ class ActorDispatcher(BackgroundService):
212
228
 
213
229
  self._dispatch_rx = running_status_receiver
214
230
  self._actor_factory = actor_factory
215
- self._actors: dict[int, Actor] = {}
216
- self._updates_channel = Broadcast[DispatchInfo](
217
- name="dispatch_updates_channel", resend_latest=True
218
- )
219
- self._updates_sender = self._updates_channel.new_sender()
231
+ self._actors: dict[int, ActorDispatcher.ActorAndChannel] = {}
232
+
220
233
  self._retrier = ActorDispatcher.FailedDispatchesRetrier(retry_interval)
221
234
 
222
235
  def start(self) -> None:
@@ -224,32 +237,34 @@ class ActorDispatcher(BackgroundService):
224
237
  self._tasks.add(asyncio.create_task(self._run()))
225
238
 
226
239
  async def _start_actor(self, dispatch: Dispatch) -> None:
227
- """Start all actors."""
240
+ """Start the actor the given dispatch refers to."""
228
241
  dispatch_update = DispatchInfo(
229
242
  components=dispatch.target,
230
243
  dry_run=dispatch.dry_run,
231
244
  options=dispatch.payload,
245
+ _src=dispatch,
232
246
  )
233
247
 
234
248
  identity = self._dispatch_identity(dispatch)
235
- actor: Actor | None = self._actors.get(identity)
249
+ actor_and_channel = self._actors.get(identity)
236
250
 
237
- if actor:
238
- sent_str = ""
239
- if self._updates_sender is not None:
240
- sent_str = ", sent a dispatch update instead of creating a new actor"
241
- await self._updates_sender.send(dispatch_update)
251
+ if actor_and_channel:
252
+ await actor_and_channel.sender.send(dispatch_update)
242
253
  _logger.info(
243
- "Actor for dispatch type %r is already running%s",
254
+ "Actor for dispatch type %r is already running, "
255
+ "sent a dispatch update instead of creating a new actor",
244
256
  dispatch.type,
245
- sent_str,
246
257
  )
247
258
  else:
248
259
  try:
249
260
  _logger.info("Starting actor for dispatch type %r", dispatch.type)
261
+ channel = Broadcast[DispatchInfo](
262
+ name=f"dispatch_updates_channel_instance={identity}",
263
+ resend_latest=True,
264
+ )
250
265
  actor = await self._actor_factory(
251
266
  dispatch_update,
252
- self._updates_channel.new_receiver(limit=1, warn_on_overflow=False),
267
+ channel.new_receiver(limit=1, warn_on_overflow=False),
253
268
  )
254
269
 
255
270
  actor.start()
@@ -263,7 +278,9 @@ class ActorDispatcher(BackgroundService):
263
278
  self._retrier.retry(dispatch)
264
279
  else:
265
280
  # No exception occurred, so we can add the actor to the list
266
- self._actors[identity] = actor
281
+ self._actors[identity] = ActorDispatcher.ActorAndChannel(
282
+ actor=actor, channel=channel, sender=channel.new_sender()
283
+ )
267
284
 
268
285
  async def _stop_actor(self, stopping_dispatch: Dispatch, msg: str) -> None:
269
286
  """Stop all actors.
@@ -274,8 +291,9 @@ class ActorDispatcher(BackgroundService):
274
291
  """
275
292
  identity = self._dispatch_identity(stopping_dispatch)
276
293
 
277
- if actor := self._actors.pop(identity, None):
278
- await actor.stop(msg)
294
+ if actor_and_channel := self._actors.pop(identity, None):
295
+ await actor_and_channel.actor.stop(msg)
296
+ await actor_and_channel.channel.close()
279
297
  else:
280
298
  _logger.warning(
281
299
  "Actor for dispatch type %r is not running", stopping_dispatch.type
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: frequenz-dispatch
3
- Version: 0.6.0
3
+ Version: 0.6.2
4
4
  Summary: A highlevel interface for the dispatch API
5
5
  Author-email: Frequenz Energy-as-a-Service GmbH <floss@frequenz.com>
6
6
  License: MIT
@@ -20,51 +20,52 @@ Classifier: Typing :: Typed
20
20
  Requires-Python: <4,>=3.11
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: typing-extensions<5.0.0,>=4.11.0
24
- Requires-Dist: frequenz-sdk<1.0.0-rc1800,>=1.0.0-rc1302
23
+ Requires-Dist: typing-extensions<5.0.0,>=4.13.0
24
+ Requires-Dist: frequenz-sdk<1.0.0-rc1900,>=1.0.0-rc1302
25
25
  Requires-Dist: frequenz-channels<2.0.0,>=1.6.1
26
26
  Requires-Dist: frequenz-client-dispatch<0.9.0,>=0.8.4
27
27
  Provides-Extra: dev-flake8
28
- Requires-Dist: flake8==7.1.1; extra == "dev-flake8"
28
+ Requires-Dist: flake8==7.2.0; extra == "dev-flake8"
29
29
  Requires-Dist: flake8-docstrings==1.7.0; extra == "dev-flake8"
30
30
  Requires-Dist: flake8-pyproject==1.2.3; extra == "dev-flake8"
31
- Requires-Dist: pydoclint==0.6.0; extra == "dev-flake8"
31
+ Requires-Dist: pydoclint==0.6.4; extra == "dev-flake8"
32
32
  Requires-Dist: pydocstyle==6.3.0; extra == "dev-flake8"
33
33
  Provides-Extra: dev-formatting
34
34
  Requires-Dist: black==25.1.0; extra == "dev-formatting"
35
- Requires-Dist: isort==6.0.0; extra == "dev-formatting"
35
+ Requires-Dist: isort==6.0.1; extra == "dev-formatting"
36
36
  Provides-Extra: dev-mkdocs
37
37
  Requires-Dist: black==25.1.0; extra == "dev-mkdocs"
38
38
  Requires-Dist: Markdown==3.7; extra == "dev-mkdocs"
39
39
  Requires-Dist: mike==2.1.3; extra == "dev-mkdocs"
40
40
  Requires-Dist: mkdocs-gen-files==0.5.0; extra == "dev-mkdocs"
41
- Requires-Dist: mkdocs-literate-nav==0.6.1; extra == "dev-mkdocs"
41
+ Requires-Dist: mkdocs-literate-nav==0.6.2; extra == "dev-mkdocs"
42
42
  Requires-Dist: mkdocs-macros-plugin==1.3.7; extra == "dev-mkdocs"
43
- Requires-Dist: mkdocs-material==9.6.1; extra == "dev-mkdocs"
44
- Requires-Dist: mkdocstrings[python]==0.27.0; extra == "dev-mkdocs"
45
- Requires-Dist: mkdocstrings-python==1.13.0; extra == "dev-mkdocs"
46
- Requires-Dist: frequenz-repo-config[lib]==0.11.0; extra == "dev-mkdocs"
43
+ Requires-Dist: mkdocs-material==9.6.11; extra == "dev-mkdocs"
44
+ Requires-Dist: mkdocstrings[python]==0.29.1; extra == "dev-mkdocs"
45
+ Requires-Dist: mkdocstrings-python==1.16.8; extra == "dev-mkdocs"
46
+ Requires-Dist: frequenz-repo-config[lib]==0.13.1; extra == "dev-mkdocs"
47
47
  Provides-Extra: dev-mypy
48
- Requires-Dist: mypy==1.14.1; extra == "dev-mypy"
48
+ Requires-Dist: mypy==1.15.0; extra == "dev-mypy"
49
49
  Requires-Dist: grpc-stubs==1.53.0.5; extra == "dev-mypy"
50
- Requires-Dist: types-Markdown==3.7.0.20241204; extra == "dev-mypy"
50
+ Requires-Dist: types-Markdown==3.7.0.20250322; extra == "dev-mypy"
51
51
  Requires-Dist: frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-mypy"
52
52
  Provides-Extra: dev-noxfile
53
- Requires-Dist: uv==0.5.26; extra == "dev-noxfile"
53
+ Requires-Dist: uv==0.6.11; extra == "dev-noxfile"
54
54
  Requires-Dist: nox==2025.2.9; extra == "dev-noxfile"
55
- Requires-Dist: frequenz-repo-config[lib]==0.11.0; extra == "dev-noxfile"
55
+ Requires-Dist: frequenz-repo-config[lib]==0.13.1; extra == "dev-noxfile"
56
56
  Provides-Extra: dev-pylint
57
- Requires-Dist: pylint==3.3.4; extra == "dev-pylint"
57
+ Requires-Dist: pylint==3.3.6; extra == "dev-pylint"
58
58
  Requires-Dist: frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-pylint"
59
59
  Provides-Extra: dev-pytest
60
- Requires-Dist: pytest==8.3.4; extra == "dev-pytest"
61
- Requires-Dist: frequenz-repo-config[extra-lint-examples]==0.11.0; extra == "dev-pytest"
60
+ Requires-Dist: pytest==8.3.5; extra == "dev-pytest"
61
+ Requires-Dist: frequenz-repo-config[extra-lint-examples]==0.13.1; extra == "dev-pytest"
62
62
  Requires-Dist: pytest-mock==3.14.0; extra == "dev-pytest"
63
- Requires-Dist: pytest-asyncio==0.25.3; extra == "dev-pytest"
63
+ Requires-Dist: pytest-asyncio==0.26.0; extra == "dev-pytest"
64
64
  Requires-Dist: async-solipsism==0.7; extra == "dev-pytest"
65
65
  Requires-Dist: time-machine==2.16.0; extra == "dev-pytest"
66
66
  Provides-Extra: dev
67
67
  Requires-Dist: frequenz-dispatch[dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]; extra == "dev"
68
+ Dynamic: license-file
68
69
 
69
70
  # Dispatch Highlevel Interface
70
71
 
@@ -1,5 +1,5 @@
1
- typing-extensions<5.0.0,>=4.11.0
2
- frequenz-sdk<1.0.0-rc1800,>=1.0.0-rc1302
1
+ typing-extensions<5.0.0,>=4.13.0
2
+ frequenz-sdk<1.0.0-rc1900,>=1.0.0-rc1302
3
3
  frequenz-channels<2.0.0,>=1.6.1
4
4
  frequenz-client-dispatch<0.9.0,>=0.8.4
5
5
 
@@ -7,47 +7,47 @@ frequenz-client-dispatch<0.9.0,>=0.8.4
7
7
  frequenz-dispatch[dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]
8
8
 
9
9
  [dev-flake8]
10
- flake8==7.1.1
10
+ flake8==7.2.0
11
11
  flake8-docstrings==1.7.0
12
12
  flake8-pyproject==1.2.3
13
- pydoclint==0.6.0
13
+ pydoclint==0.6.4
14
14
  pydocstyle==6.3.0
15
15
 
16
16
  [dev-formatting]
17
17
  black==25.1.0
18
- isort==6.0.0
18
+ isort==6.0.1
19
19
 
20
20
  [dev-mkdocs]
21
21
  black==25.1.0
22
22
  Markdown==3.7
23
23
  mike==2.1.3
24
24
  mkdocs-gen-files==0.5.0
25
- mkdocs-literate-nav==0.6.1
25
+ mkdocs-literate-nav==0.6.2
26
26
  mkdocs-macros-plugin==1.3.7
27
- mkdocs-material==9.6.1
28
- mkdocstrings[python]==0.27.0
29
- mkdocstrings-python==1.13.0
30
- frequenz-repo-config[lib]==0.11.0
27
+ mkdocs-material==9.6.11
28
+ mkdocstrings[python]==0.29.1
29
+ mkdocstrings-python==1.16.8
30
+ frequenz-repo-config[lib]==0.13.1
31
31
 
32
32
  [dev-mypy]
33
- mypy==1.14.1
33
+ mypy==1.15.0
34
34
  grpc-stubs==1.53.0.5
35
- types-Markdown==3.7.0.20241204
35
+ types-Markdown==3.7.0.20250322
36
36
  frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]
37
37
 
38
38
  [dev-noxfile]
39
- uv==0.5.26
39
+ uv==0.6.11
40
40
  nox==2025.2.9
41
- frequenz-repo-config[lib]==0.11.0
41
+ frequenz-repo-config[lib]==0.13.1
42
42
 
43
43
  [dev-pylint]
44
- pylint==3.3.4
44
+ pylint==3.3.6
45
45
  frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]
46
46
 
47
47
  [dev-pytest]
48
- pytest==8.3.4
49
- frequenz-repo-config[extra-lint-examples]==0.11.0
48
+ pytest==8.3.5
49
+ frequenz-repo-config[extra-lint-examples]==0.13.1
50
50
  pytest-mock==3.14.0
51
- pytest-asyncio==0.25.3
51
+ pytest-asyncio==0.26.0
52
52
  async-solipsism==0.7
53
53
  time-machine==2.16.0
@@ -1,70 +0,0 @@
1
- # Dispatch Highlevel Interface Release Notes
2
-
3
- ## Summary
4
-
5
- This release introduces a more flexible and powerful mechanism for managing dispatch events with new strategies for merging intervals, enhanced customization options, and better overall alignment with evolving SDK dependencies. It also simplifies actor initialization while maintaining robust support for diverse dispatch scenarios.
6
-
7
- ## Upgrading
8
-
9
- A new simplified way to manage actors has been introduced:
10
-
11
- Change your code from:
12
- ```python
13
- dispatcher = Dispatcher(
14
- microgrid_id=microgrid_id,
15
- server_url=url,
16
- key=key
17
- )
18
- dispatcher.start()
19
-
20
- status_receiver = dispatcher.new_running_state_event_receiver("EXAMPLE_TYPE")
21
-
22
- managing_actor = ActorDispatcher(
23
- actor_factory=MyActor.new_with_dispatch,
24
- running_status_receiver=status_receiver,
25
- )
26
-
27
- await run(managing_actor)
28
- ```
29
-
30
- to
31
-
32
- ```python
33
- async with Dispatcher(
34
- microgrid_id=microgrid_id,
35
- server_url=url,
36
- key=key
37
- ) as dispatcher:
38
- await dispatcher.start_managing(
39
- dispatch_type="EXAMPLE_TYPE",
40
- actor_factory=MyActor.new_with_dispatch, # now async factory!
41
- merge_strategy=MergeByType,
42
- )
43
- await dispatcher
44
- ```
45
-
46
- Further changes:
47
-
48
- * `Dispatcher.start` is no longer `async`. Remove `await` when calling it.
49
- * Two properties have been replaced by methods that require a type as parameter.
50
- * `Dispatcher.lifecycle_events` has been replaced by the method `Dispatcher.new_lifecycle_events_receiver(self, dispatch_type: str)`.
51
- * `Dispatcher.running_status_change` has been replaced by the method `Dispatcher.new_running_state_event_receiver(self, dispatch_type: str, merge_strategy: MergeStrategy)`.
52
- * The managing actor constructor no longer requires the `dispatch_type` parameter. Instead you're expected to pass the type to the new_receiver function.
53
- * The `DispatchManagingActor` class has been renamed to `DispatchActorsService`.
54
- * It's interface has been simplified and now only requires an actor factory and a running status receiver.
55
- * It only starts/stops a single actor at a time now instead of a set of actors.
56
- * Refer to the updated [usage example](https://frequenz-floss.github.io/frequenz-dispatch-python/latest/reference/frequenz/dispatch/#frequenz.dispatch.DispatchActorsService) for more information.
57
- * `DispatchUpdate` was renamed to `DispatchInfo`.
58
-
59
-
60
- ## New Features
61
-
62
- * A new feature "merge strategy" (`MergeByType`, `MergeByTypeTarget`) has been added to the `Dispatcher.new_running_state_event_receiver` method. Using it, you can automatically merge consecutive and overlapping dispatch start/stop events of the same type. E.g. dispatch `A` starting at 10:10 and ending at 10:30 and dispatch `B` starts at 10:30 until 11:00, with the feature enabled this would in total trigger one start event, one reconfigure event at 10:30 and one stop event at 11:00.
63
- * The SDK dependency was widened to allow versions up to (excluding) v1.0.0-rc1800.
64
- * Actor management with dispatches has been simplified:
65
- * `Dispatcher.start_managing(dispatch_type, actor_factory, merge_strategy, retry_interval)` to manage your actor for the given type and merge strategy. All you need provide is an actor factory.
66
- * `Dispatcher.stop_managing(dispatch_type)` to stop dispatching for the given type.
67
- * `Dispatcher.is_managed(dispatch_type)` to check if dispatching is active for the given type.
68
- * Dispatches that failed to start will now be retried after a delay.
69
- * A new method `Dispatcher.wait_for_initialization()` has been added to wait for all actors to be initialized.
70
- * When using `async with Dispatcher(..) as dispatcher`, the dispatcher will first wait for the dispatch service to be initialized before entering the block.