Settings: disable automatic yaml line breaks (#3096)

* Settings: disable automatic yaml line breaks

* Tests: add settings formatting checks

* Tests: fix typing in test_host_yaml
This commit is contained in:
black-sliver 2024-04-18 19:13:43 +02:00 committed by GitHub
parent f89cee4b15
commit 6087ec539b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 53 additions and 3 deletions

View File

@ -200,7 +200,7 @@ class Group:
def _dump_value(cls, value: Any, f: TextIO, indent: str) -> None:
"""Write a single yaml line to f"""
from Utils import dump, Dumper as BaseDumper
yaml_line: str = dump(value, Dumper=cast(BaseDumper, cls._dumper))
yaml_line: str = dump(value, Dumper=cast(BaseDumper, cls._dumper), width=2**31-1)
assert yaml_line.count("\n") == 1, f"Unexpected input for yaml dumper: {value}"
f.write(f"{indent}{yaml_line}")

View File

@ -1,18 +1,24 @@
import os
import unittest
from io import StringIO
from tempfile import TemporaryFile
from typing import Any, Dict, List, cast
from settings import Settings
import Utils
from settings import Settings, Group
class TestIDs(unittest.TestCase):
yaml_options: Dict[Any, Any]
@classmethod
def setUpClass(cls) -> None:
with TemporaryFile("w+", encoding="utf-8") as f:
Settings(None).dump(f)
f.seek(0, os.SEEK_SET)
cls.yaml_options = Utils.parse_yaml(f.read())
yaml_options = Utils.parse_yaml(f.read())
assert isinstance(yaml_options, dict)
cls.yaml_options = yaml_options
def test_utils_in_yaml(self) -> None:
"""Tests that the auto generated host.yaml has default settings in it"""
@ -30,3 +36,47 @@ class TestIDs(unittest.TestCase):
self.assertIn(option_key, utils_options)
for sub_option_key in option_set:
self.assertIn(sub_option_key, utils_options[option_key])
class TestSettingsDumper(unittest.TestCase):
def test_string_format(self) -> None:
"""Test that dumping a string will yield the expected output"""
# By default, pyyaml has automatic line breaks in strings and quoting is optional.
# What we want for consistency instead is single-line strings and always quote them.
# Line breaks have to become \n in that quoting style.
class AGroup(Group):
key: str = " ".join(["x"] * 60) + "\n" # more than 120 chars, contains spaces and a line break
with StringIO() as writer:
AGroup().dump(writer, 0)
expected_value = AGroup.key.replace("\n", "\\n")
self.assertEqual(writer.getvalue(), f"key: \"{expected_value}\"\n",
"dumped string has unexpected formatting")
def test_indentation(self) -> None:
"""Test that dumping items will add indentation"""
# NOTE: we don't care how many spaces there are, but it has to be a multiple of level
class AList(List[Any]):
__doc__ = None # make sure we get no doc string
class AGroup(Group):
key: AList = cast(AList, ["a", "b", [1]])
for level in range(3):
with StringIO() as writer:
AGroup().dump(writer, level)
lines = writer.getvalue().split("\n", 5)
key_line = lines[0]
key_spaces = len(key_line) - len(key_line.lstrip(" "))
value_lines = lines[1:-1]
value_spaces = [len(value_line) - len(value_line.lstrip(" ")) for value_line in value_lines]
if level == 0:
self.assertEqual(key_spaces, 0)
else:
self.assertGreaterEqual(key_spaces, level)
self.assertEqual(key_spaces % level, 0)
self.assertGreaterEqual(value_spaces[0], key_spaces) # a
self.assertEqual(value_spaces[1], value_spaces[0]) # b
self.assertEqual(value_spaces[2], value_spaces[0]) # start of sub-list
self.assertGreater(value_spaces[3], value_spaces[0],
f"{value_lines[3]} should have more indentation than {value_lines[0]} in {lines}")