frequenz-gridpool 0.6.3__tar.gz → 0.7.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.
- {frequenz_gridpool-0.6.3/src/frequenz_gridpool.egg-info → frequenz_gridpool-0.7.0}/PKG-INFO +71 -11
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/README.md +64 -4
- frequenz_gridpool-0.7.0/RELEASE_NOTES.md +119 -0
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/pyproject.toml +9 -8
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/__init__.py +0 -16
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/cli/__main__.py +24 -24
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/cli/_dump_config.py +9 -9
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/cli/_patch_config.py +7 -6
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/config/__init__.py +15 -15
- frequenz_gridpool-0.7.0/src/frequenz/gridpool/config/_assets.py +422 -0
- frequenz_gridpool-0.6.3/src/frequenz/gridpool/config/load.py → frequenz_gridpool-0.7.0/src/frequenz/gridpool/config/_load.py +51 -89
- frequenz_gridpool-0.6.3/src/frequenz/gridpool/config/microgrid.py → frequenz_gridpool-0.7.0/src/frequenz/gridpool/config/_microgrid.py +11 -119
- frequenz_gridpool-0.7.0/src/frequenz/gridpool/config/_migrations.py +139 -0
- frequenz_gridpool-0.7.0/src/frequenz/gridpool/config/_topology.py +377 -0
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0/src/frequenz_gridpool.egg-info}/PKG-INFO +71 -11
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz_gridpool.egg-info/SOURCES.txt +5 -2
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz_gridpool.egg-info/requires.txt +6 -6
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz_gridpool.egg-info/scm_file_list.json +47 -42
- frequenz_gridpool-0.7.0/src/frequenz_gridpool.egg-info/scm_version.json +8 -0
- frequenz_gridpool-0.6.3/RELEASE_NOTES.md +0 -17
- frequenz_gridpool-0.6.3/src/frequenz_gridpool.egg-info/scm_version.json +0 -8
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/LICENSE +0 -0
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/MANIFEST.in +0 -0
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/setup.cfg +0 -0
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/_graph_generator.py +0 -0
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/cli/__init__.py +0 -0
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/cli/_render_graph.py +0 -0
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/conftest.py +0 -0
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/py.typed +0 -0
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz_gridpool.egg-info/dependency_links.txt +0 -0
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz_gridpool.egg-info/entry_points.txt +0 -0
- {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz_gridpool.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frequenz-gridpool
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: High-level interface to grid pools for the Frequenz platform.
|
|
5
5
|
Author-email: Frequenz Energy-as-a-Service GmbH <floss@frequenz.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -35,7 +35,7 @@ Requires-Dist: flake8==7.3.0; extra == "dev-flake8"
|
|
|
35
35
|
Requires-Dist: flake8-datetimez==20.10.0; extra == "dev-flake8"
|
|
36
36
|
Requires-Dist: flake8-docstrings==1.7.0; extra == "dev-flake8"
|
|
37
37
|
Requires-Dist: flake8-pyproject==1.2.4; extra == "dev-flake8"
|
|
38
|
-
Requires-Dist: pydoclint==0.9.
|
|
38
|
+
Requires-Dist: pydoclint==0.9.1; extra == "dev-flake8"
|
|
39
39
|
Requires-Dist: pydocstyle==6.3.0; extra == "dev-flake8"
|
|
40
40
|
Provides-Extra: dev-formatting
|
|
41
41
|
Requires-Dist: black==26.5.1; extra == "dev-formatting"
|
|
@@ -47,17 +47,17 @@ Requires-Dist: mike==2.2.0; extra == "dev-mkdocs"
|
|
|
47
47
|
Requires-Dist: mkdocs-gen-files==0.6.1; extra == "dev-mkdocs"
|
|
48
48
|
Requires-Dist: mkdocs-literate-nav==0.6.3; extra == "dev-mkdocs"
|
|
49
49
|
Requires-Dist: mkdocs-macros-plugin==1.5.0; extra == "dev-mkdocs"
|
|
50
|
-
Requires-Dist: mkdocs-material==9.7.
|
|
51
|
-
Requires-Dist: mkdocstrings[python]==1.0.
|
|
50
|
+
Requires-Dist: mkdocs-material==9.7.7; extra == "dev-mkdocs"
|
|
51
|
+
Requires-Dist: mkdocstrings[python]==1.0.6; extra == "dev-mkdocs"
|
|
52
52
|
Requires-Dist: mkdocstrings-python==2.0.5; extra == "dev-mkdocs"
|
|
53
53
|
Requires-Dist: frequenz-repo-config[lib]==0.18.0; extra == "dev-mkdocs"
|
|
54
54
|
Provides-Extra: dev-mypy
|
|
55
|
-
Requires-Dist: mypy==2.
|
|
55
|
+
Requires-Dist: mypy==2.3.0; extra == "dev-mypy"
|
|
56
56
|
Requires-Dist: types-networkx>=3.6.1.20251220; extra == "dev-mypy"
|
|
57
|
-
Requires-Dist: types-Markdown==3.10.2.
|
|
57
|
+
Requires-Dist: types-Markdown==3.10.2.20260712; extra == "dev-mypy"
|
|
58
58
|
Requires-Dist: frequenz-gridpool[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-mypy"
|
|
59
59
|
Provides-Extra: dev-noxfile
|
|
60
|
-
Requires-Dist: nox==2026.
|
|
60
|
+
Requires-Dist: nox==2026.7.11; extra == "dev-noxfile"
|
|
61
61
|
Requires-Dist: frequenz-repo-config[lib]==0.18.0; extra == "dev-noxfile"
|
|
62
62
|
Provides-Extra: dev-pylint
|
|
63
63
|
Requires-Dist: frequenz-gridpool[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-pylint"
|
|
@@ -81,9 +81,64 @@ Dynamic: license-file
|
|
|
81
81
|
|
|
82
82
|
## Introduction
|
|
83
83
|
|
|
84
|
-
High-level interface to
|
|
84
|
+
High-level interface to gridpools for the Frequenz platform.
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
## Market topology configuration
|
|
87
|
+
|
|
88
|
+
Market topology is stored under the `assets` namespace. A relation names at
|
|
89
|
+
least two of a gridpool, microgrid and market location:
|
|
90
|
+
|
|
91
|
+
```toml
|
|
92
|
+
assets.microgrids.241.meta.microgrid_id = 241
|
|
93
|
+
|
|
94
|
+
assets.market_locations.10208446344.id = "10208446344"
|
|
95
|
+
|
|
96
|
+
assets.relations.G80M241L10208446344.gridpool_id = 80
|
|
97
|
+
assets.relations.G80M241L10208446344.microgrid_id = 241
|
|
98
|
+
assets.relations.G80M241L10208446344.market_location_id = "10208446344"
|
|
99
|
+
assets.relations.G80M241L10208446344.delivery_area.code = "10YDE-RWENET---I"
|
|
100
|
+
assets.relations.G80M241L10208446344.validity.trading.participation = "ENERGY_TRADING"
|
|
101
|
+
assets.relations.G80M241L10208446344.validity.trading.start = 2026-01-01T00:00:00Z
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
A relation naming a gridpool requires a delivery area. A gridpool-free relation
|
|
105
|
+
must link a microgrid and market location, and may carry a delivery area for a
|
|
106
|
+
direct market-location-to-area mapping. Omitted market-location types default
|
|
107
|
+
to `MALO_ID`; omitted market areas default to `101` (`EU_DE`).
|
|
108
|
+
|
|
109
|
+
A delivery area is a `code` and a `code_type` that defaults to EIC, so an EIC
|
|
110
|
+
area is just `delivery_area.code = "..."`. EIC codes are checked for format and
|
|
111
|
+
check character, not registration with an EIC issuing office; other code types
|
|
112
|
+
are taken as given. One code is bound to a single code type across a document.
|
|
113
|
+
|
|
114
|
+
Validity periods are half-open: the start is inclusive, the end exclusive, and
|
|
115
|
+
an omitted bound is open. Bounds and query instants must include a UTC offset.
|
|
116
|
+
|
|
117
|
+
Load one or more files and query the merged document with:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from datetime import datetime, timezone
|
|
121
|
+
from pathlib import Path
|
|
122
|
+
|
|
123
|
+
from frequenz.gridpool.config import AssetsConfig
|
|
124
|
+
|
|
125
|
+
config = AssetsConfig.load_from_files(
|
|
126
|
+
[Path("topology.toml"), Path("topology-overrides.toml")]
|
|
127
|
+
)
|
|
128
|
+
relations = config.find_relations(
|
|
129
|
+
microgrid_id=241,
|
|
130
|
+
at=datetime(2026, 1, 15, tzinfo=timezone.utc),
|
|
131
|
+
)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Later files override individual fields from earlier files. The projections
|
|
135
|
+
`find_delivery_areas`, `find_market_locations` and `find_microgrids` accept
|
|
136
|
+
filters for the other relation sides and an instant. `find_delivery_areas`
|
|
137
|
+
returns each area with its code and code type; a delivery-area filter takes
|
|
138
|
+
either a bare code or a full delivery area matched on its code type.
|
|
139
|
+
|
|
140
|
+
Market locations are keyed by raw ID, so the same raw ID cannot be used in
|
|
141
|
+
several market areas within one document.
|
|
87
142
|
|
|
88
143
|
## Supported Platforms
|
|
89
144
|
|
|
@@ -161,7 +216,11 @@ Redirect stdout to save the result:
|
|
|
161
216
|
gridpool-cli generate-config <microgrid_id> > microgrid.toml
|
|
162
217
|
```
|
|
163
218
|
|
|
164
|
-
|
|
219
|
+
This command emits only microgrid entries. Topology relations, including their
|
|
220
|
+
delivery-area codes, and market-location entries from input files are not
|
|
221
|
+
included in its stdout output.
|
|
222
|
+
|
|
223
|
+
You can layer existing microgrid config files with the Assets API by precedence
|
|
165
224
|
(`--default` < Assets API < `--override`). Values from a `--default` file are
|
|
166
225
|
overridden by the API, while a `--override` file keeps its own values and the
|
|
167
226
|
API only fills the gaps:
|
|
@@ -172,7 +231,8 @@ gridpool-cli generate-config <microgrid_id> \
|
|
|
172
231
|
--override overrides.toml > microgrid.toml
|
|
173
232
|
```
|
|
174
233
|
|
|
175
|
-
If no microgrid IDs are given, they are taken from the
|
|
234
|
+
If no microgrid IDs are given, they are taken from the microgrid entries in the
|
|
235
|
+
supplied files:
|
|
176
236
|
|
|
177
237
|
```bash
|
|
178
238
|
gridpool-cli generate-config --override existing.toml > microgrid.toml
|
|
@@ -6,9 +6,64 @@
|
|
|
6
6
|
|
|
7
7
|
## Introduction
|
|
8
8
|
|
|
9
|
-
High-level interface to
|
|
9
|
+
High-level interface to gridpools for the Frequenz platform.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Market topology configuration
|
|
12
|
+
|
|
13
|
+
Market topology is stored under the `assets` namespace. A relation names at
|
|
14
|
+
least two of a gridpool, microgrid and market location:
|
|
15
|
+
|
|
16
|
+
```toml
|
|
17
|
+
assets.microgrids.241.meta.microgrid_id = 241
|
|
18
|
+
|
|
19
|
+
assets.market_locations.10208446344.id = "10208446344"
|
|
20
|
+
|
|
21
|
+
assets.relations.G80M241L10208446344.gridpool_id = 80
|
|
22
|
+
assets.relations.G80M241L10208446344.microgrid_id = 241
|
|
23
|
+
assets.relations.G80M241L10208446344.market_location_id = "10208446344"
|
|
24
|
+
assets.relations.G80M241L10208446344.delivery_area.code = "10YDE-RWENET---I"
|
|
25
|
+
assets.relations.G80M241L10208446344.validity.trading.participation = "ENERGY_TRADING"
|
|
26
|
+
assets.relations.G80M241L10208446344.validity.trading.start = 2026-01-01T00:00:00Z
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
A relation naming a gridpool requires a delivery area. A gridpool-free relation
|
|
30
|
+
must link a microgrid and market location, and may carry a delivery area for a
|
|
31
|
+
direct market-location-to-area mapping. Omitted market-location types default
|
|
32
|
+
to `MALO_ID`; omitted market areas default to `101` (`EU_DE`).
|
|
33
|
+
|
|
34
|
+
A delivery area is a `code` and a `code_type` that defaults to EIC, so an EIC
|
|
35
|
+
area is just `delivery_area.code = "..."`. EIC codes are checked for format and
|
|
36
|
+
check character, not registration with an EIC issuing office; other code types
|
|
37
|
+
are taken as given. One code is bound to a single code type across a document.
|
|
38
|
+
|
|
39
|
+
Validity periods are half-open: the start is inclusive, the end exclusive, and
|
|
40
|
+
an omitted bound is open. Bounds and query instants must include a UTC offset.
|
|
41
|
+
|
|
42
|
+
Load one or more files and query the merged document with:
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from datetime import datetime, timezone
|
|
46
|
+
from pathlib import Path
|
|
47
|
+
|
|
48
|
+
from frequenz.gridpool.config import AssetsConfig
|
|
49
|
+
|
|
50
|
+
config = AssetsConfig.load_from_files(
|
|
51
|
+
[Path("topology.toml"), Path("topology-overrides.toml")]
|
|
52
|
+
)
|
|
53
|
+
relations = config.find_relations(
|
|
54
|
+
microgrid_id=241,
|
|
55
|
+
at=datetime(2026, 1, 15, tzinfo=timezone.utc),
|
|
56
|
+
)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Later files override individual fields from earlier files. The projections
|
|
60
|
+
`find_delivery_areas`, `find_market_locations` and `find_microgrids` accept
|
|
61
|
+
filters for the other relation sides and an instant. `find_delivery_areas`
|
|
62
|
+
returns each area with its code and code type; a delivery-area filter takes
|
|
63
|
+
either a bare code or a full delivery area matched on its code type.
|
|
64
|
+
|
|
65
|
+
Market locations are keyed by raw ID, so the same raw ID cannot be used in
|
|
66
|
+
several market areas within one document.
|
|
12
67
|
|
|
13
68
|
## Supported Platforms
|
|
14
69
|
|
|
@@ -86,7 +141,11 @@ Redirect stdout to save the result:
|
|
|
86
141
|
gridpool-cli generate-config <microgrid_id> > microgrid.toml
|
|
87
142
|
```
|
|
88
143
|
|
|
89
|
-
|
|
144
|
+
This command emits only microgrid entries. Topology relations, including their
|
|
145
|
+
delivery-area codes, and market-location entries from input files are not
|
|
146
|
+
included in its stdout output.
|
|
147
|
+
|
|
148
|
+
You can layer existing microgrid config files with the Assets API by precedence
|
|
90
149
|
(`--default` < Assets API < `--override`). Values from a `--default` file are
|
|
91
150
|
overridden by the API, while a `--override` file keeps its own values and the
|
|
92
151
|
API only fills the gaps:
|
|
@@ -97,7 +156,8 @@ gridpool-cli generate-config <microgrid_id> \
|
|
|
97
156
|
--override overrides.toml > microgrid.toml
|
|
98
157
|
```
|
|
99
158
|
|
|
100
|
-
If no microgrid IDs are given, they are taken from the
|
|
159
|
+
If no microgrid IDs are given, they are taken from the microgrid entries in the
|
|
160
|
+
supplied files:
|
|
101
161
|
|
|
102
162
|
```bash
|
|
103
163
|
gridpool-cli generate-config --override existing.toml > microgrid.toml
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Frequenz Gridpool Library Release Notes
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
<!-- Here goes a general summary of what this release is about -->
|
|
6
|
+
|
|
7
|
+
## Upgrading
|
|
8
|
+
|
|
9
|
+
- `MicrogridConfig.load_from_file` is replaced by `AssetsConfig.load_from_files`,
|
|
10
|
+
which loads one or more files, merged into one document, and returns the whole
|
|
11
|
+
document rather than just its microgrids:
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
configs = AssetsConfig.load_from_files(path).microgrids
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`load_configs` now returns the whole `AssetsConfig` rather than just its
|
|
18
|
+
microgrids, so the file layers' `relations` and `market_locations` survive the
|
|
19
|
+
merge; replace `load_configs(...)` with `load_configs(...).microgrids` where
|
|
20
|
+
only the microgrid map is needed. `load_from_files` layers files field by field
|
|
21
|
+
instead of replacing a complete microgrid entry; fields omitted by a later file
|
|
22
|
+
retain the value from the earlier layer and cannot be removed by omission.
|
|
23
|
+
|
|
24
|
+
- `Metadata` is removed; its fields (`microgrid_id`, `name`, `gid`, coordinates,
|
|
25
|
+
times) now sit directly on `MicrogridConfig`:
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
MicrogridConfig(microgrid_id=1, name="Grid") # was meta=Metadata(...)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
In TOML they move up one level, `assets.microgrids.1.name` rather than
|
|
32
|
+
`assets.microgrids.1.meta.name`. A file still nesting a microgrid's fields
|
|
33
|
+
under `meta` loads, lifted with a deprecation warning.
|
|
34
|
+
|
|
35
|
+
- A microgrid's `delivery_area` is removed. Move its value to a relation's
|
|
36
|
+
`delivery_area.code`, and set `delivery_area.code_type` when the code is not
|
|
37
|
+
EIC. When relations are present, the legacy `gid` must be their sole
|
|
38
|
+
gridpool ID; remove it for a microgrid that participates in several gridpools.
|
|
39
|
+
|
|
40
|
+
- `load_configs_from_files` is removed. Use `AssetsConfig.load_from_files`,
|
|
41
|
+
which returns the whole document rather than just its microgrids: replace
|
|
42
|
+
`load_configs_from_files(files)` with
|
|
43
|
+
`AssetsConfig.load_from_files(files).microgrids`, or use the returned
|
|
44
|
+
`AssetsConfig` directly to keep relations and market locations.
|
|
45
|
+
|
|
46
|
+
- `load_configs_from_api` is now private. For an API-only load call
|
|
47
|
+
`load_configs(assets_client=..., microgrid_ids=...)` and read its `.microgrids`.
|
|
48
|
+
|
|
49
|
+
- `merge_config_maps` and `merge_microgrid_configs` are removed. Layering is now
|
|
50
|
+
done on the raw tables before loading, inside `load_configs` and
|
|
51
|
+
`AssetsConfig.load_from_files`; pass all the layers to one of those instead of
|
|
52
|
+
merging loaded objects.
|
|
53
|
+
|
|
54
|
+
- Relation validity bounds and `at` query instants must include a UTC offset.
|
|
55
|
+
|
|
56
|
+
- The implementation modules `config.load` and `config.microgrid` are now
|
|
57
|
+
private. Import their public names from `frequenz.gridpool.config` instead.
|
|
58
|
+
|
|
59
|
+
- Microgrids are now keyed by `int` microgrid ID, not `str`. This covers
|
|
60
|
+
`AssetsConfig.microgrids`, including documents returned by `load_configs`.
|
|
61
|
+
Index the mapping by integer ID:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
configs[1] # was configs["1"]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- The `AC_ACTIVE_POWER` deprecation warning is dropped. Use `AC_POWER_ACTIVE`
|
|
68
|
+
as the formula metric key; the old name is no longer flagged on load.
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
## New Features
|
|
72
|
+
|
|
73
|
+
- `AssetsConfig` gives the `assets` namespace a type, so the entities still to
|
|
74
|
+
come are added as fields rather than as more dict lookups. Microgrid IDs are
|
|
75
|
+
checked during construction. `AssetsConfig.check()` performs the topology-wide
|
|
76
|
+
checks after all layers have been merged; the file loaders call it unless
|
|
77
|
+
`AssetsConfig.load_from_files` is passed `check=False`.
|
|
78
|
+
|
|
79
|
+
File loaders ignore unknown entity tables with a warning, so a reader keeps
|
|
80
|
+
working against files that already carry newer entities.
|
|
81
|
+
|
|
82
|
+
The `assets` table may carry a `version`; on load a document is run through a
|
|
83
|
+
migration pipeline that brings older layouts up to the current format, so
|
|
84
|
+
legacy files keep working. The version tracks the assets format alone, not
|
|
85
|
+
the whole document.
|
|
86
|
+
|
|
87
|
+
- Market topology is described under `assets.relations`, based on the Assets
|
|
88
|
+
API `MarketTopologyRelation`: each record links at least two of a gridpool, a
|
|
89
|
+
microgrid and a market location, filed under a
|
|
90
|
+
`G<gridpool_id>M<microgrid_id>L<market_location_id>` key derived from its own
|
|
91
|
+
sides. A relation naming a gridpool sits in a `delivery_area` that rides on
|
|
92
|
+
the relation, so a gridpool-to-microgrid relation with no market location still
|
|
93
|
+
carries one. A relation's validity lives in `validity`, each entry a half-open
|
|
94
|
+
`[start, end)` datetime period it applies over. Use-case-specific periods
|
|
95
|
+
qualify a relation; separate relations let one microgrid participate in
|
|
96
|
+
several gridpools. The config extends the API with plain periods for relations
|
|
97
|
+
that do not distinguish use cases. A gridpool-free microgrid-to-market-location
|
|
98
|
+
relation may also carry a delivery area for a direct mapping. Market locations
|
|
99
|
+
live under `assets.market_locations` as self-describing entries carrying their
|
|
100
|
+
own identifier, how to read it (`MALO_ID` by default), and the Assets API market
|
|
101
|
+
area (`EU_DE` by default). A relation's `delivery_area` is a `code` plus a
|
|
102
|
+
`code_type` that defaults to EIC, so an EIC area is just
|
|
103
|
+
`delivery_area.code = "..."`; EIC codes are check-character-validated. Raw
|
|
104
|
+
market-location IDs must be unique within a document, including across market
|
|
105
|
+
areas.
|
|
106
|
+
|
|
107
|
+
`AssetsConfig` answers the common lookups with `find_relations` and the
|
|
108
|
+
projections `find_delivery_areas`, `find_market_locations` and
|
|
109
|
+
`find_microgrids`, each filtered by the other sides and an instant.
|
|
110
|
+
|
|
111
|
+
Time-varying enterprise ownership is outside this change;
|
|
112
|
+
`MicrogridConfig.enterprise_id` remains as a scalar field.
|
|
113
|
+
|
|
114
|
+
## Bug Fixes
|
|
115
|
+
|
|
116
|
+
- Layering config files no longer resets a field a later file leaves unset back
|
|
117
|
+
to its default. The raw tables are merged before they are loaded.
|
|
118
|
+
|
|
119
|
+
<!-- Here goes notable bug fixes that are worth a special mention or explanation -->
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
[build-system]
|
|
5
5
|
requires = [
|
|
6
|
-
"setuptools ==
|
|
7
|
-
"setuptools_scm[toml] == 10.2.
|
|
6
|
+
"setuptools == 83.0.0",
|
|
7
|
+
"setuptools_scm[toml] == 10.2.1",
|
|
8
8
|
"frequenz-repo-config[lib] == 0.18.0",
|
|
9
9
|
]
|
|
10
10
|
build-backend = "setuptools.build_meta"
|
|
@@ -56,7 +56,7 @@ dev-flake8 = [
|
|
|
56
56
|
"flake8-datetimez == 20.10.0",
|
|
57
57
|
"flake8-docstrings == 1.7.0",
|
|
58
58
|
"flake8-pyproject == 1.2.4", # For reading the flake8 config from pyproject.toml
|
|
59
|
-
"pydoclint == 0.9.
|
|
59
|
+
"pydoclint == 0.9.1",
|
|
60
60
|
"pydocstyle == 6.3.0",
|
|
61
61
|
]
|
|
62
62
|
dev-formatting = ["black == 26.5.1", "isort == 8.0.1"]
|
|
@@ -67,20 +67,20 @@ dev-mkdocs = [
|
|
|
67
67
|
"mkdocs-gen-files == 0.6.1",
|
|
68
68
|
"mkdocs-literate-nav == 0.6.3",
|
|
69
69
|
"mkdocs-macros-plugin == 1.5.0",
|
|
70
|
-
"mkdocs-material == 9.7.
|
|
71
|
-
"mkdocstrings[python] == 1.0.
|
|
70
|
+
"mkdocs-material == 9.7.7",
|
|
71
|
+
"mkdocstrings[python] == 1.0.6",
|
|
72
72
|
"mkdocstrings-python == 2.0.5",
|
|
73
73
|
"frequenz-repo-config[lib] == 0.18.0",
|
|
74
74
|
]
|
|
75
75
|
dev-mypy = [
|
|
76
|
-
"mypy == 2.
|
|
76
|
+
"mypy == 2.3.0",
|
|
77
77
|
"types-networkx>=3.6.1.20251220",
|
|
78
|
-
"types-Markdown == 3.10.2.
|
|
78
|
+
"types-Markdown == 3.10.2.20260712",
|
|
79
79
|
# For checking the noxfile, docs/ script, and tests
|
|
80
80
|
"frequenz-gridpool[dev-mkdocs,dev-noxfile,dev-pytest]",
|
|
81
81
|
]
|
|
82
82
|
dev-noxfile = [
|
|
83
|
-
"nox == 2026.
|
|
83
|
+
"nox == 2026.7.11",
|
|
84
84
|
"frequenz-repo-config[lib] == 0.18.0",
|
|
85
85
|
]
|
|
86
86
|
dev-pylint = [
|
|
@@ -148,6 +148,7 @@ min-similarity-lines = 40
|
|
|
148
148
|
disable = [
|
|
149
149
|
"too-few-public-methods",
|
|
150
150
|
"too-many-return-statements",
|
|
151
|
+
"too-many-arguments",
|
|
151
152
|
# disabled because it conflicts with isort
|
|
152
153
|
"wrong-import-order",
|
|
153
154
|
"ungrouped-imports",
|
|
@@ -6,25 +6,9 @@
|
|
|
6
6
|
from frequenz.microgrid_component_graph import ComponentGraphConfig, FormulaOverrides
|
|
7
7
|
|
|
8
8
|
from ._graph_generator import ComponentGraphGenerator
|
|
9
|
-
from .config import (
|
|
10
|
-
Metadata,
|
|
11
|
-
MicrogridConfig,
|
|
12
|
-
load_configs,
|
|
13
|
-
load_configs_from_api,
|
|
14
|
-
load_configs_from_files,
|
|
15
|
-
merge_config_maps,
|
|
16
|
-
merge_microgrid_configs,
|
|
17
|
-
)
|
|
18
9
|
|
|
19
10
|
__all__ = [
|
|
20
11
|
"ComponentGraphConfig",
|
|
21
12
|
"ComponentGraphGenerator",
|
|
22
13
|
"FormulaOverrides",
|
|
23
|
-
"Metadata",
|
|
24
|
-
"MicrogridConfig",
|
|
25
|
-
"load_configs",
|
|
26
|
-
"load_configs_from_api",
|
|
27
|
-
"load_configs_from_files",
|
|
28
|
-
"merge_config_maps",
|
|
29
|
-
"merge_microgrid_configs",
|
|
30
14
|
]
|
|
@@ -11,15 +11,11 @@ import asyncclick as click
|
|
|
11
11
|
from frequenz.client.assets import AssetsApiClient
|
|
12
12
|
from frequenz.client.common.microgrid import MicrogridId
|
|
13
13
|
|
|
14
|
-
from frequenz.gridpool import
|
|
15
|
-
ComponentGraphConfig,
|
|
16
|
-
ComponentGraphGenerator,
|
|
17
|
-
MicrogridConfig,
|
|
18
|
-
load_configs,
|
|
19
|
-
)
|
|
14
|
+
from frequenz.gridpool import ComponentGraphConfig, ComponentGraphGenerator
|
|
20
15
|
from frequenz.gridpool.cli._dump_config import dump_map
|
|
21
16
|
from frequenz.gridpool.cli._patch_config import patch_file
|
|
22
17
|
from frequenz.gridpool.cli._render_graph import ComponentGraphRenderer, RenderOptions
|
|
18
|
+
from frequenz.gridpool.config import AssetsConfig, load_configs
|
|
23
19
|
|
|
24
20
|
|
|
25
21
|
@click.group()
|
|
@@ -207,29 +203,33 @@ async def generate_config(
|
|
|
207
203
|
ids = list(dict.fromkeys(microgrid_ids)) or None
|
|
208
204
|
if inplace and ids is None:
|
|
209
205
|
assert default_file is not None
|
|
210
|
-
ids = sorted(
|
|
206
|
+
ids = sorted(AssetsConfig.load_from_files(default_file).microgrids)
|
|
211
207
|
|
|
212
208
|
async with AssetsApiClient(url, auth_key=key, sign_secret=secret) as client:
|
|
213
209
|
if inplace:
|
|
214
210
|
# default_file is the patch target here, not a merge input.
|
|
215
|
-
configs =
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
211
|
+
configs = (
|
|
212
|
+
await load_configs(
|
|
213
|
+
assets_client=client,
|
|
214
|
+
override_files=override_file,
|
|
215
|
+
microgrid_ids=ids,
|
|
216
|
+
component_graph_config=_graph_config(
|
|
217
|
+
prefer_meters_in_component_formulas
|
|
218
|
+
),
|
|
219
|
+
)
|
|
220
|
+
).microgrids
|
|
223
221
|
else:
|
|
224
|
-
configs =
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
222
|
+
configs = (
|
|
223
|
+
await load_configs(
|
|
224
|
+
default_files=default_file,
|
|
225
|
+
assets_client=client,
|
|
226
|
+
override_files=override_file,
|
|
227
|
+
microgrid_ids=ids,
|
|
228
|
+
component_graph_config=_graph_config(
|
|
229
|
+
prefer_meters_in_component_formulas
|
|
230
|
+
),
|
|
231
|
+
)
|
|
232
|
+
).microgrids
|
|
233
233
|
|
|
234
234
|
if not configs:
|
|
235
235
|
raise click.ClickException("No microgrids could be loaded; nothing to write.")
|
{frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/cli/_dump_config.py
RENAMED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
Renders a `{microgrid_id: MicrogridConfig}` mapping as dotted-key TOML, e.g.:
|
|
7
7
|
|
|
8
|
-
115.
|
|
9
|
-
115.
|
|
10
|
-
115.
|
|
8
|
+
115.microgrid_id = 115
|
|
9
|
+
115.name = "Demo Grid"
|
|
10
|
+
115.latitude = 52.52
|
|
11
11
|
|
|
12
|
-
This is the inverse of `
|
|
12
|
+
This is the inverse of `AssetsConfig.load_from_files`. Value rendering (quoting,
|
|
13
13
|
escaping, key-quoting, list/number/datetime formatting) is delegated to
|
|
14
14
|
`tomlkit`; only the flattening to dotted keys and the dropping of empty/`None`
|
|
15
15
|
fields are done here, since TOML has no null and `tomlkit` rejects it.
|
|
@@ -20,7 +20,7 @@ from typing import Any
|
|
|
20
20
|
import tomlkit
|
|
21
21
|
from tomlkit.items import Integer, Trivia
|
|
22
22
|
|
|
23
|
-
from frequenz.gridpool import MicrogridConfig
|
|
23
|
+
from frequenz.gridpool.config import MicrogridConfig
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
def _is_empty(value: Any) -> bool:
|
|
@@ -71,11 +71,11 @@ def _iter_leaves(
|
|
|
71
71
|
return leaves
|
|
72
72
|
|
|
73
73
|
|
|
74
|
-
def dump_map(configs: dict[
|
|
74
|
+
def dump_map(configs: dict[int, MicrogridConfig]) -> str:
|
|
75
75
|
"""Serialize a mapping of microgrid configs to dotted-key TOML.
|
|
76
76
|
|
|
77
77
|
Args:
|
|
78
|
-
configs: Mapping from microgrid ID
|
|
78
|
+
configs: Mapping from microgrid ID to `MicrogridConfig`.
|
|
79
79
|
|
|
80
80
|
Returns:
|
|
81
81
|
The TOML representation as a string, with one blank line between
|
|
@@ -83,10 +83,10 @@ def dump_map(configs: dict[str, MicrogridConfig]) -> str:
|
|
|
83
83
|
"""
|
|
84
84
|
schema = MicrogridConfig.Schema()
|
|
85
85
|
doc = tomlkit.document()
|
|
86
|
-
for mid in sorted(configs
|
|
86
|
+
for mid in sorted(configs):
|
|
87
87
|
dumped = schema.dump(configs[mid])
|
|
88
88
|
assert isinstance(dumped, dict)
|
|
89
|
-
leaves = _iter_leaves([mid], dumped)
|
|
89
|
+
leaves = _iter_leaves([str(mid)], dumped)
|
|
90
90
|
if not leaves:
|
|
91
91
|
continue
|
|
92
92
|
if doc.body:
|
{frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/cli/_patch_config.py
RENAMED
|
@@ -15,17 +15,17 @@ from typing import Any
|
|
|
15
15
|
import tomlkit
|
|
16
16
|
from tomlkit import TOMLDocument
|
|
17
17
|
|
|
18
|
-
from frequenz.gridpool import MicrogridConfig
|
|
18
|
+
from frequenz.gridpool.config import MicrogridConfig
|
|
19
19
|
|
|
20
20
|
from ._dump_config import _format_value, _iter_leaves
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
def patch_file(path: Path, configs: dict[
|
|
23
|
+
def patch_file(path: Path, configs: dict[int, MicrogridConfig]) -> str:
|
|
24
24
|
"""Patch the TOML file at `path` with any leaves missing from `configs`.
|
|
25
25
|
|
|
26
26
|
Args:
|
|
27
27
|
path: Path to the existing TOML file to patch.
|
|
28
|
-
configs: Mapping from microgrid ID
|
|
28
|
+
configs: Mapping from microgrid ID to `MicrogridConfig`.
|
|
29
29
|
|
|
30
30
|
Returns:
|
|
31
31
|
The patched TOML text; the caller is responsible for writing it back.
|
|
@@ -33,12 +33,12 @@ def patch_file(path: Path, configs: dict[str, MicrogridConfig]) -> str:
|
|
|
33
33
|
return patch_text(path.read_text(), configs)
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
def patch_text(original: str, configs: dict[
|
|
36
|
+
def patch_text(original: str, configs: dict[int, MicrogridConfig]) -> str:
|
|
37
37
|
"""Patch dotted-key TOML text with any leaves missing from `configs`.
|
|
38
38
|
|
|
39
39
|
Args:
|
|
40
40
|
original: The existing TOML text to patch.
|
|
41
|
-
configs: Mapping from microgrid ID
|
|
41
|
+
configs: Mapping from microgrid ID to `MicrogridConfig`.
|
|
42
42
|
|
|
43
43
|
Returns:
|
|
44
44
|
The patched TOML text.
|
|
@@ -51,7 +51,8 @@ def patch_text(original: str, configs: dict[str, MicrogridConfig]) -> str:
|
|
|
51
51
|
# into the rendered text instead.
|
|
52
52
|
orphans: dict[str, list[tuple[list[str], Any]]] = {}
|
|
53
53
|
|
|
54
|
-
for
|
|
54
|
+
for microgrid_id, cfg in configs.items():
|
|
55
|
+
mid = str(microgrid_id)
|
|
55
56
|
dumped = schema.dump(cfg)
|
|
56
57
|
assert isinstance(dumped, dict)
|
|
57
58
|
leaves = _iter_leaves([], dumped)
|
{frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/config/__init__.py
RENAMED
|
@@ -1,42 +1,42 @@
|
|
|
1
1
|
# License: MIT
|
|
2
2
|
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
|
|
3
3
|
|
|
4
|
-
"""
|
|
4
|
+
"""Asset configuration data models and loading."""
|
|
5
5
|
|
|
6
6
|
from frequenz.microgrid_component_graph import ComponentGraphConfig, FormulaOverrides
|
|
7
7
|
|
|
8
|
-
from .
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
load_configs_from_files,
|
|
12
|
-
)
|
|
13
|
-
from .microgrid import (
|
|
8
|
+
from ._assets import AssetsConfig
|
|
9
|
+
from ._load import load_configs
|
|
10
|
+
from ._microgrid import (
|
|
14
11
|
BatteryConfig,
|
|
15
12
|
ComponentCategory,
|
|
16
13
|
ComponentType,
|
|
17
14
|
ComponentTypeConfig,
|
|
18
|
-
Metadata,
|
|
19
15
|
MicrogridConfig,
|
|
20
16
|
PVConfig,
|
|
21
17
|
WindConfig,
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
)
|
|
19
|
+
from ._topology import (
|
|
20
|
+
DeliveryAreaConfig,
|
|
21
|
+
MarketLocationConfig,
|
|
22
|
+
RelationConfig,
|
|
23
|
+
ValidityConfig,
|
|
24
24
|
)
|
|
25
25
|
|
|
26
26
|
__all__ = [
|
|
27
|
+
"AssetsConfig",
|
|
27
28
|
"BatteryConfig",
|
|
28
29
|
"ComponentCategory",
|
|
29
30
|
"ComponentGraphConfig",
|
|
30
31
|
"ComponentType",
|
|
31
32
|
"ComponentTypeConfig",
|
|
33
|
+
"DeliveryAreaConfig",
|
|
32
34
|
"FormulaOverrides",
|
|
33
|
-
"
|
|
35
|
+
"MarketLocationConfig",
|
|
34
36
|
"MicrogridConfig",
|
|
35
37
|
"PVConfig",
|
|
38
|
+
"RelationConfig",
|
|
39
|
+
"ValidityConfig",
|
|
36
40
|
"WindConfig",
|
|
37
41
|
"load_configs",
|
|
38
|
-
"load_configs_from_api",
|
|
39
|
-
"load_configs_from_files",
|
|
40
|
-
"merge_config_maps",
|
|
41
|
-
"merge_microgrid_configs",
|
|
42
42
|
]
|