Skip to content

Commit fd83a77

Browse files
committed
Implement ast_to_dict utility.
Closes #9.
1 parent 001bc46 commit fd83a77

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed

graphql/core/utils/ast_to_dict.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from ..language.ast import Node
2+
3+
4+
def ast_to_dict(node, include_loc=False):
5+
if isinstance(node, Node):
6+
d = {
7+
'kind': node.__class__.__name__
8+
}
9+
if hasattr(node, '_fields'):
10+
for field in node._fields:
11+
d[field] = ast_to_dict(getattr(node, field), include_loc)
12+
13+
if include_loc and hasattr(node, 'loc') and node.loc:
14+
d['loc'] = {
15+
'start': node.loc.start,
16+
'end': node.loc.end
17+
}
18+
19+
return d
20+
21+
elif isinstance(node, list):
22+
return [ast_to_dict(item, include_loc) for item in node]
23+
24+
return node

tests/core_utils/test_ast_to_dict.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
from graphql.core.language import ast
2+
from graphql.core.language.parser import Loc, parse
3+
from graphql.core.utils.ast_to_dict import ast_to_dict
4+
5+
6+
def test_converts_simple_ast_to_dict():
7+
node = ast.Name(value='test', loc=Loc(start=5, end=10))
8+
9+
assert ast_to_dict(node) == {'kind': 'Name', 'value': 'test'}
10+
assert ast_to_dict(node, include_loc=True) == {
11+
'kind': 'Name', 'value': 'test', 'loc': {
12+
'start': 5,
13+
'end': 10
14+
}
15+
}
16+
17+
18+
def test_converts_nested_ast_to_dict():
19+
parsed_ast = parse('''
20+
query x {
21+
someQuery(arg: "x") {
22+
a
23+
b
24+
}
25+
fragment Test on TestFoo {
26+
c
27+
d
28+
}
29+
}
30+
''')
31+
32+
expected_ast_dict = {'definitions': [{'directives': [],
33+
'kind': 'OperationDefinition',
34+
'name': {'kind': 'Name', 'value': 'x'},
35+
'operation': 'query',
36+
'selection_set': {'kind': 'SelectionSet',
37+
'selections': [{'alias': None,
38+
'arguments': [{'kind': 'Argument',
39+
'name': {'kind': 'Name',
40+
'value': 'arg'},
41+
'value': {
42+
'kind': 'StringValue',
43+
'value': 'x'}}],
44+
'directives': [],
45+
'kind': 'Field',
46+
'name': {'kind': 'Name',
47+
'value': 'someQuery'},
48+
'selection_set': {'kind': 'SelectionSet',
49+
'selections': [
50+
{'alias': None,
51+
'arguments': [],
52+
'directives': [],
53+
'kind': 'Field',
54+
'name': {
55+
'kind': 'Name',
56+
'value': 'a'},
57+
'selection_set': None},
58+
{'alias': None,
59+
'arguments': [],
60+
'directives': [],
61+
'kind': 'Field',
62+
'name': {
63+
'kind': 'Name',
64+
'value': 'b'},
65+
'selection_set': None}]}},
66+
{'alias': None,
67+
'arguments': [],
68+
'directives': [],
69+
'kind': 'Field',
70+
'name': {'kind': 'Name',
71+
'value': 'fragment'},
72+
'selection_set': None},
73+
{'alias': None,
74+
'arguments': [],
75+
'directives': [],
76+
'kind': 'Field',
77+
'name': {'kind': 'Name',
78+
'value': 'Test'},
79+
'selection_set': None},
80+
{'alias': None,
81+
'arguments': [],
82+
'directives': [],
83+
'kind': 'Field',
84+
'name': {'kind': 'Name',
85+
'value': 'on'},
86+
'selection_set': None},
87+
{'alias': None,
88+
'arguments': [],
89+
'directives': [],
90+
'kind': 'Field',
91+
'name': {'kind': 'Name',
92+
'value': 'TestFoo'},
93+
'selection_set': {'kind': 'SelectionSet',
94+
'selections': [
95+
{'alias': None,
96+
'arguments': [],
97+
'directives': [],
98+
'kind': 'Field',
99+
'name': {
100+
'kind': 'Name',
101+
'value': 'c'},
102+
'selection_set': None},
103+
{'alias': None,
104+
'arguments': [],
105+
'directives': [],
106+
'kind': 'Field',
107+
'name': {
108+
'kind': 'Name',
109+
'value': 'd'},
110+
'selection_set': None}]}}]},
111+
'variable_definitions': []}],
112+
'kind': 'Document'}
113+
114+
assert ast_to_dict(parsed_ast) == expected_ast_dict

0 commit comments

Comments
 (0)