-
Notifications
You must be signed in to change notification settings - Fork 180
/
Copy pathschema_printer.py
220 lines (161 loc) · 6.01 KB
/
schema_printer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
from ..language.printer import print_ast
from ..type.definition import (
GraphQLEnumType,
GraphQLInputObjectType,
GraphQLInterfaceType,
GraphQLObjectType,
GraphQLScalarType,
GraphQLUnionType,
)
from ..type.directives import DEFAULT_DEPRECATION_REASON
from .ast_from_value import ast_from_value
# Necessary for static type checking
if False: # flake8: noqa
from ..type.definition import (
GraphQLArgument,
GraphQLType,
GraphQLField,
GraphQLInputObjectField,
GraphQLEnumValue,
)
from ..type.schema import GraphQLSchema
from ..type.directives import GraphQLDirective
from typing import Any, Union, Callable
def print_schema(schema):
# type: (GraphQLSchema) -> str
return _print_filtered_schema(
schema, lambda n: not (is_spec_directive(n)), _is_defined_type
)
def print_introspection_schema(schema):
# type: (GraphQLSchema) -> str
return _print_filtered_schema(schema, is_spec_directive, _is_introspection_type)
def is_spec_directive(directive_name):
# type: (str) -> bool
return directive_name in ("skip", "include", "deprecated", "defer")
def _is_defined_type(typename):
# type: (Any) -> bool
return not _is_introspection_type(typename) and not _is_builtin_scalar(typename)
def _is_introspection_type(typename):
# type: (str) -> bool
return typename.startswith("__")
_builtin_scalars = frozenset(["String", "Boolean", "Int", "Float", "ID"])
def _is_builtin_scalar(typename):
# type: (str) -> bool
return typename in _builtin_scalars
def _print_filtered_schema(schema, directive_filter, type_filter):
# type: (GraphQLSchema, Callable[[str], bool], Callable[[str], bool]) -> str
return (
"\n\n".join(
[_print_schema_definition(schema)]
+ [
_print_directive(directive)
for directive in schema.get_directives()
if directive_filter(directive.name)
]
+ [
_print_type(type)
for typename, type in sorted(schema.get_type_map().items())
if type_filter(typename)
]
)
+ "\n"
)
def _print_schema_definition(schema):
# type: (GraphQLSchema) -> str
operation_types = []
query_type = schema.get_query_type()
if query_type:
operation_types.append(" query: {}".format(query_type))
mutation_type = schema.get_mutation_type()
if mutation_type:
operation_types.append(" mutation: {}".format(mutation_type))
subscription_type = schema.get_subscription_type()
if subscription_type:
operation_types.append(" subscription: {}".format(subscription_type))
return "schema {{\n{}\n}}".format("\n".join(operation_types))
def _print_type(type):
# type: (GraphQLType) -> str
if isinstance(type, GraphQLScalarType):
return _print_scalar(type)
elif isinstance(type, GraphQLObjectType):
return _print_object(type)
elif isinstance(type, GraphQLInterfaceType):
return _print_interface(type)
elif isinstance(type, GraphQLUnionType):
return _print_union(type)
elif isinstance(type, GraphQLEnumType):
return _print_enum(type)
assert isinstance(type, GraphQLInputObjectType)
return _print_input_object(type)
def _print_scalar(type):
# type: (GraphQLScalarType) -> str
return "scalar {}".format(type.name)
def _print_object(type):
# type: (GraphQLObjectType) -> str
interfaces = type.interfaces
implemented_interfaces = (
" implements {}".format(", ".join(i.name for i in interfaces))
if interfaces
else ""
)
return ("type {}{} {{\n" "{}\n" "}}").format(
type.name, implemented_interfaces, _print_fields(type)
)
def _print_interface(type):
# type: (GraphQLInterfaceType) -> str
return ("interface {} {{\n" "{}\n" "}}").format(type.name, _print_fields(type))
def _print_union(type):
# type: (GraphQLUnionType) -> str
return "union {} = {}".format(type.name, " | ".join(str(t) for t in type.types))
def _print_enum(type):
# type: (GraphQLEnumType) -> str
return ("enum {} {{\n" "{}\n" "}}").format(
type.name, "\n".join(" " + v.name + _print_deprecated(v) for v in type.values)
)
def _print_input_object(type):
# type: (GraphQLInputObjectType) -> str
return ("input {} {{\n" "{}\n" "}}").format(
type.name,
"\n".join(
" " + _print_input_value(name, field)
for name, field in type.fields.items()
),
)
def _print_fields(type):
# type: (Union[GraphQLObjectType, GraphQLInterfaceType]) -> str
return "\n".join(
" {}{}: {}{}".format(f_name, _print_args(f), f.type, _print_deprecated(f))
for f_name, f in type.fields.items()
)
def _print_deprecated(field_or_enum_value):
# type: (Union[GraphQLField, GraphQLEnumValue]) -> str
reason = field_or_enum_value.deprecation_reason
if reason is None:
return ""
elif reason in ("", DEFAULT_DEPRECATION_REASON):
return " @deprecated"
else:
return " @deprecated(reason: {})".format(print_ast(ast_from_value(reason)))
def _print_args(field_or_directives):
# type: (Union[GraphQLField, GraphQLDirective]) -> str
if not field_or_directives.args:
return ""
return "({})".format(
", ".join(
_print_input_value(arg_name, arg)
for arg_name, arg in field_or_directives.args.items()
)
)
def _print_input_value(name, arg):
# type: (str, GraphQLArgument) -> str
if arg.default_value is not None:
default_value = " = " + print_ast(ast_from_value(arg.default_value, arg.type))
else:
default_value = ""
return "{}: {}{}".format(name, arg.type, default_value)
def _print_directive(directive):
# type: (GraphQLDirective) -> str
return "directive @{}{} on {}".format(
directive.name, _print_args(directive), " | ".join(directive.locations)
)
__all__ = ["print_schema", "print_introspection_schema"]