frequenz-client-assets 0.0.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 (60) hide show
  1. frequenz_client_assets-0.0.2/LICENSE +21 -0
  2. frequenz_client_assets-0.0.2/MANIFEST.in +13 -0
  3. frequenz_client_assets-0.0.2/PKG-INFO +94 -0
  4. frequenz_client_assets-0.0.2/README.md +22 -0
  5. frequenz_client_assets-0.0.2/RELEASE_NOTES.md +32 -0
  6. frequenz_client_assets-0.0.2/pyproject.toml +199 -0
  7. frequenz_client_assets-0.0.2/setup.cfg +4 -0
  8. frequenz_client_assets-0.0.2/src/frequenz/client/assets/__init__.py +18 -0
  9. frequenz_client_assets-0.0.2/src/frequenz/client/assets/_client.py +140 -0
  10. frequenz_client_assets-0.0.2/src/frequenz/client/assets/_delivery_area.py +89 -0
  11. frequenz_client_assets-0.0.2/src/frequenz/client/assets/_delivery_area_proto.py +44 -0
  12. frequenz_client_assets-0.0.2/src/frequenz/client/assets/_lifetime.py +54 -0
  13. frequenz_client_assets-0.0.2/src/frequenz/client/assets/_lifetime_proto.py +26 -0
  14. frequenz_client_assets-0.0.2/src/frequenz/client/assets/_location.py +31 -0
  15. frequenz_client_assets-0.0.2/src/frequenz/client/assets/_location_proto.py +47 -0
  16. frequenz_client_assets-0.0.2/src/frequenz/client/assets/_microgrid.py +87 -0
  17. frequenz_client_assets-0.0.2/src/frequenz/client/assets/_microgrid_json.py +15 -0
  18. frequenz_client_assets-0.0.2/src/frequenz/client/assets/_microgrid_proto.py +79 -0
  19. frequenz_client_assets-0.0.2/src/frequenz/client/assets/_utils.py +63 -0
  20. frequenz_client_assets-0.0.2/src/frequenz/client/assets/cli/__init__.py +1 -0
  21. frequenz_client_assets-0.0.2/src/frequenz/client/assets/cli/__main__.py +219 -0
  22. frequenz_client_assets-0.0.2/src/frequenz/client/assets/cli/_utils.py +44 -0
  23. frequenz_client_assets-0.0.2/src/frequenz/client/assets/conftest.py +13 -0
  24. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/__init__.py +90 -0
  25. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_battery.py +133 -0
  26. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_breaker.py +20 -0
  27. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_capacitor_bank.py +20 -0
  28. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_category.py +88 -0
  29. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_chp.py +18 -0
  30. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_converter.py +20 -0
  31. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_crypto_miner.py +20 -0
  32. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_electrical_component.py +78 -0
  33. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_electrical_component_json.py +21 -0
  34. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_electrical_component_proto.py +507 -0
  35. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_electrolyzer.py +20 -0
  36. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_ev_charger.py +157 -0
  37. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_grid_connection_point.py +61 -0
  38. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_hvac.py +20 -0
  39. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_inverter.py +157 -0
  40. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_meter.py +20 -0
  41. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_plc.py +18 -0
  42. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_power_transformer.py +32 -0
  43. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_precharger.py +20 -0
  44. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_problematic.py +52 -0
  45. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_static_transfer_switch.py +20 -0
  46. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_types.py +73 -0
  47. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_uninterruptible_power_supply.py +20 -0
  48. frequenz_client_assets-0.0.2/src/frequenz/client/assets/electrical_component/_wind_turbine.py +20 -0
  49. frequenz_client_assets-0.0.2/src/frequenz/client/assets/exceptions.py +51 -0
  50. frequenz_client_assets-0.0.2/src/frequenz/client/assets/metrics/__init__.py +12 -0
  51. frequenz_client_assets-0.0.2/src/frequenz/client/assets/metrics/_bounds.py +44 -0
  52. frequenz_client_assets-0.0.2/src/frequenz/client/assets/metrics/_bounds_proto.py +17 -0
  53. frequenz_client_assets-0.0.2/src/frequenz/client/assets/metrics/_metric.py +261 -0
  54. frequenz_client_assets-0.0.2/src/frequenz/client/assets/py.typed +0 -0
  55. frequenz_client_assets-0.0.2/src/frequenz_client_assets.egg-info/PKG-INFO +94 -0
  56. frequenz_client_assets-0.0.2/src/frequenz_client_assets.egg-info/SOURCES.txt +58 -0
  57. frequenz_client_assets-0.0.2/src/frequenz_client_assets.egg-info/dependency_links.txt +1 -0
  58. frequenz_client_assets-0.0.2/src/frequenz_client_assets.egg-info/entry_points.txt +2 -0
  59. frequenz_client_assets-0.0.2/src/frequenz_client_assets.egg-info/requires.txt +57 -0
  60. frequenz_client_assets-0.0.2/src/frequenz_client_assets.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright © 2025 Frequenz Energy-as-a-Service GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ exclude .cookiecutter-replay.json
2
+ exclude .editorconfig
3
+ exclude .gitignore
4
+ exclude CODEOWNERS
5
+ exclude CONTRIBUTING.md
6
+ exclude mkdocs.yml
7
+ exclude noxfile.py
8
+ exclude src/conftest.py
9
+ recursive-exclude .github *
10
+ recursive-exclude benchmarks *
11
+ recursive-exclude docs *
12
+ recursive-exclude tests *
13
+ recursive-include py *.pyi
@@ -0,0 +1,94 @@
1
+ Metadata-Version: 2.4
2
+ Name: frequenz-client-assets
3
+ Version: 0.0.2
4
+ Summary: Assets API client for Python
5
+ Author-email: Frequenz Energy-as-a-Service GmbH <floss@frequenz.com>
6
+ License: MIT
7
+ Project-URL: Documentation, https://frequenz-floss.github.io/frequenz-client-assets-python/
8
+ Project-URL: Changelog, https://github.com/frequenz-floss/frequenz-client-assets-python/releases
9
+ Project-URL: Issues, https://github.com/frequenz-floss/frequenz-client-assets-python/issues
10
+ Project-URL: Repository, https://github.com/frequenz-floss/frequenz-client-assets-python
11
+ Project-URL: Support, https://github.com/frequenz-floss/frequenz-client-assets-python/discussions/categories/support
12
+ Keywords: frequenz,python,lib,library,frequenz-client-assets,client-assets,client,assets,api
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Topic :: Software Development :: Libraries
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: <4,>=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: typing-extensions<5,>=4.13.0
24
+ Requires-Dist: frequenz-api-assets<0.2.0,>=0.1.0
25
+ Requires-Dist: frequenz-api-common<1,>=0.8.0
26
+ Requires-Dist: frequenz-client-base<0.12.0,>=0.11.0
27
+ Requires-Dist: frequenz-client-common<0.4.0,>=0.3.6
28
+ Requires-Dist: grpcio<2,>=1.73.1
29
+ Provides-Extra: cli
30
+ Requires-Dist: asyncclick==8.3.0.4; extra == "cli"
31
+ Provides-Extra: dev-flake8
32
+ Requires-Dist: flake8==7.3.0; extra == "dev-flake8"
33
+ Requires-Dist: flake8-docstrings==1.7.0; extra == "dev-flake8"
34
+ Requires-Dist: flake8-pyproject==1.2.3; extra == "dev-flake8"
35
+ Requires-Dist: pydoclint==0.6.10; extra == "dev-flake8"
36
+ Requires-Dist: pydocstyle==6.3.0; extra == "dev-flake8"
37
+ Provides-Extra: dev-formatting
38
+ Requires-Dist: black==25.9.0; extra == "dev-formatting"
39
+ Requires-Dist: isort==6.1.0; extra == "dev-formatting"
40
+ Provides-Extra: dev-mkdocs
41
+ Requires-Dist: Markdown==3.9; extra == "dev-mkdocs"
42
+ Requires-Dist: black==25.9.0; extra == "dev-mkdocs"
43
+ Requires-Dist: mike==2.1.3; extra == "dev-mkdocs"
44
+ Requires-Dist: mkdocs-gen-files==0.5.0; extra == "dev-mkdocs"
45
+ Requires-Dist: mkdocs-literate-nav==0.6.2; extra == "dev-mkdocs"
46
+ Requires-Dist: mkdocs-macros-plugin==1.4.0; extra == "dev-mkdocs"
47
+ Requires-Dist: mkdocs-material==9.6.17; extra == "dev-mkdocs"
48
+ Requires-Dist: mkdocstrings[python]==0.30.0; extra == "dev-mkdocs"
49
+ Requires-Dist: mkdocstrings-python==1.18.2; extra == "dev-mkdocs"
50
+ Requires-Dist: frequenz-repo-config[lib]==0.13.5; extra == "dev-mkdocs"
51
+ Provides-Extra: dev-mypy
52
+ Requires-Dist: mypy==1.18.2; extra == "dev-mypy"
53
+ Requires-Dist: grpc-stubs==1.53.0.6; extra == "dev-mypy"
54
+ Requires-Dist: types-Markdown==3.9.0.20250906; extra == "dev-mypy"
55
+ Requires-Dist: types-protobuf==6.32.1.20250918; extra == "dev-mypy"
56
+ Requires-Dist: frequenz-client-assets[cli,dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-mypy"
57
+ Provides-Extra: dev-noxfile
58
+ Requires-Dist: nox==2025.5.1; extra == "dev-noxfile"
59
+ Requires-Dist: frequenz-repo-config[lib]==0.13.5; extra == "dev-noxfile"
60
+ Provides-Extra: dev-pylint
61
+ Requires-Dist: frequenz-client-assets[cli,dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-pylint"
62
+ Provides-Extra: dev-pytest
63
+ Requires-Dist: pytest==8.4.1; extra == "dev-pytest"
64
+ Requires-Dist: pylint==3.3.8; extra == "dev-pytest"
65
+ Requires-Dist: frequenz-repo-config[extra-lint-examples]==0.13.5; extra == "dev-pytest"
66
+ Requires-Dist: pytest-mock==3.15.1; extra == "dev-pytest"
67
+ Requires-Dist: pytest-asyncio==1.1.0; extra == "dev-pytest"
68
+ Requires-Dist: async-solipsism==0.8; extra == "dev-pytest"
69
+ Provides-Extra: dev
70
+ Requires-Dist: frequenz-client-assets[dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]; extra == "dev"
71
+ Dynamic: license-file
72
+
73
+ # Frequenz Assets API Client
74
+
75
+ [![Build Status](https://github.com/frequenz-floss/frequenz-client-assets-python/actions/workflows/ci.yaml/badge.svg)](https://github.com/frequenz-floss/frequenz-client-assets-python/actions/workflows/ci.yaml)
76
+ [![PyPI Package](https://img.shields.io/pypi/v/frequenz-client-assets)](https://pypi.org/project/frequenz-client-assets/)
77
+ [![Docs](https://img.shields.io/badge/docs-latest-informational)](https://frequenz-floss.github.io/frequenz-client-assets-python/)
78
+
79
+ ## Introduction
80
+
81
+ Assets API client for Python
82
+
83
+ ## Supported Platforms
84
+
85
+ The following platforms are officially supported (tested):
86
+
87
+ - **Python:** 3.11
88
+ - **Operating System:** Ubuntu Linux 20.04
89
+ - **Architectures:** amd64, arm64
90
+
91
+ ## Contributing
92
+
93
+ If you want to know how to build this project and contribute to it, please
94
+ check out the [Contributing Guide](CONTRIBUTING.md).
@@ -0,0 +1,22 @@
1
+ # Frequenz Assets API Client
2
+
3
+ [![Build Status](https://github.com/frequenz-floss/frequenz-client-assets-python/actions/workflows/ci.yaml/badge.svg)](https://github.com/frequenz-floss/frequenz-client-assets-python/actions/workflows/ci.yaml)
4
+ [![PyPI Package](https://img.shields.io/pypi/v/frequenz-client-assets)](https://pypi.org/project/frequenz-client-assets/)
5
+ [![Docs](https://img.shields.io/badge/docs-latest-informational)](https://frequenz-floss.github.io/frequenz-client-assets-python/)
6
+
7
+ ## Introduction
8
+
9
+ Assets API client for Python
10
+
11
+ ## Supported Platforms
12
+
13
+ The following platforms are officially supported (tested):
14
+
15
+ - **Python:** 3.11
16
+ - **Operating System:** Ubuntu Linux 20.04
17
+ - **Architectures:** amd64, arm64
18
+
19
+ ## Contributing
20
+
21
+ If you want to know how to build this project and contribute to it, please
22
+ check out the [Contributing Guide](CONTRIBUTING.md).
@@ -0,0 +1,32 @@
1
+ # Frequenz Assets API Client Release Notes
2
+
3
+ ## Summary
4
+
5
+ This release updates the `frequenz-api-assets` dependency to use a version range instead of a specific Git reference, providing more flexibility for dependency updates while maintaining compatibility.
6
+
7
+ ## Changes
8
+
9
+ ### Dependency Updates
10
+
11
+ * **Updated `frequenz-api-assets` dependency**:
12
+ * Changed from Git reference (`@ git+https://github.com/frequenz-floss/frequenz-api-assets.git@v0.x.x`) to version range (`>= 0.1.0, < 0.2.0`)
13
+ * Enables automatic updates within the specified version range
14
+ * Maintains backward compatibility while reducing maintenance overhead
15
+
16
+ ## Benefits
17
+
18
+ * **Improved dependency management**: Version ranges allow for automatic updates within the specified range
19
+ * **Better compatibility**: Ensures compatibility with the project while allowing for patch and minor version updates
20
+ * **Reduced maintenance overhead**: Eliminates the need to manually update Git references for compatible versions
21
+
22
+ ## Migration Notes
23
+
24
+ No migration required. This is a transparent dependency update that maintains full backward compatibility.
25
+
26
+ ## Files Changed
27
+
28
+ * `pyproject.toml`: Updated the `frequenz-api-assets` dependency specification
29
+
30
+ ## Type of Change
31
+
32
+ * [x] Dependency update
@@ -0,0 +1,199 @@
1
+ # License: MIT
2
+ # Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3
+
4
+ [build-system]
5
+ requires = [
6
+ "setuptools == 80.9.0",
7
+ "setuptools_scm[toml] == 9.2.0",
8
+ "frequenz-repo-config[lib] == 0.13.5",
9
+ ]
10
+ build-backend = "setuptools.build_meta"
11
+
12
+ [project]
13
+ name = "frequenz-client-assets"
14
+ description = "Assets API client for Python"
15
+ readme = "README.md"
16
+ license = { text = "MIT" }
17
+ keywords = [
18
+ "frequenz",
19
+ "python",
20
+ "lib",
21
+ "library",
22
+ "frequenz-client-assets",
23
+ "client-assets",
24
+ "client",
25
+ "assets",
26
+ "api",
27
+ ]
28
+ classifiers = [
29
+ "Development Status :: 3 - Alpha",
30
+ "Intended Audience :: Developers",
31
+ "License :: OSI Approved :: MIT License",
32
+ "Programming Language :: Python :: 3",
33
+ "Programming Language :: Python :: 3 :: Only",
34
+ "Topic :: Software Development :: Libraries",
35
+ "Typing :: Typed",
36
+ ]
37
+ requires-python = ">= 3.11, < 4"
38
+ dependencies = [
39
+ "typing-extensions >= 4.13.0, < 5",
40
+ "frequenz-api-assets >= 0.1.0, < 0.2.0",
41
+ "frequenz-api-common >= 0.8.0, < 1",
42
+ "frequenz-client-base >= 0.11.0, < 0.12.0",
43
+ "frequenz-client-common >= 0.3.6, < 0.4.0",
44
+ "grpcio >= 1.73.1, < 2",
45
+ ]
46
+ dynamic = ["version"]
47
+
48
+ [project.scripts]
49
+ assets-cli = "frequenz.client.assets.cli.__main__:main"
50
+
51
+ [[project.authors]]
52
+ name = "Frequenz Energy-as-a-Service GmbH"
53
+ email = "floss@frequenz.com"
54
+
55
+ [project.optional-dependencies]
56
+ cli = ["asyncclick == 8.3.0.4"]
57
+ dev-flake8 = [
58
+ "flake8 == 7.3.0",
59
+ "flake8-docstrings == 1.7.0",
60
+ "flake8-pyproject == 1.2.3", # For reading the flake8 config from pyproject.toml
61
+ "pydoclint == 0.6.10",
62
+ "pydocstyle == 6.3.0",
63
+ ]
64
+ dev-formatting = ["black == 25.9.0", "isort == 6.1.0"]
65
+ dev-mkdocs = [
66
+ "Markdown == 3.9",
67
+ "black == 25.9.0",
68
+ "mike == 2.1.3",
69
+ "mkdocs-gen-files == 0.5.0",
70
+ "mkdocs-literate-nav == 0.6.2",
71
+ "mkdocs-macros-plugin == 1.4.0",
72
+ "mkdocs-material == 9.6.17",
73
+ "mkdocstrings[python] == 0.30.0",
74
+ "mkdocstrings-python == 1.18.2",
75
+ "frequenz-repo-config[lib] == 0.13.5",
76
+ ]
77
+ dev-mypy = [
78
+ "mypy == 1.18.2",
79
+ "grpc-stubs == 1.53.0.6",
80
+ "types-Markdown == 3.9.0.20250906",
81
+ "types-protobuf == 6.32.1.20250918",
82
+ # For checking the noxfile, docs/ script, and tests
83
+ "frequenz-client-assets[dev-mkdocs,dev-noxfile,dev-pytest,cli]",
84
+ ]
85
+ dev-noxfile = ["nox == 2025.5.1", "frequenz-repo-config[lib] == 0.13.5"]
86
+ dev-pylint = [
87
+ # dev-pytest already defines a dependency to pylint because of the examples
88
+ # For checking the noxfile, docs/ script, and tests
89
+ "frequenz-client-assets[dev-mkdocs,dev-noxfile,dev-pytest,cli]",
90
+ ]
91
+ dev-pytest = [
92
+ "pytest == 8.4.1",
93
+ "pylint == 3.3.8", # We need this to check for the examples
94
+ "frequenz-repo-config[extra-lint-examples] == 0.13.5",
95
+ "pytest-mock == 3.15.1",
96
+ "pytest-asyncio == 1.1.0",
97
+ "async-solipsism == 0.8",
98
+ ]
99
+ dev = [
100
+ "frequenz-client-assets[dev-mkdocs,dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]",
101
+ ]
102
+
103
+ [project.urls]
104
+ Documentation = "https://frequenz-floss.github.io/frequenz-client-assets-python/"
105
+ Changelog = "https://github.com/frequenz-floss/frequenz-client-assets-python/releases"
106
+ Issues = "https://github.com/frequenz-floss/frequenz-client-assets-python/issues"
107
+ Repository = "https://github.com/frequenz-floss/frequenz-client-assets-python"
108
+ Support = "https://github.com/frequenz-floss/frequenz-client-assets-python/discussions/categories/support"
109
+
110
+ [tool.black]
111
+ line-length = 88
112
+ target-version = ['py311']
113
+ include = '\.pyi?$'
114
+
115
+ [tool.isort]
116
+ profile = "black"
117
+ line_length = 88
118
+ src_paths = ["benchmarks", "examples", "src", "tests"]
119
+
120
+ [tool.flake8]
121
+ # We give some flexibility to go over 88, there are cases like long URLs or
122
+ # code in documentation that have extra indentation. Black will still take care
123
+ # of making everything that can be 88 wide, 88 wide.
124
+ max-line-length = 100
125
+ extend-ignore = [
126
+ "E203", # Whitespace before ':' (conflicts with black)
127
+ "W503", # Line break before binary operator (conflicts with black)
128
+ ]
129
+ # pydoclint options
130
+ style = "google"
131
+ check-return-types = false
132
+ check-yield-types = false
133
+ arg-type-hints-in-docstring = false
134
+ arg-type-hints-in-signature = true
135
+ allow-init-docstring = true
136
+
137
+ [tool.pylint.similarities]
138
+ ignore-comments = ['yes']
139
+ ignore-docstrings = ['yes']
140
+ ignore-imports = ['no']
141
+ min-similarity-lines = 40
142
+
143
+ [tool.pylint.messages_control]
144
+ disable = [
145
+ "too-few-public-methods",
146
+ "too-many-return-statements",
147
+ # disabled because it conflicts with isort
148
+ "wrong-import-order",
149
+ "ungrouped-imports",
150
+ # pylint's unsubscriptable check is buggy and is not needed because
151
+ # it is a type-check, for which we already have mypy.
152
+ "unsubscriptable-object",
153
+ # Checked by mypy
154
+ "no-member",
155
+ "possibly-used-before-assignment",
156
+ "no-name-in-module",
157
+ # Checked by flake8
158
+ "f-string-without-interpolation",
159
+ "line-too-long",
160
+ "missing-function-docstring",
161
+ "redefined-outer-name",
162
+ "unnecessary-lambda-assignment",
163
+ "unused-import",
164
+ "unused-variable",
165
+ ]
166
+
167
+ [tool.pytest.ini_options]
168
+ addopts = "-vv"
169
+ filterwarnings = [
170
+ "error",
171
+ "once::DeprecationWarning",
172
+ "once::PendingDeprecationWarning",
173
+ # We use a raw string (single quote) to avoid the need to escape special
174
+ # chars as this is a regex
175
+ 'ignore:Protobuf gencode version .*exactly one major version older.*:UserWarning',
176
+ ]
177
+ testpaths = ["tests", "src"]
178
+ asyncio_mode = "auto"
179
+ asyncio_default_fixture_loop_scope = "function"
180
+ required_plugins = ["pytest-asyncio", "pytest-mock"]
181
+
182
+ [tool.mypy]
183
+ explicit_package_bases = true
184
+ namespace_packages = true
185
+ # This option disables mypy cache, and it is sometimes useful to enable it if
186
+ # you are getting weird intermittent error, or error in the CI but not locally
187
+ # (or vice versa). In particular errors saying that type: ignore is not
188
+ # used but getting the original ignored error when removing the type: ignore.
189
+ # See for example: https://github.com/python/mypy/issues/2960
190
+ #no_incremental = true
191
+ packages = ["frequenz.client.assets"]
192
+ strict = true
193
+
194
+ [[tool.mypy.overrides]]
195
+ module = ["mkdocs_macros.*", "sybil", "sybil.*"]
196
+ ignore_missing_imports = true
197
+
198
+ [tool.setuptools_scm]
199
+ version_scheme = "post-release"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,18 @@
1
+ # License: MIT
2
+ # Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3
+
4
+ """Assets API client."""
5
+
6
+ from ._client import AssetsApiClient
7
+ from ._delivery_area import DeliveryArea, EnergyMarketCodeType
8
+ from ._location import Location
9
+ from ._microgrid import Microgrid, MicrogridStatus
10
+
11
+ __all__ = [
12
+ "AssetsApiClient",
13
+ "DeliveryArea",
14
+ "EnergyMarketCodeType",
15
+ "Microgrid",
16
+ "MicrogridStatus",
17
+ "Location",
18
+ ]
@@ -0,0 +1,140 @@
1
+ # License: MIT
2
+ # Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3
+
4
+ """
5
+ Assets API client.
6
+
7
+ This module provides a client for the Assets API.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from frequenz.api.assets.v1 import assets_pb2, assets_pb2_grpc
13
+ from frequenz.client.base import channel
14
+ from frequenz.client.base.client import BaseApiClient, call_stub_method
15
+
16
+ from frequenz.client.assets.electrical_component._electrical_component import (
17
+ ElectricalComponent,
18
+ )
19
+
20
+ from ._microgrid import Microgrid
21
+ from ._microgrid_proto import microgrid_from_proto
22
+ from .electrical_component._electrical_component_proto import electrical_component_proto
23
+ from .exceptions import ClientNotConnected
24
+
25
+ DEFAULT_GRPC_CALL_TIMEOUT = 60.0
26
+ """The default timeout for gRPC calls made by this client (in seconds)."""
27
+
28
+
29
+ class AssetsApiClient(
30
+ BaseApiClient[assets_pb2_grpc.PlatformAssetsStub]
31
+ ): # pylint: disable=too-many-arguments
32
+ """A client for the Assets API."""
33
+
34
+ def __init__(
35
+ self,
36
+ server_url: str,
37
+ *,
38
+ auth_key: str | None = None,
39
+ sign_secret: str | None = None,
40
+ channel_defaults: channel.ChannelOptions = channel.ChannelOptions(),
41
+ connect: bool = True,
42
+ ) -> None:
43
+ """
44
+ Initialize the AssetsApiClient.
45
+
46
+ Args:
47
+ server_url: The location of the microgrid API server in the form of a URL.
48
+ The following format is expected:
49
+ "grpc://hostname{:`port`}{?ssl=`ssl`}",
50
+ where the `port` should be an int between 0 and 65535 (defaulting to
51
+ 9090) and `ssl` should be a boolean (defaulting to `true`).
52
+ For example: `grpc://localhost:1090?ssl=true`.
53
+ auth_key: The authentication key to use for the connection.
54
+ sign_secret: The secret to use for signing requests.
55
+ channel_defaults: The default options use to create the channel when not
56
+ specified in the URL.
57
+ connect: Whether to connect to the server as soon as a client instance is
58
+ created. If `False`, the client will not connect to the server until
59
+ [connect()][frequenz.client.base.client.BaseApiClient.connect] is
60
+ called.
61
+ """
62
+ super().__init__(
63
+ server_url,
64
+ assets_pb2_grpc.PlatformAssetsStub,
65
+ connect=connect,
66
+ channel_defaults=channel_defaults,
67
+ auth_key=auth_key,
68
+ sign_secret=sign_secret,
69
+ )
70
+
71
+ @property
72
+ def stub(self) -> assets_pb2_grpc.PlatformAssetsAsyncStub:
73
+ """
74
+ The gRPC stub for the Assets API.
75
+
76
+ Returns:
77
+ The gRPC stub for the Assets API.
78
+
79
+ Raises:
80
+ ClientNotConnected: If the client is not connected to the server.
81
+ """
82
+ if self._channel is None or self._stub is None:
83
+ raise ClientNotConnected(server_url=self.server_url, operation="stub")
84
+ # This type: ignore is needed because the stub is a sync stub, but we need to
85
+ # use the async stub, so we cast the sync stub to the async stub.
86
+ return self._stub # type: ignore
87
+
88
+ async def get_microgrid( # noqa: DOC502 (raises ApiClientError indirectly)
89
+ self, microgrid_id: int
90
+ ) -> Microgrid:
91
+ """
92
+ Get the details of a microgrid.
93
+
94
+ Args:
95
+ microgrid_id: The ID of the microgrid to get the details of.
96
+
97
+ Returns:
98
+ The details of the microgrid.
99
+
100
+ Raises:
101
+ ApiClientError: If there are any errors communicating with the Assets API,
102
+ most likely a subclass of [GrpcError][frequenz.client.base.exception.GrpcError].
103
+ """
104
+ response = await call_stub_method(
105
+ self,
106
+ lambda: self.stub.GetMicrogrid(
107
+ assets_pb2.GetMicrogridRequest(microgrid_id=microgrid_id),
108
+ timeout=DEFAULT_GRPC_CALL_TIMEOUT,
109
+ ),
110
+ method_name="GetMicrogrid",
111
+ )
112
+
113
+ return microgrid_from_proto(response.microgrid)
114
+
115
+ async def list_microgrid_electrical_components(
116
+ self, microgrid_id: int
117
+ ) -> list[ElectricalComponent]:
118
+ """
119
+ Get the electrical components of a microgrid.
120
+
121
+ Args:
122
+ microgrid_id: The ID of the microgrid to get the electrical components of.
123
+
124
+ Returns:
125
+ The electrical components of the microgrid.
126
+ """
127
+ response = await call_stub_method(
128
+ self,
129
+ lambda: self.stub.ListMicrogridElectricalComponents(
130
+ assets_pb2.ListMicrogridElectricalComponentsRequest(
131
+ microgrid_id=microgrid_id,
132
+ ),
133
+ timeout=DEFAULT_GRPC_CALL_TIMEOUT,
134
+ ),
135
+ method_name="ListMicrogridElectricalComponents",
136
+ )
137
+
138
+ return [
139
+ electrical_component_proto(component) for component in response.components
140
+ ]
@@ -0,0 +1,89 @@
1
+ # License: MIT
2
+ # Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3
+
4
+ """Delivery area information for the energy market."""
5
+
6
+ import enum
7
+ from dataclasses import dataclass
8
+
9
+ from frequenz.api.common.v1alpha8.grid import delivery_area_pb2
10
+
11
+
12
+ @enum.unique
13
+ class EnergyMarketCodeType(enum.Enum):
14
+ """The identification code types used in the energy market.
15
+
16
+ CodeType specifies the type of identification code used for uniquely
17
+ identifying various entities such as delivery areas, market participants,
18
+ and grid components within the energy market.
19
+
20
+ This enumeration aims to
21
+ offer compatibility across different jurisdictional standards.
22
+
23
+ Note: Understanding Code Types
24
+ Different regions or countries may have their own standards for uniquely
25
+ identifying various entities within the energy market. For example, in
26
+ Europe, the Energy Identification Code (EIC) is commonly used for this
27
+ purpose.
28
+
29
+ Note: Extensibility
30
+ New code types can be added to this enum to accommodate additional regional
31
+ standards, enhancing the API's adaptability.
32
+
33
+ Danger: Validation Required
34
+ The chosen code type should correspond correctly with the `code` field in
35
+ the relevant message objects, such as `DeliveryArea` or `Counterparty`.
36
+ Failure to match the code type with the correct code could lead to
37
+ processing errors.
38
+ """
39
+
40
+ UNSPECIFIED = delivery_area_pb2.ENERGY_MARKET_CODE_TYPE_UNSPECIFIED
41
+ """Unspecified type. This value is a placeholder and should not be used."""
42
+
43
+ EUROPE_EIC = delivery_area_pb2.ENERGY_MARKET_CODE_TYPE_EUROPE_EIC
44
+ """European Energy Identification Code Standard."""
45
+
46
+ US_NERC = delivery_area_pb2.ENERGY_MARKET_CODE_TYPE_US_NERC
47
+ """North American Electric Reliability Corporation identifiers."""
48
+
49
+
50
+ @dataclass(frozen=True, kw_only=True)
51
+ class DeliveryArea:
52
+ """A geographical or administrative region where electricity deliveries occur.
53
+
54
+ DeliveryArea represents the geographical or administrative region, usually defined
55
+ and maintained by a Transmission System Operator (TSO), where electricity deliveries
56
+ for a contract occur.
57
+
58
+ The concept is important to energy trading as it delineates the agreed-upon delivery
59
+ location. Delivery areas can have different codes based on the jurisdiction in
60
+ which they operate.
61
+
62
+ Note: Jurisdictional Differences
63
+ This is typically represented by specific codes according to local jurisdiction.
64
+
65
+ In Europe, this is represented by an
66
+ [EIC](https://en.wikipedia.org/wiki/Energy_Identification_Code) (Energy
67
+ Identification Code). [List of
68
+ EICs](https://www.entsoe.eu/data/energy-identification-codes-eic/eic-approved-codes/).
69
+ """
70
+
71
+ code: str | None
72
+ """The code representing the unique identifier for the delivery area."""
73
+
74
+ code_type: EnergyMarketCodeType | int
75
+ """Type of code used for identifying the delivery area itself.
76
+
77
+ This code could be extended in the future, in case an unknown code type is
78
+ encountered, a plain integer value is used to represent it.
79
+ """
80
+
81
+ def __str__(self) -> str:
82
+ """Return a human-readable string representation of this instance."""
83
+ code = self.code or "<NO CODE>"
84
+ code_type = (
85
+ f"type={self.code_type}"
86
+ if isinstance(self.code_type, int)
87
+ else self.code_type.name
88
+ )
89
+ return f"{code}[{code_type}]"
@@ -0,0 +1,44 @@
1
+ # License: MIT
2
+ # Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3
+
4
+ """Loading of DeliveryArea objects from protobuf messages."""
5
+
6
+ import logging
7
+
8
+ from frequenz.api.common.v1alpha8.grid import delivery_area_pb2
9
+ from frequenz.client.common import enum_proto
10
+
11
+ from ._delivery_area import DeliveryArea, EnergyMarketCodeType
12
+
13
+ _logger = logging.getLogger(__name__)
14
+
15
+
16
+ def delivery_area_from_proto(message: delivery_area_pb2.DeliveryArea) -> DeliveryArea:
17
+ """Convert a protobuf delivery area message to a delivery area object.
18
+
19
+ Args:
20
+ message: The protobuf message to convert.
21
+
22
+ Returns:
23
+ The resulting delivery area object.
24
+ """
25
+ issues: list[str] = []
26
+
27
+ code = message.code or None
28
+ if code is None:
29
+ issues.append("code is empty")
30
+
31
+ code_type = enum_proto.enum_from_proto(message.code_type, EnergyMarketCodeType)
32
+ if code_type is EnergyMarketCodeType.UNSPECIFIED:
33
+ issues.append("code_type is unspecified")
34
+ elif isinstance(code_type, int):
35
+ issues.append("code_type is unrecognized")
36
+
37
+ if issues:
38
+ _logger.warning(
39
+ "Found issues in delivery area: %s | Protobuf message:\n%s",
40
+ ", ".join(issues),
41
+ message,
42
+ )
43
+
44
+ return DeliveryArea(code=code, code_type=code_type)