Skip to content

Commit 2f1078c

Browse files
committed
Bring mutation subpackage up to date
1 parent 38cdb53 commit 2f1078c

File tree

12 files changed

+523
-368
lines changed

12 files changed

+523
-368
lines changed

src/graphql_relay/connection/connection.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1+
from typing import Any
2+
13
from graphql.type import (
24
GraphQLArgument,
35
GraphQLBoolean,
6+
GraphQLField,
47
GraphQLInt,
5-
GraphQLNonNull,
68
GraphQLList,
9+
GraphQLNonNull,
710
GraphQLObjectType,
811
GraphQLString,
9-
GraphQLField
12+
Thunk
1013
)
11-
from ..utils import resolve_maybe_thunk
12-
1314

1415
connection_args = {
1516
'before': GraphQLArgument(GraphQLString),
@@ -19,6 +20,10 @@
1920
}
2021

2122

23+
def resolve_maybe_thunk(thing_or_thunk: Thunk) -> Any:
24+
return thing_or_thunk() if callable(thing_or_thunk) else thing_or_thunk
25+
26+
2227
def connection_definitions(
2328
name, node_type,
2429
resolve_node=None, resolve_cursor=None,
Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,76 @@
11
from inspect import isawaitable
2+
from typing import Any, Callable, Dict
23

4+
from graphql.error import GraphQLError
5+
from graphql.pyutils import AwaitableOrValue, inspect
36
from graphql.type import (
47
GraphQLArgument,
8+
GraphQLField,
9+
GraphQLFieldMap,
510
GraphQLInputField,
11+
GraphQLInputFieldMap,
612
GraphQLInputObjectType,
713
GraphQLNonNull,
814
GraphQLObjectType,
15+
GraphQLResolveInfo,
916
GraphQLString,
10-
GraphQLField,
17+
Thunk
1118
)
12-
from graphql.error import GraphQLError
13-
from graphql.pyutils import inspect
1419

15-
from ..utils import resolve_maybe_thunk
20+
MutationFn = Callable[[Dict[str, Any], GraphQLResolveInfo], AwaitableOrValue[Any]]
21+
22+
23+
def resolve_maybe_thunk(thing_or_thunk: Thunk) -> Any:
24+
return thing_or_thunk() if callable(thing_or_thunk) else thing_or_thunk
1625

1726

1827
def mutation_with_client_mutation_id(
19-
name, input_fields, output_fields, mutate_and_get_payload):
20-
augmented_input_fields = dict(
21-
resolve_maybe_thunk(input_fields),
22-
clientMutationId=GraphQLInputField(
23-
GraphQLNonNull(GraphQLString)))
24-
augmented_output_fields = dict(
25-
resolve_maybe_thunk(output_fields),
26-
clientMutationId=GraphQLField(
27-
GraphQLNonNull(GraphQLString)))
28-
input_type = GraphQLInputObjectType(
29-
name + 'Input',
30-
fields=augmented_input_fields)
28+
name: str,
29+
input_fields: Thunk[GraphQLInputFieldMap],
30+
output_fields: Thunk[GraphQLFieldMap],
31+
mutate_and_get_payload: MutationFn,
32+
description: str = None,
33+
deprecation_reason: str = None) -> GraphQLField:
34+
"""
35+
Returns a GraphQLFieldConfig for the specified mutation.
36+
37+
The input_fields and output_fields should not include `clientMutationId`,
38+
as this will be provided automatically.
39+
40+
An input object will be created containing the input fields, and an
41+
object will be created containing the output fields.
42+
43+
mutate_and_get_payload will receive a dict with a key for each input field,
44+
and it should return an object (or a dict) with an attribute (or a key)
45+
for each output field. It may return synchronously or asynchronously.
46+
"""
47+
def augmented_input_fields() -> GraphQLInputFieldMap:
48+
return dict(
49+
resolve_maybe_thunk(input_fields),
50+
clientMutationId=GraphQLInputField(
51+
GraphQLNonNull(GraphQLString)))
52+
53+
def augmented_output_fields() -> GraphQLFieldMap:
54+
return dict(
55+
resolve_maybe_thunk(output_fields),
56+
clientMutationId=GraphQLField(
57+
GraphQLNonNull(GraphQLString)))
58+
3159
output_type = GraphQLObjectType(
3260
name + 'Payload',
3361
fields=augmented_output_fields)
3462

35-
async def resolve(_root, info, **args):
36-
input_ = args.get('input') or {}
37-
payload = mutate_and_get_payload(info, **input_)
63+
input_type = GraphQLInputObjectType(
64+
name + 'Input',
65+
fields=augmented_input_fields)
66+
67+
# noinspection PyShadowingBuiltins
68+
async def resolve(_root, info, input):
69+
payload = mutate_and_get_payload(input, info)
3870
if isawaitable(payload):
3971
payload = await payload
4072
try:
41-
payload.clientMutationId = input_['clientMutationId']
73+
payload.clientMutationId = input['clientMutationId']
4274
except KeyError:
4375
raise GraphQLError(
4476
'Cannot set clientMutationId'
@@ -47,5 +79,7 @@ async def resolve(_root, info, **args):
4779

4880
return GraphQLField(
4981
output_type,
82+
description=description,
83+
deprecation_reason=deprecation_reason,
5084
args={'input': GraphQLArgument(GraphQLNonNull(input_type))},
5185
resolve=resolve)

src/graphql_relay/utils/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
11
"""graphql_relay.utils"""
2-
3-
4-
def resolve_maybe_thunk(f): # TODO: do we need that?
5-
return f() if callable(f) else f

tests/connection/test_connection.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from pytest import mark
1+
from pytest import mark # type: ignore
22

33
from collections import namedtuple
44

0 commit comments

Comments
 (0)