You are trying to make a difference at the YAML string representation level, and I think you shouldn't. YAML can load objects, and these objects can affect loaded elements by connecting to the parser. Thus, you can replace complete nodes with data, change values in scalars, etc.
Suppose you have this YAML main.yml file:
- !YAMLPreProcessor verbose: '3' escape: ♦ - ♦replace(verbose) - abcd - ♦include(xyz.yml) - xyz
and what xyz.yml :
k: 9 l: 8 m: [7. 6]
and you have ♦ as a special character (it can be anything if the YAMLPreProcessor value for special matches starts with the keyword action ( replace and include ). You want this to be rounded (loaded into data in memory, and then reset to next yaml:
- !YAMLPreProcessor verbose: '3' escape: ♦ - '3' - abcd - k: 9 l: 8 m: [7. 6]
This can be done by overloading the scalar constructor, which is called for each scalar and the corresponding class YAMLPreProcessor :
# coding: utf-8 from __future__ import print_function import ruamel.yaml as yaml def construct_scalar(loader, node): self = getattr(loader, '_yaml_preprocessor', None) if self and self.d.get('escape'): if node.value and node.value.startswith(self.d['escape']): key_word, rest = node.value[1:].split('(', 1) args, rest = rest.split(')', 1) if key_word == 'replace': res = u'' for arg in args.split(','): res += str(self.d[arg]) node.value = res + rest elif key_word == 'include': inc_yml = yaml.load( open(args), Loader=yaml.RoundTripLoader )
The above version of ruamel.yaml (0.9.6) requires an older version of the choke if construct_scalar returns a non-string object.
Please note that the position of the comment after the line with the key m refers to the beginning of the line, and in the example it is not a compensation for the indentation level of the node where the xyz.yml file is xyz.yml .