Skip to content

Commit 41648b5

Browse files
committed
Improved relay integration
1 parent 28d89a4 commit 41648b5

File tree

6 files changed

+59
-53
lines changed

6 files changed

+59
-53
lines changed

graphene/core/types/field.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ def __init__(self, type, description=None, args=None, name=None, resolver=None,
2121
self.name = name
2222
if isinstance(type, six.string_types):
2323
type = LazyType(type)
24-
if required:
24+
self.required = required
25+
if self.required:
2526
type = NonNull(type)
2627
self.type = type
2728
self.description = description
@@ -68,7 +69,7 @@ def internal_type(self, schema):
6869
type_objecttype = schema.objecttype(type)
6970
if type_objecttype and type_objecttype._meta.is_mutation:
7071
assert len(arguments) == 0
71-
arguments = type_objecttype.arguments
72+
arguments = type_objecttype.get_arguments()
7273
resolver = getattr(type_objecttype, 'mutate')
7374

7475
assert type, 'Internal type for field %s is None' % str(self)

graphene/core/types/objecttype.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,6 @@ def __new__(cls, name, bases, attrs):
5252
assert not (
5353
new_class._meta.is_interface and new_class._meta.is_mutation)
5454

55-
input_class = None
56-
if new_class._meta.is_mutation:
57-
input_class = attrs.pop('Input', None)
58-
5955
# Add all attributes to the class.
6056
for obj_name, obj in attrs.items():
6157
new_class.add_to_class(obj_name, obj)
@@ -64,14 +60,6 @@ def __new__(cls, name, bases, attrs):
6460
assert hasattr(
6561
new_class, 'mutate'), "All mutations must implement mutate method"
6662

67-
if input_class:
68-
items = dict(input_class.__dict__)
69-
items.pop('__dict__', None)
70-
items.pop('__doc__', None)
71-
items.pop('__module__', None)
72-
arguments = ArgumentsGroup(**items)
73-
new_class.add_to_class('arguments', arguments)
74-
7563
new_class.add_extra_fields()
7664

7765
new_fields = new_class._meta.local_fields
@@ -215,7 +203,21 @@ class ObjectType(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
215203

216204

217205
class Mutation(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
218-
pass
206+
@classmethod
207+
def _prepare_class(cls):
208+
input_class = getattr(cls, 'Input', None)
209+
if input_class:
210+
items = dict(input_class.__dict__)
211+
items.pop('__dict__', None)
212+
items.pop('__doc__', None)
213+
items.pop('__module__', None)
214+
arguments = ArgumentsGroup(**items)
215+
cls.add_to_class('arguments', arguments)
216+
delattr(cls, 'Input')
217+
218+
@classmethod
219+
def get_arguments(cls):
220+
return cls.arguments
219221

220222

221223
class InputObjectType(ObjectType):

graphene/relay/fields.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
from collections import Iterable
22

33
from graphene.core.fields import Field, IDField
4+
from graphene.core.types.scalars import String, ID
45
from graphql.core.type import GraphQLArgument, GraphQLID, GraphQLNonNull
56
from graphql_relay.connection.arrayconnection import connection_from_list
6-
from graphql_relay.connection.connection import connection_args
77
from graphql_relay.node.node import from_global_id
88

99

1010
class ConnectionField(Field):
1111

12-
def __init__(self, field_type, resolve=None, description='',
12+
def __init__(self, field_type, resolver=None, description='',
1313
connection_type=None, edge_type=None, **kwargs):
14-
super(ConnectionField, self).__init__(field_type, resolve=resolve,
15-
args=connection_args,
14+
super(ConnectionField, self).__init__(field_type, resolver=resolver,
15+
before=String(),
16+
after=String(),
17+
first=String(),
18+
last=String(),
1619
description=description, **kwargs)
1720
self.connection_type = connection_type
1821
self.edge_type = edge_type
@@ -60,12 +63,9 @@ class NodeField(Field):
6063

6164
def __init__(self, object_type=None, *args, **kwargs):
6265
from graphene.relay.types import Node
66+
kwargs['id'] = ID(description='The ID of an object')
6367
super(NodeField, self).__init__(object_type or Node, *args, **kwargs)
6468
self.field_object_type = object_type
65-
self.args['id'] = GraphQLArgument(
66-
GraphQLNonNull(GraphQLID),
67-
description='The ID of an object'
68-
)
6969

7070
def id_fetcher(self, global_id, info):
7171
from graphene.relay.utils import is_node
@@ -88,11 +88,11 @@ class GlobalIDField(IDField):
8888
'''The ID of an object'''
8989
required = True
9090

91-
def contribute_to_class(self, cls, name, add=True):
91+
def contribute_to_class(self, cls, name):
9292
from graphene.relay.utils import is_node, is_node_type
9393
in_node = is_node(cls) or is_node_type(cls)
9494
assert in_node, 'GlobalIDField could only be inside a Node, but got %r' % cls
95-
super(GlobalIDField, self).contribute_to_class(cls, name, add)
95+
super(GlobalIDField, self).contribute_to_class(cls, name)
9696

9797
def resolve(self, instance, args, info):
9898
return self.object_type.to_global_id(instance, args, info)

graphene/relay/types.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from graphene.core.fields import BooleanField, Field, ListField, StringField
22
from graphene.core.types import (InputObjectType, Interface, Mutation,
33
ObjectType)
4+
from graphene.core.types.argument import ArgumentsGroup
5+
from graphene.core.types.definitions import NonNull
46
from graphene.relay.fields import GlobalIDField
57
from graphene.utils import memoize
68
from graphql_relay.node.node import to_global_id
@@ -90,7 +92,7 @@ def get_edge_type(cls):
9092

9193
class Node(BaseNode, Interface):
9294
'''An object with an ID'''
93-
id = GlobalIDField()
95+
id = GlobalIDField(required=True)
9496

9597

9698
class MutationInputType(InputObjectType):
@@ -102,19 +104,19 @@ class ClientIDMutation(Mutation):
102104

103105
@classmethod
104106
def _prepare_class(cls):
105-
input_type = getattr(cls, 'input_type', None)
106-
if input_type:
107+
Input = getattr(cls, 'Input', None)
108+
if Input:
107109
assert hasattr(
108110
cls, 'mutate_and_get_payload'), 'You have to implement mutate_and_get_payload'
109-
new_input_inner_type = type('{}InnerInput'.format(
110-
cls._meta.type_name), (MutationInputType, input_type, ), {})
111-
items = {
112-
'input': Field(new_input_inner_type)
113-
}
114-
assert issubclass(new_input_inner_type, InputObjectType)
115-
input_type = type('{}Input'.format(
116-
cls._meta.type_name), (ObjectType, ), items)
117-
setattr(cls, 'input_type', input_type)
111+
112+
items = dict(Input.__dict__)
113+
items.pop('__dict__', None)
114+
new_input_type = type('{}Input'.format(
115+
cls._meta.type_name), (MutationInputType, ), items)
116+
cls.add_to_class('input_type', new_input_type)
117+
arguments = ArgumentsGroup(input=NonNull(new_input_type))
118+
cls.add_to_class('arguments', arguments)
119+
delattr(cls, 'Input')
118120

119121
@classmethod
120122
def mutate(cls, instance, args, info):

tests/relay/test_relay_mutations.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,19 @@ class MyResultMutation(graphene.ObjectType):
3232
schema = Schema(query=Query, mutation=MyResultMutation)
3333

3434

35-
def test_mutation_input():
36-
assert ChangeNumber.input_type
37-
assert ChangeNumber.input_type._meta.type_name == 'ChangeNumberInput'
38-
assert list(ChangeNumber.input_type._meta.fields_map.keys()) == ['input']
39-
_input = ChangeNumber.input_type._meta.fields_map['input']
40-
inner_type = _input.get_object_type(schema)
41-
client_mutation_id_field = inner_type._meta.fields_map[
42-
'client_mutation_id']
43-
assert issubclass(inner_type, InputObjectType)
44-
assert isinstance(client_mutation_id_field, graphene.StringField)
45-
assert client_mutation_id_field.object_type == inner_type
46-
assert isinstance(client_mutation_id_field.internal_field(
47-
schema), GraphQLInputObjectField)
35+
def test_mutation_arguments():
36+
assert ChangeNumber.arguments
37+
assert list(ChangeNumber.arguments) == ['input']
38+
_input = ChangeNumber.arguments['input']
39+
40+
# inner_type = _input.get_object_type(schema)
41+
# client_mutation_id_field = inner_type._meta.fields_map[
42+
# 'client_mutation_id']
43+
# assert issubclass(inner_type, InputObjectType)
44+
# assert isinstance(client_mutation_id_field, graphene.StringField)
45+
# assert client_mutation_id_field.object_type == inner_type
46+
# assert isinstance(client_mutation_id_field.internal_field(
47+
# schema), GraphQLInputObjectField)
4848

4949

5050
def test_execute_mutations():

tests/relay/test_relayfields.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def get_node(cls, id):
2121
class Query(graphene.ObjectType):
2222
my_node = relay.NodeField(MyNode)
2323
all_my_nodes = relay.ConnectionField(
24-
MyNode, connection_type=MyConnection, customArg=graphene.Argument(graphene.String))
24+
MyNode, connection_type=MyConnection, customArg=graphene.String())
2525

2626
def resolve_all_my_nodes(self, args, info):
2727
custom_arg = args.get('customArg')
@@ -73,5 +73,6 @@ def test_nodefield_query():
7373

7474
def test_nodeidfield():
7575
id_field = MyNode._meta.fields_map['id']
76-
assert isinstance(id_field.internal_field(schema).type, GraphQLNonNull)
77-
assert id_field.internal_field(schema).type.of_type == GraphQLID
76+
id_field_type = schema.T(id_field)
77+
assert isinstance(id_field_type.type, GraphQLNonNull)
78+
assert id_field_type.type.of_type == GraphQLID

0 commit comments

Comments
 (0)