'Use placeholders in yaml
Is there a way to use placeholders in yaml like this:
foo: &FOO
<<propname>>:
type: number
default: <<default>>
bar:
- *FOO
propname: "some_prop"
default: "some default"
Solution 1:[1]
With Yglu Structural Templating, your example can be written:
foo: !()
!? $.propname:
type: number
default: !? $.default
bar:
!apply .foo:
propname: "some_prop"
default: "some default"
Disclaimer: I am the author or Yglu.
Solution 2:[2]
I suppose https://get-ytt.io/ would be an acceptable solution to your problem
Solution 3:[3]
I wanted to achieve templating in yaml files as well and I found dreftymac's answer really helpful as a starting point. After researching and coding for few hours this is my answer, please let me know if/how I can improve this.
I am not doing anything too special, I try to leverage python's string templating syntax and abuse the string format method a little. So it's all python's string templating and substitution that is doing the magic here. I have modified the way dreftymac's answer templated his yaml file to use as an example.
YAML:
part01_customer_info:
cust_fname: "Homer"
cust_lname: "Himpson"
cust_motto: "I love donuts!"
cust_email: [email protected]
part01_government_info:
govt_sales_taxrate: 1.15
part01_purchase_info:
prch_unit_label: "Bacon-Wrapped Fancy Glazed Donut"
prch_unit_price: 3.00
prch_unit_quant: 7
prch_product_cost: "eval!#{part01_purchase_info[prch_unit_price]} * {part01_purchase_info[prch_unit_quant]}"
prch_total_cost: "eval!#{part01_purchase_info[prch_product_cost]} * {part01_government_info[govt_sales_taxrate]}"
part02_shipping_info:
cust_fname: "{part01_customer_info[cust_fname]}"
cust_lname: "{part01_customer_info[cust_lname]}"
ship_city: Houston
ship_state: Hexas
part03_email_info:
cust_email: "{part01_customer_info[cust_email]}"
mail_subject: Thanks for your DoughNutz order!
mail_notes: |
We want the mail_greeting to have all the expected values
with filled-in placeholders (and not curly-braces).
mail_greeting: |
Greetings {part01_customer_info[cust_fname]} {part01_customer_info[cust_lname]}!
We love your motto "{part01_customer_info[cust_motto]}" and we agree with you!
Your total purchase price is {part01_purchase_info[prch_total_cost]}
I have changed
{{}}to{}and addedeval!#which is an identifier
Python:
from pprint import pprint
import yaml
EVAL_IDENTIFIER = "eval!#"
def eval_math_expr(val):
if val.startswith(EVAL_IDENTIFIER):
val = val.replace(EVAL_IDENTIFIER, "")
val = eval(val)
return val
def str_template_substitute(full, val=None, initial=True):
val = val or full if initial else val
if isinstance(val, dict):
for k, v in val.items():
val[k] = str_template_substitute(full, v, False)
elif isinstance(val, list):
for idx, i in enumerate(val):
val[idx] = str_template_substitute(full, i, False)
elif isinstance(val, str):
# NOTE:
# Templating shouldn't be confused or tasked with extra work.
# I am attaching evaluation to string substitution here,
# just to prove this can be done.
val = eval_math_expr(val.format(**full))
return val
data = yaml.load(open('./data.yml'))
str_template_substitute(data)
pprint(data)
Note: This function is pretty powerful as this can work on dictionaries which is what JSON/YAML and many other formats convert to in python.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Cmag |
| Solution 3 | dreftymac |
