-
Couldn't load subscription status.
- Fork 18
Add config parser utilities #175
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
base: develop
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #175 +/- ##
===========================================
- Coverage 56.60% 56.41% -0.19%
===========================================
Files 316 315 -1
Lines 20490 20473 -17
Branches 1569 1594 +25
===========================================
- Hits 11598 11550 -48
- Misses 8892 8923 +31 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
c12921f to
cad1163
Compare
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.
This is much-much nicer. Thank you.
Co-authored-by: Philipp Geier <[email protected]>
cad1163 to
b70feb5
Compare
Field -> Entry config -> localConfig when type is eckit::LocalConfiguration
| template <typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, bool> = true> | ||
| struct EnumTrait; |
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.
Maybe we should move the EnumTrait somewhere else in multio::util and implement toString and fromString methods.
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.
This would require a discussion and a separate PR.
With this PR we intended to create something small and specifically for configs.
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.
Made some comments and have some questions.
Is there a reason for renaming it back to Entry?
There are a couple of TODO: Improve error message!. Are these fixed or still need adjustment?
Can we create a test that prints a error message? Are they user friendly and carry enough context?
| template <typename TEnum, std::enable_if_t<std::is_enum_v<TEnum>, bool> = true> | ||
| struct EnumTrait; |
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.
This would require a discussion and a separate PR.
With this PR we intended to create something small and specifically for configs.
| namespace multio::util::config { | ||
|
|
||
|
|
||
| /** |
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.
I'm not sure which code style we adopt to.
In Metkit/FDB we use /// and @COMMAND. But in the multio header we do /** */ and \command.
To be consistent with the other repositories, I opt for /// & @COMMAND.
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.
Ah, I successfully managed to mix both styles somehow. :^)
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.
Well, it is quite a mix in all repositories, including fdb/metkit. There is a clear preference there for /// & @, but examples for both. In, e.g. atlas and mir, we have a more 'even' mix. So I wouldn't lose too much sleep over it.
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.
But in general, trying to converge on a single style would be preferable, of course.
| * @throws If an unknown key is present in the localConfig, or if a value cannot be parsed | ||
| */ | ||
| template <typename TConfig> | ||
| TConfig parseConfig(const eckit::LocalConfiguration& localConfig) { |
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.
Given that we separate details, this body should also be moved to details.
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.
Can you be more precise, where should this be moved?
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.
For example:
template <typename TConfig>
TConfig parseConfig(const eckit::LocalConfiguration& localConfig) {
return details::parseConfig<TConfig>(localConfig);
}
|
|
||
|
|
||
| // Double value | ||
| // TODO(knobel) parse double |
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.
Remove comments.
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.
Only when we implement the test.
All the TODO's are still not addressed. I focused on the structure for now. |
|
|
||
| template <> | ||
| struct multio::util::config::detail::EnumTrait<multio::test::FancyEnum> { | ||
| static constexpr std::array values{ |
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.
Why is this an array of std::pairs, rather than an std::map (which is also a container of std::pairs)?
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 intention is the make the definition of the string mapping readable in the header file.
With an array<pair>> we can simply create a static constexpr member. That would not be possible with a map/unordered_map - instead we would either
- create a
static const- which has downside that the definition/initialization must be put in a compilation unit (.cc file) - or create a
staticfunction that returns a map and itself uses astatic constvariable - would be just a few lines more of code e.g.template <> struct multio::util::config::detail::EnumTrait<multio::test::FancyEnum> { static const auto& values() { static const map<string, Enum> values_{ std::pair{multio::test::FancyEnum::Rock, "rock"}, std::pair{multio::test::FancyEnum::Paper, "paper"}, std::pair{multio::test::FancyEnum::Scissors, "scissors"}}; return values_; } };
|
|
||
| // Configuration to struct parsing | ||
|
|
||
| struct MyConfig { |
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.
So if you think about the configuration as key-value pairs, then 'required' and 'optional' are about the existence of the keys in the config. And we use the enum trait to restrict the allowable values of any given key (when this restriction makes sense). Is my understanding correct?
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.
Yes, if by config you mean the eckit::LocalConfiguration. In the example below the idea is:
nameis required, because there is no default, and it is not anstd::optional;enabledis optional, even though it is not anstd::optional, but there is a default value;choiceis optional and can be unset after parsing, because it is anstd::optional.
The enum makes sense for situations where there are a finite number of possible values. For example for statistics operations (although that would be an std::vector<SomeEnumForTheOperation>).
Similar to what we have in
datamod::corefor metadata, but now simplified implementation to parse action configurations.This is not meant to be the final version yet, but rather a simple prototype we can discuss.
🌈🌦️📖🚧 Documentation 🚧📖🌦️🌈
https://sites.ecmwf.int/docs/dev-section/multio/pull-requests/PR-175