-
Couldn't load subscription status.
- Fork 1.4k
Implement ConfigProvider Structural Operators #7767
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
| test("unnested") { | ||
| val configProvider1 = ConfigProvider.fromMap(Map("key" -> "value")) | ||
| val config1 = Config.string("key") | ||
| val configProvider2 = ConfigProvider.fromMap(Map("key" -> "value")).unnested("nested") |
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 isn't exactly what I imagined unnested doing.
Rather, I would expect that, if you do:
val configProvider2 = ConfigProvider.fromMap(Map("nested.key" -> "nested.value")).unnested("nested")Then you can successfully load Config.string("key") from such a ConfigProvider.
In other words, the unnested operator lets you take a ConfigProvider that is overly nested, and unnest it, such that it can be used with "flatter" configs.
The ConfigProvider#nested operator "pretends" the config data is nested, and can be used when the Config expects data that is actually more nested than it actually is; the ConfigProvider#unnested operator "pretends" the config data is not nested, and can be used when the Config expects data that is less nested than it actually is.
Maybe there are issues with this approach or maybe I just don't see how this test demonstrates such a relationship?
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 think you may be confusing nested with unnested.
nested takes each Config and nests it under the specified name. So the way you would do what you want would be nested:
val configProvider = ConfigProvider.fromMap(Map("nested.key" -> "value")).nested("nested")
configProvider.load(Config.string("key")) // "value"It gives you a ConfigProvider that automatically nests each Config under the specified property name.
unnested is the inverse of this so whereas nested automatically adds the specified layer of nesting to every Config that is fed to it, unnested removes a layer of nesting.
val configProvider = ConfigProvider.fromMap(Map("key" -> "value")).unnested("nested")
configProvider.load(Config.string("key").nested("nested") // "value"I think these two operators need to have this relationship with each other, though their names could potentially be flipped. I think the overall issue is that ConfigProvider is contravariant with respect to the path whereas we intuitively expect it to be covariant. In other words, it is something that when fed a path gives you some values whereas intuitively we think of it as something that just has basically a map from paths to values.
So when we have the current nested we could either describe it as "nesting" each of the Config values loaded, which is accurate, or allowing us to "unnest" an overly nested config provider by allowing us to treat it as if it did not have that layer of nesting.
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.
Makes sense, 👍
| result <- configProvider.load(config) | ||
| } yield assertTrue(result == "value1" -> "value2") | ||
| } + | ||
| test("within with multiple layers of nesting") { |
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.
Looks great! Lets you make targeted changes to a region of configuration data, effectively massaging the structure of data as it is, into the structure of data as a Config wants it to be.
Resolves #7759.