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.
Files changed (65) hide show
  1. {frequenz_client_common-0.3.6/src/frequenz_client_common.egg-info → frequenz_client_common-0.3.8}/PKG-INFO +31 -28
  2. frequenz_client_common-0.3.8/RELEASE_NOTES.md +38 -0
  3. {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/pyproject.toml +32 -28
  4. frequenz_client_common-0.3.8/src/frequenz/client/common/enum_proto.py +82 -0
  5. frequenz_client_common-0.3.8/src/frequenz/client/common/grid/__init__.py +11 -0
  6. frequenz_client_common-0.3.8/src/frequenz/client/common/grid/_delivery_area.py +89 -0
  7. frequenz_client_common-0.3.8/src/frequenz/client/common/grid/proto/__init__.py +4 -0
  8. frequenz_client_common-0.3.8/src/frequenz/client/common/grid/proto/v1alpha8/__init__.py +16 -0
  9. frequenz_client_common-0.3.8/src/frequenz/client/common/grid/proto/v1alpha8/_delivery_area.py +73 -0
  10. {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz/client/common/metric/__init__.py +8 -1
  11. frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/__init__.py +24 -0
  12. frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/_bounds.py +45 -0
  13. frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/_metric.py +277 -0
  14. frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/_sample.py +233 -0
  15. frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/proto/__init__.py +119 -0
  16. frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/proto/v1alpha8/__init__.py +28 -0
  17. frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/proto/v1alpha8/_bounds.py +49 -0
  18. frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/proto/v1alpha8/_metric.py +33 -0
  19. frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/proto/v1alpha8/_metric_connection_category.py +38 -0
  20. frequenz_client_common-0.3.8/src/frequenz/client/common/metrics/proto/v1alpha8/_sample.py +152 -0
  21. frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/__init__.py +11 -0
  22. 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
  23. {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz/client/common/microgrid/components/__init__.py +34 -3
  24. frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/__init__.py +16 -0
  25. frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/_category.py +134 -0
  26. frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/_diagnostic_code.py +330 -0
  27. frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/_ids.py +13 -0
  28. frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/_state_code.py +149 -0
  29. frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/proto/__init__.py +4 -0
  30. frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/proto/v1alpha8/__init__.py +22 -0
  31. frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/electrical_components/proto/v1alpha8/_electrical_component.py +108 -0
  32. frequenz_client_common-0.3.8/src/frequenz/client/common/microgrid/sensors/__init__.py +10 -0
  33. 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
  34. {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz/client/common/pagination/__init__.py +10 -64
  35. frequenz_client_common-0.3.8/src/frequenz/client/common/pagination/_pagination_info.py +94 -0
  36. frequenz_client_common-0.3.8/src/frequenz/client/common/pagination/proto/__init__.py +4 -0
  37. frequenz_client_common-0.3.8/src/frequenz/client/common/pagination/proto/v1alpha8/__init__.py +14 -0
  38. frequenz_client_common-0.3.8/src/frequenz/client/common/pagination/proto/v1alpha8/_pagination_info.py +40 -0
  39. frequenz_client_common-0.3.8/src/frequenz/client/common/proto/__init__.py +13 -0
  40. frequenz_client_common-0.3.8/src/frequenz/client/common/proto/_timestamp.py +69 -0
  41. frequenz_client_common-0.3.8/src/frequenz/client/common/streaming/__init__.py +8 -0
  42. frequenz_client_common-0.3.8/src/frequenz/client/common/streaming/_event.py +24 -0
  43. frequenz_client_common-0.3.8/src/frequenz/client/common/streaming/proto/__init__.py +4 -0
  44. frequenz_client_common-0.3.8/src/frequenz/client/common/streaming/proto/v1alpha8/__init__.py +11 -0
  45. frequenz_client_common-0.3.8/src/frequenz/client/common/streaming/proto/v1alpha8/_event.py +34 -0
  46. frequenz_client_common-0.3.8/src/frequenz/client/common/test/__init__.py +4 -0
  47. frequenz_client_common-0.3.8/src/frequenz/client/common/test/enum_parity.py +181 -0
  48. {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8/src/frequenz_client_common.egg-info}/PKG-INFO +31 -28
  49. frequenz_client_common-0.3.8/src/frequenz_client_common.egg-info/SOURCES.txt +58 -0
  50. frequenz_client_common-0.3.8/src/frequenz_client_common.egg-info/requires.txt +53 -0
  51. frequenz_client_common-0.3.6/RELEASE_NOTES.md +0 -21
  52. frequenz_client_common-0.3.6/src/frequenz/client/common/microgrid/electrical_components/__init__.py +0 -459
  53. frequenz_client_common-0.3.6/src/frequenz/client/common/streaming/__init__.py +0 -26
  54. frequenz_client_common-0.3.6/src/frequenz_client_common.egg-info/SOURCES.txt +0 -21
  55. frequenz_client_common-0.3.6/src/frequenz_client_common.egg-info/requires.txt +0 -49
  56. {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/LICENSE +0 -0
  57. {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/MANIFEST.in +0 -0
  58. {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/README.md +0 -0
  59. {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/setup.cfg +0 -0
  60. {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz/client/common/__init__.py +0 -0
  61. {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz/client/common/conftest.py +0 -0
  62. /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
  63. {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz/client/common/py.typed +0 -0
  64. {frequenz_client_common-0.3.6 → frequenz_client_common-0.3.8}/src/frequenz_client_common.egg-info/dependency_links.txt +0 -0
  65. {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.6
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.0
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.3; extra == "dev-flake8"
30
- Requires-Dist: pydoclint==0.6.6; extra == "dev-flake8"
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==25.1.0; extra == "dev-formatting"
34
- Requires-Dist: isort==6.0.1; extra == "dev-formatting"
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.8.2; extra == "dev-mkdocs"
37
- Requires-Dist: black==25.1.0; extra == "dev-mkdocs"
38
- Requires-Dist: mike==2.1.3; extra == "dev-mkdocs"
39
- Requires-Dist: mkdocs-gen-files==0.5.0; extra == "dev-mkdocs"
40
- Requires-Dist: mkdocs-literate-nav==0.6.2; extra == "dev-mkdocs"
41
- Requires-Dist: mkdocs-macros-plugin==1.3.7; extra == "dev-mkdocs"
42
- Requires-Dist: mkdocs-material==9.6.16; extra == "dev-mkdocs"
43
- Requires-Dist: mkdocstrings[python]==0.30.0; extra == "dev-mkdocs"
44
- Requires-Dist: mkdocstrings-python==1.16.12; extra == "dev-mkdocs"
45
- Requires-Dist: frequenz-repo-config[lib]==0.13.5; extra == "dev-mkdocs"
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.17.1; extra == "dev-mypy"
48
- Requires-Dist: types-Markdown==3.8.0.20250708; extra == "dev-mypy"
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==2025.5.1; extra == "dev-noxfile"
52
- Requires-Dist: frequenz-repo-config[lib]==0.13.5; extra == "dev-noxfile"
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==3.3.7; extra == "dev-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==8.4.1; extra == "dev-pytest"
58
- Requires-Dist: frequenz-repo-config[extra-lint-examples]==0.13.5; extra == "dev-pytest"
59
- Requires-Dist: pytest-mock==3.14.1; extra == "dev-pytest"
60
- Requires-Dist: pytest-asyncio==1.1.0; extra == "dev-pytest"
61
- Requires-Dist: async-solipsism==0.8; extra == "dev-pytest"
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 == 80.9.0",
7
- "setuptools_scm[toml] == 8.3.1",
8
- "frequenz-repo-config[lib] == 0.13.5",
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 = { text = "MIT" }
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.0, < 1",
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.3", # For reading the flake8 config from pyproject.toml
44
- "pydoclint == 0.6.6",
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 == 25.1.0", "isort == 6.0.1"]
49
+ dev-formatting = ["black == 26.5.1", "isort == 8.0.1"]
48
50
  dev-mkdocs = [
49
- "Markdown == 3.8.2",
50
- "black == 25.1.0",
51
- "mike == 2.1.3",
52
- "mkdocs-gen-files == 0.5.0",
53
- "mkdocs-literate-nav == 0.6.2",
54
- "mkdocs-macros-plugin == 1.3.7",
55
- "mkdocs-material == 9.6.16",
56
- "mkdocstrings[python] == 0.30.0",
57
- "mkdocstrings-python == 1.16.12",
58
- "frequenz-repo-config[lib] == 0.13.5",
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.17.1",
62
- "types-Markdown == 3.8.0.20250708",
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 == 2025.5.1", "frequenz-repo-config[lib] == 0.13.5"]
69
+ dev-noxfile = ["nox == 2026.4.10", "frequenz-repo-config[lib] == 0.18.0"]
67
70
  dev-pylint = [
68
- "pylint == 3.3.7",
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 == 8.4.1",
74
- "frequenz-repo-config[extra-lint-examples] == 0.13.5",
75
- "pytest-mock == 3.14.1",
76
- "pytest-asyncio == 1.1.0",
77
- "async-solipsism == 0.8",
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,11 @@
1
+ # License: MIT
2
+ # Copyright © 2025 Frequenz Energy-as-a-Service GmbH
3
+
4
+ """Grid definitions for the energy market."""
5
+
6
+ from ._delivery_area import DeliveryArea, EnergyMarketCodeType
7
+
8
+ __all__ = [
9
+ "DeliveryArea",
10
+ "EnergyMarketCodeType",
11
+ ]
@@ -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,4 @@
1
+ # License: MIT
2
+ # Copyright © 2026 Frequenz Energy-as-a-Service GmbH
3
+
4
+ """Grid objects from/to proto conversion functions."""
@@ -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("Use `frequenz.client.common.enum_proto.enum_from_proto` instead.")
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}]"