1- from . import rules as Rules
2- from ..error import GraphQLError
3- from ..language .ast import FragmentDefinition , FragmentSpread
4- from ..language .visitor import Visitor , visit
1+ from ..language .visitor import visit
52from ..type import GraphQLSchema
63from ..utils .type_info import TypeInfo
7-
8- specified_rules = [
9- Rules .UniqueOperationNames ,
10- Rules .LoneAnonymousOperation ,
11- Rules .KnownTypeNames ,
12- Rules .FragmentsOnCompositeTypes ,
13- Rules .VariablesAreInputTypes ,
14- Rules .ScalarLeafs ,
15- Rules .FieldsOnCorrectType ,
16- Rules .UniqueFragmentNames ,
17- Rules .KnownFragmentNames ,
18- Rules .NoUnusedFragments ,
19- Rules .PossibleFragmentSpreads ,
20- Rules .NoFragmentCycles ,
21- Rules .NoUndefinedVariables ,
22- Rules .NoUnusedVariables ,
23- Rules .KnownDirectives ,
24- Rules .KnownArgumentNames ,
25- Rules .UniqueArgumentNames ,
26- Rules .ArgumentsOfCorrectType ,
27- Rules .ProvidedNonNullArguments ,
28- Rules .DefaultValuesOfCorrectType ,
29- Rules .VariablesInAllowedPosition ,
30- Rules .OverlappingFieldsCanBeMerged ,
31- Rules .UniqueInputFieldNames
32- ]
4+ from .context import ValidationContext
5+ from .rules import specified_rules
6+ from .visitor import ValidationVisitor
337
348
359def validate (schema , ast , rules = None ):
@@ -48,140 +22,3 @@ def visit_using_rules(schema, ast, rules):
4822 rules = [rule (context ) for rule in rules ]
4923 visit (ast , ValidationVisitor (rules , context , type_info , errors ))
5024 return errors
51-
52-
53- class ValidationVisitor (Visitor ):
54- def __init__ (self , rules , context , type_info , errors ):
55- self .context = context
56- self .rules = rules
57- self .total_rules = len (rules )
58- self .type_info = type_info
59- self .errors = errors
60- self .ignore_children = {}
61-
62- def enter (self , node , key , parent , path , ancestors ):
63- self .type_info .enter (node )
64- to_ignore = None
65- rules_wanting_to_visit_fragment = None
66-
67- skipped = 0
68- for rule in self .rules :
69- if rule in self .ignore_children :
70- skipped += 1
71- continue
72-
73- visit_spread_fragments = getattr (rule , 'visit_spread_fragments' , False )
74-
75- if isinstance (node , FragmentDefinition ) and key and visit_spread_fragments :
76- if to_ignore is None :
77- to_ignore = []
78-
79- to_ignore .append (rule )
80- continue
81-
82- result = rule .enter (node , key , parent , path , ancestors )
83-
84- if result and is_error (result ):
85- append (self .errors , result )
86- result = False
87-
88- if result is None and visit_spread_fragments and isinstance (node , FragmentSpread ):
89- if rules_wanting_to_visit_fragment is None :
90- rules_wanting_to_visit_fragment = []
91-
92- rules_wanting_to_visit_fragment .append (rule )
93-
94- if result is False :
95- if to_ignore is None :
96- to_ignore = []
97-
98- to_ignore .append (rule )
99-
100- if rules_wanting_to_visit_fragment :
101- fragment = self .context .get_fragment (node .name .value )
102-
103- if fragment :
104- sub_visitor = ValidationVisitor (rules_wanting_to_visit_fragment , self .context , self .type_info ,
105- self .errors )
106- visit (fragment , sub_visitor )
107-
108- should_skip = (len (to_ignore ) if to_ignore else 0 + skipped ) == self .total_rules
109-
110- if should_skip :
111- self .type_info .leave (node )
112-
113- elif to_ignore :
114- for rule in to_ignore :
115- self .ignore_children [rule ] = node
116-
117- if should_skip :
118- return False
119-
120- def leave (self , node , key , parent , path , ancestors ):
121- for rule in self .rules :
122- if rule in self .ignore_children :
123- if self .ignore_children [rule ] is node :
124- del self .ignore_children [rule ]
125-
126- continue
127-
128- result = rule .leave (node , key , parent , path , ancestors )
129-
130- if result and is_error (result ):
131- append (self .errors , result )
132-
133- self .type_info .leave (node )
134-
135-
136- def is_error (value ):
137- if isinstance (value , list ):
138- return all (isinstance (item , GraphQLError ) for item in value )
139- return isinstance (value , GraphQLError )
140-
141-
142- def append (arr , items ):
143- if isinstance (items , list ):
144- arr .extend (items )
145- else :
146- arr .append (items )
147-
148-
149- class ValidationContext (object ):
150- def __init__ (self , schema , ast , type_info ):
151- self ._schema = schema
152- self ._ast = ast
153- self ._type_info = type_info
154- self ._fragments = None
155-
156- def get_schema (self ):
157- return self ._schema
158-
159- def get_ast (self ):
160- return self ._ast
161-
162- def get_fragment (self , name ):
163- fragments = self ._fragments
164- if fragments is None :
165- self ._fragments = fragments = {}
166- for statement in self .get_ast ().definitions :
167- if isinstance (statement , FragmentDefinition ):
168- fragments [statement .name .value ] = statement
169- return fragments .get (name )
170-
171- def get_type (self ):
172- return self ._type_info .get_type ()
173-
174- def get_parent_type (self ):
175- return self ._type_info .get_parent_type ()
176-
177- def get_input_type (self ):
178- return self ._type_info .get_input_type ()
179-
180- def get_field_def (self ):
181- return self ._type_info .get_field_def ()
182-
183- def get_directive (self ):
184- return self ._type_info .get_directive ()
185-
186- def get_argument (self ):
187- return self ._type_info .get_argument ()
0 commit comments