frequenz-client-common 0.3.6__tar.gz → 0.3.8__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_client_common-0.3.6/src/frequenz_client_common.egg-info → frequenz_client_common-0.3.8}/PKG-INFO +31 -28
- frequenz_client_common-0.3.8/RELEASE_NOTES.md +38 -0
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/pyproject.toml +32 -28
- frequenz_client_common-0.3.8/src/frequenz/client/common/enum_proto.py +82 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/grid/__init__.py +11 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/grid/_delivery_area.py +89 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/grid/proto/__init__.py +4 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/grid/proto/v1alpha8/__init__.py +16 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/grid/proto/v1alpha8/_delivery_area.py +73 -0
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz/client/common/metric/__init__.py +8 -1
- frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/__init__.py +24 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/_bounds.py +45 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/_metric.py +277 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/_sample.py +233 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/proto/__init__.py +119 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/proto/v1alpha8/__init__.py +28 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/proto/v1alpha8/_bounds.py +49 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/proto/v1alpha8/_metric.py +33 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/proto/v1alpha8/_metric_connection_category.py +38 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/proto/v1alpha8/_sample.py +152 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/__init__.py +11 -0
- frequenz_client_common-0.3.6/src/frequenz/client/common/microgrid/__init__.py → frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/_ids.py +1 -1
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz/client/common/microgrid/components/__init__.py +34 -3
- frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/__init__.py +16 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/_category.py +134 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/_diagnostic_code.py +330 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/_ids.py +13 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/_state_code.py +149 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/proto/__init__.py +4 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/proto/v1alpha8/__init__.py +22 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/proto/v1alpha8/_electrical_component.py +108 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/sensors/__init__.py +10 -0
- frequenz_client_common-0.3.6/src/frequenz/client/common/microgrid/sensors.py → frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/sensors/_id.py +1 -1
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz/client/common/pagination/__init__.py +10 -64
- frequenz_client_common-0.3.8/src/frequenz/client/common/pagination/_pagination_info.py +94 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/pagination/proto/__init__.py +4 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/pagination/proto/v1alpha8/__init__.py +14 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/pagination/proto/v1alpha8/_pagination_info.py +40 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/proto/__init__.py +13 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/proto/_timestamp.py +69 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/streaming/__init__.py +8 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/streaming/_event.py +24 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/streaming/proto/__init__.py +4 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/streaming/proto/v1alpha8/__init__.py +11 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/streaming/proto/v1alpha8/_event.py +34 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/test/__init__.py +4 -0
- frequenz_client_common-0.3.8/src/frequenz/client/common/test/enum_parity.py +181 -0
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8/src/frequenz_client_common.egg-info}/PKG-INFO +31 -28
- frequenz_client_common-0.3.8/src/frequenz_client_common.egg-info/SOURCES.txt +58 -0
- frequenz_client_common-0.3.8/src/frequenz_client_common.egg-info/requires.txt +53 -0
- frequenz_client_common-0.3.6/RELEASE_NOTES.md +0 -21
- frequenz_client_common-0.3.6/src/frequenz/client/common/microgrid/electrical_components/__init__.py +0 -459
- frequenz_client_common-0.3.6/src/frequenz/client/common/streaming/__init__.py +0 -26
- frequenz_client_common-0.3.6/src/frequenz_client_common.egg-info/SOURCES.txt +0 -21
- frequenz_client_common-0.3.6/src/frequenz_client_common.egg-info/requires.txt +0 -49
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/LICENSE +0 -0
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/MANIFEST.in +0 -0
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/README.md +0 -0
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/setup.cfg +0 -0
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz/client/common/__init__.py +0 -0
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz/client/common/conftest.py +0 -0
- /frequenz_client_common-0.3.6/src/frequenz/client/common/enum_proto.py → /frequenz_client_common-0.3.8/src/frequenz/client/common/proto/_enum.py +0 -0
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz/client/common/py.typed +0 -0
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz_client_common.egg-info/dependency_links.txt +0 -0
- {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz_client_common.egg-info/top_level.txt +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: frequenz-client-common
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.8
|
|
4
4
|
Summary: Common code and utilities for Frequenz API clients
|
|
5
5
|
Author-email: Frequenz Energy-as-a-Service GmbH <floss@frequenz.com>
|
|
6
|
-
License: MIT
|
|
6
|
+
License-Expression: MIT
|
|
7
7
|
Project-URL: Documentation, https://frequenz-floss.github.io/frequenz-client-common-python/
|
|
8
8
|
Project-URL: Changelog, https://github.com/frequenz-floss/frequenz-client-common-python/releases
|
|
9
9
|
Project-URL: Issues, https://github.com/frequenz-floss/frequenz-client-common-python/issues
|
|
@@ -12,7 +12,6 @@ Project-URL: Support, https://github.com/frequenz-floss/frequenz-client-common-p
|
|
|
12
12
|
Keywords: frequenz,python,lib,library,client-common
|
|
13
13
|
Classifier: Development Status :: 3 - Alpha
|
|
14
14
|
Classifier: Intended Audience :: Developers
|
|
15
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
16
15
|
Classifier: Programming Language :: Python :: 3
|
|
17
16
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
17
|
Classifier: Topic :: Software Development :: Libraries
|
|
@@ -21,44 +20,48 @@ Requires-Python: <4,>=3.11
|
|
|
21
20
|
Description-Content-Type: text/markdown
|
|
22
21
|
License-File: LICENSE
|
|
23
22
|
Requires-Dist: typing-extensions<5,>=4.13.0
|
|
24
|
-
Requires-Dist: frequenz-api-common<1,>=0.8.
|
|
23
|
+
Requires-Dist: frequenz-api-common<1,>=0.8.4
|
|
25
24
|
Requires-Dist: frequenz-core<2,>=1.0.2
|
|
25
|
+
Requires-Dist: protobuf<8,>=6.33.6
|
|
26
26
|
Provides-Extra: dev-flake8
|
|
27
27
|
Requires-Dist: flake8==7.3.0; extra == "dev-flake8"
|
|
28
|
+
Requires-Dist: flake8-datetimez==20.10.0; extra == "dev-flake8"
|
|
28
29
|
Requires-Dist: flake8-docstrings==1.7.0; extra == "dev-flake8"
|
|
29
|
-
Requires-Dist: flake8-pyproject==1.2.
|
|
30
|
-
Requires-Dist: pydoclint==0.
|
|
30
|
+
Requires-Dist: flake8-pyproject==1.2.4; extra == "dev-flake8"
|
|
31
|
+
Requires-Dist: pydoclint==0.8.6; extra == "dev-flake8"
|
|
31
32
|
Requires-Dist: pydocstyle==6.3.0; extra == "dev-flake8"
|
|
32
33
|
Provides-Extra: dev-formatting
|
|
33
|
-
Requires-Dist: black==
|
|
34
|
-
Requires-Dist: isort==
|
|
34
|
+
Requires-Dist: black==26.5.1; extra == "dev-formatting"
|
|
35
|
+
Requires-Dist: isort==8.0.1; extra == "dev-formatting"
|
|
35
36
|
Provides-Extra: dev-mkdocs
|
|
36
|
-
Requires-Dist: Markdown==3.
|
|
37
|
-
Requires-Dist: black==
|
|
38
|
-
Requires-Dist: mike==2.
|
|
39
|
-
Requires-Dist: mkdocs-gen-files==0.
|
|
40
|
-
Requires-Dist: mkdocs-literate-nav==0.6.
|
|
41
|
-
Requires-Dist: mkdocs-macros-plugin==1.
|
|
42
|
-
Requires-Dist: mkdocs-material==9.6
|
|
43
|
-
Requires-Dist: mkdocstrings[python]==0.
|
|
44
|
-
Requires-Dist: mkdocstrings-python==
|
|
45
|
-
Requires-Dist: frequenz-repo-config[lib]==0.
|
|
37
|
+
Requires-Dist: Markdown==3.10.2; extra == "dev-mkdocs"
|
|
38
|
+
Requires-Dist: black==26.5.1; extra == "dev-mkdocs"
|
|
39
|
+
Requires-Dist: mike==2.2.0; extra == "dev-mkdocs"
|
|
40
|
+
Requires-Dist: mkdocs-gen-files==0.6.1; extra == "dev-mkdocs"
|
|
41
|
+
Requires-Dist: mkdocs-literate-nav==0.6.3; extra == "dev-mkdocs"
|
|
42
|
+
Requires-Dist: mkdocs-macros-plugin==1.5.0; extra == "dev-mkdocs"
|
|
43
|
+
Requires-Dist: mkdocs-material==9.7.6; extra == "dev-mkdocs"
|
|
44
|
+
Requires-Dist: mkdocstrings[python]==1.0.4; extra == "dev-mkdocs"
|
|
45
|
+
Requires-Dist: mkdocstrings-python==2.0.3; extra == "dev-mkdocs"
|
|
46
|
+
Requires-Dist: frequenz-repo-config[lib]==0.18.0; extra == "dev-mkdocs"
|
|
46
47
|
Provides-Extra: dev-mypy
|
|
47
|
-
Requires-Dist: mypy==1.
|
|
48
|
-
Requires-Dist: types-Markdown==3.
|
|
48
|
+
Requires-Dist: mypy==2.1.0; extra == "dev-mypy"
|
|
49
|
+
Requires-Dist: types-Markdown==3.10.2.20260518; extra == "dev-mypy"
|
|
50
|
+
Requires-Dist: types-protobuf==7.34.1.20260518; extra == "dev-mypy"
|
|
49
51
|
Requires-Dist: frequenz-client-common[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-mypy"
|
|
50
52
|
Provides-Extra: dev-noxfile
|
|
51
|
-
Requires-Dist: nox==
|
|
52
|
-
Requires-Dist: frequenz-repo-config[lib]==0.
|
|
53
|
+
Requires-Dist: nox==2026.4.10; extra == "dev-noxfile"
|
|
54
|
+
Requires-Dist: frequenz-repo-config[lib]==0.18.0; extra == "dev-noxfile"
|
|
53
55
|
Provides-Extra: dev-pylint
|
|
54
|
-
Requires-Dist: pylint==
|
|
56
|
+
Requires-Dist: pylint==4.0.5; extra == "dev-pylint"
|
|
55
57
|
Requires-Dist: frequenz-client-common[dev-mkdocs,dev-noxfile,dev-pytest]; extra == "dev-pylint"
|
|
56
58
|
Provides-Extra: dev-pytest
|
|
57
|
-
Requires-Dist: pytest==
|
|
58
|
-
Requires-Dist: frequenz-repo-config[extra-lint-examples]==0.
|
|
59
|
-
Requires-Dist:
|
|
60
|
-
Requires-Dist: pytest-
|
|
61
|
-
Requires-Dist:
|
|
59
|
+
Requires-Dist: pytest==9.0.3; extra == "dev-pytest"
|
|
60
|
+
Requires-Dist: frequenz-repo-config[extra-lint-examples]==0.18.0; extra == "dev-pytest"
|
|
61
|
+
Requires-Dist: hypothesis==6.155.1; extra == "dev-pytest"
|
|
62
|
+
Requires-Dist: pytest-mock==3.15.1; extra == "dev-pytest"
|
|
63
|
+
Requires-Dist: pytest-asyncio==1.4.0; extra == "dev-pytest"
|
|
64
|
+
Requires-Dist: async-solipsism==0.9; extra == "dev-pytest"
|
|
62
65
|
Provides-Extra: dev
|
|
63
66
|
Requires-Dist: frequenz-client-common[dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]; extra == "dev"
|
|
64
67
|
Dynamic: license-file
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Frequenz Client Common Library Release Notes
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
This release adds a new `grid` package for delivery area definitions, introduces explicit v1alpha8 protobuf conversion helpers across public modules (`metrics`, `streaming`, `electrical_components`, `pagination`, `grid`), and reorganises a number of subpackages to mirror the established `proto/v1alpha8/` layout. Several legacy conversion entry points have been deprecated in favour of new free functions.
|
|
6
|
+
|
|
7
|
+
## New Features
|
|
8
|
+
|
|
9
|
+
- Added a new `frequenz.client.common.grid` package with `DeliveryArea` and `EnergyMarketCodeType` definitions for representing energy delivery areas.
|
|
10
|
+
- Added v1alpha8 conversion functions for `DeliveryArea` and `EnergyMarketCodeType` in `frequenz.client.common.grid.proto.v1alpha8`, preserving unrecognized code types as raw `int` values.
|
|
11
|
+
- Added v1alpha8 conversion functions for `MetricConnectionCategory`, `Event`, and the electrical component enums.
|
|
12
|
+
- Added v1alpha8 conversion functions for `PaginationInfo` in `frequenz.client.common.pagination.proto.v1alpha8` (`pagination_info_from_proto`, `pagination_info_to_proto`).
|
|
13
|
+
- Added new enum values up to `frequenz-api-common` 0.8.4.
|
|
14
|
+
- Added a new `frequenz.client.common.test` package with an `enum_parity` module providing a convenient class to test for protobuf-Python enum parity.
|
|
15
|
+
|
|
16
|
+
## Deprecations
|
|
17
|
+
|
|
18
|
+
> [!IMPORTANT]
|
|
19
|
+
> Passing enum values directly to build protobuf messages is now deprecated, but it **does NOT emit a deprecation warning**, so migration needs to be done manually. Use the new conversion functions to convert enum values to their protobuf equivalents before passing them to message builders.
|
|
20
|
+
>
|
|
21
|
+
> **Implicit conversions will fail type checking in v0.4.0.**
|
|
22
|
+
|
|
23
|
+
- `frequenz.client.common.metrics.proto` is deprecated; use `frequenz.client.common.metrics.proto.v1alpha8` instead.
|
|
24
|
+
- `frequenz.client.common.pagination.PaginationInfo.from_proto` is deprecated; use `frequenz.client.common.pagination.proto.v1alpha8.pagination_info_from_proto` instead.
|
|
25
|
+
- `frequenz.client.common.pagination.PaginationInfo.to_proto` is deprecated; use `frequenz.client.common.pagination.proto.v1alpha8.pagination_info_to_proto` instead.
|
|
26
|
+
- `frequenz.client.common.pagination.PaginationInfo.to_proto_v1alpha8` is deprecated; use `frequenz.client.common.pagination.proto.v1alpha8.pagination_info_to_proto` instead.
|
|
27
|
+
- `frequenz.client.common.microgrid.electrical_components.ElectricalComponentCategory.from_proto()` is deprecated; use `frequenz.client.common.microgrid.electrical_components.proto.v1alpha8.electrical_component_category_from_proto` instead.
|
|
28
|
+
- `frequenz.client.common.microgrid.electrical_components.ElectricalComponentCategory.to_proto()` is deprecated; use `frequenz.client.common.microgrid.electrical_components.proto.v1alpha8.electrical_component_category_to_proto` instead.
|
|
29
|
+
- `frequenz.client.common.microgrid.electrical_components.ElectricalComponentStateCode.from_proto()` is deprecated; use `frequenz.client.common.microgrid.electrical_components.proto.v1alpha8.electrical_component_state_code_from_proto` instead.
|
|
30
|
+
- `frequenz.client.common.microgrid.electrical_components.ElectricalComponentStateCode.to_proto()` is deprecated; use `frequenz.client.common.microgrid.electrical_components.proto.v1alpha8.electrical_component_state_code_to_proto` instead.
|
|
31
|
+
- `frequenz.client.common.microgrid.electrical_components.ElectricalComponentDiagnosticCode.from_proto()` is deprecated; use `frequenz.client.common.microgrid.electrical_components.proto.v1alpha8.electrical_component_diagnostic_code_from_proto` instead.
|
|
32
|
+
- `frequenz.client.common.microgrid.electrical_components.ElectricalComponentDiagnosticCode.to_proto()` is deprecated; use `frequenz.client.common.microgrid.electrical_components.proto.v1alpha8.electrical_component_diagnostic_code_to_proto` instead.
|
|
33
|
+
- `frequenz.client.common.enum_proto.enum_from_proto` is deprecated; use `frequenz.client.common.proto.enum_from_proto` instead.
|
|
34
|
+
- `frequenz.client.common.metric.Metric` (based on the deprecated `frequenz.api.common.v1` namespace) is deprecated; use `frequenz.client.common.metrics.Metric` instead.
|
|
35
|
+
- `frequenz.client.common.microgrid.components.ComponentCategory` (based on the deprecated `frequenz.api.common.v1` namespace) is deprecated; use `frequenz.client.common.microgrid.electrical_components.ElectricalComponentCategory` instead.
|
|
36
|
+
- `frequenz.client.common.microgrid.components.ComponentStateCode` (based on the deprecated `frequenz.api.common.v1` namespace) is deprecated; use `frequenz.client.common.microgrid.electrical_components.ElectricalComponentStateCode` instead.
|
|
37
|
+
- `frequenz.client.common.microgrid.components.ComponentErrorCode` (based on the deprecated `frequenz.api.common.v1` namespace) is deprecated; use `frequenz.client.common.microgrid.electrical_components.ElectricalComponentDiagnosticCode` instead.
|
|
38
|
+
- `frequenz.client.common.microgrid.components.ComponentId` is deprecated; use `frequenz.client.common.microgrid.electrical_components.ElectricalComponentId` instead.
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
[build-system]
|
|
5
5
|
requires = [
|
|
6
|
-
"setuptools ==
|
|
7
|
-
"setuptools_scm[toml] ==
|
|
8
|
-
"frequenz-repo-config[lib] == 0.
|
|
6
|
+
"setuptools == 82.0.1",
|
|
7
|
+
"setuptools_scm[toml] == 10.0.5",
|
|
8
|
+
"frequenz-repo-config[lib] == 0.18.0",
|
|
9
9
|
]
|
|
10
10
|
build-backend = "setuptools.build_meta"
|
|
11
11
|
|
|
@@ -13,12 +13,12 @@ build-backend = "setuptools.build_meta"
|
|
|
13
13
|
name = "frequenz-client-common"
|
|
14
14
|
description = "Common code and utilities for Frequenz API clients"
|
|
15
15
|
readme = "README.md"
|
|
16
|
-
license =
|
|
16
|
+
license = "MIT"
|
|
17
|
+
license-files = ["LICENSE"]
|
|
17
18
|
keywords = ["frequenz", "python", "lib", "library", "client-common"]
|
|
18
19
|
classifiers = [
|
|
19
20
|
"Development Status :: 3 - Alpha",
|
|
20
21
|
"Intended Audience :: Developers",
|
|
21
|
-
"License :: OSI Approved :: MIT License",
|
|
22
22
|
"Programming Language :: Python :: 3",
|
|
23
23
|
"Programming Language :: Python :: 3 :: Only",
|
|
24
24
|
"Topic :: Software Development :: Libraries",
|
|
@@ -27,8 +27,9 @@ classifiers = [
|
|
|
27
27
|
requires-python = ">= 3.11, < 4"
|
|
28
28
|
dependencies = [
|
|
29
29
|
"typing-extensions >= 4.13.0, < 5",
|
|
30
|
-
"frequenz-api-common >= 0.8.
|
|
30
|
+
"frequenz-api-common >= 0.8.4, < 1",
|
|
31
31
|
"frequenz-core >= 1.0.2, < 2",
|
|
32
|
+
"protobuf >= 6.33.6, < 8",
|
|
32
33
|
]
|
|
33
34
|
dynamic = ["version"]
|
|
34
35
|
|
|
@@ -39,42 +40,45 @@ email = "floss@frequenz.com"
|
|
|
39
40
|
[project.optional-dependencies]
|
|
40
41
|
dev-flake8 = [
|
|
41
42
|
"flake8 == 7.3.0",
|
|
43
|
+
"flake8-datetimez == 20.10.0",
|
|
42
44
|
"flake8-docstrings == 1.7.0",
|
|
43
|
-
"flake8-pyproject == 1.2.
|
|
44
|
-
"pydoclint == 0.
|
|
45
|
+
"flake8-pyproject == 1.2.4", # For reading the flake8 config from pyproject.toml
|
|
46
|
+
"pydoclint == 0.8.6",
|
|
45
47
|
"pydocstyle == 6.3.0",
|
|
46
48
|
]
|
|
47
|
-
dev-formatting = ["black ==
|
|
49
|
+
dev-formatting = ["black == 26.5.1", "isort == 8.0.1"]
|
|
48
50
|
dev-mkdocs = [
|
|
49
|
-
"Markdown == 3.
|
|
50
|
-
"black ==
|
|
51
|
-
"mike == 2.
|
|
52
|
-
"mkdocs-gen-files == 0.
|
|
53
|
-
"mkdocs-literate-nav == 0.6.
|
|
54
|
-
"mkdocs-macros-plugin == 1.
|
|
55
|
-
"mkdocs-material == 9.6
|
|
56
|
-
"mkdocstrings[python] == 0.
|
|
57
|
-
"mkdocstrings-python ==
|
|
58
|
-
"frequenz-repo-config[lib] == 0.
|
|
51
|
+
"Markdown == 3.10.2",
|
|
52
|
+
"black == 26.5.1",
|
|
53
|
+
"mike == 2.2.0",
|
|
54
|
+
"mkdocs-gen-files == 0.6.1",
|
|
55
|
+
"mkdocs-literate-nav == 0.6.3",
|
|
56
|
+
"mkdocs-macros-plugin == 1.5.0",
|
|
57
|
+
"mkdocs-material == 9.7.6",
|
|
58
|
+
"mkdocstrings[python] == 1.0.4",
|
|
59
|
+
"mkdocstrings-python == 2.0.3",
|
|
60
|
+
"frequenz-repo-config[lib] == 0.18.0",
|
|
59
61
|
]
|
|
60
62
|
dev-mypy = [
|
|
61
|
-
"mypy == 1.
|
|
62
|
-
"types-Markdown == 3.
|
|
63
|
+
"mypy == 2.1.0",
|
|
64
|
+
"types-Markdown == 3.10.2.20260518",
|
|
65
|
+
"types-protobuf == 7.34.1.20260518",
|
|
63
66
|
# For checking the noxfile, docs/ script, and tests
|
|
64
67
|
"frequenz-client-common[dev-mkdocs,dev-noxfile,dev-pytest]",
|
|
65
68
|
]
|
|
66
|
-
dev-noxfile = ["nox ==
|
|
69
|
+
dev-noxfile = ["nox == 2026.4.10", "frequenz-repo-config[lib] == 0.18.0"]
|
|
67
70
|
dev-pylint = [
|
|
68
|
-
"pylint ==
|
|
71
|
+
"pylint == 4.0.5",
|
|
69
72
|
# For checking the noxfile, docs/ script, and tests
|
|
70
73
|
"frequenz-client-common[dev-mkdocs,dev-noxfile,dev-pytest]",
|
|
71
74
|
]
|
|
72
75
|
dev-pytest = [
|
|
73
|
-
"pytest ==
|
|
74
|
-
"frequenz-repo-config[extra-lint-examples] == 0.
|
|
75
|
-
"
|
|
76
|
-
"pytest-
|
|
77
|
-
"
|
|
76
|
+
"pytest == 9.0.3",
|
|
77
|
+
"frequenz-repo-config[extra-lint-examples] == 0.18.0",
|
|
78
|
+
"hypothesis == 6.155.1",
|
|
79
|
+
"pytest-mock == 3.15.1",
|
|
80
|
+
"pytest-asyncio == 1.4.0",
|
|
81
|
+
"async-solipsism == 0.9",
|
|
78
82
|
]
|
|
79
83
|
dev = [
|
|
80
84
|
"frequenz-client-common[dev-mkdocs,dev-flake8,dev-formatting,dev-mkdocs,dev-mypy,dev-noxfile,dev-pylint,dev-pytest]",
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# License: MIT
|
|
2
|
+
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
|
|
3
|
+
|
|
4
|
+
"""Conversion of protobuf int enums to Python enums."""
|
|
5
|
+
|
|
6
|
+
import enum
|
|
7
|
+
from typing import Literal, TypeVar, overload
|
|
8
|
+
|
|
9
|
+
from typing_extensions import deprecated
|
|
10
|
+
|
|
11
|
+
EnumT = TypeVar("EnumT", bound=enum.Enum)
|
|
12
|
+
"""A type variable that is bound to an enum."""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@overload
|
|
16
|
+
def enum_from_proto(
|
|
17
|
+
value: int, enum_type: type[EnumT], *, allow_invalid: Literal[False]
|
|
18
|
+
) -> EnumT: ...
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@overload
|
|
22
|
+
def enum_from_proto(
|
|
23
|
+
value: int, enum_type: type[EnumT], *, allow_invalid: Literal[True] = True
|
|
24
|
+
) -> EnumT | int: ...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@deprecated(
|
|
28
|
+
"frequenz.client.common.enum_proto.enum_from_proto is deprecated. "
|
|
29
|
+
"Please use frequenz.client.common.proto.enum_from_proto instead."
|
|
30
|
+
)
|
|
31
|
+
def enum_from_proto(
|
|
32
|
+
value: int, enum_type: type[EnumT], *, allow_invalid: bool = True
|
|
33
|
+
) -> EnumT | int:
|
|
34
|
+
"""Convert a protobuf int enum value to a python enum.
|
|
35
|
+
|
|
36
|
+
Example:
|
|
37
|
+
```python
|
|
38
|
+
import enum
|
|
39
|
+
|
|
40
|
+
from proto import proto_pb2 # Just an example. pylint: disable=import-error
|
|
41
|
+
|
|
42
|
+
@enum.unique
|
|
43
|
+
class SomeEnum(enum.Enum):
|
|
44
|
+
# These values should match the protobuf enum values.
|
|
45
|
+
UNSPECIFIED = 0
|
|
46
|
+
SOME_VALUE = 1
|
|
47
|
+
|
|
48
|
+
enum_value = enum_from_proto(proto_pb2.SomeEnum.SOME_ENUM_SOME_VALUE, SomeEnum)
|
|
49
|
+
# -> SomeEnum.SOME_VALUE
|
|
50
|
+
|
|
51
|
+
enum_value = enum_from_proto(42, SomeEnum)
|
|
52
|
+
# -> 42
|
|
53
|
+
|
|
54
|
+
enum_value = enum_from_proto(
|
|
55
|
+
proto_pb2.SomeEnum.SOME_ENUM_UNKNOWN_VALUE, SomeEnum, allow_invalid=False
|
|
56
|
+
)
|
|
57
|
+
# -> ValueError
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
value: The protobuf int enum value.
|
|
62
|
+
enum_type: The python enum type to convert to.
|
|
63
|
+
allow_invalid: If `True`, return the value as an `int` if the value is not
|
|
64
|
+
a valid member of the enum (this allows for forward-compatibility with new
|
|
65
|
+
enum values defined in the protocol but not added to the Python enum yet).
|
|
66
|
+
If `False`, raise a `ValueError` if the value is not a valid member of the
|
|
67
|
+
enum.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
The resulting python enum value if the protobuf value is known, otherwise
|
|
71
|
+
the input value converted to a plain `int`.
|
|
72
|
+
|
|
73
|
+
Raises:
|
|
74
|
+
ValueError: If `allow_invalid` is `False` and the value is not a valid member
|
|
75
|
+
of the enum.
|
|
76
|
+
"""
|
|
77
|
+
try:
|
|
78
|
+
return enum_type(value)
|
|
79
|
+
except ValueError:
|
|
80
|
+
if allow_invalid:
|
|
81
|
+
return value
|
|
82
|
+
raise
|
|
@@ -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,16 @@
|
|
|
1
|
+
# License: MIT
|
|
2
|
+
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
|
|
3
|
+
|
|
4
|
+
"""Conversion of grid objects from/to protobuf v1alpha8."""
|
|
5
|
+
|
|
6
|
+
from ._delivery_area import (
|
|
7
|
+
delivery_area_from_proto,
|
|
8
|
+
energy_market_code_type_from_proto,
|
|
9
|
+
energy_market_code_type_to_proto,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"delivery_area_from_proto",
|
|
14
|
+
"energy_market_code_type_from_proto",
|
|
15
|
+
"energy_market_code_type_to_proto",
|
|
16
|
+
]
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# License: MIT
|
|
2
|
+
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
|
|
3
|
+
|
|
4
|
+
"""Conversion of DeliveryArea and EnergyMarketCodeType to/from protobuf v1alpha8."""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
from frequenz.api.common.v1alpha8.grid import delivery_area_pb2
|
|
9
|
+
|
|
10
|
+
from ....proto import enum_from_proto
|
|
11
|
+
from ..._delivery_area import DeliveryArea, EnergyMarketCodeType
|
|
12
|
+
|
|
13
|
+
_logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def energy_market_code_type_from_proto(
|
|
17
|
+
message: delivery_area_pb2.EnergyMarketCodeType.ValueType,
|
|
18
|
+
) -> EnergyMarketCodeType | int:
|
|
19
|
+
"""Convert a protobuf EnergyMarketCodeType enum value to an enum member.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
message: A protobuf EnergyMarketCodeType enum value.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
The corresponding EnergyMarketCodeType enum member, or the raw `int` if the
|
|
26
|
+
protobuf value is not recognized.
|
|
27
|
+
"""
|
|
28
|
+
return enum_from_proto(message, EnergyMarketCodeType)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def energy_market_code_type_to_proto(
|
|
32
|
+
code_type: EnergyMarketCodeType,
|
|
33
|
+
) -> delivery_area_pb2.EnergyMarketCodeType.ValueType:
|
|
34
|
+
"""Convert an EnergyMarketCodeType enum member to a protobuf enum value.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
code_type: An EnergyMarketCodeType enum member.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
The corresponding protobuf EnergyMarketCodeType enum value.
|
|
41
|
+
"""
|
|
42
|
+
return delivery_area_pb2.EnergyMarketCodeType.ValueType(code_type.value)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def delivery_area_from_proto(message: delivery_area_pb2.DeliveryArea) -> DeliveryArea:
|
|
46
|
+
"""Convert a protobuf delivery area message to a delivery area object.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
message: The protobuf message to convert.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
The resulting delivery area object.
|
|
53
|
+
"""
|
|
54
|
+
issues: list[str] = []
|
|
55
|
+
|
|
56
|
+
code = message.code or None
|
|
57
|
+
if code is None:
|
|
58
|
+
issues.append("code is empty")
|
|
59
|
+
|
|
60
|
+
code_type = energy_market_code_type_from_proto(message.code_type)
|
|
61
|
+
if code_type is EnergyMarketCodeType.UNSPECIFIED:
|
|
62
|
+
issues.append("code_type is unspecified")
|
|
63
|
+
elif isinstance(code_type, int):
|
|
64
|
+
issues.append("code_type is unrecognized")
|
|
65
|
+
|
|
66
|
+
if issues:
|
|
67
|
+
_logger.warning(
|
|
68
|
+
"Found issues in delivery area: %s | Protobuf message:\n%s",
|
|
69
|
+
", ".join(issues),
|
|
70
|
+
message,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
return DeliveryArea(code=code, code_type=code_type)
|
|
@@ -13,6 +13,10 @@ from typing_extensions import deprecated
|
|
|
13
13
|
# pylint: enable=no-name-in-module
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
@deprecated(
|
|
17
|
+
"frequenz.client.common.metric.Metric is deprecated. "
|
|
18
|
+
"Use frequenz.client.common.metrics.Metric instead."
|
|
19
|
+
)
|
|
16
20
|
@enum.unique
|
|
17
21
|
class Metric(enum.Enum):
|
|
18
22
|
"""List of supported metrics.
|
|
@@ -142,7 +146,10 @@ class Metric(enum.Enum):
|
|
|
142
146
|
SENSOR_IRRADIANCE = PBMetric.METRIC_SENSOR_IRRADIANCE
|
|
143
147
|
|
|
144
148
|
@classmethod
|
|
145
|
-
@deprecated(
|
|
149
|
+
@deprecated(
|
|
150
|
+
"frequenz.client.common.metric.Metric.from_proto() is deprecated. "
|
|
151
|
+
"Use frequenz.client.common.proto.enum_from_proto instead."
|
|
152
|
+
)
|
|
146
153
|
def from_proto(cls, metric: PBMetric.ValueType) -> Self:
|
|
147
154
|
"""Convert a protobuf Metric value to Metric enum.
|
|
148
155
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# License: MIT
|
|
2
|
+
# Copyright © 2025 Frequenz Energy-as-a-Service GmbH
|
|
3
|
+
|
|
4
|
+
"""Metrics definitions."""
|
|
5
|
+
|
|
6
|
+
from ._bounds import Bounds
|
|
7
|
+
from ._metric import Metric
|
|
8
|
+
from ._sample import (
|
|
9
|
+
AggregatedMetricValue,
|
|
10
|
+
AggregationMethod,
|
|
11
|
+
MetricConnection,
|
|
12
|
+
MetricConnectionCategory,
|
|
13
|
+
MetricSample,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"AggregatedMetricValue",
|
|
18
|
+
"AggregationMethod",
|
|
19
|
+
"Bounds",
|
|
20
|
+
"Metric",
|
|
21
|
+
"MetricConnection",
|
|
22
|
+
"MetricConnectionCategory",
|
|
23
|
+
"MetricSample",
|
|
24
|
+
]
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# License: MIT
|
|
2
|
+
# Copyright © 2024 Frequenz Energy-as-a-Service GmbH
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
"""Definitions for bounds."""
|
|
6
|
+
|
|
7
|
+
import dataclasses
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclasses.dataclass(frozen=True, kw_only=True)
|
|
11
|
+
class Bounds:
|
|
12
|
+
"""A set of lower and upper bounds for any metric.
|
|
13
|
+
|
|
14
|
+
The lower bound must be less than or equal to the upper bound.
|
|
15
|
+
|
|
16
|
+
The units of the bounds are always the same as the related metric.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
lower: float | None = None
|
|
20
|
+
"""The lower bound.
|
|
21
|
+
|
|
22
|
+
If `None`, there is no lower bound.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
upper: float | None = None
|
|
26
|
+
"""The upper bound.
|
|
27
|
+
|
|
28
|
+
If `None`, there is no upper bound.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __post_init__(self) -> None:
|
|
32
|
+
"""Validate these bounds."""
|
|
33
|
+
if self.lower is None:
|
|
34
|
+
return
|
|
35
|
+
if self.upper is None:
|
|
36
|
+
return
|
|
37
|
+
if self.lower > self.upper:
|
|
38
|
+
raise ValueError(
|
|
39
|
+
f"Lower bound ({self.lower}) must be less than or equal to upper "
|
|
40
|
+
f"bound ({self.upper})"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def __str__(self) -> str:
|
|
44
|
+
"""Return a string representation of these bounds."""
|
|
45
|
+
return f"[{self.lower}, {self.upper}]"
|