YAML Parsing#
AccelForge inputs can be evaluated from YAML files. YAML parsing occurs once when YAML files are loaded into Python.
We use an extended version of the standard YAML syntax, including the << and <<<
operators. <<, when used as a dictionary key, will merge the contents of its value
with the current dictionary. <<< will merge the contents of its value and will merge
nested dictionaries. The !nomerge tag will block merging from occuring.
The following is a YAML parsing cheat sheet:
# YAML Nodes
listNode:
- element1
- element2
dict_node:
key1: value1
key2: value2
# Styles
list_block_style:
- element1
- element2
list_flow_style: {element1, element2}
dict_block_style:
key1: value1
key2: value2
dict_flow_style: {key1: value1, key2: value2}
# Anchors, Aliases, and Merge Keys
# Anchors
anchored_list_flow_style: &my_anchored_list
- element1
- element2
anchored_list_block_style: &my_anchored_list [1, 2, 3, 4, 5]
anchored_dict_flow_style: &my_anchored_dict
key1: value1
key2: value2
anchored_dict_block_style: &my_anchored_dict {key1: value1, key2: value2}
# Aliases
my_list_alias: *my_anchored_list
result_of_my_list_alias: [1, 2, 3, 4, 5]
my_dict_alias: *my_anchored_dict
result_of_my_dict_alias: {key1: value1, key2: value2}
# Merge Keys
anchored_dict_1: &my_anchored_dict
key1: value1_dict1
key2: value2_dict1
anchored_dict_2: &my_anchored_dict2
key2: value2_dict2
key3: value3_dict2
merged_dict:
<<: [*my_anchored_dict, *my_anchored_dict2] # My_anchored_dict takes precedence
result_of_merged_dict:
key1: value1_dict1
key2: value2_dict1 # Earlier anchors take precedence
key3: value3_dict2
merged_dict2:
<<: *my_anchored_dict
value2: override_value2 # Override value2
result_of_merged_dict2:
key1: value1_dict1
key2: override_value2
# Hierarchical Merge Keys
anchored_dict_hierarchical_1: &my_anchored_dict
key1: value1_dict1
key2: {subkey1: subvalue1, subkey2: subvalue2}
mylist: [d, e, f]
mylist_nomerge: [4, 5, 6]
merged_dict_hierarchical:
<<<: *my_anchored_dict
key2: {subkey1: override1} # subkey2: subvalue2 will come from the merge
mylist: [a, b, c]
mylist_nomerge: !nomerge [1, 2, 3]
result_of_merged_dict_hierarchical:
key1: value1_dict1
key2: {subkey1: override1, subkey2: subvalue2}
mylist: [a, b, c, d, e, f]
mylist_nomerge: [1, 2, 3]
merged_dict_non_hierarchical:
<<: *my_anchored_dict
key2: {subkey1: override1} # This will override all of key2
mylist: [a, b, c]
mylist_nomerge: !nomerge [1, 2, 3]
result_of_merged_dict_non_hierarchical:
key1: value1_dict1
key2: {subkey1: override1}
mylist: [a, b, c]
mylist_nomerge: [1, 2, 3]
Jinja2 Templating#
We also support Jinja2 templating. To substitute Jinja2 variables, the
jinja_parse_data argument can be passed to the
from_yaml() function. Additional Jinja2
functions are also supported, including:
add_to_path(path): Add a path to the search path for theincludefunction.cwd(): Return the current working directory.find_path(path): Find a file in the search path and return the path to the file.include(path, key): Include a file and return the value of the key. For example,include(path/x.yaml, a)will open the filepath/x.yaml, look for a top-level dictionary, and return theakey from that dictionary. Multiple levels of indexing can be used, such asinclude(path/x.yaml, a.b.c).include_all(path, key): Include all files in a directory and return the value of the key. For example,include_all(path/dir, a)will open all files in the directorypath/dir, look for a top-level dictionary, and return theakey from that dictionary.include_text(path): Include a file and return the text of the file.path_exists(path): Check if a file exists in the search path.
The following is a Jinja2 template cheat sheet:
# Add files to be included in the environment
{{add_to_path('path/to/some/dir')}}
{{add_to_path('path/to/some/other/dir')}}
variables:
var1: 5
var3: "{{cwd()}}/some_file.yaml" # {{cwd()}} is the directory of this file
var4: "{{find_path('some_file.yaml')}}" # find_path searches all paths added by add_to_path
var5: {{set_by_jinja}} # Sets the value to a "set_by_jinja" variable that must be defined
{% if path_exists('some_file.yaml') %} # Check if a file exists
var6: "some_file.yaml exists" # Include this line if the file exists
{% else %}
arch:
# Include a subset of the file. Index into the structure with
# dot-separated keys.
nodes: {{include('other.arch.yaml', 'arch.nodes')}}
# Include the entire file
{{include_text('grab_text_from_file.yaml')}}
compound_components:
# Include the subsets of multiple files. They will be merged into one list.
classes: {{include_all('compound_components/*.yaml', 'compound_components.classes')}}
{% if enable_text_flag|default(False) %}
text_included_if_enable_text_flag_is_true: |
This text will be included if enable_text_flag is true. The |default(False) sets
the default value of enable_text_flag to False if it is not set.
{% endif %}