mirror of
https://github.com/graphql-python/graphene.git
synced 2025-02-02 20:54:16 +03:00
Improved resolver logic middleware by using promises
This commit is contained in:
parent
25fd60d1ff
commit
8421b59d3a
|
@ -8,20 +8,11 @@ from graphql.utils.schema_printer import print_schema
|
||||||
from graphene import signals
|
from graphene import signals
|
||||||
|
|
||||||
from ..plugins import CamelCase, PluginManager
|
from ..plugins import CamelCase, PluginManager
|
||||||
|
from ..utils import promise_middleware
|
||||||
from .classtypes.base import ClassType
|
from .classtypes.base import ClassType
|
||||||
from .types.base import InstanceType
|
from .types.base import InstanceType
|
||||||
|
|
||||||
|
|
||||||
class ACI(object):
|
|
||||||
def __init__(self, args, context, info):
|
|
||||||
self.args = args
|
|
||||||
self.context = context
|
|
||||||
self.info = info
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "ACI(args={}, context={}, info={})".format(repr(self.args), repr(self.context), repr(self.info))
|
|
||||||
|
|
||||||
|
|
||||||
class GraphQLSchema(_GraphQLSchema):
|
class GraphQLSchema(_GraphQLSchema):
|
||||||
|
|
||||||
def __init__(self, schema, *args, **kwargs):
|
def __init__(self, schema, *args, **kwargs):
|
||||||
|
@ -121,25 +112,9 @@ class Schema(object):
|
||||||
raise KeyError('Type %r not found in %r' % (type_name, self))
|
raise KeyError('Type %r not found in %r' % (type_name, self))
|
||||||
return self._types_names[type_name]
|
return self._types_names[type_name]
|
||||||
|
|
||||||
def resolve(self, resolver, root, args, context, info):
|
def resolver_with_middleware(self, resolver):
|
||||||
aci = ACI(args, context, info)
|
plugins_resolve = self.plugins.get_plugin_functions('resolve')
|
||||||
plugins_process_aci = self.plugins.get_plugin_functions('process_aci')
|
return promise_middleware(resolver, plugins_resolve)
|
||||||
plugins_process_response = self.plugins.get_plugin_functions('process_response')
|
|
||||||
for process_aci in plugins_process_aci:
|
|
||||||
processed_aci = process_aci(aci)
|
|
||||||
if processed_aci is None:
|
|
||||||
continue
|
|
||||||
return processed_aci
|
|
||||||
|
|
||||||
response = resolver(root, aci.args, aci.context, aci.info)
|
|
||||||
|
|
||||||
for process_response in plugins_process_response:
|
|
||||||
processed_response = process_response(response, aci)
|
|
||||||
if processed_response is None:
|
|
||||||
continue
|
|
||||||
return processed_response
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def types(self):
|
def types(self):
|
||||||
|
|
|
@ -93,7 +93,7 @@ def test_field_resolve():
|
||||||
f = StringField(required=True, resolve=lambda *args: 'RESOLVED').as_field()
|
f = StringField(required=True, resolve=lambda *args: 'RESOLVED').as_field()
|
||||||
f.contribute_to_class(MyOt, 'field_name')
|
f.contribute_to_class(MyOt, 'field_name')
|
||||||
field_type = schema.T(f)
|
field_type = schema.T(f)
|
||||||
assert 'RESOLVED' == field_type.resolver(MyOt, None, None, None)
|
assert 'RESOLVED' == field_type.resolver(MyOt, None, None, None).value
|
||||||
|
|
||||||
|
|
||||||
def test_field_resolve_type_custom():
|
def test_field_resolve_type_custom():
|
||||||
|
|
|
@ -115,10 +115,13 @@ class Field(NamedType, OrderedType):
|
||||||
resolver = wrapped_func
|
resolver = wrapped_func
|
||||||
|
|
||||||
assert type, 'Internal type for field %s is None' % str(self)
|
assert type, 'Internal type for field %s is None' % str(self)
|
||||||
return GraphQLField(type, args=schema.T(arguments),
|
return GraphQLField(
|
||||||
resolver=partial(schema.resolve, resolver),
|
type,
|
||||||
|
args=schema.T(arguments),
|
||||||
|
resolver=schema.resolver_with_middleware(resolver),
|
||||||
deprecation_reason=self.deprecation_reason,
|
deprecation_reason=self.deprecation_reason,
|
||||||
description=description,)
|
description=description,
|
||||||
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
"""
|
"""
|
||||||
|
@ -172,7 +175,8 @@ class InputField(NamedType, OrderedType):
|
||||||
def internal_type(self, schema):
|
def internal_type(self, schema):
|
||||||
return GraphQLInputObjectField(
|
return GraphQLInputObjectField(
|
||||||
schema.T(self.type),
|
schema.T(self.type),
|
||||||
default_value=self.default, description=self.description)
|
default_value=self.default, description=self.description
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class FieldsGroupType(GroupNamedType):
|
class FieldsGroupType(GroupNamedType):
|
||||||
|
|
|
@ -24,7 +24,7 @@ def test_field_internal_type():
|
||||||
assert field.attname == 'my_field'
|
assert field.attname == 'my_field'
|
||||||
assert isinstance(type, GraphQLField)
|
assert isinstance(type, GraphQLField)
|
||||||
assert type.description == 'My argument'
|
assert type.description == 'My argument'
|
||||||
assert type.resolver(None, {}, None, None) == 'RESOLVED'
|
assert type.resolver(None, {}, None, None).value == 'RESOLVED'
|
||||||
assert type.type == GraphQLString
|
assert type.type == GraphQLString
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ def test_field_objectype_resolver():
|
||||||
type = schema.T(field)
|
type = schema.T(field)
|
||||||
assert isinstance(type, GraphQLField)
|
assert isinstance(type, GraphQLField)
|
||||||
assert type.description == 'Custom description'
|
assert type.description == 'Custom description'
|
||||||
assert type.resolver(Query(), {}, None, None) == 'RESOLVED'
|
assert type.resolver(Query(), {}, None, None).value == 'RESOLVED'
|
||||||
|
|
||||||
|
|
||||||
def test_field_custom_name():
|
def test_field_custom_name():
|
||||||
|
@ -161,7 +161,7 @@ def test_field_resolve_argument():
|
||||||
schema = Schema(query=Query)
|
schema = Schema(query=Query)
|
||||||
|
|
||||||
type = schema.T(field)
|
type = schema.T(field)
|
||||||
assert type.resolver(None, {'firstName': 'Peter'}, None, None) == 'Peter'
|
assert type.resolver(None, {'firstName': 'Peter'}, None, None).value == 'Peter'
|
||||||
|
|
||||||
|
|
||||||
def test_field_resolve_vars():
|
def test_field_resolve_vars():
|
||||||
|
@ -216,7 +216,6 @@ def test_field_resolve_object():
|
||||||
att_func = field_func
|
att_func = field_func
|
||||||
|
|
||||||
assert field.resolver(Root, {}, None) is True
|
assert field.resolver(Root, {}, None) is True
|
||||||
assert field.resolver(Root, {}, None) is True
|
|
||||||
|
|
||||||
|
|
||||||
def test_field_resolve_source_object():
|
def test_field_resolve_source_object():
|
||||||
|
@ -235,4 +234,3 @@ def test_field_resolve_source_object():
|
||||||
att_func = field_func
|
att_func = field_func
|
||||||
|
|
||||||
assert field.resolver(Root, {}, None) is True
|
assert field.resolver(Root, {}, None) is True
|
||||||
assert field.resolver(Root, {}, None) is True
|
|
||||||
|
|
|
@ -6,5 +6,6 @@ class CamelCase(object):
|
||||||
def get_default_namedtype_name(self, value):
|
def get_default_namedtype_name(self, value):
|
||||||
return to_camel_case(value)
|
return to_camel_case(value)
|
||||||
|
|
||||||
def process_aci(self, aci):
|
def resolve(self, next, root, args, context, info):
|
||||||
aci.args = ProxySnakeDict(aci.args)
|
args = ProxySnakeDict(args)
|
||||||
|
return next(root, args, context, info)
|
||||||
|
|
|
@ -3,6 +3,7 @@ from .proxy_snake_dict import ProxySnakeDict
|
||||||
from .caching import cached_property, memoize
|
from .caching import cached_property, memoize
|
||||||
from .maybe_func import maybe_func
|
from .maybe_func import maybe_func
|
||||||
from .misc import enum_to_graphql_enum
|
from .misc import enum_to_graphql_enum
|
||||||
|
from .promise_middleware import promise_middleware
|
||||||
from .resolve_only_args import resolve_only_args
|
from .resolve_only_args import resolve_only_args
|
||||||
from .lazylist import LazyList
|
from .lazylist import LazyList
|
||||||
from .wrap_resolver_function import with_context, wrap_resolver_function
|
from .wrap_resolver_function import with_context, wrap_resolver_function
|
||||||
|
@ -10,5 +11,5 @@ from .wrap_resolver_function import with_context, wrap_resolver_function
|
||||||
|
|
||||||
__all__ = ['to_camel_case', 'to_snake_case', 'to_const', 'ProxySnakeDict',
|
__all__ = ['to_camel_case', 'to_snake_case', 'to_const', 'ProxySnakeDict',
|
||||||
'cached_property', 'memoize', 'maybe_func', 'enum_to_graphql_enum',
|
'cached_property', 'memoize', 'maybe_func', 'enum_to_graphql_enum',
|
||||||
'resolve_only_args', 'LazyList', 'with_context',
|
'promise_middleware', 'resolve_only_args', 'LazyList', 'with_context',
|
||||||
'wrap_resolver_function']
|
'wrap_resolver_function']
|
||||||
|
|
17
graphene/utils/promise_middleware.py
Normal file
17
graphene/utils/promise_middleware.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
from functools import partial
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
|
from promise import Promise
|
||||||
|
|
||||||
|
|
||||||
|
def promise_middleware(func, middlewares):
|
||||||
|
middlewares = chain((func, make_it_promise), middlewares)
|
||||||
|
past = None
|
||||||
|
for m in middlewares:
|
||||||
|
past = partial(m, past) if past else m
|
||||||
|
|
||||||
|
return past
|
||||||
|
|
||||||
|
|
||||||
|
def make_it_promise(next, *a, **b):
|
||||||
|
return Promise.resolve(next(*a, **b))
|
Loading…
Reference in New Issue
Block a user