Skip to content

Commit 190c858

Browse files
committed
Bugfixes to interface field resolver resolution
Implement starwars tests from graphql-core. Rename `register` to `Regsiter`.
1 parent 3c2b282 commit 190c858

File tree

8 files changed

+504
-15
lines changed

8 files changed

+504
-15
lines changed

epoxy/bases/object_type.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ def __init__(self, **kwargs):
2727
))
2828

2929
def __repr__(self):
30+
if self._field_attr_map is None:
31+
return '<{}>'.format(self.T)
32+
3033
return '<{} {}>'.format(
3134
self.T,
3235
' '.join('{}={!r}'.format(field_name, getattr(self, field_name))

epoxy/field.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ def __init__(self, type, description=None, args=None, name=None, resolver=None,
1414
self._counter = _counter or gen_id()
1515

1616
def to_field(self, registry, resolver):
17-
return GraphQLField(registry[self.type](), self.args, resolver)
17+
return GraphQLField(registry[self.type](), args=self.args, resolver=resolver)

epoxy/metaclasses/object_type.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def _build_field_map(class_ref, declared_fields):
5858
known_interface_resolvers = {}
5959

6060
for interface in interfaces:
61+
interface.get_fields() # This triggers the interface to resolve the field thunks.
6162
fields += registry._get_interface_declared_fields(interface)
6263

6364
for field_attr_name, field in fields:

epoxy/registry.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,26 +53,27 @@ def __init__(self):
5353
self.Interface = self._create_interface_type_class()
5454

5555
for type in builtin_scalars:
56-
self.register(type)
56+
self.Register(type)
5757

5858
@method_dispatch
59-
def register(self, t):
59+
def Register(self, t):
6060
# Can't use dispatch, as it's not an instance, but a subclass of.
6161
if issubclass(t, Enum):
62-
return self.register(enum_to_graphql_enum(t))
62+
self.Register(enum_to_graphql_enum(t))
63+
return t
6364

6465
raise NotImplementedError('Unable to register {}.'.format(t))
6566

66-
@register.register(GraphQLObjectType)
67-
@register.register(GraphQLUnionType)
68-
@register.register(GraphQLEnumType)
69-
@register.register(GraphQLInterfaceType)
70-
@register.register(GraphQLInputObjectType)
71-
@register.register(GraphQLScalarType)
67+
@Register.register(GraphQLObjectType)
68+
@Register.register(GraphQLUnionType)
69+
@Register.register(GraphQLEnumType)
70+
@Register.register(GraphQLInterfaceType)
71+
@Register.register(GraphQLInputObjectType)
72+
@Register.register(GraphQLScalarType)
7273
def register_(self, t):
7374
assert not t.name.startswith('_'), \
7475
'Registered type name cannot start with an "_".'
75-
assert t.name not in ('ObjectType', 'Implements', 'Interface', 'Schema'), \
76+
assert t.name not in ('ObjectType', 'Implements', 'Interface', 'Schema', 'Register'), \
7677
'You cannot register a type named "{}".'.format(type.name)
7778
assert t.name not in self._registered_types, \
7879
'There is already a registered type named "{}".'.format(type.name)
@@ -105,15 +106,15 @@ def __getitem__(self, item):
105106
return RootTypeThunk(self, self._resolve_type, item)
106107

107108
def __call__(self, t):
108-
return self.register(t)
109+
return self.Register(t)
109110

110111
def _create_object_type_class(self, interface_thunk=None):
111112
registry = self
112113

113114
class RegistryObjectTypeMeta(ObjectTypeMeta):
114115
@staticmethod
115116
def _register(object_type, type_class):
116-
registry.register(object_type)
117+
registry.Register(object_type)
117118
registry._registered_types_can_be[object_type].add(type_class)
118119

119120
@staticmethod
@@ -139,7 +140,7 @@ def _create_interface_type_class(self):
139140
class RegistryInterfaceMeta(InterfaceMeta):
140141
@staticmethod
141142
def _register(interface, declared_fields):
142-
registry.register(interface)
143+
registry.Register(interface)
143144
registry._add_interface_declared_fields(interface, declared_fields)
144145

145146
@staticmethod
@@ -157,7 +158,7 @@ def _create_union_type_class(self, types_thunk):
157158
class RegistryUnionMeta(UnionMeta):
158159
@staticmethod
159160
def _register(union):
160-
registry.register(union)
161+
registry.Register(union)
161162

162163
@staticmethod
163164
def _get_registry():

tests/test_starwars/__init__.py

Whitespace-only changes.

tests/test_starwars/data.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from .schema import Human, Droid, Episode
2+
3+
luke = Human(
4+
id='1000',
5+
name='Luke Skywalker',
6+
friends=['1002', '1003', '2000', '2001'],
7+
appears_in=[4, 5, 6],
8+
home_planet='Tatooine'
9+
)
10+
11+
vader = Human(
12+
id='1001',
13+
name='Darth Vader',
14+
friends=['1004'],
15+
appears_in=[4, 5, 6],
16+
home_planet=['Tatooine']
17+
)
18+
19+
han = Human(
20+
id='1002',
21+
name='Han Solo',
22+
friends=['1000', '1003', '2001'],
23+
appears_in=[4, 5, 6]
24+
)
25+
26+
leia = Human(
27+
id='1003',
28+
name='Leia Organa',
29+
friends=['1000', '1002', '2000', '2001'],
30+
appears_in=[4, 5, 6],
31+
home_planet='Alderaan'
32+
)
33+
34+
tarkin = Human(
35+
id='1004',
36+
name='Wilhuff Tarkin',
37+
friends=['1001'],
38+
appears_in=[4]
39+
)
40+
41+
humans = {i.id: i for i in (luke, vader, han, leia, tarkin)}
42+
43+
threepio = Droid(
44+
id='2000',
45+
name='C-3PO',
46+
friends=['1000', '1002', '1003', '2001'],
47+
appears_in=[4, 5, 6],
48+
primary_function='Protocol'
49+
)
50+
51+
artoo = Droid(
52+
id='2001',
53+
name='R2-D2',
54+
friends=['1000', '1002', '1003'],
55+
appears_in=[4, 5, 6],
56+
primary_function='Astromech'
57+
)
58+
59+
droids = {i.id: i for i in (threepio, artoo)}
60+
61+
62+
def get_character(id):
63+
return humans.get(id) or droids.get(id)
64+
65+
66+
def get_hero(episode):
67+
if episode == 5:
68+
return luke
69+
70+
return artoo
71+
72+
73+
get_human = humans.get
74+
get_droid = droids.get
75+
76+
77+
def get_friends(character):
78+
return [get_character(id) for id in character.friends]

tests/test_starwars/schema.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from graphql.core.type.definition import GraphQLArgument
2+
from epoxy.registry import TypeRegistry
3+
import enum
4+
5+
R = TypeRegistry()
6+
7+
8+
@R.Register
9+
class Episode(enum.Enum):
10+
NEWHOPE = 4
11+
EMPIRE = 5
12+
JEDI = 6
13+
14+
15+
class Character(R.Interface):
16+
id = R.String.NonNull
17+
name = R.String
18+
friends = R.Character.List
19+
appears_in = R.Episode.List
20+
21+
def resolve_friends(self, obj, args, info):
22+
from .data import get_friends
23+
return get_friends(obj)
24+
25+
class Human(R.Implements.Character):
26+
home_planet = R.String
27+
28+
29+
class Droid(R.Implements.Character):
30+
primary_function = R.String
31+
32+
33+
class Query(R.ObjectType):
34+
# Args API will change.
35+
hero = R.Field(R.Character, args={
36+
'episode': GraphQLArgument(R.Episode())
37+
})
38+
39+
human = R.Field(R.Human, args={
40+
'id': GraphQLArgument(R.String())
41+
})
42+
43+
droid = R.Field(R.Droid, args={
44+
'id': GraphQLArgument(R.String())
45+
})
46+
47+
def resolve_hero(self, obj, args, info):
48+
from .data import get_hero
49+
return get_hero(args.get('episode'))
50+
51+
def resolve_human(self, obj, args, info):
52+
from .data import get_human
53+
return get_human(args['id'])
54+
55+
def resolve_droid(self, obj, args, info):
56+
from .data import get_droid
57+
return get_droid(args['id'])
58+
59+
60+
StarWarsSchema = R.Schema(R.Query)

0 commit comments

Comments
 (0)