Skip to content

Commit 0a2289a

Browse files
author
Noah Negin-Ulster
committed
feat(serializer): preserve key ordering of OrderedDict
BREAKING CHANGE: Key order is now preserved if using OrderedDict in both the Amber serializer and JSON serializer.
1 parent 80e2fcd commit 0a2289a

File tree

6 files changed

+52
-7
lines changed

6 files changed

+52
-7
lines changed

src/syrupy/extensions/amber/serializer.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
from collections import OrderedDict
23
from types import (
34
GeneratorType,
45
MappingProxyType,
@@ -246,9 +247,13 @@ def serialize_namedtuple(cls, data: NamedTuple, **kwargs: Any) -> str:
246247
def serialize_dict(
247248
cls, data: Dict["PropertyName", "SerializableData"], **kwargs: Any
248249
) -> str:
250+
keys = (
251+
data.keys() if isinstance(data, (OrderedDict,)) else cls.sort(data.keys())
252+
)
253+
249254
return cls.__serialize_iterable(
250255
data=data,
251-
resolve_entries=(cls.sort(data.keys()), item_getter, None),
256+
resolve_entries=(keys, item_getter, None),
252257
open_paren="{",
253258
close_paren="}",
254259
separator=": ",

src/syrupy/extensions/json/__init__.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import datetime
22
import json
3+
from collections import OrderedDict
34
from types import GeneratorType
45
from typing import (
56
TYPE_CHECKING,
@@ -69,8 +70,14 @@ def _filter(
6970

7071
filtered_dct: Dict[Any, Any]
7172
if isinstance(data, (dict,)):
72-
filtered_dct = {}
73-
for key, value in data.items():
73+
filtered_dct = OrderedDict()
74+
keys = (
75+
cls.sort(data.keys())
76+
if not isinstance(data, (OrderedDict,))
77+
else data.keys()
78+
)
79+
for key in keys:
80+
value = data[key]
7481
if exclude and exclude(prop=key, path=path):
7582
continue
7683
if not isinstance(key, (str,)):
@@ -86,7 +93,7 @@ def _filter(
8693
return filtered_dct
8794

8895
if cls.__is_namedtuple(data):
89-
filtered_dct = {}
96+
filtered_dct = OrderedDict()
9097
for key in cls.sort(data._fields):
9198
value = getattr(data, key)
9299
filtered_dct[key] = cls._filter(
@@ -135,4 +142,4 @@ def serialize(
135142
data = self._filter(
136143
data=data, depth=0, path=(), exclude=exclude, matcher=matcher
137144
)
138-
return json.dumps(data, indent=2, ensure_ascii=False, sort_keys=True) + "\n"
145+
return json.dumps(data, indent=2, ensure_ascii=False, sort_keys=False) + "\n"

tests/syrupy/extensions/amber/__snapshots__/test_amber_serializer.ambr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,12 @@
310310
# name: test_numbers.2
311311
0.3333333333333333
312312
# ---
313+
# name: test_ordered_dict
314+
OrderedDict({
315+
'b': 0,
316+
'a': 1,
317+
})
318+
# ---
313319
# name: test_parameter_with_dot[value.with.dot]
314320
'value.with.dot'
315321
# ---

tests/syrupy/extensions/amber/test_amber_serializer.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
from collections import namedtuple
1+
from collections import (
2+
OrderedDict,
3+
namedtuple,
4+
)
25

36
import pytest
47

@@ -218,3 +221,10 @@ def test_parameter_with_dot(parameter_with_dot, snapshot):
218221
def test_doubly_parametrized(parameter_1, parameter_2, snapshot):
219222
assert parameter_1 == snapshot
220223
assert parameter_2 == snapshot
224+
225+
226+
def test_ordered_dict(snapshot):
227+
d = OrderedDict()
228+
d["b"] = 0
229+
d["a"] = 1
230+
assert snapshot == d
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"b": 0,
3+
"a": {
4+
"b": true,
5+
"a": false
6+
}
7+
}

tests/syrupy/extensions/json/test_json_serializer.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
from collections import namedtuple
1+
from collections import (
2+
OrderedDict,
3+
namedtuple,
4+
)
25

36
import pytest
47

@@ -222,3 +225,10 @@ def test_parameter_with_dot(parameter_with_dot, snapshot_json):
222225
def test_doubly_parametrized(parameter_1, parameter_2, snapshot_json):
223226
assert parameter_1 == snapshot_json
224227
assert parameter_2 == snapshot_json
228+
229+
230+
def test_ordered_dict(snapshot_json):
231+
d = OrderedDict()
232+
d["b"] = 0
233+
d["a"] = OrderedDict(b=True, a=False)
234+
assert snapshot_json == d

0 commit comments

Comments
 (0)