Skip to content

Commit b3b2247

Browse files
committed
Update build-system to maturin and expose ComponentGraph to python
Also add tests to make sure graph creation and formula creation work. Signed-off-by: Sahas Subramanian <[email protected]>
1 parent 7b1bfcb commit b3b2247

File tree

3 files changed

+99
-11
lines changed

3 files changed

+99
-11
lines changed

pyproject.toml

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,15 @@
22
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
33

44
[build-system]
5-
requires = [
6-
"setuptools == 75.8.0",
7-
"setuptools_scm[toml] == 9.2.2",
8-
"frequenz-repo-config[lib] == 0.13.6",
9-
]
10-
build-backend = "setuptools.build_meta"
5+
requires = ["maturin>=1.9.6,<2.0"]
6+
build-backend = "maturin"
117

128
[project]
139
name = "frequenz-microgrid-component-graph"
1410
description = "Python bindings for the Frequenz microgrid component graph rust library."
1511
readme = "README.md"
1612
license = { text = "MIT" }
1713
keywords = ["frequenz", "python", "lib", "library", "microgrid-component-graph"]
18-
# TODO(cookiecutter): Remove and add more classifiers if appropriate
1914
classifiers = [
2015
"Development Status :: 3 - Alpha",
2116
"Intended Audience :: Developers",
@@ -26,7 +21,6 @@ classifiers = [
2621
"Typing :: Typed",
2722
]
2823
requires-python = ">= 3.11, < 4"
29-
# TODO(cookiecutter): Remove and add more dependencies if appropriate
3024
dependencies = [
3125
"typing-extensions >= 4.14.1, < 5",
3226
]
@@ -36,8 +30,13 @@ dynamic = ["version"]
3630
name = "Frequenz Energy-as-a-Service GmbH"
3731
3832

39-
# TODO(cookiecutter): Remove and add more optional dependencies if appropriate
4033
[project.optional-dependencies]
34+
microgrid = [
35+
"frequenz-client-microgrid >= 0.18.0, < 0.19",
36+
]
37+
assets = [
38+
"frequenz-client-assets >= 0.1.0, < 0.2",
39+
]
4140
dev-flake8 = [
4241
"flake8 == 7.3.0",
4342
"flake8-docstrings == 1.7.0",
@@ -74,6 +73,7 @@ dev-pylint = [
7473
"frequenz-microgrid-component-graph[dev-mkdocs,dev-noxfile,dev-pytest]",
7574
]
7675
dev-pytest = [
76+
"frequenz-microgrid-component-graph[microgrid]",
7777
"pytest == 8.4.2",
7878
"pylint == 4.0.2", # We need this to check for the examples
7979
"frequenz-repo-config[extra-lint-examples] == 0.13.6",
@@ -92,6 +92,11 @@ Issues = "https://github.com/frequenz-floss/frequenz-microgrid-component-graph-p
9292
Repository = "https://github.com/frequenz-floss/frequenz-microgrid-component-graph-python"
9393
Support = "https://github.com/frequenz-floss/frequenz-microgrid-component-graph-python/discussions/categories/support"
9494

95+
[tool.maturin]
96+
features = ["pyo3/extension-module"]
97+
module-name = "frequenz.microgrid_component_graph._component_graph"
98+
python-source = "python"
99+
95100
[tool.black]
96101
line-length = 88
97102
target-version = ['py311']
@@ -101,6 +106,7 @@ include = '\.pyi?$'
101106
profile = "black"
102107
line_length = 88
103108
src_paths = ["benchmarks", "examples", "python", "tests"]
109+
skip_glob = ["*.pyi"]
104110

105111
[tool.flake8]
106112
# We give some flexibility to go over 88, there are cases like long URLs or

python/frequenz/microgrid_component_graph/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,17 @@
22
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
33

44
"""Python bindings for the Frequenz microgrid component graph rust library."""
5+
6+
from ._component_graph import (
7+
ComponentGraph,
8+
ComponentGraphConfig,
9+
FormulaGenerationError,
10+
InvalidGraphError,
11+
)
12+
13+
__all__ = [
14+
"ComponentGraph",
15+
"ComponentGraphConfig",
16+
"FormulaGenerationError",
17+
"InvalidGraphError",
18+
]

tests/test_microgrid_component_graph.py

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,77 @@
33

44
"""Tests for the frequenz.microgrid_component_graph package."""
55

6+
from frequenz.client.common.microgrid import MicrogridId
7+
from frequenz.client.common.microgrid.components import ComponentId
8+
from frequenz.client.microgrid.component import (
9+
Component,
10+
ComponentConnection,
11+
GridConnectionPoint,
12+
Meter,
13+
SolarInverter,
14+
)
15+
616
from frequenz import microgrid_component_graph
717

818

9-
def test_loading() -> None:
19+
def test_graph_creation() -> None:
1020
"""Test that the microgrid_component_graph module loads correctly."""
11-
assert microgrid_component_graph is not None
21+
graph: microgrid_component_graph.ComponentGraph[
22+
Component, ComponentConnection, ComponentId
23+
] = microgrid_component_graph.ComponentGraph(
24+
components={
25+
GridConnectionPoint(
26+
id=ComponentId(1),
27+
microgrid_id=MicrogridId(1),
28+
rated_fuse_current=100,
29+
),
30+
Meter(id=ComponentId(2), microgrid_id=MicrogridId(1)),
31+
Meter(id=ComponentId(3), microgrid_id=MicrogridId(1)),
32+
SolarInverter(id=ComponentId(4), microgrid_id=MicrogridId(1)),
33+
},
34+
connections={
35+
ComponentConnection(source=ComponentId(1), destination=ComponentId(2)),
36+
ComponentConnection(source=ComponentId(1), destination=ComponentId(3)),
37+
ComponentConnection(source=ComponentId(2), destination=ComponentId(4)),
38+
},
39+
)
40+
assert graph.components() == {
41+
GridConnectionPoint(
42+
id=ComponentId(1), microgrid_id=MicrogridId(1), rated_fuse_current=100
43+
),
44+
Meter(id=ComponentId(2), microgrid_id=MicrogridId(1)),
45+
Meter(id=ComponentId(3), microgrid_id=MicrogridId(1)),
46+
SolarInverter(id=ComponentId(4), microgrid_id=MicrogridId(1)),
47+
}
48+
assert graph.connections() == {
49+
ComponentConnection(source=ComponentId(1), destination=ComponentId(2)),
50+
ComponentConnection(source=ComponentId(1), destination=ComponentId(3)),
51+
ComponentConnection(source=ComponentId(2), destination=ComponentId(4)),
52+
}
53+
assert graph.components(matching_ids=[ComponentId(2), ComponentId(3)]) == {
54+
Meter(id=ComponentId(2), microgrid_id=MicrogridId(1)),
55+
Meter(id=ComponentId(3), microgrid_id=MicrogridId(1)),
56+
}
57+
assert graph.components(matching_ids=ComponentId(1)) == {
58+
GridConnectionPoint(
59+
id=ComponentId(1), microgrid_id=MicrogridId(1), rated_fuse_current=100
60+
)
61+
}
62+
assert graph.components(matching_types=Meter) == {
63+
Meter(id=ComponentId(2), microgrid_id=MicrogridId(1)),
64+
Meter(id=ComponentId(3), microgrid_id=MicrogridId(1)),
65+
}
66+
assert graph.components(matching_types=[Meter, GridConnectionPoint]) == {
67+
Meter(id=ComponentId(2), microgrid_id=MicrogridId(1)),
68+
Meter(id=ComponentId(3), microgrid_id=MicrogridId(1)),
69+
GridConnectionPoint(
70+
id=ComponentId(1), microgrid_id=MicrogridId(1), rated_fuse_current=100
71+
),
72+
}
73+
assert graph.components(
74+
matching_types=[Meter, SolarInverter],
75+
matching_ids=[ComponentId(1), ComponentId(3), ComponentId(4)],
76+
) == {
77+
Meter(id=ComponentId(3), microgrid_id=MicrogridId(1)),
78+
SolarInverter(id=ComponentId(4), microgrid_id=MicrogridId(1)),
79+
}

0 commit comments

Comments
 (0)