Skip to content

Commit f39ac7d

Browse files
committed
Some cleanup in build_ast_schema
Replicates graphql/graphql-js@7fe9985
1 parent 30c8f6e commit f39ac7d

File tree

4 files changed

+135
-106
lines changed

4 files changed

+135
-106
lines changed

graphql/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
GraphQLScalarType,
5252
GraphQLObjectType,
5353
GraphQLInterfaceType,
54+
GraphQLInterfaceList,
5455
GraphQLUnionType,
5556
GraphQLEnumType,
5657
GraphQLInputObjectType,
@@ -132,6 +133,7 @@
132133
assert_valid_schema,
133134
# Types
134135
GraphQLType,
136+
GraphQLTypeList,
135137
GraphQLInputType,
136138
GraphQLOutputType,
137139
GraphQLLeafType,
@@ -375,6 +377,7 @@
375377
"GraphQLScalarType",
376378
"GraphQLObjectType",
377379
"GraphQLInterfaceType",
380+
"GraphQLInterfaceList",
378381
"GraphQLUnionType",
379382
"GraphQLEnumType",
380383
"GraphQLInputObjectType",
@@ -445,6 +448,7 @@
445448
"validate_schema",
446449
"assert_valid_schema",
447450
"GraphQLType",
451+
"GraphQLTypeList",
448452
"GraphQLInputType",
449453
"GraphQLOutputType",
450454
"GraphQLLeafType",

graphql/type/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
GraphQLScalarType,
5959
GraphQLObjectType,
6060
GraphQLInterfaceType,
61+
GraphQLInterfaceList,
6162
GraphQLUnionType,
6263
GraphQLEnumType,
6364
GraphQLInputObjectType,
@@ -66,6 +67,7 @@
6667
GraphQLNonNull,
6768
# Types
6869
GraphQLType,
70+
GraphQLTypeList,
6971
GraphQLInputType,
7072
GraphQLOutputType,
7173
GraphQLLeafType,
@@ -181,6 +183,7 @@
181183
"GraphQLScalarType",
182184
"GraphQLObjectType",
183185
"GraphQLInterfaceType",
186+
"GraphQLInterfaceList",
184187
"GraphQLUnionType",
185188
"GraphQLEnumType",
186189
"GraphQLInputObjectType",
@@ -189,6 +192,7 @@
189192
"GraphQLList",
190193
"GraphQLNonNull",
191194
"GraphQLType",
195+
"GraphQLTypeList",
192196
"GraphQLInputType",
193197
"GraphQLOutputType",
194198
"GraphQLLeafType",

graphql/type/definition.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@
101101
"GraphQLInputFieldMap",
102102
"GraphQLInputObjectType",
103103
"GraphQLInputType",
104+
"GraphQLInterfaceType",
105+
"GraphQLInterfaceList",
104106
"GraphQLIsTypeOfFn",
105107
"GraphQLLeafType",
106108
"GraphQLList",
@@ -114,8 +116,8 @@
114116
"GraphQLScalarLiteralParser",
115117
"GraphQLObjectType",
116118
"GraphQLOutputType",
117-
"GraphQLInterfaceType",
118119
"GraphQLType",
120+
"GraphQLTypeList",
119121
"GraphQLTypeResolver",
120122
"GraphQLUnionType",
121123
"GraphQLWrappingType",

graphql/utilities/build_ast_schema.py

Lines changed: 124 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,13 @@
3131
GraphQLEnumType,
3232
GraphQLEnumValue,
3333
GraphQLField,
34+
GraphQLFieldMap,
3435
GraphQLIncludeDirective,
3536
GraphQLInputType,
3637
GraphQLInputField,
38+
GraphQLInputFieldMap,
3739
GraphQLInputObjectType,
40+
GraphQLInterfaceList,
3841
GraphQLInterfaceType,
3942
GraphQLList,
4043
GraphQLNamedType,
@@ -46,7 +49,9 @@
4649
GraphQLSchema,
4750
GraphQLSkipDirective,
4851
GraphQLType,
52+
GraphQLTypeList,
4953
GraphQLUnionType,
54+
Thunk,
5055
introspection_types,
5156
specified_scalar_types,
5257
)
@@ -216,21 +221,17 @@ def _build_wrapped_type(self, type_node: TypeNode) -> GraphQLType:
216221
)
217222
return self.build_type(cast(NamedTypeNode, type_node))
218223

219-
def build_directive(
220-
self, directive_node: DirectiveDefinitionNode
221-
) -> GraphQLDirective:
224+
def build_directive(self, directive: DirectiveDefinitionNode) -> GraphQLDirective:
225+
locations = [DirectiveLocation[node.value] for node in directive.locations]
226+
222227
return GraphQLDirective(
223-
name=directive_node.name.value,
224-
description=directive_node.description.value
225-
if directive_node.description
226-
else None,
227-
locations=[
228-
DirectiveLocation[node.value] for node in directive_node.locations
229-
],
230-
args=self._make_args(directive_node.arguments)
231-
if directive_node.arguments
232-
else None,
233-
ast_node=directive_node,
228+
name=directive.name.value,
229+
description=directive.description.value if directive.description else None,
230+
locations=locations,
231+
args={
232+
arg.name.value: self.build_arg(arg) for arg in directive.arguments or []
233+
},
234+
ast_node=directive,
234235
)
235236

236237
def build_field(self, field: FieldDefinitionNode) -> GraphQLField:
@@ -242,11 +243,24 @@ def build_field(self, field: FieldDefinitionNode) -> GraphQLField:
242243
return GraphQLField(
243244
type_=type_,
244245
description=field.description.value if field.description else None,
245-
args=self._make_args(field.arguments) if field.arguments else None,
246+
args={arg.name.value: self.build_arg(arg) for arg in field.arguments or []},
246247
deprecation_reason=get_deprecation_reason(field),
247248
ast_node=field,
248249
)
249250

251+
def build_arg(self, value: InputValueDefinitionNode) -> GraphQLArgument:
252+
# Note: While this could make assertions to get the correctly typed value, that
253+
# would throw immediately while type system validation with `validate_schema()`
254+
# will produce more actionable results.
255+
type_ = self._build_wrapped_type(value.type)
256+
type_ = cast(GraphQLInputType, type_)
257+
return GraphQLArgument(
258+
type_=type_,
259+
description=value.description.value if value.description else None,
260+
default_value=value_from_ast(value.default_value, type_),
261+
ast_node=value,
262+
)
263+
250264
def build_input_field(self, value: InputValueDefinitionNode) -> GraphQLInputField:
251265
# Note: While this could make assertions to get the correctly typed value, that
252266
# would throw immediately while type system validation with `validate_schema()`
@@ -268,137 +282,142 @@ def build_enum_value(value: EnumValueDefinitionNode) -> GraphQLEnumValue:
268282
ast_node=value,
269283
)
270284

271-
def _make_schema_def(self, type_def: TypeDefinitionNode) -> GraphQLNamedType:
285+
def _make_schema_def(self, ast_node: TypeDefinitionNode) -> GraphQLNamedType:
272286
method = {
273287
"object_type_definition": self._make_type_def,
274288
"interface_type_definition": self._make_interface_def,
275289
"enum_type_definition": self._make_enum_def,
276290
"union_type_definition": self._make_union_def,
277291
"scalar_type_definition": self._make_scalar_def,
278292
"input_object_type_definition": self._make_input_object_def,
279-
}.get(type_def.kind)
293+
}.get(ast_node.kind)
280294
if not method:
281-
raise TypeError(f"Type kind '{type_def.kind}' not supported.")
282-
return method(type_def) # type: ignore
283-
284-
def _make_type_def(self, type_def: ObjectTypeDefinitionNode) -> GraphQLObjectType:
285-
interfaces = type_def.interfaces
286-
return GraphQLObjectType(
287-
name=type_def.name.value,
288-
description=type_def.description.value if type_def.description else None,
289-
fields=lambda: self._make_field_def_map(type_def),
290-
# Note: While this could make early assertions to get the correctly typed
291-
# values, that would throw immediately while type system validation with
292-
# `validate_schema()` will produce more actionable results.
293-
interfaces=(
294-
lambda: [self.build_type(ref) for ref in interfaces] # type: ignore
295-
)
296-
if interfaces
297-
else [],
298-
ast_node=type_def,
295+
raise TypeError(f"Type kind '{ast_node.kind}' not supported.")
296+
return method(ast_node) # type: ignore
297+
298+
def _make_type_def(self, ast_node: ObjectTypeDefinitionNode) -> GraphQLObjectType:
299+
interface_nodes = ast_node.interfaces
300+
field_nodes = ast_node.fields
301+
302+
# Note: While this could make early assertions to get the correctly typed
303+
# values, that would throw immediately while type system validation with
304+
# `validate_schema()` will produce more actionable results.
305+
interfaces = cast(
306+
Thunk[GraphQLInterfaceList],
307+
(
308+
(lambda: [self.build_type(ref) for ref in interface_nodes])
309+
if interface_nodes
310+
else []
311+
),
299312
)
300313

301-
def _make_field_def_map(
302-
self, type_def: Union[ObjectTypeDefinitionNode, InterfaceTypeDefinitionNode]
303-
) -> Dict[str, GraphQLField]:
304-
fields = type_def.fields
305-
return (
306-
{field.name.value: self.build_field(field) for field in fields}
307-
if fields
308-
else {}
314+
fields = cast(
315+
Thunk[GraphQLFieldMap],
316+
(
317+
(
318+
lambda: {
319+
field.name.value: self.build_field(field)
320+
for field in field_nodes
321+
}
322+
)
323+
if field_nodes
324+
else {}
325+
),
309326
)
310327

311-
def _make_arg(self, value_node: InputValueDefinitionNode) -> GraphQLArgument:
312-
# Note: While this could make assertions to get the correctly typed value, that
313-
# would throw immediately while type system validation with `validate_schema()`
314-
# will produce more actionable results.
315-
type_ = self._build_wrapped_type(value_node.type)
316-
type_ = cast(GraphQLInputType, type_)
317-
return GraphQLArgument(
318-
type_=type_,
319-
description=value_node.description.value
320-
if value_node.description
321-
else None,
322-
default_value=value_from_ast(value_node.default_value, type_),
323-
ast_node=value_node,
328+
return GraphQLObjectType(
329+
name=ast_node.name.value,
330+
description=ast_node.description.value if ast_node.description else None,
331+
fields=fields,
332+
interfaces=interfaces,
333+
ast_node=ast_node,
324334
)
325335

326-
def _make_args(
327-
self, values: List[InputValueDefinitionNode]
328-
) -> Dict[str, GraphQLArgument]:
329-
return {value.name.value: self._make_arg(value) for value in values}
330-
331-
def _make_input_fields(
332-
self, values: List[InputValueDefinitionNode]
333-
) -> Dict[str, GraphQLInputField]:
334-
return {value.name.value: self.build_input_field(value) for value in values}
335-
336336
def _make_interface_def(
337-
self, type_def: InterfaceTypeDefinitionNode
337+
self, ast_node: InterfaceTypeDefinitionNode
338338
) -> GraphQLInterfaceType:
339+
field_nodes = ast_node.fields
340+
341+
fields = cast(
342+
Thunk[GraphQLFieldMap],
343+
(
344+
lambda: {
345+
field.name.value: self.build_field(field) for field in field_nodes
346+
}
347+
)
348+
if field_nodes
349+
else {},
350+
)
351+
339352
return GraphQLInterfaceType(
340-
name=type_def.name.value,
341-
description=type_def.description.value if type_def.description else None,
342-
fields=lambda: self._make_field_def_map(type_def),
343-
ast_node=type_def,
353+
name=ast_node.name.value,
354+
description=ast_node.description.value if ast_node.description else None,
355+
fields=fields,
356+
ast_node=ast_node,
344357
)
345358

346-
def _make_enum_def(self, type_def: EnumTypeDefinitionNode) -> GraphQLEnumType:
359+
def _make_enum_def(self, ast_node: EnumTypeDefinitionNode) -> GraphQLEnumType:
360+
value_nodes = ast_node.values or []
361+
347362
return GraphQLEnumType(
348-
name=type_def.name.value,
349-
description=type_def.description.value if type_def.description else None,
350-
values=self._make_value_def_map(type_def),
351-
ast_node=type_def,
363+
name=ast_node.name.value,
364+
description=ast_node.description.value if ast_node.description else None,
365+
values={
366+
value.name.value: self.build_enum_value(value) for value in value_nodes
367+
},
368+
ast_node=ast_node,
352369
)
353370

354-
def _make_value_def_map(
355-
self, type_def: EnumTypeDefinitionNode
356-
) -> Dict[str, GraphQLEnumValue]:
357-
return (
358-
{
359-
value.name.value: self.build_enum_value(value)
360-
for value in type_def.values
361-
}
362-
if type_def.values
363-
else {}
371+
def _make_union_def(self, type_def: UnionTypeDefinitionNode) -> GraphQLUnionType:
372+
type_nodes = type_def.types
373+
374+
# Note: While this could make assertions to get the correctly typed values
375+
# below, that would throw immediately while type system validation with
376+
# `validate_schema()` will get more actionable results.
377+
types = cast(
378+
Thunk[GraphQLTypeList],
379+
(lambda: [self.build_type(ref) for ref in type_nodes])
380+
if type_nodes
381+
else [],
364382
)
365383

366-
def _make_union_def(self, type_def: UnionTypeDefinitionNode) -> GraphQLUnionType:
367-
types = type_def.types
368384
return GraphQLUnionType(
369385
name=type_def.name.value,
370386
description=type_def.description.value if type_def.description else None,
371-
# Note: While this could make assertions to get the correctly typed values
372-
# below, that would throw immediately while type system validation with
373-
# `validate_schema()` will get more actionable results.
374-
types=(lambda: [self.build_type(ref) for ref in types]) # type: ignore
375-
if types
376-
else [],
387+
types=types,
377388
ast_node=type_def,
378389
)
379390

380391
@staticmethod
381-
def _make_scalar_def(type_def: ScalarTypeDefinitionNode) -> GraphQLScalarType:
392+
def _make_scalar_def(ast_node: ScalarTypeDefinitionNode) -> GraphQLScalarType:
382393
return GraphQLScalarType(
383-
name=type_def.name.value,
384-
description=type_def.description.value if type_def.description else None,
385-
ast_node=type_def,
394+
name=ast_node.name.value,
395+
description=ast_node.description.value if ast_node.description else None,
396+
ast_node=ast_node,
386397
serialize=lambda value: value,
387398
)
388399

389400
def _make_input_object_def(
390401
self, type_def: InputObjectTypeDefinitionNode
391402
) -> GraphQLInputObjectType:
403+
field_nodes = type_def.fields
404+
405+
fields = cast(
406+
Thunk[GraphQLInputFieldMap],
407+
(
408+
lambda: {
409+
field.name.value: self.build_input_field(field)
410+
for field in field_nodes
411+
}
412+
)
413+
if field_nodes
414+
else {},
415+
)
416+
392417
return GraphQLInputObjectType(
393418
name=type_def.name.value,
394419
description=type_def.description.value if type_def.description else None,
395-
fields=(
396-
lambda: self._make_input_fields(
397-
cast(List[InputValueDefinitionNode], type_def.fields)
398-
)
399-
)
400-
if type_def.fields
401-
else cast(Dict[str, GraphQLInputField], {}),
420+
fields=fields,
402421
ast_node=type_def,
403422
)
404423

0 commit comments

Comments
 (0)