Deprecate UNSPECIFIED for simple enums#221
Open
llucax wants to merge 9 commits into
Open
Conversation
Contributor
Author
|
Blocked because it is based on #220. |
This was referenced Jun 23, 2026
c249ece to
829c162
Compare
Contributor
Author
|
Unblocked, ready for review. |
There was a problem hiding this comment.
Pull request overview
This PR updates frequenz-client-common’s high-level enum handling to discourage using UNSPECIFIED enum members directly while preserving forward compatibility with raw protobuf integer values. It introduces “safe” accessors that return only recognized enum members and otherwise raise explicit exceptions, keeping the public API Pythonic and making rare/erroneous cases more explicit (per #223).
Changes:
- Deprecate
UNSPECIFIEDmembers for selected “simple” enums and store the unspecified protobuf value as rawint(0)in dataclass-level conversions. - Add semantic accessor methods (
get_*) that either return a known enum member or raiseUnspecifiedValueError/ the newUnrecognizedValueError. - Enhance enum parity tests to support deprecated/absent members and expand unit/proto conversion test coverage for the new behavior.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_exception.py | Adds tests for new UnrecognizedValueError and verifies __all__ export ordering. |
| tests/metrics/test_sample_metric_sample.py | Adds unit tests for MetricSample.get_metric() behavior across known/unspecified/unrecognized values. |
| tests/metrics/test_sample_metric_connection.py | Adds unit tests for MetricConnection.get_category() behavior across known/unspecified/unrecognized values. |
| tests/metrics/proto/v1alpha8/test_sample_metric_sample.py | Verifies proto→dataclass conversion stores unspecified metric as raw 0 without deprecation warnings. |
| tests/metrics/proto/v1alpha8/test_sample_metric_connection.py | Verifies proto→dataclass conversion stores unspecified category as raw 0 and remains warning-clean. |
| tests/metrics/proto/v1alpha8/test_metric.py | Marks UNSPECIFIED as a deprecated member for parity testing. |
| tests/metrics/proto/v1alpha8/test_metric_connection_category.py | Marks UNSPECIFIED as a deprecated member for parity testing. |
| tests/grid/test_delivery_area.py | Adds unit tests for DeliveryArea.get_code_type() and deprecation behavior of UNSPECIFIED. |
| tests/grid/proto/v1alpha8/test_delivery_area.py | Updates expectations for unspecified code type stored as raw 0 and adds accessor error test. |
| src/frequenz/client/common/test/enum_parity.py | Extends parity scaffold with deprecation-aware and “absent member” modes. |
| src/frequenz/client/common/microgrid/electrical_components/proto/v1alpha8/_electrical_component.py | Avoids resolving deprecated Metric.UNSPECIFIED by handling raw 0 directly when parsing config bounds. |
| src/frequenz/client/common/microgrid/electrical_components/_electrical_component.py | Updates docstring to describe unspecified metric as proto value 0 rather than enum member. |
| src/frequenz/client/common/metrics/proto/v1alpha8/_sample.py | Stores unspecified metric/category as raw 0 before invoking enum converters (prevents deprecation warnings). |
| src/frequenz/client/common/metrics/_sample.py | Deprecates MetricConnectionCategory.UNSPECIFIED and adds get_category() / get_metric() safe accessors. |
| src/frequenz/client/common/metrics/_metric.py | Deprecates Metric.UNSPECIFIED using frequenz.core.enum.deprecated_member. |
| src/frequenz/client/common/grid/proto/v1alpha8/_delivery_area.py | Stores unspecified code type as raw 0 and reports issues without resolving deprecated enum member. |
| src/frequenz/client/common/grid/_delivery_area.py | Deprecates EnergyMarketCodeType.UNSPECIFIED and adds DeliveryArea.get_code_type() safe accessor. |
| src/frequenz/client/common/_exception.py | Introduces UnrecognizedValueError and clarifies UnspecifiedValueError semantics. |
| src/frequenz/client/common/init.py | Exports UnrecognizedValueError at the package root via __all__. |
| RELEASE_NOTES.md | Documents enum deprecations, new safe getters, and exception behavior (needs edits per review comments). |
| pyproject.toml | Bumps frequenz-core minimum version to support deprecated enum members. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
e8dea3f to
dbca974
Compare
12 tasks
Contributor
|
needs rebase |
Semantic accessors need to tell apart two distinct situations: a value the server left unspecified, and a value the server set but this client version does not recognize yet. The latter must carry the raw integer so resilient callers can forward it. Add `UnrecognizedValueError(ClientCommonError, ValueError)` storing the raw value on `.value`, and narrow `UnspecifiedValueError`'s docstring to the unspecified-only case, cross-referencing the new error. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Give the shared enum-parity scaffold two opt-in class variables, `deprecated_members` and `absent_members`, both defaulting to an empty `frozenset` so every existing subclass keeps its current behaviour. When a member name is listed in `deprecated_members`, the parity checks that merely resolve it suppress the `DeprecationWarning` (via a small `_maybe_ignore_deprecation` context manager), `test_from_proto` asserts the enum-level converter returns the still-present member and warns, and a new `test_deprecated_members_warn` asserts the warning directly. A new `test_absent_members` covers the future case where a member is removed from the Python enum while the protobuf enum still defines its value. This unblocks deprecating the three `UNSPECIFIED` members in later commit without touching their parity subclasses yet. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Mark `EnergyMarketCodeType.UNSPECIFIED` as a deprecated member. The dataclass-level `delivery_area_from_proto` now stores the raw int `0` for an unspecified value instead of materializing the deprecated member. The enum-level `energy_market_code_type_from_proto`/`_to_proto` converters are left untouched and still return the member for known values. These will automatically stop handling `UNSPECIFIED` once it's completely removed. `DeliveryArea.get_code_type()` will be introduced in a follow-up commit. Bump the `frequenz-core` dependency to be able to use the `deprecated_member()` helper. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
The dataclass-level converters now store the raw int `0` for an unspecified value instead of materializing the deprecated member: `metric_sample_from_proto_with_issues` reads the raw proto value and keep `0` as a plain `int`, and the enum-level converters are left untouched. `MetricSample.get_metric()` will be introduced in a follow-up commit. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
The dataclass-level converters now store the raw int `0` for an unspecified value instead of materializing the deprecated member: `metric_connection_from_proto_with_issues` reads the raw proto value and keep `0` as a plain `int`. `MetricConnection.get_category()` will be added in a follow-up commit. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
This is the higher-level accessor for the `code_type` attribute: it resolves the value to a known `EnergyMarketCodeType` member or raises a clear, catchable error. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Reading the low-level `category` fields can yield the raw int `0` for an unspecified value or an unknown `int` for a value this client does not recognize. These convenience methods resolve the field to a known enum member or raise a clear, catchable error. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Reading the low-level `metric` fields can yield the raw int `0` for an unspecified value or an unknown `int` for a value this client does not recognize. These convenience methods resolve the field to a known enum member or raise a clear, catchable error. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
dbca974 to
3cdc627
Compare
Contributor
Author
|
Done. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Deprecate
EnergyMarketCodeType.UNSPECIFIED,Metric.UNSPECIFIEDandMetricConnectionCategory.UNSPECIFIEDand add new safe accessor methods to retrieve the valid enum values or raise an exception:DeliveryArea.get_code_type()MetricConnection.get_category()MetricSample.get_metric()The
UNSPECIFIEDvalue is now stored as a low-level0integer, so users can still access it directly if needed, but regular use will raise an exception if trying to use an unspecified or unrecognized value. This should lead to much simpler happy path, while still allowing for the possibility of handling unspecified values in a controlled manner and making rare and error conditions more explicit.The
ElectricalComponentCategoryandXxxTypeenums are not affected by this change, as they do not have anUNSPECIFIEDvalue, but will be completely removed in the future.Part of #223.