Skip to content

Commit 3d6714d

Browse files
authored
Coerce a single value to a list when serializing list variables (#611)
1 parent bd131cc commit 3d6714d

2 files changed

Lines changed: 82 additions & 2 deletions

File tree

gql/utilities/serialize_variable_values.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
OperationDefinitionNode,
1515
type_from_ast,
1616
)
17-
from graphql.pyutils import inspect
17+
from graphql.pyutils import inspect, is_iterable
1818

1919

2020
def _get_document_operation(
@@ -76,6 +76,9 @@ def serialize_value(type_: GraphQLType, value: Any) -> Any:
7676
return serialize_value(inner_type, value)
7777

7878
elif isinstance(type_, GraphQLList):
79+
if not is_iterable(value):
80+
# Lists accept a non-list value as a list of one.
81+
return [serialize_value(inner_type, value)]
7982
return [serialize_value(inner_type, v) for v in value]
8083

8184
elif isinstance(type_, (GraphQLScalarType, GraphQLEnumType)):

tests/test_graphql_request.py

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@
1515
GraphQLObjectType,
1616
GraphQLScalarType,
1717
GraphQLSchema,
18+
GraphQLString,
1819
)
19-
from graphql.utilities import value_from_ast_untyped
20+
from graphql.utilities import build_schema, value_from_ast_untyped
2021

2122
from gql import GraphQLRequest
2223

@@ -206,6 +207,82 @@ def test_serialize_variables_using_money_example():
206207
assert req.variable_values == {"money": {"amount": 10, "currency": "DM"}}
207208

208209

210+
def test_serialize_variables_single_value_for_list_type():
211+
# A value which is not a list, provided for a list type, should be
212+
# coerced into a list of one instead of being iterated over.
213+
list_schema = build_schema("type Query {f(ids: [String!], ns: [Int]): String}")
214+
215+
req = GraphQLRequest(
216+
"query q($ids: [String!], $ns: [Int]) {f(ids: $ids, ns: $ns)}",
217+
variable_values={"ids": "abc", "ns": 5},
218+
)
219+
220+
req = req.serialize_variable_values(list_schema)
221+
222+
assert req.variable_values == {"ids": ["abc"], "ns": [5]}
223+
224+
225+
def test_serialize_variables_mapping_as_singleton_input_object():
226+
schema = build_schema(
227+
"input ItemInput { name: String } type Query { f(items: [ItemInput]): String }"
228+
)
229+
req = GraphQLRequest(
230+
"query q($items: [ItemInput]) { f(items: $items) }",
231+
variable_values={"items": {"name": "abc"}},
232+
)
233+
req = req.serialize_variable_values(schema)
234+
assert req.variable_values == {"items": [{"name": "abc"}]}
235+
236+
237+
def test_serialize_variables_recursive_list_coercion():
238+
schema = build_schema("type Query { f(values: [[Int]]): String }")
239+
240+
req1 = GraphQLRequest(
241+
"query q($values: [[Int]]) { f(values: $values) }",
242+
variable_values={"values": 1},
243+
)
244+
req1 = req1.serialize_variable_values(schema)
245+
assert req1.variable_values == {"values": [[1]]}
246+
247+
req2 = GraphQLRequest(
248+
"query q($values: [[Int]]) { f(values: $values) }",
249+
variable_values={"values": [1, 2]},
250+
)
251+
req2 = req2.serialize_variable_values(schema)
252+
assert req2.variable_values == {"values": [[1], [2]]}
253+
254+
255+
def test_serialize_variables_collection_behavior():
256+
schema = build_schema("type Query { f(values: [Int]): String }")
257+
req = GraphQLRequest(
258+
"query q($values: [Int]) { f(values: $values) }",
259+
variable_values={"values": (1, 2)},
260+
)
261+
req = req.serialize_variable_values(schema)
262+
assert req.variable_values == {"values": [1, 2]}
263+
264+
265+
def test_serialize_variables_bytes_behavior():
266+
bytes_scalar = GraphQLScalarType(name="Bytes", serialize=lambda v: v)
267+
schema = GraphQLSchema(
268+
query=GraphQLObjectType(
269+
"Query",
270+
fields={
271+
"f": GraphQLField(
272+
GraphQLString,
273+
args={"values": GraphQLArgument(GraphQLList(bytes_scalar))},
274+
)
275+
},
276+
)
277+
)
278+
req = GraphQLRequest(
279+
"query q($values: [Bytes]) { f(values: $values) }",
280+
variable_values={"values": b"abc"},
281+
)
282+
req = req.serialize_variable_values(schema)
283+
assert req.variable_values == {"values": [b"abc"]}
284+
285+
209286
def test_graphql_request_using_string_instead_of_document():
210287
request = GraphQLRequest("{balance}")
211288

0 commit comments

Comments
 (0)