-
Notifications
You must be signed in to change notification settings - Fork 6
Merge v0.18.x into v0.x.x #209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The API changed so much in v0.17 that building on top of the previous version will just add noise to the diff of the following commits, and we won't have checks passing for a long time either if we go this route because after upgrading the API bindings files nothings works anymore. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
We also need to bump many other dependencies to be compatible with the new `frequenz-api-microgrid` version. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
This will be used to retrieve the microgrid information. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
This will be used to retrieve the microgrid information. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
This will be used to retrieve the microgrid information. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
`DEFAULT_GRPC_CALL_TIMEOUT` could be potentially tuned by the user and `DEFAULT_CHANNEL_OPTIONS` is important as documentation for the defaults. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
This commit introduces a new module which provides a framework for testing gRPC client implementations. The module simplifies mocking gRPC stub interactions and asserting client behavior for both unary and streaming calls. It allows defining test cases in separate Python files with a conventional structure, making tests more organized and maintainable. Key features include: - Discovery of test case files based on directory structure. - Mocking of gRPC responses and errors. - Assertion helpers for gRPC requests and client results/exceptions. - Support for unary-unary and unary-stream gRPC methods. Detailed usage instructions and examples are available in the module's docstring. Please note this module is added here temporarily and will be moved to the `frequenz-client-base` repository as a general test utility in the near future. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
We call the `MicrogridApiClient` method `get_microgrid_info()` to be more forward-compatible with upcoming changes. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
This is a major breaking change, as we jump to the API specification version 0.17.x, which introduces big and fundamental breaking changes. This also starts using the `v1` namespace in `frequenz-api-common`, which also introduces major breaking changes. It would be very hard to detail all the API changes here, please refer to the [Microgrid API releases](https://github.com/frequenz-floss/frequenz-api-microgrid/releases) and [Common API releases](https://github.com/frequenz-floss/frequenz-api-common/releases). This PR also only focus on migrating the current functionality to v0.17.x, and it is the starting point, only implementing `GetMicrogridMetadata`. Other RPCs will be implemented in follow-up PRs. Also many of the things added here will be moved to other repos. All protobuf wrappers for `api-common` will be moved to `client-common`, and the test framework for API clients will be moved to `client-base`. Part of #55.
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Arguments of `pytest`s are pretty self descriptive, as they come from figures, parametrization or other decorators. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
We will need to add more metrics-related wrappers in the future, so it is better to make it a package. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
This class will be used to combine classic inheritance (all components will derive from it), a mix-in to provide common functionality of all components, and also build "algebraic data types", so they can be used in `match` statements and easily do exhaustion checks to make sure all possible types of components are handled when needed. Note it doesn't make sense to make this a `abc.ABC` because there are no abstract methods. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
These 2 calls are identically, they just affect active or reactive power
respectively, so there are a few utility function that are shared, as
well as test cases.
For test cases we need to use a couple of hacks to share them.
* `*_case.py` files for `set_reactive_power` are symlinks to
`set_active_power()`
* Both have their own `_config.py` file where we define the classes used
for the tests, so we can share them, as only the request/response
objects change between both.
* Because of the client test framework works, `_config` must be imported
as a top-level module.
* We need to ignore `pylint` and `mypy` checks when importing, as they
can't find the `_config` module at the top-level.
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
The following classes are added: * `Chp` * `Converter` * `CryptoMiner` * `Electrolyzer` * `Hvac` * `Meter` * `Precharger` * `Relay` All these components are just plain subclasses of `Component` that only override the category. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Battery components have an attached battery type. To encode this into the Python type system, we create a sub-class per each battery type, similar to what we do with components. The special types `UnspecifiedBattery` and `UnrecognizedBattery` are added to represent a battery with type `UNSPECIFIED` and a battery with a battery type we don't recognize (this could happen if using a newer server providing new battery types) respectively. On top of that, we define a `BatteryTypes` type alias to make it easy to type-hint function that want to return all known battery types as a type union instead of using inheritance. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Like batteries, EV charger components have an attached type. To encode this into the Python type system, we create a sub-class per each type. As with batteries, special types are using to represent a EV charger with type `UNSPECIFIED` and with type we don't recognize, and define a type alias to make it easy to type-hint function that want to return all known EV charger types as a type union instead of using inheritance. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Like batteries and EV chargers, inverter components have an attached type. To encode this into the Python type system, we create a sub-class per each type. Special types are also used to represent a inverter with type `UNSPECIFIED` and with type we don't recognize, and we define a type alias to make it easy to type-hint function that want to return all known inverter types as a type union instead of using inheritance. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Problematic components are components that can't be mapped to known category types (or are `UNSPECIFIED`). They also include components with mismatched a category, i.e. a component with a particular known category but that also has category-specific information that doesn't match the specified category. For example if the category is `BATTERY` but the category-specific information is for a `INVERTER`. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
These aliases are type unions for all supported components, and for all known problematic, unspecified and unrecognized components. These include the specific types of components with sub-types, like batteries, EV chargers and inverters. These type aliases only include concrete types, the base types are not included, this way they can be used as type hints where match statements should be used. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
These members are restored for better backwards compatibility, and created as deprecated enum members to remind users to upgrade. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
The timeout counts for the whole duration of the call, not each individual streamed message, so it always times out, as we expect this stream to basically last forever. On top of this, disconnecting the stream seems to trigger some bug in the SDK, so we better avoid it for now. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
When converting a component from its protobuf representation, we need to handle multiple component types, so we end up with multiple branches in the function, but this is OK, so we just silence the pylint warning for that specific case. This is in preparation to the merge to v0.x.x branch, as only the new version detects this case. Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR merges the v0.18.x branch into v0.x.x, making the v0.18.x branch the default main branch. The merge includes a major restructuring of the test suite and adds significant new testing infrastructure.
- Complete rewrite of the test infrastructure with a new testing utilities framework in
tests/util.py - Removal of old test files (
test_sensor_proto.py,test_sensor.py,test_metrics.py,test_metadata.py,test_connection.py,test_component_data.py,test_component.py) and replacement with a more organized test structure - Addition of comprehensive test coverage for components, metrics, lifetime, location, delivery area, and microgrid info
- Introduction of a parameterized client test structure using test case files in
tests/client_test_cases/
Reviewed Changes
Copilot reviewed 128 out of 128 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/util.py | Adds comprehensive testing utilities framework for gRPC client testing with mocking and test case discovery |
| tests/test_client.py | Restructured to use new testing framework with parameterized test cases |
| tests/test_microgrid_info.py | New test file for MicrogridInfo class functionality |
| tests/test_location.py | New test file for location protobuf conversion |
| tests/test_lifetime.py | Enhanced with protobuf conversion tests |
| tests/test_delivery_area.py | New test file for DeliveryArea class |
| tests/metrics/test_sample.py | New comprehensive test suite for metric samples |
| tests/metrics/test_bounds.py | New test suite for Bounds class |
| tests/component/* | Multiple new test files for various component types and their protobuf conversions |
| tests/client_test_cases/* | New test case data files for client method testing |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| assert result == expiry_time | ||
| """Assert that the client result matches the expected expiry time.""" | ||
| assert result == expiry_time |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function docstring in line 37 has duplicate text. The same "Assert that the client result matches the expected expiry time." appears twice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| assert result == expiry_time | |
| """Assert that the client result matches the expected expiry time.""" | |
| assert result == expiry_time | |
| assert result == expiry_time |
| """Assert that the client result is None when no lifetime is provided.""" | ||
| assert result is None | ||
| assert result is None |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The assertion appears twice at the end of this function. Lines 34-35 duplicate the same assertion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| """Assert that the client result is None when no lifetime is provided.""" | |
| assert result is None | |
| assert result is None | |
| """Assert that the client result is None when no lifetime is provided.""" | |
| assert result is None |
|
GitHub is not being able to apply the suggestions so I will remove the duplicated code in a follow-up PR preparing the release. |
The v0.18.x branch is good enough to make a release, so we want to merge it to v0.x.x to make it clear it is the default main branch now.
Fixes #55.