Skip to content

Commit 07c88c6

Browse files
perlpunkingydotnet
authored andcommitted
Allow to turn off sorting keys in Dumper
1 parent 611ba39 commit 07c88c6

14 files changed

+110
-35
lines changed

lib/yaml/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ def dump_all(documents, stream=None, Dumper=Dumper,
256256
canonical=None, indent=None, width=None,
257257
allow_unicode=None, line_break=None,
258258
encoding='utf-8', explicit_start=None, explicit_end=None,
259-
version=None, tags=None):
259+
version=None, tags=None, sort_keys=True):
260260
"""
261261
Serialize a sequence of Python objects into a YAML stream.
262262
If stream is None, return the produced string instead.
@@ -274,7 +274,7 @@ def dump_all(documents, stream=None, Dumper=Dumper,
274274
canonical=canonical, indent=indent, width=width,
275275
allow_unicode=allow_unicode, line_break=line_break,
276276
encoding=encoding, version=version, tags=tags,
277-
explicit_start=explicit_start, explicit_end=explicit_end)
277+
explicit_start=explicit_start, explicit_end=explicit_end, sort_keys=sort_keys)
278278
try:
279279
dumper.open()
280280
for data in documents:

lib/yaml/cyaml.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ def __init__(self, stream,
5555
canonical=None, indent=None, width=None,
5656
allow_unicode=None, line_break=None,
5757
encoding=None, explicit_start=None, explicit_end=None,
58-
version=None, tags=None):
58+
version=None, tags=None, sort_keys=True):
5959
CEmitter.__init__(self, stream, canonical=canonical,
6060
indent=indent, width=width, encoding=encoding,
6161
allow_unicode=allow_unicode, line_break=line_break,
6262
explicit_start=explicit_start, explicit_end=explicit_end,
6363
version=version, tags=tags)
6464
Representer.__init__(self, default_style=default_style,
65-
default_flow_style=default_flow_style)
65+
default_flow_style=default_flow_style, sort_keys=sort_keys)
6666
Resolver.__init__(self)
6767

6868
class CSafeDumper(CEmitter, SafeRepresenter, Resolver):
@@ -72,14 +72,14 @@ def __init__(self, stream,
7272
canonical=None, indent=None, width=None,
7373
allow_unicode=None, line_break=None,
7474
encoding=None, explicit_start=None, explicit_end=None,
75-
version=None, tags=None):
75+
version=None, tags=None, sort_keys=True):
7676
CEmitter.__init__(self, stream, canonical=canonical,
7777
indent=indent, width=width, encoding=encoding,
7878
allow_unicode=allow_unicode, line_break=line_break,
7979
explicit_start=explicit_start, explicit_end=explicit_end,
8080
version=version, tags=tags)
8181
SafeRepresenter.__init__(self, default_style=default_style,
82-
default_flow_style=default_flow_style)
82+
default_flow_style=default_flow_style, sort_keys=sort_keys)
8383
Resolver.__init__(self)
8484

8585
class CDumper(CEmitter, Serializer, Representer, Resolver):
@@ -89,13 +89,13 @@ def __init__(self, stream,
8989
canonical=None, indent=None, width=None,
9090
allow_unicode=None, line_break=None,
9191
encoding=None, explicit_start=None, explicit_end=None,
92-
version=None, tags=None):
92+
version=None, tags=None, sort_keys=True):
9393
CEmitter.__init__(self, stream, canonical=canonical,
9494
indent=indent, width=width, encoding=encoding,
9595
allow_unicode=allow_unicode, line_break=line_break,
9696
explicit_start=explicit_start, explicit_end=explicit_end,
9797
version=version, tags=tags)
9898
Representer.__init__(self, default_style=default_style,
99-
default_flow_style=default_flow_style)
99+
default_flow_style=default_flow_style, sort_keys=sort_keys)
100100
Resolver.__init__(self)
101101

lib/yaml/dumper.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ def __init__(self, stream,
1313
canonical=None, indent=None, width=None,
1414
allow_unicode=None, line_break=None,
1515
encoding=None, explicit_start=None, explicit_end=None,
16-
version=None, tags=None):
16+
version=None, tags=None, sort_keys=True):
1717
Emitter.__init__(self, stream, canonical=canonical,
1818
indent=indent, width=width,
1919
allow_unicode=allow_unicode, line_break=line_break)
2020
Serializer.__init__(self, encoding=encoding,
2121
explicit_start=explicit_start, explicit_end=explicit_end,
2222
version=version, tags=tags)
2323
Representer.__init__(self, default_style=default_style,
24-
default_flow_style=default_flow_style)
24+
default_flow_style=default_flow_style, sort_keys=sort_keys)
2525
Resolver.__init__(self)
2626

2727
class SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver):
@@ -31,15 +31,15 @@ def __init__(self, stream,
3131
canonical=None, indent=None, width=None,
3232
allow_unicode=None, line_break=None,
3333
encoding=None, explicit_start=None, explicit_end=None,
34-
version=None, tags=None):
34+
version=None, tags=None, sort_keys=True):
3535
Emitter.__init__(self, stream, canonical=canonical,
3636
indent=indent, width=width,
3737
allow_unicode=allow_unicode, line_break=line_break)
3838
Serializer.__init__(self, encoding=encoding,
3939
explicit_start=explicit_start, explicit_end=explicit_end,
4040
version=version, tags=tags)
4141
SafeRepresenter.__init__(self, default_style=default_style,
42-
default_flow_style=default_flow_style)
42+
default_flow_style=default_flow_style, sort_keys=sort_keys)
4343
Resolver.__init__(self)
4444

4545
class Dumper(Emitter, Serializer, Representer, Resolver):
@@ -49,14 +49,14 @@ def __init__(self, stream,
4949
canonical=None, indent=None, width=None,
5050
allow_unicode=None, line_break=None,
5151
encoding=None, explicit_start=None, explicit_end=None,
52-
version=None, tags=None):
52+
version=None, tags=None, sort_keys=True):
5353
Emitter.__init__(self, stream, canonical=canonical,
5454
indent=indent, width=width,
5555
allow_unicode=allow_unicode, line_break=line_break)
5656
Serializer.__init__(self, encoding=encoding,
5757
explicit_start=explicit_start, explicit_end=explicit_end,
5858
version=version, tags=tags)
5959
Representer.__init__(self, default_style=default_style,
60-
default_flow_style=default_flow_style)
60+
default_flow_style=default_flow_style, sort_keys=sort_keys)
6161
Resolver.__init__(self)
6262

lib/yaml/representer.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ class BaseRepresenter(object):
1717
yaml_representers = {}
1818
yaml_multi_representers = {}
1919

20-
def __init__(self, default_style=None, default_flow_style=None):
20+
def __init__(self, default_style=None, default_flow_style=None, sort_keys=True):
2121
self.default_style = default_style
2222
self.default_flow_style = default_flow_style
23+
self.sort_keys = sort_keys
2324
self.represented_objects = {}
2425
self.object_keeper = []
2526
self.alias_key = None
@@ -117,7 +118,8 @@ def represent_mapping(self, tag, mapping, flow_style=None):
117118
best_style = True
118119
if hasattr(mapping, 'items'):
119120
mapping = mapping.items()
120-
mapping.sort()
121+
if self.sort_keys:
122+
mapping.sort()
121123
for item_key, item_value in mapping:
122124
node_key = self.represent_data(item_key)
123125
node_value = self.represent_data(item_value)

lib3/yaml/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ def dump_all(documents, stream=None, Dumper=Dumper,
254254
canonical=None, indent=None, width=None,
255255
allow_unicode=None, line_break=None,
256256
encoding=None, explicit_start=None, explicit_end=None,
257-
version=None, tags=None):
257+
version=None, tags=None, sort_keys=True):
258258
"""
259259
Serialize a sequence of Python objects into a YAML stream.
260260
If stream is None, return the produced string instead.
@@ -271,7 +271,7 @@ def dump_all(documents, stream=None, Dumper=Dumper,
271271
canonical=canonical, indent=indent, width=width,
272272
allow_unicode=allow_unicode, line_break=line_break,
273273
encoding=encoding, version=version, tags=tags,
274-
explicit_start=explicit_start, explicit_end=explicit_end)
274+
explicit_start=explicit_start, explicit_end=explicit_end, sort_keys=sort_keys)
275275
try:
276276
dumper.open()
277277
for data in documents:

lib3/yaml/cyaml.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ def __init__(self, stream,
5555
canonical=None, indent=None, width=None,
5656
allow_unicode=None, line_break=None,
5757
encoding=None, explicit_start=None, explicit_end=None,
58-
version=None, tags=None):
58+
version=None, tags=None, sort_keys=True):
5959
CEmitter.__init__(self, stream, canonical=canonical,
6060
indent=indent, width=width, encoding=encoding,
6161
allow_unicode=allow_unicode, line_break=line_break,
6262
explicit_start=explicit_start, explicit_end=explicit_end,
6363
version=version, tags=tags)
6464
Representer.__init__(self, default_style=default_style,
65-
default_flow_style=default_flow_style)
65+
default_flow_style=default_flow_style, sort_keys=sort_keys)
6666
Resolver.__init__(self)
6767

6868
class CSafeDumper(CEmitter, SafeRepresenter, Resolver):
@@ -72,14 +72,14 @@ def __init__(self, stream,
7272
canonical=None, indent=None, width=None,
7373
allow_unicode=None, line_break=None,
7474
encoding=None, explicit_start=None, explicit_end=None,
75-
version=None, tags=None):
75+
version=None, tags=None, sort_keys=True):
7676
CEmitter.__init__(self, stream, canonical=canonical,
7777
indent=indent, width=width, encoding=encoding,
7878
allow_unicode=allow_unicode, line_break=line_break,
7979
explicit_start=explicit_start, explicit_end=explicit_end,
8080
version=version, tags=tags)
8181
SafeRepresenter.__init__(self, default_style=default_style,
82-
default_flow_style=default_flow_style)
82+
default_flow_style=default_flow_style, sort_keys=sort_keys)
8383
Resolver.__init__(self)
8484

8585
class CDumper(CEmitter, Serializer, Representer, Resolver):
@@ -89,13 +89,13 @@ def __init__(self, stream,
8989
canonical=None, indent=None, width=None,
9090
allow_unicode=None, line_break=None,
9191
encoding=None, explicit_start=None, explicit_end=None,
92-
version=None, tags=None):
92+
version=None, tags=None, sort_keys=True):
9393
CEmitter.__init__(self, stream, canonical=canonical,
9494
indent=indent, width=width, encoding=encoding,
9595
allow_unicode=allow_unicode, line_break=line_break,
9696
explicit_start=explicit_start, explicit_end=explicit_end,
9797
version=version, tags=tags)
9898
Representer.__init__(self, default_style=default_style,
99-
default_flow_style=default_flow_style)
99+
default_flow_style=default_flow_style, sort_keys=sort_keys)
100100
Resolver.__init__(self)
101101

lib3/yaml/dumper.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ def __init__(self, stream,
1313
canonical=None, indent=None, width=None,
1414
allow_unicode=None, line_break=None,
1515
encoding=None, explicit_start=None, explicit_end=None,
16-
version=None, tags=None):
16+
version=None, tags=None, sort_keys=True):
1717
Emitter.__init__(self, stream, canonical=canonical,
1818
indent=indent, width=width,
1919
allow_unicode=allow_unicode, line_break=line_break)
2020
Serializer.__init__(self, encoding=encoding,
2121
explicit_start=explicit_start, explicit_end=explicit_end,
2222
version=version, tags=tags)
2323
Representer.__init__(self, default_style=default_style,
24-
default_flow_style=default_flow_style)
24+
default_flow_style=default_flow_style, sort_keys=sort_keys)
2525
Resolver.__init__(self)
2626

2727
class SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver):
@@ -31,15 +31,15 @@ def __init__(self, stream,
3131
canonical=None, indent=None, width=None,
3232
allow_unicode=None, line_break=None,
3333
encoding=None, explicit_start=None, explicit_end=None,
34-
version=None, tags=None):
34+
version=None, tags=None, sort_keys=True):
3535
Emitter.__init__(self, stream, canonical=canonical,
3636
indent=indent, width=width,
3737
allow_unicode=allow_unicode, line_break=line_break)
3838
Serializer.__init__(self, encoding=encoding,
3939
explicit_start=explicit_start, explicit_end=explicit_end,
4040
version=version, tags=tags)
4141
SafeRepresenter.__init__(self, default_style=default_style,
42-
default_flow_style=default_flow_style)
42+
default_flow_style=default_flow_style, sort_keys=sort_keys)
4343
Resolver.__init__(self)
4444

4545
class Dumper(Emitter, Serializer, Representer, Resolver):
@@ -49,14 +49,14 @@ def __init__(self, stream,
4949
canonical=None, indent=None, width=None,
5050
allow_unicode=None, line_break=None,
5151
encoding=None, explicit_start=None, explicit_end=None,
52-
version=None, tags=None):
52+
version=None, tags=None, sort_keys=True):
5353
Emitter.__init__(self, stream, canonical=canonical,
5454
indent=indent, width=width,
5555
allow_unicode=allow_unicode, line_break=line_break)
5656
Serializer.__init__(self, encoding=encoding,
5757
explicit_start=explicit_start, explicit_end=explicit_end,
5858
version=version, tags=tags)
5959
Representer.__init__(self, default_style=default_style,
60-
default_flow_style=default_flow_style)
60+
default_flow_style=default_flow_style, sort_keys=sort_keys)
6161
Resolver.__init__(self)
6262

lib3/yaml/representer.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ class BaseRepresenter:
1515
yaml_representers = {}
1616
yaml_multi_representers = {}
1717

18-
def __init__(self, default_style=None, default_flow_style=None):
18+
def __init__(self, default_style=None, default_flow_style=None, sort_keys=True):
1919
self.default_style = default_style
20+
self.sort_keys = sort_keys
2021
self.default_flow_style = default_flow_style
2122
self.represented_objects = {}
2223
self.object_keeper = []
@@ -107,10 +108,11 @@ def represent_mapping(self, tag, mapping, flow_style=None):
107108
best_style = True
108109
if hasattr(mapping, 'items'):
109110
mapping = list(mapping.items())
110-
try:
111-
mapping = sorted(mapping)
112-
except TypeError:
113-
pass
111+
if self.sort_keys:
112+
try:
113+
mapping = sorted(mapping)
114+
except TypeError:
115+
pass
114116
for item_key, item_value in mapping:
115117
node_key = self.represent_data(item_key)
116118
node_value = self.represent_data(item_value)

tests/data/mapping.sort

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
z: 1
2+
a: 2
3+
y: 3
4+
b: 4
5+
x: 5
6+
c: 6

tests/data/mapping.sorted

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
a: 2
2+
b: 4
3+
c: 6
4+
x: 5
5+
y: 3
6+
z: 1

tests/lib/test_sort_keys.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import yaml
2+
import pprint
3+
import sys
4+
5+
def test_sort_keys(input_filename, sorted_filename, verbose=False):
6+
input = open(input_filename, 'rb').read().decode('utf-8')
7+
sorted = open(sorted_filename, 'rb').read().decode('utf-8')
8+
data = yaml.load(input, Loader=yaml.FullLoader)
9+
dump_sorted = yaml.dump(data, default_flow_style=False, sort_keys=True)
10+
dump_unsorted = yaml.dump(data, default_flow_style=False, sort_keys=False)
11+
dump_unsorted = yaml.dump(data, default_flow_style=False, sort_keys=False, Dumper=yaml.SafeDumper)
12+
if verbose:
13+
print("INPUT:")
14+
print(input)
15+
print("DATA:")
16+
print(data)
17+
18+
assert dump_sorted == sorted
19+
20+
21+
22+
23+
test_sort_keys.unittest = ['.sort', '.sorted']
24+
25+
if __name__ == '__main__':
26+
import test_appliance
27+
test_appliance.run(globals())
28+

tests/lib/test_yaml.py

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from test_representer import *
1212
from test_recursive import *
1313
from test_input_output import *
14+
from test_sort_keys import *
1415

1516
if __name__ == '__main__':
1617
import test_appliance

tests/lib3/test_sort_keys.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import yaml
2+
import pprint
3+
import sys
4+
5+
def test_sort_keys(input_filename, sorted_filename, verbose=False):
6+
input = open(input_filename, 'rb').read().decode('utf-8')
7+
sorted = open(sorted_filename, 'rb').read().decode('utf-8')
8+
data = yaml.load(input, Loader=yaml.FullLoader)
9+
dump_sorted = yaml.dump(data, default_flow_style=False, sort_keys=True)
10+
dump_unsorted = yaml.dump(data, default_flow_style=False, sort_keys=False)
11+
dump_unsorted_safe = yaml.dump(data, default_flow_style=False, sort_keys=False, Dumper=yaml.SafeDumper)
12+
if verbose:
13+
print("INPUT:")
14+
print(input)
15+
print("DATA:")
16+
print(data)
17+
18+
assert dump_sorted == sorted
19+
20+
if sys.version_info>=(3,7):
21+
assert dump_unsorted == input
22+
assert dump_unsorted_safe == input
23+
24+
test_sort_keys.unittest = ['.sort', '.sorted']
25+
26+
if __name__ == '__main__':
27+
import test_appliance
28+
test_appliance.run(globals())
29+

tests/lib3/test_yaml.py

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from test_representer import *
1212
from test_recursive import *
1313
from test_input_output import *
14+
from test_sort_keys import *
1415

1516
if __name__ == '__main__':
1617
import test_appliance

0 commit comments

Comments
 (0)