Skip to content

Commit 8421b59

Browse files
committed
Improved resolver logic middleware by using promises
1 parent 25fd60d commit 8421b59

File tree

7 files changed

+39
-43
lines changed

7 files changed

+39
-43
lines changed

graphene/core/schema.py

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,11 @@
88
from graphene import signals
99

1010
from ..plugins import CamelCase, PluginManager
11+
from ..utils import promise_middleware
1112
from .classtypes.base import ClassType
1213
from .types.base import InstanceType
1314

1415

15-
class ACI(object):
16-
def __init__(self, args, context, info):
17-
self.args = args
18-
self.context = context
19-
self.info = info
20-
21-
def __repr__(self):
22-
return "ACI(args={}, context={}, info={})".format(repr(self.args), repr(self.context), repr(self.info))
23-
24-
2516
class GraphQLSchema(_GraphQLSchema):
2617

2718
def __init__(self, schema, *args, **kwargs):
@@ -121,25 +112,9 @@ def get_type(self, type_name):
121112
raise KeyError('Type %r not found in %r' % (type_name, self))
122113
return self._types_names[type_name]
123114

124-
def resolve(self, resolver, root, args, context, info):
125-
aci = ACI(args, context, info)
126-
plugins_process_aci = self.plugins.get_plugin_functions('process_aci')
127-
plugins_process_response = self.plugins.get_plugin_functions('process_response')
128-
for process_aci in plugins_process_aci:
129-
processed_aci = process_aci(aci)
130-
if processed_aci is None:
131-
continue
132-
return processed_aci
133-
134-
response = resolver(root, aci.args, aci.context, aci.info)
135-
136-
for process_response in plugins_process_response:
137-
processed_response = process_response(response, aci)
138-
if processed_response is None:
139-
continue
140-
return processed_response
141-
142-
return response
115+
def resolver_with_middleware(self, resolver):
116+
plugins_resolve = self.plugins.get_plugin_functions('resolve')
117+
return promise_middleware(resolver, plugins_resolve)
143118

144119
@property
145120
def types(self):

graphene/core/tests/test_old_fields.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ def test_field_resolve():
9393
f = StringField(required=True, resolve=lambda *args: 'RESOLVED').as_field()
9494
f.contribute_to_class(MyOt, 'field_name')
9595
field_type = schema.T(f)
96-
assert 'RESOLVED' == field_type.resolver(MyOt, None, None, None)
96+
assert 'RESOLVED' == field_type.resolver(MyOt, None, None, None).value
9797

9898

9999
def test_field_resolve_type_custom():

graphene/core/types/field.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,13 @@ def wrapped_func(instance, args, context, info):
115115
resolver = wrapped_func
116116

117117
assert type, 'Internal type for field %s is None' % str(self)
118-
return GraphQLField(type, args=schema.T(arguments),
119-
resolver=partial(schema.resolve, resolver),
120-
deprecation_reason=self.deprecation_reason,
121-
description=description,)
118+
return GraphQLField(
119+
type,
120+
args=schema.T(arguments),
121+
resolver=schema.resolver_with_middleware(resolver),
122+
deprecation_reason=self.deprecation_reason,
123+
description=description,
124+
)
122125

123126
def __repr__(self):
124127
"""
@@ -172,7 +175,8 @@ def contribute_to_class(self, cls, attname):
172175
def internal_type(self, schema):
173176
return GraphQLInputObjectField(
174177
schema.T(self.type),
175-
default_value=self.default, description=self.description)
178+
default_value=self.default, description=self.description
179+
)
176180

177181

178182
class FieldsGroupType(GroupNamedType):

graphene/core/types/tests/test_field.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class Query(ObjectType):
2424
assert field.attname == 'my_field'
2525
assert isinstance(type, GraphQLField)
2626
assert type.description == 'My argument'
27-
assert type.resolver(None, {}, None, None) == 'RESOLVED'
27+
assert type.resolver(None, {}, None, None).value == 'RESOLVED'
2828
assert type.type == GraphQLString
2929

3030

@@ -43,7 +43,7 @@ def resolve_my_field(self, *args, **kwargs):
4343
type = schema.T(field)
4444
assert isinstance(type, GraphQLField)
4545
assert type.description == 'Custom description'
46-
assert type.resolver(Query(), {}, None, None) == 'RESOLVED'
46+
assert type.resolver(Query(), {}, None, None).value == 'RESOLVED'
4747

4848

4949
def test_field_custom_name():
@@ -161,7 +161,7 @@ class Query(ObjectType):
161161
schema = Schema(query=Query)
162162

163163
type = schema.T(field)
164-
assert type.resolver(None, {'firstName': 'Peter'}, None, None) == 'Peter'
164+
assert type.resolver(None, {'firstName': 'Peter'}, None, None).value == 'Peter'
165165

166166

167167
def test_field_resolve_vars():
@@ -216,7 +216,6 @@ class Query(ObjectType):
216216
att_func = field_func
217217

218218
assert field.resolver(Root, {}, None) is True
219-
assert field.resolver(Root, {}, None) is True
220219

221220

222221
def test_field_resolve_source_object():
@@ -235,4 +234,3 @@ class Query(ObjectType):
235234
att_func = field_func
236235

237236
assert field.resolver(Root, {}, None) is True
238-
assert field.resolver(Root, {}, None) is True

graphene/plugins/camel_case.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ class CamelCase(object):
66
def get_default_namedtype_name(self, value):
77
return to_camel_case(value)
88

9-
def process_aci(self, aci):
10-
aci.args = ProxySnakeDict(aci.args)
9+
def resolve(self, next, root, args, context, info):
10+
args = ProxySnakeDict(args)
11+
return next(root, args, context, info)

graphene/utils/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
from .caching import cached_property, memoize
44
from .maybe_func import maybe_func
55
from .misc import enum_to_graphql_enum
6+
from .promise_middleware import promise_middleware
67
from .resolve_only_args import resolve_only_args
78
from .lazylist import LazyList
89
from .wrap_resolver_function import with_context, wrap_resolver_function
910

1011

1112
__all__ = ['to_camel_case', 'to_snake_case', 'to_const', 'ProxySnakeDict',
1213
'cached_property', 'memoize', 'maybe_func', 'enum_to_graphql_enum',
13-
'resolve_only_args', 'LazyList', 'with_context',
14+
'promise_middleware', 'resolve_only_args', 'LazyList', 'with_context',
1415
'wrap_resolver_function']
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from functools import partial
2+
from itertools import chain
3+
4+
from promise import Promise
5+
6+
7+
def promise_middleware(func, middlewares):
8+
middlewares = chain((func, make_it_promise), middlewares)
9+
past = None
10+
for m in middlewares:
11+
past = partial(m, past) if past else m
12+
13+
return past
14+
15+
16+
def make_it_promise(next, *a, **b):
17+
return Promise.resolve(next(*a, **b))

0 commit comments

Comments
 (0)