Allow to turn off sorting keys in Dumper

This commit is contained in:
Tina Müller 2018-03-16 23:25:44 +01:00 committed by Ingy döt Net
parent 611ba39507
commit 07c88c6c1b
14 changed files with 110 additions and 35 deletions

View file

@ -256,7 +256,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.
@ -274,7 +274,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:

View file

@ -55,14 +55,14 @@ class CBaseDumper(CEmitter, BaseRepresenter, BaseResolver):
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 CSafeDumper(CEmitter, SafeRepresenter, Resolver):
@ -72,14 +72,14 @@ class CSafeDumper(CEmitter, SafeRepresenter, Resolver):
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)
class CDumper(CEmitter, Serializer, Representer, Resolver):
@ -89,13 +89,13 @@ class CDumper(CEmitter, Serializer, Representer, Resolver):
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)

View file

@ -13,7 +13,7 @@ class BaseDumper(Emitter, Serializer, BaseRepresenter, BaseResolver):
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 @@ class BaseDumper(Emitter, Serializer, BaseRepresenter, BaseResolver):
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 SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver):
@ -31,7 +31,7 @@ class SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver):
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 @@ class SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver):
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)
class Dumper(Emitter, Serializer, Representer, Resolver):
@ -49,7 +49,7 @@ class Dumper(Emitter, Serializer, Representer, Resolver):
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)
@ -57,6 +57,6 @@ class Dumper(Emitter, Serializer, Representer, Resolver):
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)

View file

@ -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 @@ class BaseRepresenter(object):
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)

View file

@ -254,7 +254,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.
@ -271,7 +271,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:

View file

@ -55,14 +55,14 @@ class CBaseDumper(CEmitter, BaseRepresenter, BaseResolver):
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 CSafeDumper(CEmitter, SafeRepresenter, Resolver):
@ -72,14 +72,14 @@ class CSafeDumper(CEmitter, SafeRepresenter, Resolver):
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)
class CDumper(CEmitter, Serializer, Representer, Resolver):
@ -89,13 +89,13 @@ class CDumper(CEmitter, Serializer, Representer, Resolver):
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)

View file

@ -13,7 +13,7 @@ class BaseDumper(Emitter, Serializer, BaseRepresenter, BaseResolver):
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 @@ class BaseDumper(Emitter, Serializer, BaseRepresenter, BaseResolver):
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 SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver):
@ -31,7 +31,7 @@ class SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver):
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 @@ class SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver):
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)
class Dumper(Emitter, Serializer, Representer, Resolver):
@ -49,7 +49,7 @@ class Dumper(Emitter, Serializer, Representer, Resolver):
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)
@ -57,6 +57,6 @@ class Dumper(Emitter, Serializer, Representer, Resolver):
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)

View file

@ -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 @@ class BaseRepresenter:
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)

6
tests/data/mapping.sort Normal file
View file

@ -0,0 +1,6 @@
z: 1
a: 2
y: 3
b: 4
x: 5
c: 6

View file

@ -0,0 +1,6 @@
a: 2
b: 4
c: 6
x: 5
y: 3
z: 1

View file

@ -0,0 +1,28 @@
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, Loader=yaml.FullLoader)
dump_sorted = yaml.dump(data, default_flow_style=False, sort_keys=True)
dump_unsorted = yaml.dump(data, default_flow_style=False, sort_keys=False)
dump_unsorted = yaml.dump(data, default_flow_style=False, sort_keys=False, Dumper=yaml.SafeDumper)
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())

View file

@ -11,6 +11,7 @@ from test_emitter import *
from test_representer import *
from test_recursive import *
from test_input_output import *
from test_sort_keys import *
if __name__ == '__main__':
import test_appliance

View file

@ -0,0 +1,29 @@
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, Loader=yaml.FullLoader)
dump_sorted = yaml.dump(data, default_flow_style=False, sort_keys=True)
dump_unsorted = yaml.dump(data, default_flow_style=False, sort_keys=False)
dump_unsorted_safe = yaml.dump(data, default_flow_style=False, sort_keys=False, Dumper=yaml.SafeDumper)
if verbose:
print("INPUT:")
print(input)
print("DATA:")
print(data)
assert dump_sorted == sorted
if sys.version_info>=(3,7):
assert dump_unsorted == input
assert dump_unsorted_safe == input
test_sort_keys.unittest = ['.sort', '.sorted']
if __name__ == '__main__':
import test_appliance
test_appliance.run(globals())

View file

@ -11,6 +11,7 @@ from test_emitter import *
from test_representer import *
from test_recursive import *
from test_input_output import *
from test_sort_keys import *
if __name__ == '__main__':
import test_appliance