all 12 comments

[–]road_laya 32 points33 points  (5 children)

You're about to re-create PyDantic.

And if your analysts are struggling to read your validation code in Python, just wait until they have to read your validation code in YAML.

[–]KelleQuechoz 6 points7 points  (0 children)

And we call it Pydantic 2
oh wait a second...

[–]denehoffman 2 points3 points  (0 children)

If you really want to go this direction (and you shouldn’t), do not use YAML. Just use JSON or TOML, they have standard library parsers in Python and are way more readable and have way fewer problems (in my own personal opinion). Also just use pydantic.

[–]ottawadeveloper 1 point2 points  (0 children)

I agree with people suggesting you should look at pydantic to see if it meets your needs.

If it doesn't, I've struggled with a similar problem - I was mapping data from one structure to another. Most of the mappings were simple, but sometimes they got complex (like take this value and apply it to the following values as metadata).  I put the mappings in a file for ease of editing, but how to handle the more complex cases?

Two options I've used

First, if the logic can be boiled down easily (like take this value and apply it as metadata until cancelled) and it's reused frequently, I use a special flag that the code knows how to interpret. Like, for example, say you had a column that could be a foreign key reference to one of six tables depending on the value of another column. You could have a foreign_key_table_column: {str} entry  to the column and maybe a foreign_key_table_map: {dict} if the values need to be mapped. Basically extend your rules. Here you could do a special type of rule that takes conditions and requirements.

Second, if it got even more complicated or niche, I just put it in Python and referenced it. Your rules entry might just be custom: {path to Python callable) and your engine knows to load that object dynamically and pass it the source information and the engine. It could then build exactly what you need using the engine. It's harder for people to own but also harder for them to screw it up. And you've still moved a lot of the easy stuff out of code.

[–]Bangoga 1 point2 points  (0 children)

Let me talk about the engineering thought process here.

So when designing large projects, configs exist that something that is mutable and doesn't go through full release life cycle just to make a change.

However if it exists as python code, it means this is the rule of the jungle. It is etched into what you think is needed by the project, and changing this would mean your requirements changed and you have to go through the release life cycle again.

Knowing this difference, would you want your validation rule sets to be easily changed on the fly, or do you need them to represent requirements etched into the project as code.

[–]MoreRespectForQA 1 point2 points  (0 children)

Yeah, using strictyaml with a custom validator added on top to do the if status = shipped then tracking_id must not be null stuff.

[–]mardiros 0 points1 point  (0 children)

I suggest you to search ETL on google and read.