Skip to content

Commit 3b0da96

Browse files
committed
Union, Field argument
1 parent b6caf7a commit 3b0da96

File tree

2 files changed

+119
-1
lines changed

2 files changed

+119
-1
lines changed

graphql/api.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,38 @@ def __init__(self, typerefspec, args=None, resolver=None,
8181
self.description = description
8282

8383
def resolve(self, schema):
84+
args = {}
85+
if self.args:
86+
for arg_name, arg in self.args.items():
87+
args[arg_name] = arg.resolve(schema)
8488
return graphql.type.GraphQLField(
8589
self.typeref.resolve(schema),
86-
self.args, self.resolver, self.deprecation_reason, self.description
90+
args, self.resolver, self.deprecation_reason, self.description
91+
)
92+
93+
94+
class LazyArgument(object):
95+
def __init__(self, typerefspec, default_value=None, description=None):
96+
self.typeref = build_typeref(typerefspec)
97+
self.default_value = default_value
98+
self.description = description
99+
100+
def resolve(self, schema):
101+
return graphql.type.GraphQLArgument(
102+
self.typeref.resolve(schema),
103+
self.default_value, self.description
87104
)
88105

89106

90107
class Schema(object):
91108
String = InternalTypeRef(graphql.type.GraphQLString)
92109
Int = InternalTypeRef(graphql.type.GraphQLInt)
93110
Float = InternalTypeRef(graphql.type.GraphQLFloat)
111+
Boolean = InternalTypeRef(graphql.type.GraphQLBoolean)
94112
ID = InternalTypeRef(graphql.type.GraphQLID)
95113

96114
Field = LazyField
115+
Argument = LazyArgument
97116
EnumValue = graphql.type.GraphQLEnumValue
98117

99118
def __init__(self):
@@ -108,6 +127,7 @@ def __init__(self):
108127

109128
self.EnumType = self._build_type_definer(self._define_enum)
110129
self.InterfaceType = self._build_type_definer(self._define_interface)
130+
self.UnionType = self._build_type_definer(self._define_union)
111131
self.ObjectType = self._build_type_definer(self._define_object)
112132
self.QueryRoot = self._build_type_definer(self._define_query_root)
113133
self.MutationRoot = self._build_type_definer(self._define_mutation_root)
@@ -134,6 +154,15 @@ def _define_interface(self, dct):
134154
description=dct.get('__doc__'),
135155
)
136156

157+
def _define_union(self, dct):
158+
types = [self._public_types[public_type] for public_type in dct['types']]
159+
return graphql.type.GraphQLUnionType(
160+
name=dct['__typename__'],
161+
types=types,
162+
resolve_type=dct.get('resolve_type'),
163+
description=dct.get('__doc__'),
164+
)
165+
137166
def _define_object(self, dct):
138167
fields = {}
139168
for k, v in dct.items():

tests/test_api.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,56 @@ class QueryRoot(gql.QueryRoot):
146146
})
147147

148148

149+
def test_field_arguments():
150+
gql = Schema()
151+
152+
class A(gql.ObjectType):
153+
pass
154+
155+
class QueryRoot(gql.QueryRoot):
156+
field = gql.Field(gql.String, {
157+
'byPublicType': gql.Argument(A),
158+
'byName': gql.Argument('A'),
159+
'byInternalType': gql.Argument(gql.String),
160+
'byPublicTypeWrapped': gql.Argument(gql.List(A)),
161+
'byNameWrapped': gql.Argument(gql.List('A')),
162+
'byInternalTypeWrapped': gql.Argument(gql.List(gql.String)),
163+
})
164+
165+
result = graphql(gql.to_internal(), '''{
166+
type: __type(name: "QueryRoot") {
167+
fields {
168+
args {
169+
name
170+
type { ...TypeRef }
171+
}
172+
}
173+
}
174+
}
175+
fragment TypeRef on __Type {
176+
kind, name
177+
ofType {
178+
kind, name
179+
ofType { kind, name, ofType }
180+
}
181+
}''')
182+
assert not result.errors
183+
a_type = {"kind": "OBJECT", "name": "A", "ofType": None}
184+
string_type = {"kind": "SCALAR", "name": "String", "ofType": None}
185+
assert sort_lists(result.data) == sort_lists({
186+
"type": {
187+
"fields": [{"args": [
188+
{"name": "byPublicType", "type": a_type},
189+
{"name": "byName", "type": a_type},
190+
{"name": "byInternalType", "type": string_type},
191+
{"name": "byPublicTypeWrapped", "type": {"kind": "LIST", "name": None, "ofType": a_type}},
192+
{"name": "byNameWrapped", "type": {"kind": "LIST", "name": None, "ofType": a_type}},
193+
{"name": "byInternalTypeWrapped", "type": {"kind": "LIST", "name": None, "ofType": string_type}},
194+
]}]
195+
}
196+
})
197+
198+
149199
def test_prevent_defining_many_query_roots():
150200
gql = Schema()
151201

@@ -155,3 +205,42 @@ class QueryRoot(gql.QueryRoot):
155205
with raises(Exception):
156206
class SecondQueryRoot(gql.QueryRoot):
157207
pass
208+
209+
210+
def test_define_union_type():
211+
gql = Schema()
212+
213+
class A(gql.ObjectType):
214+
pass
215+
216+
class B(gql.ObjectType):
217+
pass
218+
219+
class UnionType(gql.UnionType):
220+
"""description"""
221+
__typename__ = 'Union'
222+
types = [A, B]
223+
224+
class QueryRoot(gql.QueryRoot):
225+
union = gql.Field(UnionType)
226+
227+
result = graphql(gql.to_internal(), '''{
228+
type: __type(name: "Union") {
229+
kind
230+
name
231+
description
232+
possibleTypes { name }
233+
}
234+
}''')
235+
assert not result.errors
236+
assert sort_lists(result.data) == sort_lists({
237+
"type": {
238+
"name": "Union",
239+
"description": "description",
240+
"kind": "UNION",
241+
"possibleTypes": [
242+
{"name": "A"},
243+
{"name": "B"},
244+
]
245+
}
246+
})

0 commit comments

Comments
 (0)