Question

My target is to allow an easy way to “filter” previously defined nodes. Consider this fictional YAML file:

%YAML 1.1
---
- fruit: &fruitref { type: banana, color: yellow }
- another_fruit: !rotten *fruitref

What do I need to define in either the YAML file or the Python code that parses this file in order to call a custom function with *fruitref (i.e. the previously defined object, in this case a map) as argument and get the return value? The target is as simple and terse a syntax for “filtering” a previously defined value (map, sequence, whatever).

Note

It seems to me that the construct !tag *alias is invalid YAML, because of the error:

expected <block end>, but found '<alias>'
  in "/tmp/test.yaml", line 4, column 21

which most possibly implies that I won't be able to achieve the required syntax, but I do care about terseness (or rather, the target users will).

Routes taken

YAML: !!python/object/apply:__main__.rotten [*fruitref]

It works but it is too verbose for the intended use; and there is no need for multiple arguments, the use case is ALWAYS a filter for an alias (a previously defined map/sequence/object).

YAML: %TAG !f! !!python/object/apply:__main__.

Perhaps !f!rotten [*fruitref] would be acceptable, but I can't find how to make use of the %TAG directive.
EDIT: I discovered that the !! doesn't work for PyYAML 3.10, it has to be the complete URL like this: %TAG !f! %TAG !f! tag:yaml.org,2002:python/object/apply:__main__.

Python: yaml.add_constructor

I already use add_constructor for “casting” maps to specific instances of my classes; the caveat is that tag alias seems to be invalid YAML.

Best so far

add_constructor('!rotten', filter_rotten) in Python and !rotten [*fruitref] in YAML seem to work, but I'm wondering how to omit the square brackets if possible.

Was it helpful?

Solution

It seems that it is not possible to apply a tag to an already tagged reference, so:

!tag *reference

is not acceptable. The best possible solution is to enclose the reference to square brackets (create a sequence) and make the tag to be either a function call or a special constructor expecting a sequence of one object, so the tersest syntax available is:

!prefix!suffix [*reference]

or

!tag [*reference]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top