1
1
from collections import defaultdict
2
- from typing import Dict , List , Set
2
+ from typing import DefaultDict , Dict , List , Set
3
3
4
4
from ..language import (
5
5
DocumentNode ,
6
- ExecutableDefinitionNode ,
7
6
FragmentDefinitionNode ,
8
7
OperationDefinitionNode ,
9
8
Visitor ,
13
12
__all__ = ["separate_operations" ]
14
13
15
14
16
- DepGraph = Dict [str , Set [str ]]
15
+ DepGraph = DefaultDict [str , Set [str ]]
17
16
18
17
19
18
def separate_operations (document_ast : DocumentNode ) -> Dict [str , DocumentNode ]:
@@ -23,13 +22,10 @@ def separate_operations(document_ast: DocumentNode) -> Dict[str, DocumentNode]:
23
22
fragments and returns a collection of AST documents each of which contains a single
24
23
operation as well the fragment definitions it refers to.
25
24
"""
26
-
27
25
# Populate metadata and build a dependency graph.
28
26
visitor = SeparateOperations ()
29
27
visit (document_ast , visitor )
30
28
operations = visitor .operations
31
- fragments = visitor .fragments
32
- positions = visitor .positions
33
29
dep_graph = visitor .dep_graph
34
30
35
31
# For each operation, produce a new synthesized AST which includes only what is
@@ -40,44 +36,42 @@ def separate_operations(document_ast: DocumentNode) -> Dict[str, DocumentNode]:
40
36
dependencies : Set [str ] = set ()
41
37
collect_transitive_dependencies (dependencies , dep_graph , operation_name )
42
38
43
- # The list of definition nodes to be included for this operation, sorted to
44
- # retain the same order as the original document.
45
- definitions : List [ExecutableDefinitionNode ] = [operation ]
46
- for name in dependencies :
47
- definitions .append (fragments [name ])
48
- definitions .sort (key = lambda n : positions .get (n , 0 ))
49
-
50
- separated_document_asts [operation_name ] = DocumentNode (definitions = definitions )
39
+ # The list of definition nodes to be included for this operation, sorted
40
+ # to retain the same order as the original document.
41
+ separated_document_asts [operation_name ] = DocumentNode (
42
+ definitions = [
43
+ node
44
+ for node in document_ast .definitions
45
+ if node is operation
46
+ or (
47
+ isinstance (node , FragmentDefinitionNode )
48
+ and node .name .value in dependencies
49
+ )
50
+ ]
51
+ )
51
52
52
53
return separated_document_asts
53
54
54
55
55
- # noinspection PyAttributeOutsideInit
56
56
class SeparateOperations (Visitor ):
57
+ operations : List [OperationDefinitionNode ]
58
+ dep_graph : DepGraph
59
+ from_name : str
60
+
57
61
def __init__ (self ):
58
62
super ().__init__ ()
59
- self .operations : List [OperationDefinitionNode ] = []
60
- self .fragments : Dict [str , FragmentDefinitionNode ] = {}
61
- self .positions : Dict [ExecutableDefinitionNode , int ] = {}
62
- self .dep_graph : DepGraph = defaultdict (set )
63
- self .from_name : str
64
- self .idx = 0
63
+ self .operations = []
64
+ self .dep_graph = defaultdict (set )
65
65
66
66
def enter_operation_definition (self , node , * _args ):
67
67
self .from_name = op_name (node )
68
68
self .operations .append (node )
69
- self .positions [node ] = self .idx
70
- self .idx += 1
71
69
72
70
def enter_fragment_definition (self , node , * _args ):
73
71
self .from_name = node .name .value
74
- self .fragments [self .from_name ] = node
75
- self .positions [node ] = self .idx
76
- self .idx += 1
77
72
78
73
def enter_fragment_spread (self , node , * _args ):
79
- to_name = node .name .value
80
- self .dep_graph [self .from_name ].add (to_name )
74
+ self .dep_graph [self .from_name ].add (node .name .value )
81
75
82
76
83
77
def op_name (operation : OperationDefinitionNode ) -> str :
0 commit comments