Custom Tags
Tags are used to denote the type of a YAML node when converting to a Python object.
UW supports the use of standard YAML tags, denoted by !! as defined in the YAML specification. Additionally, UW defines the following tags to support use cases not covered by standard tags, denoted by ! and described in detail below. Where standard YAML tags are applied to their values immediately, application of UW YAML tags is delayed until after Jinja2 expressions in tagged values are dereferenced.
Tags may be implicit:
boolean: true
integer: 3
float: 3.14
Or explicit:
boolean: !!bool "true"
integer: !!int "3"
float: !!float "3.14"
NB Values tagged with UW YAML tags must be strings. Use quotes as necessary to ensure that they are.
!bool
Converts the tagged node to a Python bool object. For example, given input.yaml:
flag1: True
flag2: !bool "{{ flag1 }}"
flag3: !bool "0"
$ uw config realize -i input.yaml --output-format yaml
flag1: True
flag2: True
flag3: False
!datetime
Converts the tagged node to a Python datetime object. For example, given input.yaml:
date1: 2024-09-01
date2: !datetime "{{ date1 }}"
$ uw config realize -i input.yaml --output-format yaml
date1: 2024-09-01
date2: 2024-09-01T00:00:00
The value provided to the tag must be in ISO 8601 format to be interpreted correctly by the !datetime tag.
!dict
Converts the tagged node to a Python dict value. For example, given input.yaml:
d1: {'k0': 0, 'k1': 1, 'k2': 2}
d2: !dict "{ k0: 0, k1: 1, k2: 2 }"
d3: !dict "{{ '{' }}{% for n in range(3) %} k{{ n }}:{{ n }},{% endfor %}{{ '}' }}"
d4: !dict "[{% for n in range(3) %}[k{{ n }},{{ n }}],{% endfor %}]"
$ uw config realize -i input.yaml --output-format yaml
d1: {'k0': 0, 'k1': 1, 'k2': 2}
d2: {'k0': 0, 'k1': 1, 'k2': 2}
d3: {'k0': 0, 'k1': 1, 'k2': 2}
d4: {'k0': 0, 'k1': 1, 'k2': 2}
!extend
Extends an existing list in a base config with additional items. For example, given input.yaml:
values:
- 1
- 2
and update.yaml:
values: !extend
- 3
- 4
$ uw config realize -i input.yaml --update-file update.yaml
values:
- 1
- 2
- 3
- 4
Note
There are use cases where !extend is the ideal tool, but it also has significant limitations:
It must be applied to a literal YAML sequence.
It must be applied via a second, updating config, either via
uw config realizewith--update-filespecified, as shown above, or viauw config compose.The value-to-extend in the base config must exist at the same key path as the value tagged
!extendin the updating config.The value-to-extend in the base config must be a literal YAML sequence; in particular, it cannot be a tagged Jinaj2 expression like
!list '{{ x }}'that will only eventually be a extendable sequence.
Tip
In light of these limitations, note that Jinja2 expressions combining and slicing Python
listobjects may address a larger set of use cases. They can be used within a single config, can reference values at arbitrary key paths, can prepend as well as append elements, can insert items at abitrary positions, and can even remove items. For example:lo: [1, 2] hi: [7, 8] numbers: [3, 5, 6, 42] final: !list '{{ lo + numbers[:1] + [4] + numbers[1:3] + hi }}'
$ uw config realize -i a.yaml --key-path final
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
!float
Converts the tagged node to a Python float value. For example, given input.yaml:
f2: !float "{{ 3.141 + 2.718 }}"
$ uw config realize -i input.yaml --output-format yaml
f2: 5.859
!glob
Only for use in File Blocks. See Glob Support for more information.
!include
Load and parse the files specified in the tagged sequence value and insert their contents here. For example, given numbers.yaml:
values: !include [constants.yaml]
and constants.yaml:
e: 2.718
pi: 3.141
$ uw config realize -i numbers.yaml --output-format yaml
values:
e: 2.718
pi: 3.141
Values from files later in the sequence overwrite their predecessors, and full-value replacement, not structural merging, is performed. For example, given numbers.yaml:
values: !include [e.yaml, pi.yaml]
e.yaml:
constants:
e: 2.718
and pi.yaml:
constants:
pi: 3.141
$ uw config realize -i numbers.yaml --output-format yaml
values:
constants:
pi: 3.141
!int
Converts the tagged node to a Python int value. For example, given input.yaml:
f1: 3
f2: 11
f3: !int "{{ (f1 + f2) * 10 }}"
f4: !int '{{ leadtime.total_seconds() / 3600 }}'
$ uw config realize -i input.yaml --leadtime 6
f1: 3
f2: 11
f3: 140
f4: 6
!list
Converts the tagged node to a Python list value. For example, given input.yaml:
l1: [1, 2, 3]
l2: !list "[{% for n in range(3) %} a{{ n }},{% endfor %} ]"
l3: !list "[ a0, a1, a2, ]"
$ uw config realize -i input.yaml --output-format yaml
l1: [1, 2, 3]
l2: ['a0', 'a1', 'a2']
l3: ['a0', 'a1', 'a2']
!remove
Removes the tagged YAML key-value pair. For example, given input.yaml:
e: 2.718
pi: 3.141
and update.yaml:
e: !remove
$ uw config realize -i input.yaml --update-file update.yaml --output-format yaml
pi: 3.141
!timedelta
Converts the tagged node to a Python timedelta object. For example:
base: !datetime 2025-07-31T12:00:00
offset: !timedelta 6
cycle: !datetime "{{ base + offset }}"
$ uw config realize -i input.yaml --output-format yaml
base: 2025-07-31T12:00:00
offset: !timedelta '6:00:00'
cycle: 2025-07-31T18:00:00
The value provided to the tag may be an integer number of hours, or a string of the form hours[:minutes[:seconds]], where the hours, minutes, and seconds components are (possibly zero-padded) integers.