frequenz-dispatch 0.2.0__tar.gz → 0.3.0__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 (21) hide show
  1. {frequenz-dispatch-0.2.0/src/frequenz_dispatch.egg-info → frequenz-dispatch-0.3.0}/PKG-INFO +10 -7
  2. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/README.md +9 -6
  3. frequenz-dispatch-0.3.0/RELEASE_NOTES.md +20 -0
  4. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/pyproject.toml +37 -25
  5. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/src/frequenz/dispatch/_dispatcher.py +15 -38
  6. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/src/frequenz/dispatch/actor.py +21 -22
  7. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0/src/frequenz_dispatch.egg-info}/PKG-INFO +10 -7
  8. frequenz-dispatch-0.3.0/src/frequenz_dispatch.egg-info/requires.txt +55 -0
  9. frequenz-dispatch-0.2.0/RELEASE_NOTES.md +0 -5
  10. frequenz-dispatch-0.2.0/src/frequenz_dispatch.egg-info/requires.txt +0 -53
  11. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/LICENSE +0 -0
  12. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/MANIFEST.in +0 -0
  13. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/setup.cfg +0 -0
  14. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/src/frequenz/dispatch/__init__.py +0 -0
  15. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/src/frequenz/dispatch/_dispatch.py +0 -0
  16. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/src/frequenz/dispatch/_event.py +0 -0
  17. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/src/frequenz/dispatch/conftest.py +0 -0
  18. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/src/frequenz/dispatch/py.typed +0 -0
  19. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/src/frequenz_dispatch.egg-info/SOURCES.txt +0 -0
  20. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/src/frequenz_dispatch.egg-info/dependency_links.txt +0 -0
  21. {frequenz-dispatch-0.2.0 → frequenz-dispatch-0.3.0}/src/frequenz_dispatch.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: frequenz-dispatch
3
- Version: 0.2.0
3
+ Version: 0.3.0
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
@@ -52,17 +52,20 @@ The [`Dispatcher` class](https://frequenz-floss.github.io/frequenz-dispatch-pyth
52
52
 
53
53
  ```python
54
54
  import os
55
- import grpc.aio
55
+ from frequenz.dispatch import Dispatcher, RunningState
56
56
  from unittest.mock import MagicMock
57
57
 
58
58
  async def run():
59
- host = os.getenv("DISPATCH_API_HOST", "localhost")
60
- port = os.getenv("DISPATCH_API_PORT", "50051")
59
+ url = os.getenv("DISPATCH_API_URL", "grpc://fz-0004.frequenz.io:50051")
60
+ key = os.getenv("DISPATCH_API_KEY", "some-key")
61
61
 
62
- service_address = f"{host}:{port}"
63
- grpc_channel = grpc.aio.insecure_channel(service_address)
64
62
  microgrid_id = 1
65
- dispatcher = Dispatcher(microgrid_id, grpc_channel, service_address)
63
+
64
+ dispatcher = Dispatcher(
65
+ microgrid_id=microgrid_id,
66
+ server_url=url,
67
+ key=key
68
+ )
66
69
  await dispatcher.start()
67
70
 
68
71
  actor = MagicMock() # replace with your actor
@@ -21,17 +21,20 @@ The [`Dispatcher` class](https://frequenz-floss.github.io/frequenz-dispatch-pyth
21
21
 
22
22
  ```python
23
23
  import os
24
- import grpc.aio
24
+ from frequenz.dispatch import Dispatcher, RunningState
25
25
  from unittest.mock import MagicMock
26
26
 
27
27
  async def run():
28
- host = os.getenv("DISPATCH_API_HOST", "localhost")
29
- port = os.getenv("DISPATCH_API_PORT", "50051")
28
+ url = os.getenv("DISPATCH_API_URL", "grpc://fz-0004.frequenz.io:50051")
29
+ key = os.getenv("DISPATCH_API_KEY", "some-key")
30
30
 
31
- service_address = f"{host}:{port}"
32
- grpc_channel = grpc.aio.insecure_channel(service_address)
33
31
  microgrid_id = 1
34
- dispatcher = Dispatcher(microgrid_id, grpc_channel, service_address)
32
+
33
+ dispatcher = Dispatcher(
34
+ microgrid_id=microgrid_id,
35
+ server_url=url,
36
+ key=key
37
+ )
35
38
  await dispatcher.start()
36
39
 
37
40
  actor = MagicMock() # replace with your actor
@@ -0,0 +1,20 @@
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
+ - The dispatch high level interface now depends on `frequenz-sdk` version `v1.0.0-rc900`.
10
+ - We are now using the version `0.6.0` of the underlying `frequenz-client-dispatch` client library.
11
+ - The init parameter of the `Dispatcher` class has been changed to accept a `server_url` instead.
12
+
13
+ ## New Features
14
+
15
+ * Using the new dispatch client, we now have support for pagination in the dispatch list request.
16
+ * The new client version also supports streaming, however it is not yet used internally in the high level interface.
17
+
18
+ ## Bug Fixes
19
+
20
+ - Fix documentation cross-linking to the `frequenz-client-dispatch` package.
@@ -5,7 +5,7 @@
5
5
  requires = [
6
6
  "setuptools == 68.1.0",
7
7
  "setuptools_scm[toml] == 7.1.0",
8
- "frequenz-repo-config[lib] == 0.9.2",
8
+ "frequenz-repo-config[lib] == 0.10.0",
9
9
  ]
10
10
  build-backend = "setuptools.build_meta"
11
11
 
@@ -39,9 +39,9 @@ dependencies = [
39
39
  # Make sure to update the version for cross-referencing also in the
40
40
  # mkdocs.yml file when changing the version here (look for the config key
41
41
  # plugins.mkdocstrings.handlers.python.import)
42
- "frequenz-sdk == 1.0.0rc601",
43
- "frequenz-channels >= 1.0.1, < 2.0.0",
44
- "frequenz-client-dispatch >= 0.5.0, < 0.6.0",
42
+ "frequenz-sdk == 1.0.0-rc900",
43
+ "frequenz-channels >= 1.1.0, < 2.0.0",
44
+ "frequenz-client-dispatch >= 0.6.0, < 0.7.0",
45
45
  ]
46
46
  dynamic = ["version"]
47
47
 
@@ -51,48 +51,50 @@ email = "floss@frequenz.com"
51
51
 
52
52
  [project.optional-dependencies]
53
53
  dev-flake8 = [
54
- "flake8 == 7.1.0",
54
+ "flake8 == 7.1.1",
55
55
  "flake8-docstrings == 1.7.0",
56
56
  "flake8-pyproject == 1.2.3", # For reading the flake8 config from pyproject.toml
57
- "pydoclint == 0.5.3",
57
+ "pydoclint == 0.5.6",
58
58
  "pydocstyle == 6.3.0",
59
59
  ]
60
- dev-formatting = ["black == 24.4.2", "isort == 5.13.2"]
60
+ dev-formatting = ["black == 24.8.0", "isort == 5.13.2"]
61
61
  dev-mkdocs = [
62
- "black == 24.4.2",
63
- "Markdown==3.6",
64
- "mike == 2.1.2",
62
+ "black == 24.8.0",
63
+ "Markdown==3.7",
64
+ "mike == 2.1.3",
65
65
  "mkdocs-gen-files == 0.5.0",
66
66
  "mkdocs-literate-nav == 0.6.1",
67
67
  "mkdocs-macros-plugin == 1.0.5",
68
- "mkdocs-material == 9.5.27",
69
- "mkdocstrings[python] == 0.25.1",
70
- "frequenz-repo-config[lib] == 0.9.2",
68
+ "mkdocs-material == 9.5.34",
69
+ "mkdocstrings[python] == 0.25.2",
70
+ "mkdocstrings-python == 1.10.9",
71
+ "frequenz-repo-config[lib] == 0.10.0",
71
72
  ]
72
73
  dev-mypy = [
73
- "mypy == 1.10.1",
74
- "types-Markdown == 3.6.0.20240316",
75
- "types-python-dateutil==2.9.0.20240316",
74
+ "mypy == 1.11.2",
75
+ "grpc-stubs == 1.53.0.5", # This dependency introduces breaking changes in patch releases
76
+ "types-Markdown == 3.7.0.20240822",
77
+ "types-python-dateutil==2.9.0.20240821",
76
78
  # For checking the noxfile, docs/ script, and tests
77
79
  "frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]",
78
80
  ]
79
81
  dev-noxfile = [
80
- "uv == 0.2.18",
82
+ "uv == 0.4.1",
81
83
  "nox == 2024.4.15",
82
- "frequenz-repo-config[lib] == 0.9.2",
84
+ "frequenz-repo-config[lib] == 0.10.0",
83
85
  ]
84
86
  dev-pylint = [
85
- "pylint == 3.2.5",
87
+ "pylint == 3.2.7",
86
88
  # For checking the noxfile, docs/ script, and tests
87
89
  "frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]",
88
90
  ]
89
91
  dev-pytest = [
90
- "pytest == 8.2.2",
91
- "frequenz-repo-config[extra-lint-examples] == 0.9.2",
92
+ "pytest == 8.3.2",
93
+ "frequenz-repo-config[extra-lint-examples] == 0.10.0",
92
94
  "pytest-mock == 3.14.0",
93
- "pytest-asyncio == 0.23.7",
94
- "async-solipsism == 0.6",
95
- "time-machine == 2.14.2",
95
+ "pytest-asyncio == 0.24.0",
96
+ "async-solipsism == 0.7",
97
+ "time-machine == 2.15.0",
96
98
  ]
97
99
  dev = [
98
100
  "frequenz-dispatch[dev-mkdocs,dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]",
@@ -148,8 +150,12 @@ disable = [
148
150
  # pylint's unsubscriptable check is buggy and is not needed because
149
151
  # it is a type-check, for which we already have mypy.
150
152
  "unsubscriptable-object",
153
+ # Checked by mypy
154
+ "no-member",
151
155
  # Checked by flake8
156
+ "f-string-without-interpolation",
152
157
  "line-too-long",
158
+ "missing-function-docstring",
153
159
  "redefined-outer-name",
154
160
  "unnecessary-lambda-assignment",
155
161
  "unused-import",
@@ -174,7 +180,13 @@ packages = ["frequenz.dispatch"]
174
180
  strict = true
175
181
 
176
182
  [[tool.mypy.overrides]]
177
- module = ["mkdocs_macros.*", "async_solipsism", "async_solipsism.*"]
183
+ module = [
184
+ "mkdocs_macros.*",
185
+ "async_solipsism",
186
+ "async_solipsism.*",
187
+ "grpc.aio",
188
+ "grpc.aio.*",
189
+ ]
178
190
  ignore_missing_imports = true
179
191
 
180
192
  [tool.setuptools_scm]
@@ -6,7 +6,6 @@
6
6
  import abc
7
7
  from typing import Protocol, TypeVar
8
8
 
9
- import grpc.aio
10
9
  from frequenz.channels import Broadcast, Receiver
11
10
  from frequenz.client.dispatch import Client
12
11
 
@@ -55,24 +54,18 @@ class Dispatcher:
55
54
  Example: Processing running state change dispatches
56
55
  ```python
57
56
  import os
58
- import grpc.aio
59
57
  from frequenz.dispatch import Dispatcher, RunningState
60
58
  from unittest.mock import MagicMock
61
59
 
62
60
  async def run():
63
- host = os.getenv("DISPATCH_API_HOST", "localhost")
64
- port = os.getenv("DISPATCH_API_PORT", "50051")
61
+ url = os.getenv("DISPATCH_API_URL", "grpc://fz-0004.frequenz.io:50051")
65
62
  key = os.getenv("DISPATCH_API_KEY", "some-key")
66
63
 
67
- service_address = f"{host}:{port}"
68
- grpc_channel = grpc.aio.secure_channel(
69
- service_address,
70
- credentials=grpc.ssl_channel_credentials()
71
- )
64
+ microgrid_id = 1
65
+
72
66
  dispatcher = Dispatcher(
73
- microgrid_id=1,
74
- grpc_channel=grpc_channel,
75
- svc_addr=service_address,
67
+ microgrid_id=microgrid_id,
68
+ server_url=url,
76
69
  key=key
77
70
  )
78
71
  await dispatcher.start()
@@ -112,23 +105,17 @@ class Dispatcher:
112
105
  import os
113
106
  from typing import assert_never
114
107
 
115
- import grpc.aio
116
108
  from frequenz.dispatch import Created, Deleted, Dispatcher, Updated
117
109
 
118
110
  async def run():
119
- host = os.getenv("DISPATCH_API_HOST", "localhost")
120
- port = os.getenv("DISPATCH_API_PORT", "50051")
111
+ url = os.getenv("DISPATCH_API_URL", "grpc://fz-0004.frequenz.io:50051")
121
112
  key = os.getenv("DISPATCH_API_KEY", "some-key")
122
113
 
123
- service_address = f"{host}:{port}"
124
- grpc_channel = grpc.aio.secure_channel(
125
- service_address,
126
- credentials=grpc.ssl_channel_credentials()
127
- )
114
+ microgrid_id = 1
115
+
128
116
  dispatcher = Dispatcher(
129
- microgrid_id=1,
130
- grpc_channel=grpc_channel,
131
- svc_addr=service_address,
117
+ microgrid_id=microgrid_id,
118
+ server_url=url,
132
119
  key=key
133
120
  )
134
121
  await dispatcher.start() # this will start the actor
@@ -154,27 +141,19 @@ class Dispatcher:
154
141
  import os
155
142
  from datetime import datetime, timedelta, timezone
156
143
 
157
- import grpc.aio
158
144
  from frequenz.client.common.microgrid.components import ComponentCategory
159
145
 
160
146
  from frequenz.dispatch import Dispatcher
161
147
 
162
148
  async def run():
163
- host = os.getenv("DISPATCH_API_HOST", "localhost")
164
- port = os.getenv("DISPATCH_API_PORT", "50051")
149
+ url = os.getenv("DISPATCH_API_URL", "grpc://fz-0004.frequenz.io:50051")
165
150
  key = os.getenv("DISPATCH_API_KEY", "some-key")
166
151
 
167
152
  microgrid_id = 1
168
153
 
169
- service_address = f"{host}:{port}"
170
- grpc_channel = grpc.aio.secure_channel(
171
- service_address,
172
- credentials=grpc.ssl_channel_credentials()
173
- )
174
154
  dispatcher = Dispatcher(
175
155
  microgrid_id=microgrid_id,
176
- grpc_channel=grpc_channel,
177
- svc_addr=service_address,
156
+ server_url=url,
178
157
  key=key
179
158
  )
180
159
  await dispatcher.start() # this will start the actor
@@ -208,23 +187,21 @@ class Dispatcher:
208
187
  self,
209
188
  *,
210
189
  microgrid_id: int,
211
- grpc_channel: grpc.aio.Channel,
212
- svc_addr: str,
190
+ server_url: str,
213
191
  key: str,
214
192
  ):
215
193
  """Initialize the dispatcher.
216
194
 
217
195
  Args:
218
196
  microgrid_id: The microgrid id.
219
- grpc_channel: The gRPC channel.
220
- svc_addr: The service address.
197
+ server_url: The URL of the dispatch service.
221
198
  key: The key to access the service.
222
199
  """
223
200
  self._running_state_channel = Broadcast[Dispatch](name="running_state_change")
224
201
  self._lifecycle_events_channel = Broadcast[DispatchEvent](
225
202
  name="lifecycle_events"
226
203
  )
227
- self._client = Client(grpc_channel=grpc_channel, svc_addr=svc_addr, key=key)
204
+ self._client = Client(server_url=server_url, key=key)
228
205
  self._actor = DispatchingActor(
229
206
  microgrid_id,
230
207
  self._client,
@@ -89,28 +89,27 @@ class DispatchingActor(Actor):
89
89
 
90
90
  try:
91
91
  _logger.info("Fetching dispatches for microgrid %s", self._microgrid_id)
92
- async for client_dispatch in self._client.list(
93
- microgrid_id=self._microgrid_id
94
- ):
95
- dispatch = Dispatch(client_dispatch)
96
-
97
- self._dispatches[dispatch.id] = Dispatch(client_dispatch)
98
- old_dispatch = old_dispatches.pop(dispatch.id, None)
99
- if not old_dispatch:
100
- self._update_dispatch_schedule(dispatch, None)
101
- _logger.info("New dispatch: %s", dispatch)
102
- await self._lifecycle_updates_sender.send(
103
- Created(dispatch=dispatch)
104
- )
105
- elif dispatch.update_time != old_dispatch.update_time:
106
- self._update_dispatch_schedule(dispatch, old_dispatch)
107
- _logger.info("Updated dispatch: %s", dispatch)
108
- await self._lifecycle_updates_sender.send(
109
- Updated(dispatch=dispatch)
110
- )
111
-
112
- if self._running_state_change(dispatch, old_dispatch):
113
- await self._send_running_state_change(dispatch)
92
+ async for page in self._client.list(microgrid_id=self._microgrid_id):
93
+ for client_dispatch in page:
94
+ dispatch = Dispatch(client_dispatch)
95
+
96
+ self._dispatches[dispatch.id] = Dispatch(client_dispatch)
97
+ old_dispatch = old_dispatches.pop(dispatch.id, None)
98
+ if not old_dispatch:
99
+ self._update_dispatch_schedule(dispatch, None)
100
+ _logger.info("New dispatch: %s", dispatch)
101
+ await self._lifecycle_updates_sender.send(
102
+ Created(dispatch=dispatch)
103
+ )
104
+ elif dispatch.update_time != old_dispatch.update_time:
105
+ self._update_dispatch_schedule(dispatch, old_dispatch)
106
+ _logger.info("Updated dispatch: %s", dispatch)
107
+ await self._lifecycle_updates_sender.send(
108
+ Updated(dispatch=dispatch)
109
+ )
110
+
111
+ if self._running_state_change(dispatch, old_dispatch):
112
+ await self._send_running_state_change(dispatch)
114
113
 
115
114
  except grpc.aio.AioRpcError as error:
116
115
  _logger.error("Error fetching dispatches: %s", error)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: frequenz-dispatch
3
- Version: 0.2.0
3
+ Version: 0.3.0
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
@@ -52,17 +52,20 @@ The [`Dispatcher` class](https://frequenz-floss.github.io/frequenz-dispatch-pyth
52
52
 
53
53
  ```python
54
54
  import os
55
- import grpc.aio
55
+ from frequenz.dispatch import Dispatcher, RunningState
56
56
  from unittest.mock import MagicMock
57
57
 
58
58
  async def run():
59
- host = os.getenv("DISPATCH_API_HOST", "localhost")
60
- port = os.getenv("DISPATCH_API_PORT", "50051")
59
+ url = os.getenv("DISPATCH_API_URL", "grpc://fz-0004.frequenz.io:50051")
60
+ key = os.getenv("DISPATCH_API_KEY", "some-key")
61
61
 
62
- service_address = f"{host}:{port}"
63
- grpc_channel = grpc.aio.insecure_channel(service_address)
64
62
  microgrid_id = 1
65
- dispatcher = Dispatcher(microgrid_id, grpc_channel, service_address)
63
+
64
+ dispatcher = Dispatcher(
65
+ microgrid_id=microgrid_id,
66
+ server_url=url,
67
+ key=key
68
+ )
66
69
  await dispatcher.start()
67
70
 
68
71
  actor = MagicMock() # replace with your actor
@@ -0,0 +1,55 @@
1
+ python-dateutil<3.0,>=2.8.2
2
+ typing-extensions<5.0.0,>=4.11.0
3
+ frequenz-sdk==1.0.0-rc900
4
+ frequenz-channels<2.0.0,>=1.1.0
5
+ frequenz-client-dispatch<0.7.0,>=0.6.0
6
+
7
+ [dev]
8
+ frequenz-dispatch[dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]
9
+
10
+ [dev-flake8]
11
+ flake8==7.1.1
12
+ flake8-docstrings==1.7.0
13
+ flake8-pyproject==1.2.3
14
+ pydoclint==0.5.6
15
+ pydocstyle==6.3.0
16
+
17
+ [dev-formatting]
18
+ black==24.8.0
19
+ isort==5.13.2
20
+
21
+ [dev-mkdocs]
22
+ black==24.8.0
23
+ Markdown==3.7
24
+ mike==2.1.3
25
+ mkdocs-gen-files==0.5.0
26
+ mkdocs-literate-nav==0.6.1
27
+ mkdocs-macros-plugin==1.0.5
28
+ mkdocs-material==9.5.34
29
+ mkdocstrings[python]==0.25.2
30
+ mkdocstrings-python==1.10.9
31
+ frequenz-repo-config[lib]==0.10.0
32
+
33
+ [dev-mypy]
34
+ mypy==1.11.2
35
+ grpc-stubs==1.53.0.5
36
+ types-Markdown==3.7.0.20240822
37
+ types-python-dateutil==2.9.0.20240821
38
+ frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]
39
+
40
+ [dev-noxfile]
41
+ uv==0.4.1
42
+ nox==2024.4.15
43
+ frequenz-repo-config[lib]==0.10.0
44
+
45
+ [dev-pylint]
46
+ pylint==3.2.7
47
+ frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]
48
+
49
+ [dev-pytest]
50
+ pytest==8.3.2
51
+ frequenz-repo-config[extra-lint-examples]==0.10.0
52
+ pytest-mock==3.14.0
53
+ pytest-asyncio==0.24.0
54
+ async-solipsism==0.7
55
+ time-machine==2.15.0
@@ -1,5 +0,0 @@
1
- # Dispatch Highlevel Interface Release Notes
2
-
3
- ## Upgrading
4
-
5
- * An API key for authorization must now be passed to the client.
@@ -1,53 +0,0 @@
1
- python-dateutil<3.0,>=2.8.2
2
- typing-extensions<5.0.0,>=4.11.0
3
- frequenz-sdk==1.0.0rc601
4
- frequenz-channels<2.0.0,>=1.0.1
5
- frequenz-client-dispatch<0.6.0,>=0.5.0
6
-
7
- [dev]
8
- frequenz-dispatch[dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]
9
-
10
- [dev-flake8]
11
- flake8==7.1.0
12
- flake8-docstrings==1.7.0
13
- flake8-pyproject==1.2.3
14
- pydoclint==0.5.3
15
- pydocstyle==6.3.0
16
-
17
- [dev-formatting]
18
- black==24.4.2
19
- isort==5.13.2
20
-
21
- [dev-mkdocs]
22
- black==24.4.2
23
- Markdown==3.6
24
- mike==2.1.2
25
- mkdocs-gen-files==0.5.0
26
- mkdocs-literate-nav==0.6.1
27
- mkdocs-macros-plugin==1.0.5
28
- mkdocs-material==9.5.27
29
- mkdocstrings[python]==0.25.1
30
- frequenz-repo-config[lib]==0.9.2
31
-
32
- [dev-mypy]
33
- mypy==1.10.1
34
- types-Markdown==3.6.0.20240316
35
- types-python-dateutil==2.9.0.20240316
36
- frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]
37
-
38
- [dev-noxfile]
39
- uv==0.2.18
40
- nox==2024.4.15
41
- frequenz-repo-config[lib]==0.9.2
42
-
43
- [dev-pylint]
44
- pylint==3.2.5
45
- frequenz-dispatch[dev-mkdocs,dev-noxfile,dev-pytest]
46
-
47
- [dev-pytest]
48
- pytest==8.2.2
49
- frequenz-repo-config[extra-lint-examples]==0.9.2
50
- pytest-mock==3.14.0
51
- pytest-asyncio==0.23.7
52
- async-solipsism==0.6
53
- time-machine==2.14.2