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.
Files changed (32) hide show
  1. {frequenz_gridpool-0.6.3/src/frequenz_gridpool.egg-info → frequenz_gridpool-0.7.0}/PKG-INFO +71 -11
  2. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/README.md +64 -4
  3. frequenz_gridpool-0.7.0/RELEASE_NOTES.md +119 -0
  4. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/pyproject.toml +9 -8
  5. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/__init__.py +0 -16
  6. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/cli/__main__.py +24 -24
  7. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/cli/_dump_config.py +9 -9
  8. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/cli/_patch_config.py +7 -6
  9. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/config/__init__.py +15 -15
  10. frequenz_gridpool-0.7.0/src/frequenz/gridpool/config/_assets.py +422 -0
  11. frequenz_gridpool-0.6.3/src/frequenz/gridpool/config/load.py → frequenz_gridpool-0.7.0/src/frequenz/gridpool/config/_load.py +51 -89
  12. frequenz_gridpool-0.6.3/src/frequenz/gridpool/config/microgrid.py → frequenz_gridpool-0.7.0/src/frequenz/gridpool/config/_microgrid.py +11 -119
  13. frequenz_gridpool-0.7.0/src/frequenz/gridpool/config/_migrations.py +139 -0
  14. frequenz_gridpool-0.7.0/src/frequenz/gridpool/config/_topology.py +377 -0
  15. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0/src/frequenz_gridpool.egg-info}/PKG-INFO +71 -11
  16. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz_gridpool.egg-info/SOURCES.txt +5 -2
  17. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz_gridpool.egg-info/requires.txt +6 -6
  18. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz_gridpool.egg-info/scm_file_list.json +47 -42
  19. frequenz_gridpool-0.7.0/src/frequenz_gridpool.egg-info/scm_version.json +8 -0
  20. frequenz_gridpool-0.6.3/RELEASE_NOTES.md +0 -17
  21. frequenz_gridpool-0.6.3/src/frequenz_gridpool.egg-info/scm_version.json +0 -8
  22. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/LICENSE +0 -0
  23. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/MANIFEST.in +0 -0
  24. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/setup.cfg +0 -0
  25. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/_graph_generator.py +0 -0
  26. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/cli/__init__.py +0 -0
  27. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/cli/_render_graph.py +0 -0
  28. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/conftest.py +0 -0
  29. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz/gridpool/py.typed +0 -0
  30. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz_gridpool.egg-info/dependency_links.txt +0 -0
  31. {frequenz_gridpool-0.6.3 → frequenz_gridpool-0.7.0}/src/frequenz_gridpool.egg-info/entry_points.txt +0 -0
  32. {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.6.3
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.0; extra == "dev-flake8"
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.6; extra == "dev-mkdocs"
51
- Requires-Dist: mkdocstrings[python]==1.0.4; extra == "dev-mkdocs"
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.1.0; extra == "dev-mypy"
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.20260518; extra == "dev-mypy"
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.4.10; extra == "dev-noxfile"
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 grid pools for the Frequenz platform.
84
+ High-level interface to gridpools for the Frequenz platform.
85
85
 
86
- TODO(cookiecutter): Improve the README file
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
- You can layer existing config files with the Assets API by precedence
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 supplied files:
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 grid pools for the Frequenz platform.
9
+ High-level interface to gridpools for the Frequenz platform.
10
10
 
11
- TODO(cookiecutter): Improve the README file
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
- You can layer existing config files with the Assets API by precedence
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 supplied files:
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 == 82.0.1",
7
- "setuptools_scm[toml] == 10.2.0",
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.0",
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.6",
71
- "mkdocstrings[python] == 1.0.4",
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.1.0",
76
+ "mypy == 2.3.0",
77
77
  "types-networkx>=3.6.1.20251220",
78
- "types-Markdown == 3.10.2.20260518",
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.4.10",
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(int(mid) for mid in MicrogridConfig.load_from_file(default_file))
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 = await load_configs(
216
- assets_client=client,
217
- override_files=override_file,
218
- microgrid_ids=ids,
219
- component_graph_config=_graph_config(
220
- prefer_meters_in_component_formulas
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 = await load_configs(
225
- default_files=default_file,
226
- assets_client=client,
227
- override_files=override_file,
228
- microgrid_ids=ids,
229
- component_graph_config=_graph_config(
230
- prefer_meters_in_component_formulas
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.")
@@ -5,11 +5,11 @@
5
5
 
6
6
  Renders a `{microgrid_id: MicrogridConfig}` mapping as dotted-key TOML, e.g.:
7
7
 
8
- 115.meta.microgrid_id = 115
9
- 115.meta.name = "Demo Grid"
10
- 115.meta.latitude = 52.52
8
+ 115.microgrid_id = 115
9
+ 115.name = "Demo Grid"
10
+ 115.latitude = 52.52
11
11
 
12
- This is the inverse of `load_configs_from_files`. Value rendering (quoting,
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[str, MicrogridConfig]) -> str:
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 (as string) to `MicrogridConfig`.
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, key=int):
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:
@@ -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[str, MicrogridConfig]) -> str:
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 (as string) to `MicrogridConfig`.
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[str, MicrogridConfig]) -> str:
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 (as string) to `MicrogridConfig`.
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 mid, cfg in configs.items():
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)
@@ -1,42 +1,42 @@
1
1
  # License: MIT
2
2
  # Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3
3
 
4
- """Microgrid configuration data model and loading."""
4
+ """Asset configuration data models and loading."""
5
5
 
6
6
  from frequenz.microgrid_component_graph import ComponentGraphConfig, FormulaOverrides
7
7
 
8
- from .load import (
9
- load_configs,
10
- load_configs_from_api,
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
- merge_config_maps,
23
- merge_microgrid_configs,
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
- "Metadata",
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
  ]