Added annotated resolver and context

This commit is contained in:
Syrus Akbary 2017-07-23 17:19:45 -07:00
parent f7fdc9aa3d
commit d2f1024d81
6 changed files with 89 additions and 2 deletions

View File

@ -32,6 +32,8 @@ if not __SETUP__:
Argument, Argument,
Dynamic, Dynamic,
Union, Union,
Context,
ResolveInfo
) )
from .relay import ( from .relay import (
Node, Node,
@ -74,6 +76,8 @@ if not __SETUP__:
'ConnectionField', 'ConnectionField',
'PageInfo', 'PageInfo',
'lazy_import', 'lazy_import',
'Context',
'ResolveInfo',
# Deprecated # Deprecated
'AbstractType', 'AbstractType',

View File

@ -1,4 +1,5 @@
# flake8: noqa # flake8: noqa
from graphql.execution.base import ResolveInfo
from .objecttype import ObjectType from .objecttype import ObjectType
from .interface import Interface from .interface import Interface
@ -13,6 +14,7 @@ from .argument import Argument
from .inputobjecttype import InputObjectType from .inputobjecttype import InputObjectType
from .dynamic import Dynamic from .dynamic import Dynamic
from .union import Union from .union import Union
from .context import Context
# Deprecated # Deprecated
from .abstracttype import AbstractType from .abstracttype import AbstractType
@ -38,6 +40,8 @@ __all__ = [
'Argument', 'Argument',
'Dynamic', 'Dynamic',
'Union', 'Union',
'Context',
'ResolveInfo',
# Deprecated # Deprecated
'AbstractType', 'AbstractType',

View File

@ -0,0 +1,4 @@
class Context(object):
def __init__(self, **params):
for key, value in params.items():
setattr(self,key, value)

View File

@ -3,8 +3,8 @@ from functools import wraps
from ..pyutils.compat import signature from ..pyutils.compat import signature
def annotate(_func=None, **annotations): def annotate(_func=None, _trigger_warning=True, **annotations):
if not six.PY2: if not six.PY2 and _trigger_warning:
print( print(
"annotate is intended for use in Python 2 only, as you can use type annotations Python 3.\n" "annotate is intended for use in Python 2 only, as you can use type annotations Python 3.\n"
"Read more in https://docs.python.org/3/library/typing.html" "Read more in https://docs.python.org/3/library/typing.html"

View File

@ -0,0 +1,36 @@
from ..pyutils.compat import signature
from functools import wraps
from ..types import Context, ResolveInfo
def annotated_resolver(func):
func_signature = signature(func)
_context_var = None
_info_var = None
for key, parameter in func_signature.parameters.items():
param_type = parameter.annotation
if param_type is Context:
_context_var = key
elif param_type is ResolveInfo:
_info_var = key
continue
# We generate different functions as it will be faster
# than calculating the args on the fly when executing
# the function resolver.
if _context_var and _info_var:
def inner(root, args, context, info):
return func(root, **dict(args, **{_info_var: info, _context_var: context}))
elif _context_var:
def inner(root, args, context, info):
return func(root, **dict(args, **{_context_var: context}))
elif _info_var:
def inner(root, args, context, info):
return func(root, **dict(args, **{_info_var: info}))
else:
def inner(root, args, context, info):
return func(root, **args)
return wraps(func)(inner)

View File

@ -0,0 +1,39 @@
import pytest
from ..annotate import annotate
from ..annotated_resolver import annotated_resolver
from ...types import Context, ResolveInfo
@annotate
def func(root, **args):
return root, args, None, None
@annotate(context=Context)
def func_with_context(root, context, **args):
return root, args, context, None
@annotate(info=ResolveInfo)
def func_with_info(root, info, **args):
return root, args, None, info
@annotate(context=Context, info=ResolveInfo)
def func_with_context_and_info(root, context, info, **args):
return root, args, context, info
root = 1
args = {
'arg': 0
}
context = 2
info = 3
@pytest.mark.parametrize("func,expected", [
(func, (1, {'arg': 0}, None, None)),
(func_with_context, (1, {'arg': 0}, 2, None)),
(func_with_info, (1, {'arg': 0}, None, 3)),
(func_with_context_and_info, (1, {'arg': 0}, 2, 3)),
])
def test_annotated_resolver(func, expected):
resolver_func = annotated_resolver(func)
resolved = resolver_func(root, args, context, info)
assert resolved == expected