diff --git a/lib/yaml/__init__.py b/lib/yaml/__init__.py index 628eb747..93b181d9 100644 --- a/lib/yaml/__init__.py +++ b/lib/yaml/__init__.py @@ -173,7 +173,7 @@ def dump_all(documents, stream=None, Dumper=Dumper, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding='utf-8', explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): """ Serialize a sequence of Python objects into a YAML stream. If stream is None, return the produced string instead. @@ -191,7 +191,7 @@ def dump_all(documents, stream=None, Dumper=Dumper, canonical=canonical, indent=indent, width=width, allow_unicode=allow_unicode, line_break=line_break, encoding=encoding, version=version, tags=tags, - explicit_start=explicit_start, explicit_end=explicit_end) + explicit_start=explicit_start, explicit_end=explicit_end, sort_keys=sort_keys) try: dumper.open() for data in documents: diff --git a/lib/yaml/cyaml.py b/lib/yaml/cyaml.py index 5371f636..43b2fef9 100644 --- a/lib/yaml/cyaml.py +++ b/lib/yaml/cyaml.py @@ -40,14 +40,14 @@ def __init__(self, stream, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): CEmitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, encoding=encoding, allow_unicode=allow_unicode, line_break=line_break, explicit_start=explicit_start, explicit_end=explicit_end, version=version, tags=tags) Representer.__init__(self, default_style=default_style, - default_flow_style=default_flow_style) + default_flow_style=default_flow_style, sort_keys=sort_keys) Resolver.__init__(self) class CDumper(CEmitter, SafeRepresenter, Resolver): @@ -57,14 +57,14 @@ def __init__(self, stream, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): CEmitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, encoding=encoding, allow_unicode=allow_unicode, line_break=line_break, explicit_start=explicit_start, explicit_end=explicit_end, version=version, tags=tags) SafeRepresenter.__init__(self, default_style=default_style, - default_flow_style=default_flow_style) + default_flow_style=default_flow_style, sort_keys=sort_keys) Resolver.__init__(self) CSafeDumper = CDumper @@ -75,12 +75,12 @@ def __init__(self, stream, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): CEmitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, encoding=encoding, allow_unicode=allow_unicode, line_break=line_break, explicit_start=explicit_start, explicit_end=explicit_end, version=version, tags=tags) Representer.__init__(self, default_style=default_style, - default_flow_style=default_flow_style) + default_flow_style=default_flow_style, sort_keys=sort_keys) Resolver.__init__(self) diff --git a/lib/yaml/dumper.py b/lib/yaml/dumper.py index 22fd9271..6cf11bef 100644 --- a/lib/yaml/dumper.py +++ b/lib/yaml/dumper.py @@ -13,7 +13,7 @@ def __init__(self, stream, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): Emitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, allow_unicode=allow_unicode, line_break=line_break) @@ -21,7 +21,7 @@ def __init__(self, stream, explicit_start=explicit_start, explicit_end=explicit_end, version=version, tags=tags) Representer.__init__(self, default_style=default_style, - default_flow_style=default_flow_style) + default_flow_style=default_flow_style, sort_keys=sort_keys) Resolver.__init__(self) class Dumper(Emitter, Serializer, SafeRepresenter, Resolver): @@ -31,7 +31,7 @@ def __init__(self, stream, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): Emitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, allow_unicode=allow_unicode, line_break=line_break) @@ -39,7 +39,7 @@ def __init__(self, stream, explicit_start=explicit_start, explicit_end=explicit_end, version=version, tags=tags) SafeRepresenter.__init__(self, default_style=default_style, - default_flow_style=default_flow_style) + default_flow_style=default_flow_style, sort_keys=sort_keys) Resolver.__init__(self) SafeDumper = Dumper @@ -50,7 +50,7 @@ def __init__(self, stream, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): Emitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, allow_unicode=allow_unicode, line_break=line_break) @@ -58,5 +58,5 @@ def __init__(self, stream, explicit_start=explicit_start, explicit_end=explicit_end, version=version, tags=tags) Representer.__init__(self, default_style=default_style, - default_flow_style=default_flow_style) + default_flow_style=default_flow_style, sort_keys=sort_keys) Resolver.__init__(self) diff --git a/lib/yaml/representer.py b/lib/yaml/representer.py index f249f083..3432cc7e 100644 --- a/lib/yaml/representer.py +++ b/lib/yaml/representer.py @@ -17,9 +17,10 @@ class BaseRepresenter(object): yaml_representers = {} yaml_multi_representers = {} - def __init__(self, default_style=None, default_flow_style=None): + def __init__(self, default_style=None, default_flow_style=None, sort_keys=True): self.default_style = default_style self.default_flow_style = default_flow_style + self.sort_keys = sort_keys self.represented_objects = {} self.object_keeper = [] self.alias_key = None @@ -117,7 +118,8 @@ def represent_mapping(self, tag, mapping, flow_style=None): best_style = True if hasattr(mapping, 'items'): mapping = mapping.items() - mapping.sort() + if self.sort_keys: + mapping.sort() for item_key, item_value in mapping: node_key = self.represent_data(item_key) node_value = self.represent_data(item_value) diff --git a/lib3/yaml/__init__.py b/lib3/yaml/__init__.py index cbb84174..64d4f37b 100644 --- a/lib3/yaml/__init__.py +++ b/lib3/yaml/__init__.py @@ -172,7 +172,7 @@ def dump_all(documents, stream=None, Dumper=Dumper, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): """ Serialize a sequence of Python objects into a YAML stream. If stream is None, return the produced string instead. @@ -189,7 +189,7 @@ def dump_all(documents, stream=None, Dumper=Dumper, canonical=canonical, indent=indent, width=width, allow_unicode=allow_unicode, line_break=line_break, encoding=encoding, version=version, tags=tags, - explicit_start=explicit_start, explicit_end=explicit_end) + explicit_start=explicit_start, explicit_end=explicit_end, sort_keys=sort_keys) try: dumper.open() for data in documents: diff --git a/lib3/yaml/cyaml.py b/lib3/yaml/cyaml.py index ac8b0b76..b02ea40b 100644 --- a/lib3/yaml/cyaml.py +++ b/lib3/yaml/cyaml.py @@ -40,14 +40,14 @@ def __init__(self, stream, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): CEmitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, encoding=encoding, allow_unicode=allow_unicode, line_break=line_break, explicit_start=explicit_start, explicit_end=explicit_end, version=version, tags=tags) Representer.__init__(self, default_style=default_style, - default_flow_style=default_flow_style) + default_flow_style=default_flow_style, sort_keys=sort_keys) Resolver.__init__(self) class CDumper(CEmitter, SafeRepresenter, Resolver): @@ -57,14 +57,14 @@ def __init__(self, stream, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): CEmitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, encoding=encoding, allow_unicode=allow_unicode, line_break=line_break, explicit_start=explicit_start, explicit_end=explicit_end, version=version, tags=tags) SafeRepresenter.__init__(self, default_style=default_style, - default_flow_style=default_flow_style) + default_flow_style=default_flow_style, sort_keys=sort_keys) Resolver.__init__(self) CSafeDumper = CDumper @@ -75,12 +75,12 @@ def __init__(self, stream, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): CEmitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, encoding=encoding, allow_unicode=allow_unicode, line_break=line_break, explicit_start=explicit_start, explicit_end=explicit_end, version=version, tags=tags) Representer.__init__(self, default_style=default_style, - default_flow_style=default_flow_style) + default_flow_style=default_flow_style, sort_keys=sort_keys) Resolver.__init__(self) diff --git a/lib3/yaml/dumper.py b/lib3/yaml/dumper.py index b2d3a074..652b9ecc 100644 --- a/lib3/yaml/dumper.py +++ b/lib3/yaml/dumper.py @@ -13,7 +13,7 @@ def __init__(self, stream, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): Emitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, allow_unicode=allow_unicode, line_break=line_break) @@ -21,7 +21,7 @@ def __init__(self, stream, explicit_start=explicit_start, explicit_end=explicit_end, version=version, tags=tags) Representer.__init__(self, default_style=default_style, - default_flow_style=default_flow_style) + default_flow_style=default_flow_style, sort_keys=sort_keys) Resolver.__init__(self) class Dumper(Emitter, Serializer, SafeRepresenter, Resolver): @@ -31,7 +31,7 @@ def __init__(self, stream, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): Emitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, allow_unicode=allow_unicode, line_break=line_break) @@ -39,7 +39,7 @@ def __init__(self, stream, explicit_start=explicit_start, explicit_end=explicit_end, version=version, tags=tags) SafeRepresenter.__init__(self, default_style=default_style, - default_flow_style=default_flow_style) + default_flow_style=default_flow_style, sort_keys=sort_keys) Resolver.__init__(self) SafeDumper = Dumper @@ -50,7 +50,7 @@ def __init__(self, stream, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): + version=None, tags=None, sort_keys=True): Emitter.__init__(self, stream, canonical=canonical, indent=indent, width=width, allow_unicode=allow_unicode, line_break=line_break) @@ -58,5 +58,5 @@ def __init__(self, stream, explicit_start=explicit_start, explicit_end=explicit_end, version=version, tags=tags) Representer.__init__(self, default_style=default_style, - default_flow_style=default_flow_style) + default_flow_style=default_flow_style, sort_keys=sort_keys) Resolver.__init__(self) diff --git a/lib3/yaml/representer.py b/lib3/yaml/representer.py index 483005f4..2f230bb8 100644 --- a/lib3/yaml/representer.py +++ b/lib3/yaml/representer.py @@ -15,8 +15,9 @@ class BaseRepresenter: yaml_representers = {} yaml_multi_representers = {} - def __init__(self, default_style=None, default_flow_style=None): + def __init__(self, default_style=None, default_flow_style=None, sort_keys=True): self.default_style = default_style + self.sort_keys = sort_keys self.default_flow_style = default_flow_style self.represented_objects = {} self.object_keeper = [] @@ -107,10 +108,11 @@ def represent_mapping(self, tag, mapping, flow_style=None): best_style = True if hasattr(mapping, 'items'): mapping = list(mapping.items()) - try: - mapping = sorted(mapping) - except TypeError: - pass + if self.sort_keys: + try: + mapping = sorted(mapping) + except TypeError: + pass for item_key, item_value in mapping: node_key = self.represent_data(item_key) node_value = self.represent_data(item_value) diff --git a/tests/data/mapping.sort b/tests/data/mapping.sort new file mode 100644 index 00000000..802ba1ad --- /dev/null +++ b/tests/data/mapping.sort @@ -0,0 +1,6 @@ +z: 1 +a: 2 +y: 3 +b: 4 +x: 5 +c: 6 diff --git a/tests/data/mapping.sorted b/tests/data/mapping.sorted new file mode 100644 index 00000000..b3dd3464 --- /dev/null +++ b/tests/data/mapping.sorted @@ -0,0 +1,6 @@ +a: 2 +b: 4 +c: 6 +x: 5 +y: 3 +z: 1 diff --git a/tests/lib/test_sort_keys.py b/tests/lib/test_sort_keys.py new file mode 100644 index 00000000..f347659a --- /dev/null +++ b/tests/lib/test_sort_keys.py @@ -0,0 +1,27 @@ +import yaml +import pprint +import sys + +def test_sort_keys(input_filename, sorted_filename, verbose=False): + input = open(input_filename, 'rb').read().decode('utf-8') + sorted = open(sorted_filename, 'rb').read().decode('utf-8') + data = yaml.load(input) + dump_sorted = yaml.dump(data, default_flow_style=False, sort_keys=True) + dump_unsorted = yaml.dump(data, default_flow_style=False, sort_keys=False) + if verbose: + print("INPUT:") + print(input) + print("DATA:") + print(data) + + assert dump_sorted == sorted + + + + +test_sort_keys.unittest = ['.sort', '.sorted'] + +if __name__ == '__main__': + import test_appliance + test_appliance.run(globals()) + diff --git a/tests/lib3/test_sort_keys.py b/tests/lib3/test_sort_keys.py new file mode 100644 index 00000000..519ce5c0 --- /dev/null +++ b/tests/lib3/test_sort_keys.py @@ -0,0 +1,27 @@ +import yaml +import pprint +import sys + +def test_sort_keys(input_filename, sorted_filename, verbose=False): + input = open(input_filename, 'rb').read().decode('utf-8') + sorted = open(sorted_filename, 'rb').read().decode('utf-8') + data = yaml.load(input) + dump_sorted = yaml.dump(data, default_flow_style=False, sort_keys=True) + dump_unsorted = yaml.dump(data, default_flow_style=False, sort_keys=False) + if verbose: + print("INPUT:") + print(input) + print("DATA:") + print(data) + + assert dump_sorted == sorted + + if sys.version_info>=(3,7): + assert dump_unsorted == input + +test_sort_keys.unittest = ['.sort', '.sorted'] + +if __name__ == '__main__': + import test_appliance + test_appliance.run(globals()) +