23andMe / Yamale

A schema and validator for YAML.
MIT License
681 stars 89 forks source link

dict key type validation #53

Closed milos-korenciak closed 5 years ago

milos-korenciak commented 5 years ago

Would it be possible to also add validation of key type in dict (={key:val}), please?

I am missing this functionality as almost all validators work along jsonschema principles. There (by definition) is every key string. But not so in YAML (https://yaml.org/spec/1.2/spec.html#id2764196)... The key itself could be almost everything (unique).

(If I am missing something obvious in yamale docs, excuse me in advance.)

mildebrandt commented 5 years ago

Hi, thanks for your interest in Yamale!

Can you describe your use case? Perhaps there's a way to achieve what you need without using a non-scalar key.

milos-korenciak commented 5 years ago

I need to have URI as an key. I want to enforce some protocols (thus valiadate the key). Consider e.g. cache.yaml (!Data in PyYAML stand for "map into object with key !Data"):

"file:///home/u/myfile.dat" : !Data {"size": 56, "original_url": "file:///home/u/myfile.dat"} "https://github.com/123" : !Data {"size": 12345, "original_url": "https://github.com/123"}

As you can notice I use that URI key as an "uniqness constraint" over the dict of objects (which contains the key as internal attribute).

mildebrandt commented 5 years ago

Just to be sure I understand, you have a yaml with keys as strings and a custom data class as values. And you want the schema to validate that the original_url attribute in the data class matches the key of the data class in the yaml?

If that's the case, how much control do you have with this YAML? My suggestion would be to rewrite the file like this:

"file:///home/u/myfile.dat" : {"size": 56}
"https://github.com/123" : {"size": 12345}

If you can avoid custom constructors in your YAML, it'll be a lot more portable in the future.

milos-korenciak commented 5 years ago

Only I want from Yamale is to (1) allow dot (.) in string key + (2) check the correctness of URI in that string in regexp way (= it contains "://" somewhere, only allowed char from system charset, etc.).

I do not want Yamale to check the same value of inner attribute and object key at all. Maybe your way of writing the data is a bit more efficient, but I need transparent and direct mapping from python in-memory objects to YAML with as little code as possible. In RAM this is the only efficient model.

mildebrandt commented 5 years ago

Thanks for the additional explanation. Off the top of my head, this may be supported by adding a key constraint to the map validator to do something like this:

map(map(str(), int()), key=regex('.*://.*'))

We do accept pull requests. If you'd like to tackle this, we'll work with you to add this functionality. But, honestly, it'll take us a while to get to this feature request.

milos-korenciak commented 5 years ago

I assume the first challenge is escaping plague of "concatenate the keys with . to generate 'path' to the value". While it seems good idea alike XPath (exchange "." and "/"), it is generally not. At least in YAML world, where the mapping key can be string with dots inside or even number or whatever.

Maybe changing the concatenation of strings with "." to concatenation of anything into list would fix the most crucial part.

Maybe after th

mildebrandt commented 5 years ago

That work is already being done here: #60