Skip to content

Commit e1c7ece

Browse files
authored
fix(cli): YAML representer for multi-line blocks (#743)
1 parent fbbca9b commit e1c7ece

File tree

3 files changed

+30
-20
lines changed

3 files changed

+30
-20
lines changed

cli/testflinger_cli/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -820,7 +820,7 @@ def show(self):
820820
sys.exit(1)
821821
if self.args.yaml:
822822
to_print = helpers.pretty_yaml_dump(
823-
results, sort_keys=True, indent=4
823+
results, sort_keys=True, indent=4, default_flow_style=False
824824
)
825825
else:
826826
to_print = json.dumps(results, sort_keys=True, indent=4)

cli/testflinger_cli/helpers.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -134,25 +134,32 @@ def prompt_for_queue(queues: dict[str, str]) -> str:
134134
return queue
135135

136136

137+
def multiline_str_representer(dumper, data):
138+
"""
139+
Render multiline strings as blocks, leave other strings unchanged.
140+
141+
This is a custom YAML representer for strings.
142+
"""
143+
# see section "Constructors, representers resolvers"
144+
# at https://pyyaml.org/wiki/PyYAMLDocumentation
145+
# and https://yaml.org/spec/1.2.2/#literal-style
146+
if "\n" in data:
147+
# remove trailing whitespace from each line
148+
# (suggested fix for https://github.com/yaml/pyyaml/issues/240)
149+
data = "\n".join(line.rstrip() for line in data.splitlines()) + "\n"
150+
return dumper.represent_scalar(
151+
"tag:yaml.org,2002:str", data, style="|"
152+
)
153+
return dumper.represent_scalar("tag:yaml.org,2002:str", data)
154+
155+
156+
yaml.add_representer(str, multiline_str_representer)
157+
158+
137159
def pretty_yaml_dump(obj, **kwargs) -> str:
138160
"""Create a pretty YAML representation of obj.
139161
140162
:param obj: The object to be represented.
141163
:return: A pretty representation of obj as a YAML string.
142164
"""
143-
144-
# objective is to get multiline strings as blocks leaving any other string
145-
# unchanged
146-
def multiline_str_representer(dumper, data):
147-
# see section "Constructors, representers resolvers"
148-
# at https://pyyaml.org/wiki/PyYAMLDocumentation
149-
# and https://yaml.org/spec/1.2.2/#literal-style
150-
if "\n" in data:
151-
return dumper.represent_scalar(
152-
"tag:yaml.org,2002:str", data, style="|"
153-
)
154-
return dumper.represent_scalar("tag:yaml.org,2002:str", data)
155-
156-
# duplicated calls to this are no-op
157-
yaml.add_representer(str, multiline_str_representer)
158165
return yaml.dump(obj, **kwargs)

cli/testflinger_cli/tests/test_helpers.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,15 @@ def test_pretty_yaml_dump():
5959
single_line = {"a": "some"}
6060
assert pretty_yaml_dump(single_line).strip() == "a: some"
6161

62-
multiline = {"a": "some\nother"}
62+
multiline = {"a": "some \nother\n"}
6363
result = textwrap.dedent(
6464
"""
65-
a: |-
65+
a: |
6666
some
6767
other
6868
"""
69-
).strip()
70-
assert pretty_yaml_dump(multiline, indent=4).strip() == result
69+
)
70+
assert (
71+
pretty_yaml_dump(multiline, indent=4, default_flow_style=False).strip()
72+
== result.strip()
73+
)

0 commit comments

Comments
 (0)