Use cyaml when reading/writing Ansible

We subclass the yaml.SafeDumper class to adjust its behavior with an
override of the ignore_aliases method.  It is possible to subclass
the cyaml.CSafeDumper class as well.  The "C" part is actually the
Parser and Emitter, not the Dumper/Representer, so our override
is still effective whether we use the C or Python versions.

This can produce a significant performance increase when exchanging
large amounts of data with Ansible.

The C emitter is more aggressive about not using unecessary quotes,
so the ansible dumper test assertions need to change.  To add some
extra assurance, that test is also updated to check that the round-trip
load is as expected as well.

Change-Id: I30fd82c0b9472120d010f3f4a65e17fb426b0f7e
This commit is contained in:
James E. Blair 2023-08-22 15:08:05 -07:00
parent 50f773f222
commit 1d07a097ee
2 changed files with 14 additions and 6 deletions

View File

@ -64,24 +64,32 @@ class TestYamlDumper(BaseTestCase):
def test_ansible_dumper(self):
data = {'foo': 'bar'}
data = yamlutil.mark_strings_unsafe(data)
expected = "foo: !unsafe 'bar'\n"
expected = "foo: !unsafe bar\n"
yaml_out = yamlutil.ansible_unsafe_dump(data, default_flow_style=False)
# Assert the serialized string looks good
self.assertEqual(yaml_out, expected)
# Check the round trip
data_in = yamlutil.ansible_unsafe_load(yaml_out)
self.assertEqual(data, data_in)
data = {'foo': {'bar': 'baz'}, 'list': ['bar', 1, 3.0, True, None]}
data = yamlutil.mark_strings_unsafe(data)
expected = """\
foo:
bar: !unsafe 'baz'
bar: !unsafe baz
list:
- !unsafe 'bar'
- !unsafe bar
- 1
- 3.0
- true
- null
"""
yaml_out = yamlutil.ansible_unsafe_dump(data, default_flow_style=False)
# Assert the serialized string looks good
self.assertEqual(yaml_out, expected)
data_in = yamlutil.ansible_unsafe_load(yaml_out)
# Check the round trip
self.assertEqual(data, data_in)
def test_ansible_dumper_with_aliases(self):
foo = {'bar': 'baz'}

View File

@ -138,16 +138,16 @@ class AnsibleUnsafeStr:
return yaml.ScalarNode(tag=cls.yaml_tag, value=data.value)
class AnsibleUnsafeDumper(yaml.SafeDumper):
class AnsibleUnsafeDumper(SafeDumper):
pass
class AnsibleUnsafeDumperWithoutAliases(yaml.SafeDumper):
class AnsibleUnsafeDumperWithoutAliases(SafeDumper):
def ignore_aliases(self, data):
return True
class AnsibleUnsafeLoader(yaml.SafeLoader):
class AnsibleUnsafeLoader(SafeLoader):
pass