I’ve got a yaml file with aliases like this:
vars:
users: &users ['user1', 'user2', 'user3', 'user4']
refs:
users: *users
user: !rand ['user1', 'user2', 'user3', 'user4']
!rand
is a custom tag that calls python’s random.choice
on a yaml sequence.
I’m using the following implementation of the !rand
tag:
import random
import yaml
def load_yaml(file):
def rand_constructor(loader, node):
value = loader.construct_sequence(node)
return random.choice(value)
yaml.add_constructor('!rand', rand_constructor)
with open(file) as f:
return yaml.load(f)
It works as expected, and user
gets a random value from users
.
Now, when I use !rand
with the alias *users
it stops working:
vars:
users: &users ['user1', 'user2', 'user3', 'user4']
refs:
users: *users
user: !rand *users
The error is:
File ../python3.6/site-packages/yaml/parser.py", line 439, in parse_block_mapping_key
"expected <block end>, but found %r" % token.id, token.start_mark)
yaml.parser.ParserError: while parsing a block mapping
in "/temp/config.yml", line 5, column 3
expected <block end>, but found '<alias>'
in "/temp/config.yml", line 6, column 18
How do I make it work with sequence aliases?
In YAML, tags are designed to define content type. They are not designed to process content.
For this reason, you cannot tag an alias, since an alias is just a reference to content which has already been tagged at the location where it's defined. In your case, your sequence will get the
!!seq
tag according to the YAML core schema. YAML does not provide the ability to re-tag it.Having said that, you can of course do a workaround: Wrap the
!rand
parameter in a sequence:You then just need to change your code to:
But be aware that a direct call to
!rand
then looks like this:See it like the outer sequence being the parameter list of the function
!rand
(which takes one parameter) and the inner sequence being that parameter.You can also make your list callable and call it each time you need random user: