Skip to content

Commit

Permalink
Allow to turn off sorting keys in Dumper
Browse files Browse the repository at this point in the history
  • Loading branch information
perlpunk committed Jul 1, 2018
1 parent a9c28e0 commit 6aeacf0
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 35 deletions.
4 changes: 2 additions & 2 deletions lib/yaml/__init__.py
Expand Up @@ -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.
Expand All @@ -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:
Expand Down
12 changes: 6 additions & 6 deletions lib/yaml/cyaml.py
Expand Up @@ -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):
Expand All @@ -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

Expand All @@ -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)
12 changes: 6 additions & 6 deletions lib/yaml/dumper.py
Expand Up @@ -13,15 +13,15 @@ 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)
Serializer.__init__(self, encoding=encoding,
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):
Expand All @@ -31,15 +31,15 @@ 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)
Serializer.__init__(self, encoding=encoding,
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

Expand All @@ -50,13 +50,13 @@ 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)
Serializer.__init__(self, encoding=encoding,
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)
6 changes: 4 additions & 2 deletions lib/yaml/representer.py
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions lib3/yaml/__init__.py
Expand Up @@ -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.
Expand All @@ -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:
Expand Down
12 changes: 6 additions & 6 deletions lib3/yaml/cyaml.py
Expand Up @@ -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):
Expand All @@ -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

Expand All @@ -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)
12 changes: 6 additions & 6 deletions lib3/yaml/dumper.py
Expand Up @@ -13,15 +13,15 @@ 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)
Serializer.__init__(self, encoding=encoding,
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):
Expand All @@ -31,15 +31,15 @@ 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)
Serializer.__init__(self, encoding=encoding,
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

Expand All @@ -50,13 +50,13 @@ 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)
Serializer.__init__(self, encoding=encoding,
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)
12 changes: 7 additions & 5 deletions lib3/yaml/representer.py
Expand Up @@ -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 = []
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions tests/data/mapping.sort
@@ -0,0 +1,6 @@
z: 1
a: 2
y: 3
b: 4
x: 5
c: 6
6 changes: 6 additions & 0 deletions tests/data/mapping.sorted
@@ -0,0 +1,6 @@
a: 2
b: 4
c: 6
x: 5
y: 3
z: 1
27 changes: 27 additions & 0 deletions 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())

27 changes: 27 additions & 0 deletions 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())

0 comments on commit 6aeacf0

Please sign in to comment.