Skip to content

Commit 174a0bb

Browse files
committed
Syntax for object type arguments.
1 parent d5dd1eb commit 174a0bb

File tree

7 files changed

+137
-20
lines changed

7 files changed

+137
-20
lines changed
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
from graphql.core.type import GraphQLArgument, GraphQLInt, GraphQLString
1+
from graphql.core.type import GraphQLInt, GraphQLString
2+
3+
from ....argument import Argument
24

35
__author__ = 'jake'
46

57
connection_args = {
6-
'before': GraphQLArgument(GraphQLString),
7-
'after': GraphQLArgument(GraphQLString),
8-
'first': GraphQLArgument(GraphQLInt),
9-
'last': GraphQLArgument(GraphQLInt),
8+
'before': Argument(GraphQLString),
9+
'after': Argument(GraphQLString),
10+
'first': Argument(GraphQLInt),
11+
'last': Argument(GraphQLInt),
1012
}

epoxy/contrib/relay/mixin.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from graphql.core.type import GraphQLArgument
21
from graphql.core.type.definition import GraphQLObjectType
32
import six
43
from ...bases.mutation import MutationBase
@@ -21,10 +20,7 @@ def NodeField(self):
2120
self.R.Node,
2221
description='Fetches an object given its ID',
2322
args={
24-
'id': GraphQLArgument(
25-
self.R.ID.NonNull(),
26-
description='The ID of an object'
27-
)
23+
'id': self.R.ID.NonNull(description='The ID of an object')
2824
},
2925
resolver=lambda obj, args, info: self.fetch_node(args.get('id'), info)
3026
)

epoxy/field.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
from collections import OrderedDict
2+
13
from graphql.core.type import GraphQLField, GraphQLInputObjectField
4+
5+
from .argument import Argument
6+
from .thunk import TypeThunk
27
from .utils.gen_id import gen_id
8+
from .utils.to_camel_case import to_camel_case
39

410

511
class Field(object):
@@ -14,7 +20,31 @@ def __init__(self, type, description=None, args=None, name=None, resolver=None,
1420
self._counter = _counter or gen_id()
1521

1622
def to_field(self, registry, resolver):
17-
return GraphQLField(registry[self.type](), args=self.args, resolver=resolver)
23+
return GraphQLField(registry[self.type](), args=self.get_arguments(registry), resolver=resolver)
24+
25+
def get_arguments(self, registry):
26+
if not self.args:
27+
return None
28+
29+
arguments = []
30+
31+
for k, argument in self.args.items():
32+
if isinstance(argument, TypeThunk):
33+
argument = Argument(argument, _counter=argument._counter, **(argument._kwargs or {}))
34+
35+
elif not isinstance(argument, Argument):
36+
raise ValueError('Unknown argument value type %r' % argument)
37+
38+
arguments.append((
39+
to_camel_case(k), argument
40+
))
41+
42+
if not isinstance(self.args, OrderedDict):
43+
arguments.sort(
44+
key=lambda i: i[1]._counter
45+
)
46+
47+
return OrderedDict([(k, v.to_argument(registry)) for k, v in arguments])
1848

1949

2050
class InputField(object):

epoxy/registry.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,13 @@ class TypeRegistry(object):
5858
InputField = InputField
5959

6060
def __init__(self):
61-
self._registered_types = {}
61+
self._registered_types = OrderedDict()
6262
self._added_impl_types = set()
6363
self._interface_declared_fields = {}
6464
self._registered_types_can_be = defaultdict(set)
6565
self._pending_types_can_be = defaultdict(set)
6666
self._proxy = ResolvedRegistryProxy(self)
67-
self._mutations = {}
67+
self._mutations = OrderedDict()
6868
self.ObjectType = self._create_object_type_class()
6969
self.InputType = self._create_input_type_class()
7070
self.Implements = ClassTypeCreator(self, self._create_object_type_class)

tests/test_arguments.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
from collections import OrderedDict
2+
from graphql.core.type import GraphQLString, GraphQLInt, GraphQLID, GraphQLNonNull
3+
from epoxy.argument import Argument
4+
from epoxy.registry import TypeRegistry
5+
6+
make_args = lambda R: {
7+
'a': R.Int,
8+
'b_cool': R.String,
9+
'c': R.ID.NonNull,
10+
'd': Argument(R.String, default_value="hello world"),
11+
'z': R.String(default_value="hello again", description="This is a description"),
12+
'x': R.Int(default_value=7),
13+
'y': Argument(GraphQLString),
14+
'q': R.TestInputType,
15+
'w': Argument(R.TestInputType)
16+
}
17+
18+
make_ordered_dict_args = lambda R: OrderedDict([
19+
('a', R.Int),
20+
('b_cool', R.String),
21+
('c', R.ID.NonNull),
22+
('d', Argument(R.String, default_value="hello world")),
23+
('z', R.String(default_value="hello again", description="This is a description")),
24+
('x', R.Int(default_value=7)),
25+
('y', Argument(GraphQLString)),
26+
('q', R.TestInputType),
27+
('w', Argument(R.TestInputType)),
28+
])
29+
30+
31+
def check_args(test_input_type, args):
32+
expected_keys = ['a', 'bCool', 'c', 'd', 'z', 'x', 'y', 'q', 'w']
33+
keys = [a.name for a in args]
34+
35+
assert keys == expected_keys
36+
37+
a, b, c, d, z, x, y, q, w = args
38+
39+
assert a.type is GraphQLInt
40+
assert b.type is GraphQLString
41+
assert isinstance(c.type, GraphQLNonNull)
42+
assert c.type.of_type is GraphQLID
43+
assert d.type is GraphQLString
44+
assert d.default_value == "hello world"
45+
assert z.type is GraphQLString
46+
assert z.default_value == "hello again"
47+
assert z.description == "This is a description"
48+
assert x.type is GraphQLInt
49+
assert x.default_value == 7
50+
assert y.type is GraphQLString
51+
assert q.type is test_input_type
52+
assert w.type is test_input_type
53+
54+
55+
def test_args_will_magically_order():
56+
R = TypeRegistry()
57+
58+
class TestInputType(R.InputType):
59+
a = R.Int
60+
b = R.Int
61+
62+
class Query(R.ObjectType):
63+
int = R.Int(
64+
args=make_args(R)
65+
)
66+
int_from_field = R.Field(R.Int, args=make_args(R))
67+
68+
query_type = R.Query()
69+
check_args(TestInputType.T, query_type.get_fields()['int'].args)
70+
check_args(TestInputType.T, query_type.get_fields()['intFromField'].args)
71+
72+
73+
def test_args_can_also_use_ordered_dict():
74+
R = TypeRegistry()
75+
76+
class TestInputType(R.InputType):
77+
a = R.Int
78+
b = R.Int
79+
80+
class Query(R.ObjectType):
81+
int = R.Int(
82+
args=make_ordered_dict_args(R)
83+
)
84+
int_from_field = R.Field(R.Int, args=make_ordered_dict_args(R))
85+
86+
query_type = R.Query()
87+
check_args(TestInputType.T, query_type.get_fields()['int'].args)
88+
check_args(TestInputType.T, query_type.get_fields()['intFromField'].args)

tests/test_input_type.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class SimpleInput(R.InputType):
4646

4747
class Query(R.ObjectType):
4848
f = R.String(args={
49-
'input': GraphQLArgument(R.SimpleInput())
49+
'input': R.SimpleInput
5050
})
5151

5252
def resolve_f(self, obj, args, info):

tests/test_starwars/schema.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def resolve_friends(self, obj, args, info):
2222
from .data import get_friends
2323
return get_friends(obj)
2424

25+
2526
class Human(R.Implements.Character):
2627
home_planet = R.String
2728

@@ -32,16 +33,16 @@ class Droid(R.Implements.Character):
3233

3334
class Query(R.ObjectType):
3435
# Args API will change.
35-
hero = R.Field(R.Character, args={
36-
'episode': GraphQLArgument(R.Episode())
36+
hero = R.Character(args={
37+
'episode': R.Episode
3738
})
3839

39-
human = R.Field(R.Human, args={
40-
'id': GraphQLArgument(R.String())
40+
human = R.Human(args={
41+
'id': R.String
4142
})
4243

43-
droid = R.Field(R.Droid, args={
44-
'id': GraphQLArgument(R.String())
44+
droid = R.Droid(args={
45+
'id': R.String
4546
})
4647

4748
def resolve_hero(self, obj, args, info):

0 commit comments

Comments
 (0)