-
Notifications
You must be signed in to change notification settings - Fork 5
Allow parsing scalars and mappings into the same type #64
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: v3.x.x
Are you sure you want to change the base?
Allow parsing scalars and mappings into the same type #64
Conversation
Geod24
left a comment
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.
At first I thought it made a lot of sense to do this, but thinking again, if a configuration format supports a short and long form, the longer form (mapping) would probably allow more options, wouldn't it ? This is the case for GitLab at least.
Dub has such as use case, with its dependencies array. This is how it's implemented: https://github.com/dlang/dub/blob/82207b0b29613fd8ad4eed7265aee9bbd777ac24/source/dub/recipe/packagerecipe.d#L192-L211
The only case where this feature would make sense is if you only wanted to handle image but not entrypoint, which I don't think warrant its own feature (you can always drop to fromYAML).
Not necessarily - the case I'm using this for is a restricted sum-type (a node can be e.g.
Ah, that works too. Though, I think we have enough evidence that this is a common pattern, also encountered when projects need to extend their YAML schemas, so I think it would make sense to support it directly.
Sorry, I'm not sure what you mean by this. As it is implemented in this PR, if the node is not a scalar, it deserialises into the struct ignoring |
Can you give a code example ?
Before this,
I don't mind doing (2), as I've been thinking of revamping the FAQ to include such examples, but this PR should do (1). |
Sure: import std.conv;
import configy.attributes;
struct Type {
enum BasicType {
none, // Not a basic type - see other fields
integer,
}
// Only one of these may be set:
private @Optional BasicType _basicType;
@Optional Type* array_of;
/// A plain scalar indicates a built-in type.
static Type fromString(string s) => Type(_basicType: s.to!BasicType);
@property BasicType basicType() const => _basicType; /// ditto
}
I am a little confused by the wording here - here is how I see this:
I think it's nice that you don't have to deal with DYAML.
We actually cannot do the same thing for the constructor here. The presence of the constructor blocks deserializing into struct fields (it causes the type to fail the "does not support field-wise (default) construction" check). (This asymmetry is perhaps not a bad thing - if the user wants to force configy to never deserialize into a struct, then they can declare a constructor instead of using
I don't mind doing that either, where should that be done, the FAQ? |
|
Coming back to this, sorry for the delay. Consider the following struct MeetingSchedule {
ushort day, month, year, hour, minutes;
static string fromString (string data) {
// Parsing logic here
}
}
struct Config {
MeetingSchedule[] appointments;
}Without the appointments:
- day: 24
month: 4
year: 2025
hour: 10
minute: 42And with the appointments:
- "2024-04-04T10:42:00Z"However we do not want to accept the long form when the |
So in essence we want to be able to allow application authors to decide how their structs are parseable:
Previously we supported only the first and second. This PR changes it to support only the first and third. I think the second goal can be achieved by reducing the visibility of those fields (i.e. making them |
Geod24
left a comment
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.
Just a few nits.
|
@CyberShadow Looks like this exposed a bug, will rebase on v3.x.x |
Because fromString is being changed and we do not want to accept the long version, which is something that would specify 'value'.
Some YAML schemas seem to support specifying values either as a single string, or as a dictionary. One practical example is the `image` option in `.gitlab-ci.yml` files: https://docs.gitlab.com/ee/ci/yaml/#image GitLab accepts either ```yaml test-job: image: ruby:3.0 ``` or ```yaml test-job: image: name: ruby:3.0 ``` This change enables us to support this functionality, by calling `fromString` only on scalar nodes; mappings are deserialized as usual.
1bb6810 to
0bf3e18
Compare
|
@CyberShadow : "Fixed" by re-implementing |
|
Sure, whatever works 👍 By the way I realized that another useful use case for this feature is allowing extending the schema in a backwards compatible way (just like what GitLab did in the initial example). |
| alias value this; | ||
|
|
||
| public static Only fromString (scope string str) { | ||
| public static Only fromYAML (scope ConfigParser!Only cp) { |
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 does this need to change ?
| } | ||
|
|
||
| /// Test calling fromString on scalars only | ||
| unittest |
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 add a second unittest with both fromString and fromConfig and make sure that both path can be taken based on the input type ?
Some YAML schemas seem to support specifying values either as a single string, or as a dictionary.
One practical example is the
imageoption in.gitlab-ci.ymlfiles:https://docs.gitlab.com/ee/ci/yaml/#image
GitLab accepts either
or
This change enables us to support this functionality, by calling
fromStringonly on scalar nodes; mappings are deserialized as usual.