I’ve got an object with a short string attribute, and a long multi-line string attribute. I want to write the short string as a YAML quoted scalar, and the multi-line string as a literal scalar:
JavaScript
x
3
1
my_obj.short = "Hello"
2
my_obj.long = "Line1nLine2nLine3"
3
I’d like the YAML to look like this:
JavaScript
1
6
1
short: "Hello"
2
long: |
3
Line1
4
Line2
5
Line3
6
How can I instruct PyYAML to do this? If I call yaml.dump(my_obj)
, it produces a dict-like output:
JavaScript
1
8
1
{long: 'line1
2
3
line2
4
5
line3
6
7
', short: Hello}
8
(Not sure why long is double-spaced like that…)
Can I dictate to PyYAML how to treat my attributes? I’d like to affect both the order and style.
Advertisement
Answer
JavaScript
1
25
25
1
import yaml
2
from collections import OrderedDict
3
4
class quoted(str):
5
pass
6
7
def quoted_presenter(dumper, data):
8
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"')
9
yaml.add_representer(quoted, quoted_presenter)
10
11
class literal(str):
12
pass
13
14
def literal_presenter(dumper, data):
15
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
16
yaml.add_representer(literal, literal_presenter)
17
18
def ordered_dict_presenter(dumper, data):
19
return dumper.represent_dict(data.items())
20
yaml.add_representer(OrderedDict, ordered_dict_presenter)
21
22
d = OrderedDict(short=quoted("Hello"), long=literal("Line1nLine2nLine3n"))
23
24
print(yaml.dump(d))
25
Output
JavaScript
1
6
1
short: "Hello"
2
long: |
3
Line1
4
Line2
5
Line3
6