Skip to content

Commit 1f541e4

Browse files
committed
Add crunch utility
1 parent 9efdf4c commit 1f541e4

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

graphene/utils/crunch.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import json
2+
from collections import Mapping
3+
4+
5+
def to_key(value):
6+
return json.dumps(value)
7+
8+
9+
def insert(value, index, values):
10+
key = to_key(value)
11+
12+
if key not in index:
13+
index[key] = len(values)
14+
values.append(value)
15+
return len(values) - 1
16+
17+
return index.get(key)
18+
19+
20+
def flatten(data, index, values):
21+
if isinstance(data, (list, tuple)):
22+
flattened = [flatten(child, index, values) for child in data]
23+
elif isinstance(data, Mapping):
24+
flattened = {
25+
key: flatten(child, index, values) for key, child in data.items()
26+
}
27+
else:
28+
flattened = data
29+
return insert(flattened, index, values)
30+
31+
32+
def crunch(data):
33+
index = {}
34+
values = []
35+
36+
flatten(data, index, values)
37+
return values

graphene/utils/tests/test_crunch.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import pytest
2+
3+
from ..crunch import crunch
4+
5+
6+
@pytest.mark.parametrize("description,uncrunched,crunched", [
7+
['number primitive', 0, [0]],
8+
['boolean primitive', True, [True]],
9+
['string primitive', "string", ["string"]],
10+
['empty array', [], [[]]],
11+
['single-item array', [None], [None, [0]]],
12+
['multi-primitive all distinct array', [None, 0, True, "string"], [None, 0, True, "string", [0, 1, 2, 3]]],
13+
['multi-primitive repeated array', [True, True, True, True], [True, [0, 0, 0, 0]]],
14+
['one-level nested array', [[1, 2, 3]], [1, 2, 3, [0, 1, 2], [3]]],
15+
['two-level nested array', [[[1, 2, 3]]], [1, 2, 3, [0, 1, 2], [3], [4]]],
16+
['empty object', {}, [{}]],
17+
['single-item object', {'a': None}, [None, {'a': 0}]],
18+
[
19+
'multi-item all distinct object',
20+
{'a': None, 'b': 0, 'c': True, 'd': "string"},
21+
[None, 0, True, "string", {'a': 0, 'b': 1, 'c': 2, 'd': 3}]
22+
],
23+
[
24+
'multi-item repeated object',
25+
{'a': True, 'b': True, 'c': True, 'd': True},
26+
[True, {'a': 0, 'b': 0, 'c': 0, 'd': 0}]
27+
],
28+
[
29+
'complex array',
30+
[{'a': True, 'b': [1, 2, 3]}, [1, 2, 3]],
31+
[True, 1, 2, 3, [1, 2, 3], {'a': 0, 'b': 4}, [5, 4]]
32+
],
33+
[
34+
'complex object',
35+
{'a': True, 'b': [1, 2, 3], 'c': {'a': True, 'b': [1, 2, 3]}},
36+
[True, 1, 2, 3, [1, 2, 3], {'a': 0, 'b': 4}, {'a': 0, 'b': 4, 'c': 5}]
37+
],
38+
])
39+
def test_crunch(description, uncrunched, crunched):
40+
assert crunch(uncrunched) == crunched

0 commit comments

Comments
 (0)